<commit_before>package conn

import (
	"bytes"
	"fmt"
	"io"
	"net"
	"strings"
	"sync"
	"testing"
	"time"

	ic "github.com/ipfs/go-libp2p/p2p/crypto"
	transport "github.com/ipfs/go-libp2p/p2p/net/transport"
	peer "github.com/ipfs/go-libp2p/p2p/peer"
	tu "github.com/ipfs/go-libp2p/testutil"

	msmux "gx/ipfs/QmUeEcYJrzAEKdQXjzTxCgNZgc9sRuwharsvzzm5Gd2oGB/go-multistream"
	context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
	ma "gx/ipfs/QmcobAGsCjYt5DXoq9et9L8yR8er7o7Cu3DTvpaq12jYSz/go-multiaddr"
)

func echoListen(ctx context.Context, listener Listener) {
	for {
		c, err := listener.Accept()
		if err != nil {

			select {
			case <-ctx.Done():
				return
			default:
			}

			if ne, ok := err.(net.Error); ok && ne.Temporary() {
				<-time.After(time.Microsecond * 10)
				continue
			}

			log.Debugf("echoListen: listener appears to be closing")
			return
		}

		go echo(c.(Conn))
	}
}

func echo(c Conn) {
	io.Copy(c, c)
}

func setupSecureConn(t *testing.T, ctx context.Context) (a, b Conn, p1, p2 tu.PeerNetParams) {
	return setupConn(t, ctx, true)
}

func setupSingleConn(t *testing.T, ctx context.Context) (a, b Conn, p1, p2 tu.PeerNetParams) {
	return setupConn(t, ctx, false)
}

func Listen(ctx context.Context, addr ma.Multiaddr, local peer.ID, sk ic.PrivKey) (Listener, error) {
	list, err := transport.NewTCPTransport().Listen(addr)
	if err != nil {
		return nil, err
	}

	return WrapTransportListener(ctx, list, local, sk)
}

func dialer(t *testing.T, a ma.Multiaddr) transport.Dialer {
	tpt := transport.NewTCPTransport()
	tptd, err := tpt.Dialer(a)
	if err != nil {
		t.Fatal(err)
	}

	return tptd
}

func setupConn(t *testing.T, ctx context.Context, secure bool) (a, b Conn, p1, p2 tu.PeerNetParams) {

	p1 = tu.RandPeerNetParamsOrFatal(t)
	p2 = tu.RandPeerNetParamsOrFatal(t)

	key1 := p1.PrivKey
	key2 := p2.PrivKey
	if !secure {
		key1 = nil
		key2 = nil
	}
	l1, err := Listen(ctx, p1.Addr, p1.ID, key1)
	if err != nil {
		t.Fatal(err)
	}
	p1.Addr = l1.Multiaddr() // Addr has been determined by kernel.

	d2 := &Dialer{
		LocalPeer:  p2.ID,
		PrivateKey: key2,
	}

	d2.AddDialer(dialer(t, p2.Addr))

	var c2 Conn

	done := make(chan error)
	go func() {
		defer close(done)

		var err error
		c2, err = d2.Dial(ctx, p1.Addr, p1.ID)
		if err != nil {
			done <- err
			return
		}

		// if secure, need to read + write, as that's what triggers the handshake.
		if secure {
			if err := sayHello(c2); err != nil {
				done <- err
			}
		}
	}()

	c1, err := l1.Accept()
	if err != nil {
		t.Fatal("failed to accept", err)
	}

	// if secure, need to read + write, as that's what triggers the handshake.
	if secure {
		if err := sayHello(c1); err != nil {
			done <- err
		}
	}

	if err := <-done; err != nil {
		t.Fatal(err)
	}

	return c1.(Conn), c2, p1, p2
}

func sayHello(c net.Conn) error {
	h := []byte("hello")
	if _, err := c.Write(h); err != nil {
		return err
	}
	if _, err := c.Read(h); err != nil {
		return err
	}
	if string(h) != "hello" {
		return fmt.Errorf("did not get hello")
	}
	return nil
}

func testDialer(t *testing.T, secure bool) {
	// t.Skip("Skipping in favor of another test")

	p1 := tu.RandPeerNetParamsOrFatal(t)
	p2 := tu.RandPeerNetParamsOrFatal(t)

	key1 := p1.PrivKey
	key2 := p2.PrivKey
	if !secure {
		key1 = nil
		key2 = nil
		t.Log("testing insecurely")
	} else {
		t.Log("testing securely")
	}

	ctx, cancel := context.WithCancel(context.Background())
	l1, err := Listen(ctx, p1.Addr, p1.ID, key1)
	if err != nil {
		t.Fatal(err)
	}
	p1.Addr = l1.Multiaddr() // Addr has been determined by kernel.

	d2 := &Dialer{
		LocalPeer:  p2.ID,
		PrivateKey: key2,
	}
	d2.AddDialer(dialer(t, p2.Addr))

	go echoListen(ctx, l1)

	c, err := d2.Dial(ctx, p1.Addr, p1.ID)
	if err != nil {
		t.Fatal("error dialing peer", err)
	}

	// fmt.Println("sending")
	mc := msgioWrap(c)
	mc.WriteMsg([]byte("beep"))
	mc.WriteMsg([]byte("boop"))
	out, err := mc.ReadMsg()
	if err != nil {
		t.Fatal(err)
	}

	// fmt.Println("recving", string(out))
	data := string(out)
	if data != "beep" {
		t.Error("unexpected conn output", data)
	}

	out, err = mc.ReadMsg()
	if err != nil {
		t.Fatal(err)
	}

	data = string(out)
	if string(out) != "boop" {
		t.Error("unexpected conn output", data)
	}

	// fmt.Println("closing")
	c.Close()
	l1.Close()
	cancel()
}

func TestDialerInsecure(t *testing.T) {
	// t.Skip("Skipping in favor of another test")
	testDialer(t, false)
}

func TestDialerSecure(t *testing.T) {
	// t.Skip("Skipping in favor of another test")
	testDialer(t, true)
}

func testDialerCloseEarly(t *testing.T, secure bool) {
	// t.Skip("Skipping in favor of another test")

	p1 := tu.RandPeerNetParamsOrFatal(t)
	p2 := tu.RandPeerNetParamsOrFatal(t)

	key1 := p1.PrivKey
	if !secure {
		key1 = nil
		t.Log("testing insecurely")
	} else {
		t.Log("testing securely")
	}

	ctx, cancel := context.WithCancel(context.Background())
	l1, err := Listen(ctx, p1.Addr, p1.ID, key1)
	if err != nil {
		t.Fatal(err)
	}
	p1.Addr = l1.Multiaddr() // Addr has been determined by kernel.

	// lol nesting
	d2 := &Dialer{
		LocalPeer: p2.ID,
		// PrivateKey: key2, -- dont give it key. we'll just close the conn.
	}
	d2.AddDialer(dialer(t, p2.Addr))

	errs := make(chan error, 100)
	done := make(chan struct{}, 1)
	gotclosed := make(chan struct{}, 1)
	go func() {
		defer func() { done <- struct{}{} }()

		c, err := l1.Accept()
		if err != nil {
			if strings.Contains(err.Error(), "closed") {
				gotclosed <- struct{}{}
				return
			}
			errs <- err
		}

		if _, err := c.Write([]byte("hello")); err != nil {
			gotclosed <- struct{}{}
			return
		}

		errs <- fmt.Errorf("wrote to conn")
	}()

	c, err := d2.Dial(ctx, p1.Addr, p1.ID)
	if err != nil {
		t.Fatal(err)
	}
	c.Close() // close it early.

	readerrs := func() {
		for {
			select {
			case e := <-errs:
				t.Error(e)
			default:
				return
			}
		}
	}
	readerrs()

	l1.Close()
	<-done
	cancel()
	readerrs()
	close(errs)

	select {
	case <-gotclosed:
	default:
		t.Error("did not get closed")
	}
}

// we dont do a handshake with singleConn, so cant "close early."
// func TestDialerCloseEarlyInsecure(t *testing.T) {
// 	// t.Skip("Skipping in favor of another test")
// 	testDialerCloseEarly(t, false)
// }

func TestDialerCloseEarlySecure(t *testing.T) {
	// t.Skip("Skipping in favor of another test")
	testDialerCloseEarly(t, true)
}

func TestMultistreamHeader(t *testing.T) {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	p1 := tu.RandPeerNetParamsOrFatal(t)

	l1, err := Listen(ctx, p1.Addr, p1.ID, p1.PrivKey)
	if err != nil {
		t.Fatal(err)
	}

	p1.Addr = l1.Multiaddr() // Addr has been determined by kernel.

	go func() {
		_, _ = l1.Accept()
	}()

	con, err := net.Dial("tcp", l1.Addr().String())
	if err != nil {
		t.Fatal(err)
	}
	defer con.Close()

	err = msmux.SelectProtoOrFail(SecioTag, con)
	if err != nil {
		t.Fatal(err)
	}
}

func TestFailedAccept(t *testing.T) {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	p1 := tu.RandPeerNetParamsOrFatal(t)

	l1, err := Listen(ctx, p1.Addr, p1.ID, p1.PrivKey)
	if err != nil {
		t.Fatal(err)
	}

	p1.Addr = l1.Multiaddr() // Addr has been determined by kernel.

	done := make(chan struct{})
	go func() {
		defer close(done)
		con, err := net.Dial("tcp", l1.Addr().String())
		if err != nil {
			t.Error("first dial failed: ", err)
		}

		// write some garbage
		con.Write(bytes.Repeat([]byte{255}, 1000))

		con.Close()

		con, err = net.Dial("tcp", l1.Addr().String())
		if err != nil {
			t.Error("second dial failed: ", err)
		}
		defer con.Close()

		err = msmux.SelectProtoOrFail(SecioTag, con)
		if err != nil {
			t.Error("msmux select failed: ", err)
		}
	}()

	c, err := l1.Accept()
	if err != nil {
		t.Fatal("connections after a failed accept should still work: ", err)
	}

	c.Close()
	<-done
}

func TestHangingAccept(t *testing.T) {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	p1 := tu.RandPeerNetParamsOrFatal(t)

	l1, err := Listen(ctx, p1.Addr, p1.ID, p1.PrivKey)
	if err != nil {
		t.Fatal(err)
	}

	p1.Addr = l1.Multiaddr() // Addr has been determined by kernel.

	done := make(chan struct{})
	go func() {
		defer close(done)
		con, err := net.Dial("tcp", l1.Addr().String())
		if err != nil {
			t.Error("first dial failed: ", err)
		}
		// hang this connection
		defer con.Close()

		// ensure that the first conn hits first
		time.Sleep(time.Millisecond * 50)

		con2, err := net.Dial("tcp", l1.Addr().String())
		if err != nil {
			t.Error("second dial failed: ", err)
		}
		defer con2.Close()

		err = msmux.SelectProtoOrFail(SecioTag, con2)
		if err != nil {
			t.Error("msmux select failed: ", err)
		}

		_, err = con2.Write([]byte("test"))
		if err != nil {
			t.Error("con write failed: ", err)
		}
	}()

	c, err := l1.Accept()
	if err != nil {
		t.Fatal("connections after a failed accept should still work: ", err)
	}

	c.Close()
	<-done
}

func TestConcurrentAccept(t *testing.T) {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	p1 := tu.RandPeerNetParamsOrFatal(t)

	l1, err := Listen(ctx, p1.Addr, p1.ID, p1.PrivKey)
	if err != nil {
		t.Fatal(err)
	}

	n := 300
	delay := time.Millisecond * 20

	p1.Addr = l1.Multiaddr() // Addr has been determined by kernel.

	var wg sync.WaitGroup
	for i := 0; i < n; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			con, err := net.Dial("tcp", l1.Addr().String())
			if err != nil {
				log.Error(err)
				t.Error("first dial failed: ", err)
				return
			}
			// hang this connection
			defer con.Close()

			time.Sleep(delay)
			err = msmux.SelectProtoOrFail(SecioTag, con)
			if err != nil {
				t.Error(err)
			}
		}()
	}

	before := time.Now()
	for i := 0; i < n; i++ {
		c, err := l1.Accept()
		if err != nil {
			t.Fatal("connections after a failed accept should still work: ", err)
		}

		c.Close()
	}

	limit := delay * time.Duration(n)
	took := time.Now().Sub(before)
	if took > limit {
		t.Fatal("took too long!")
	}
	log.Errorf("took: %s (less than %s)", took, limit)
}
<commit_msg>make test smaller for osx<commit_after>package conn

import (
	"bytes"
	"fmt"
	"io"
	"net"
	"runtime"
	"strings"
	"sync"
	"testing"
	"time"

	ic "github.com/ipfs/go-libp2p/p2p/crypto"
	transport "github.com/ipfs/go-libp2p/p2p/net/transport"
	peer "github.com/ipfs/go-libp2p/p2p/peer"
	tu "github.com/ipfs/go-libp2p/testutil"

	msmux "gx/ipfs/QmUeEcYJrzAEKdQXjzTxCgNZgc9sRuwharsvzzm5Gd2oGB/go-multistream"
	context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
	ma "gx/ipfs/QmcobAGsCjYt5DXoq9et9L8yR8er7o7Cu3DTvpaq12jYSz/go-multiaddr"
)

func echoListen(ctx context.Context, listener Listener) {
	for {
		c, err := listener.Accept()
		if err != nil {

			select {
			case <-ctx.Done():
				return
			default:
			}

			if ne, ok := err.(net.Error); ok && ne.Temporary() {
				<-time.After(time.Microsecond * 10)
				continue
			}

			log.Debugf("echoListen: listener appears to be closing")
			return
		}

		go echo(c.(Conn))
	}
}

func echo(c Conn) {
	io.Copy(c, c)
}

func setupSecureConn(t *testing.T, ctx context.Context) (a, b Conn, p1, p2 tu.PeerNetParams) {
	return setupConn(t, ctx, true)
}

func setupSingleConn(t *testing.T, ctx context.Context) (a, b Conn, p1, p2 tu.PeerNetParams) {
	return setupConn(t, ctx, false)
}

func Listen(ctx context.Context, addr ma.Multiaddr, local peer.ID, sk ic.PrivKey) (Listener, error) {
	list, err := transport.NewTCPTransport().Listen(addr)
	if err != nil {
		return nil, err
	}

	return WrapTransportListener(ctx, list, local, sk)
}

func dialer(t *testing.T, a ma.Multiaddr) transport.Dialer {
	tpt := transport.NewTCPTransport()
	tptd, err := tpt.Dialer(a)
	if err != nil {
		t.Fatal(err)
	}

	return tptd
}

func setupConn(t *testing.T, ctx context.Context, secure bool) (a, b Conn, p1, p2 tu.PeerNetParams) {

	p1 = tu.RandPeerNetParamsOrFatal(t)
	p2 = tu.RandPeerNetParamsOrFatal(t)

	key1 := p1.PrivKey
	key2 := p2.PrivKey
	if !secure {
		key1 = nil
		key2 = nil
	}
	l1, err := Listen(ctx, p1.Addr, p1.ID, key1)
	if err != nil {
		t.Fatal(err)
	}
	p1.Addr = l1.Multiaddr() // Addr has been determined by kernel.

	d2 := &Dialer{
		LocalPeer:  p2.ID,
		PrivateKey: key2,
	}

	d2.AddDialer(dialer(t, p2.Addr))

	var c2 Conn

	done := make(chan error)
	go func() {
		defer close(done)

		var err error
		c2, err = d2.Dial(ctx, p1.Addr, p1.ID)
		if err != nil {
			done <- err
			return
		}

		// if secure, need to read + write, as that's what triggers the handshake.
		if secure {
			if err := sayHello(c2); err != nil {
				done <- err
			}
		}
	}()

	c1, err := l1.Accept()
	if err != nil {
		t.Fatal("failed to accept", err)
	}

	// if secure, need to read + write, as that's what triggers the handshake.
	if secure {
		if err := sayHello(c1); err != nil {
			done <- err
		}
	}

	if err := <-done; err != nil {
		t.Fatal(err)
	}

	return c1.(Conn), c2, p1, p2
}

func sayHello(c net.Conn) error {
	h := []byte("hello")
	if _, err := c.Write(h); err != nil {
		return err
	}
	if _, err := c.Read(h); err != nil {
		return err
	}
	if string(h) != "hello" {
		return fmt.Errorf("did not get hello")
	}
	return nil
}

func testDialer(t *testing.T, secure bool) {
	// t.Skip("Skipping in favor of another test")

	p1 := tu.RandPeerNetParamsOrFatal(t)
	p2 := tu.RandPeerNetParamsOrFatal(t)

	key1 := p1.PrivKey
	key2 := p2.PrivKey
	if !secure {
		key1 = nil
		key2 = nil
		t.Log("testing insecurely")
	} else {
		t.Log("testing securely")
	}

	ctx, cancel := context.WithCancel(context.Background())
	l1, err := Listen(ctx, p1.Addr, p1.ID, key1)
	if err != nil {
		t.Fatal(err)
	}
	p1.Addr = l1.Multiaddr() // Addr has been determined by kernel.

	d2 := &Dialer{
		LocalPeer:  p2.ID,
		PrivateKey: key2,
	}
	d2.AddDialer(dialer(t, p2.Addr))

	go echoListen(ctx, l1)

	c, err := d2.Dial(ctx, p1.Addr, p1.ID)
	if err != nil {
		t.Fatal("error dialing peer", err)
	}

	// fmt.Println("sending")
	mc := msgioWrap(c)
	mc.WriteMsg([]byte("beep"))
	mc.WriteMsg([]byte("boop"))
	out, err := mc.ReadMsg()
	if err != nil {
		t.Fatal(err)
	}

	// fmt.Println("recving", string(out))
	data := string(out)
	if data != "beep" {
		t.Error("unexpected conn output", data)
	}

	out, err = mc.ReadMsg()
	if err != nil {
		t.Fatal(err)
	}

	data = string(out)
	if string(out) != "boop" {
		t.Error("unexpected conn output", data)
	}

	// fmt.Println("closing")
	c.Close()
	l1.Close()
	cancel()
}

func TestDialerInsecure(t *testing.T) {
	// t.Skip("Skipping in favor of another test")
	testDialer(t, false)
}

func TestDialerSecure(t *testing.T) {
	// t.Skip("Skipping in favor of another test")
	testDialer(t, true)
}

func testDialerCloseEarly(t *testing.T, secure bool) {
	// t.Skip("Skipping in favor of another test")

	p1 := tu.RandPeerNetParamsOrFatal(t)
	p2 := tu.RandPeerNetParamsOrFatal(t)

	key1 := p1.PrivKey
	if !secure {
		key1 = nil
		t.Log("testing insecurely")
	} else {
		t.Log("testing securely")
	}

	ctx, cancel := context.WithCancel(context.Background())
	l1, err := Listen(ctx, p1.Addr, p1.ID, key1)
	if err != nil {
		t.Fatal(err)
	}
	p1.Addr = l1.Multiaddr() // Addr has been determined by kernel.

	// lol nesting
	d2 := &Dialer{
		LocalPeer: p2.ID,
		// PrivateKey: key2, -- dont give it key. we'll just close the conn.
	}
	d2.AddDialer(dialer(t, p2.Addr))

	errs := make(chan error, 100)
	done := make(chan struct{}, 1)
	gotclosed := make(chan struct{}, 1)
	go func() {
		defer func() { done <- struct{}{} }()

		c, err := l1.Accept()
		if err != nil {
			if strings.Contains(err.Error(), "closed") {
				gotclosed <- struct{}{}
				return
			}
			errs <- err
		}

		if _, err := c.Write([]byte("hello")); err != nil {
			gotclosed <- struct{}{}
			return
		}

		errs <- fmt.Errorf("wrote to conn")
	}()

	c, err := d2.Dial(ctx, p1.Addr, p1.ID)
	if err != nil {
		t.Fatal(err)
	}
	c.Close() // close it early.

	readerrs := func() {
		for {
			select {
			case e := <-errs:
				t.Error(e)
			default:
				return
			}
		}
	}
	readerrs()

	l1.Close()
	<-done
	cancel()
	readerrs()
	close(errs)

	select {
	case <-gotclosed:
	default:
		t.Error("did not get closed")
	}
}

// we dont do a handshake with singleConn, so cant "close early."
// func TestDialerCloseEarlyInsecure(t *testing.T) {
// 	// t.Skip("Skipping in favor of another test")
// 	testDialerCloseEarly(t, false)
// }

func TestDialerCloseEarlySecure(t *testing.T) {
	// t.Skip("Skipping in favor of another test")
	testDialerCloseEarly(t, true)
}

func TestMultistreamHeader(t *testing.T) {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	p1 := tu.RandPeerNetParamsOrFatal(t)

	l1, err := Listen(ctx, p1.Addr, p1.ID, p1.PrivKey)
	if err != nil {
		t.Fatal(err)
	}

	p1.Addr = l1.Multiaddr() // Addr has been determined by kernel.

	go func() {
		_, _ = l1.Accept()
	}()

	con, err := net.Dial("tcp", l1.Addr().String())
	if err != nil {
		t.Fatal(err)
	}
	defer con.Close()

	err = msmux.SelectProtoOrFail(SecioTag, con)
	if err != nil {
		t.Fatal(err)
	}
}

func TestFailedAccept(t *testing.T) {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	p1 := tu.RandPeerNetParamsOrFatal(t)

	l1, err := Listen(ctx, p1.Addr, p1.ID, p1.PrivKey)
	if err != nil {
		t.Fatal(err)
	}

	p1.Addr = l1.Multiaddr() // Addr has been determined by kernel.

	done := make(chan struct{})
	go func() {
		defer close(done)
		con, err := net.Dial("tcp", l1.Addr().String())
		if err != nil {
			t.Error("first dial failed: ", err)
		}

		// write some garbage
		con.Write(bytes.Repeat([]byte{255}, 1000))

		con.Close()

		con, err = net.Dial("tcp", l1.Addr().String())
		if err != nil {
			t.Error("second dial failed: ", err)
		}
		defer con.Close()

		err = msmux.SelectProtoOrFail(SecioTag, con)
		if err != nil {
			t.Error("msmux select failed: ", err)
		}
	}()

	c, err := l1.Accept()
	if err != nil {
		t.Fatal("connections after a failed accept should still work: ", err)
	}

	c.Close()
	<-done
}

func TestHangingAccept(t *testing.T) {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	p1 := tu.RandPeerNetParamsOrFatal(t)

	l1, err := Listen(ctx, p1.Addr, p1.ID, p1.PrivKey)
	if err != nil {
		t.Fatal(err)
	}

	p1.Addr = l1.Multiaddr() // Addr has been determined by kernel.

	done := make(chan struct{})
	go func() {
		defer close(done)
		con, err := net.Dial("tcp", l1.Addr().String())
		if err != nil {
			t.Error("first dial failed: ", err)
		}
		// hang this connection
		defer con.Close()

		// ensure that the first conn hits first
		time.Sleep(time.Millisecond * 50)

		con2, err := net.Dial("tcp", l1.Addr().String())
		if err != nil {
			t.Error("second dial failed: ", err)
		}
		defer con2.Close()

		err = msmux.SelectProtoOrFail(SecioTag, con2)
		if err != nil {
			t.Error("msmux select failed: ", err)
		}

		_, err = con2.Write([]byte("test"))
		if err != nil {
			t.Error("con write failed: ", err)
		}
	}()

	c, err := l1.Accept()
	if err != nil {
		t.Fatal("connections after a failed accept should still work: ", err)
	}

	c.Close()
	<-done
}

func TestConcurrentAccept(t *testing.T) {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	p1 := tu.RandPeerNetParamsOrFatal(t)

	l1, err := Listen(ctx, p1.Addr, p1.ID, p1.PrivKey)
	if err != nil {
		t.Fatal(err)
	}

	n := 300
	delay := time.Millisecond * 20
	if runtime.GOOS == "darwin" {
		n = 100
	}

	p1.Addr = l1.Multiaddr() // Addr has been determined by kernel.

	var wg sync.WaitGroup
	for i := 0; i < n; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			con, err := net.Dial("tcp", l1.Addr().String())
			if err != nil {
				log.Error(err)
				t.Error("first dial failed: ", err)
				return
			}
			// hang this connection
			defer con.Close()

			time.Sleep(delay)
			err = msmux.SelectProtoOrFail(SecioTag, con)
			if err != nil {
				t.Error(err)
			}
		}()
	}

	before := time.Now()
	for i := 0; i < n; i++ {
		c, err := l1.Accept()
		if err != nil {
			t.Fatal("connections after a failed accept should still work: ", err)
		}

		c.Close()
	}

	limit := delay * time.Duration(n)
	took := time.Now().Sub(before)
	if took > limit {
		t.Fatal("took too long!")
	}
	log.Errorf("took: %s (less than %s)", took, limit)
}
<|endoftext|>


<commit_before>/*
    norx.go
    ------

    This file is part of the Go reference implementation of NORX.

    :copyright: (c) 2014, 2015 Philipp Jovanovic <philipp@jovanovic.io>
    :license: CC0, see LICENSE
*/

package aead

const (
    NORX_W      = 64                                // wordsize
    NORX_L      = 4                                 // number of rounds
    NORX_P      = 1                                 // parallelism degree
    NORX_T      = NORX_W * 4                        // tag size
    WORDS_RATE  = 12                                // number of words in the rate
    WORDS_STATE = 16                                // ... in the state
    BYTES_WORD  = NORX_W / 8                        // byte size of a word
    BYTES_RATE  = WORDS_RATE * BYTES_WORD           // ... of the rate
    BYTES_TAG   = NORX_T / 8                        // ... of the tag
    HEADER_TAG  = 0x01                              // domain separation constant for header
    PAYLOAD_TAG = 0x02                              // ... for payload
    TRAILER_TAG = 0x04                              // ... for trailer
    FINAL_TAG   = 0x08                              // ... for finalisation
    BRANCH_TAG  = 0x10                              // ... for branching
    MERGE_TAG   = 0x20                              // ... for merging
    R0, R1, R2, R3 = 8, 19, 40, 63                  // rotation offsets
)

type norx_state_t struct {
    s [WORDS_STATE]uint64
}

func load64(in []uint8) uint64 {
    return (uint64(in[0]) <<  0) |
           (uint64(in[1]) <<  8) |
           (uint64(in[2]) << 16) |
           (uint64(in[3]) << 24) |
           (uint64(in[4]) << 32) |
           (uint64(in[5]) << 40) |
           (uint64(in[6]) << 48) |
           (uint64(in[7]) << 56)
}

func store64(out []uint8, in uint64) {
    out[0] = uint8(in >>  0)
    out[1] = uint8(in >>  8)
    out[2] = uint8(in >> 16)
    out[3] = uint8(in >> 24)
    out[4] = uint8(in >> 32)
    out[5] = uint8(in >> 40)
    out[6] = uint8(in >> 48)
    out[7] = uint8(in >> 56)
}

func burn8(x []uint8, xlen uint64) {
    for i := uint64(0); i < xlen; i++ {
        x[i] = 0
    }
}

func burn64(x []uint64, xlen uint64) {
    for i := uint64(0); i < xlen; i++ {
        x[i] = 0
    }
}

func rotr(x,c uint64) uint64 {
    return (x >> c | x << (NORX_W - c))
}

func h(x,y uint64) uint64 {
    return (x ^ y) ^ ((x & y) << 1)
}

func g(a,b,c,d uint64) (uint64,uint64,uint64,uint64) {

    a = h(a,b)
    d = rotr(a ^ d, R0)
    c = h(c,d)
    b = rotr(b ^ c, R1)
    a = h(a,b)
    d = rotr(a ^ d, R2)
    c = h(c,d)
    b = rotr(b ^ c, R3)
    return a,b,c,d
}

func f(s []uint64) {

    // Column step
    s[ 0], s[ 4], s[ 8], s[12] = g(s[ 0], s[ 4], s[ 8], s[12])
    s[ 1], s[ 5], s[ 9], s[13] = g(s[ 1], s[ 5], s[ 9], s[13])
    s[ 2], s[ 6], s[10], s[14] = g(s[ 2], s[ 6], s[10], s[14])
    s[ 3], s[ 7], s[11], s[15] = g(s[ 3], s[ 7], s[11], s[15])
    // Diagonal step
    s[ 0], s[ 5], s[10], s[15] = g(s[ 0], s[ 5], s[10], s[15])
    s[ 1], s[ 6], s[11], s[12] = g(s[ 1], s[ 6], s[11], s[12])
    s[ 2], s[ 7], s[ 8], s[13] = g(s[ 2], s[ 7], s[ 8], s[13])
    s[ 3], s[ 4], s[ 9], s[14] = g(s[ 3], s[ 4], s[ 9], s[14])
}

func norx_permute(state *norx_state_t) {

    var s = state.s[:]
    for i := uint64(0); i < NORX_L; i++ {
        f(s)
    }
}

func norx_init(state *norx_state_t, k []uint8, n []uint8) {

    var s = state.s[:]

    for i := uint64(0); i < 16; i++ {
        s[i] = i
    }

    f(s)
    f(s)

    state.s[ 0] = load64(n[ 0: 8])
    state.s[ 1] = load64(n[ 8:16])

    state.s[ 4] = load64(k[ 0: 8])
    state.s[ 5] = load64(k[ 8:16])
    state.s[ 6] = load64(k[16:24])
    state.s[ 7] = load64(k[24:32])

    state.s[12] ^= NORX_W
    state.s[13] ^= NORX_L
    state.s[14] ^= NORX_P
    state.s[15] ^= NORX_T

    norx_permute(state)
}

func norx_absorb_data(state *norx_state_t, in []uint8, inlen uint64, tag uint64) {

    if inlen > 0 {

        var i uint64 = 0
        const n uint64 = BYTES_RATE

        for i = 0; inlen >= n; inlen, i = inlen-n, i+1 {
            norx_absorb_block(state, in[n*i:n*(i+1)], tag)
        }
        norx_absorb_lastblock(state, in[n*i:n*i+inlen], inlen, tag)
    }
}

func norx_encrypt_data(state *norx_state_t, out []uint8, in []uint8, inlen uint64) {

    if inlen > 0 {

        var i uint64 = 0
        const n uint64 = BYTES_RATE

        for i = 0; inlen >= n; inlen, i = inlen-n, i+1 {
            norx_encrypt_block(state, out[n*i:n*(i+1)], in[n*i:n*(i+1)])
        }
        encrypt_lastblock(state, out[n*i:n*i+inlen], in[n*i:n*i+inlen], inlen)
    }
}

func norx_decrypt_data(state *norx_state_t, out []uint8, in []uint8, inlen uint64) {

    if inlen > 0 {

        var i uint64 = 0
        const n uint64 = BYTES_RATE

        for i = 0; inlen >= n; inlen, i = inlen-n, i+1 {
            norx_decrypt_block(state, out[n*i:n*(i+1)], in[n*i:n*(i+1)])
        }
        norx_decrypt_lastblock(state, out[n*i:n*i+inlen], in[n*i:n*i+inlen], inlen)
    }
}

func norx_output_tag(state *norx_state_t, tag []uint8) {

    state.s[15] ^= FINAL_TAG
    norx_permute(state)
    norx_permute(state)

    var s = state.s[:]
    var lastblock [BYTES_RATE]uint8
    const b uint64 = BYTES_WORD

    for i := uint64(0); i < WORDS_RATE; i++ {
        store64(lastblock[b*i:b*(i+1)], s[i])
    }
    copy(tag[:], lastblock[:])
    burn8(lastblock[:], BYTES_RATE)
}

func norx_verify_tag(tag1 []uint8, tag2 []uint8) int {

    var acc int = 0

    for i := uint64(0); i < BYTES_TAG; i++ {
        acc |= int(tag1[i] ^ tag2[i])
    }
    return (((acc - 1) >> 8) & 1) - 1
}

func norx_pad(out []uint8, in []uint8, inlen uint64) {

    copy(out[:],in[:inlen])
    out[inlen] = 0x01
    out[BYTES_RATE - 1] |= 0x80
}

func norx_absorb_block(state *norx_state_t, in []uint8, tag uint64) {

    state.s[15] ^= tag
    norx_permute(state)

    var s = state.s[:]
    const b uint64 = BYTES_WORD

    for i := uint64(0); i < WORDS_RATE; i++ {
        s[i] ^= load64(in[b*i:b*(i+1)])
    }
}

func norx_absorb_lastblock(state *norx_state_t, in []uint8, inlen uint64, tag uint64) {

    var lastblock [BYTES_RATE]uint8
    norx_pad(lastblock[:], in[:], inlen)
    norx_absorb_block(state, lastblock[:], tag)
    burn8(lastblock[:], BYTES_RATE)
}

func norx_encrypt_block(state *norx_state_t, out []uint8, in []uint8) {

    state.s[15] ^= PAYLOAD_TAG
    norx_permute(state)

    var s = state.s[:]
    const b uint64 = BYTES_WORD

    for i := uint64(0); i < WORDS_RATE; i++ {
        s[i] ^= load64(in[b*i:b*(i+1)])
        store64(out[b*i:b*(i+1)], s[i])
    }
}

func encrypt_lastblock(state *norx_state_t, out []uint8, in []uint8, inlen uint64) {

    var lastblock [BYTES_RATE]uint8
    norx_pad(lastblock[:], in[:], inlen)
    norx_encrypt_block(state, lastblock[:], lastblock[:])
    copy(out[:], lastblock[:])
    burn8(lastblock[:], BYTES_RATE)
}

func norx_decrypt_block(state *norx_state_t, out []uint8, in []uint8) {

    state.s[15] ^= PAYLOAD_TAG
    norx_permute(state)

    var s = state.s[:]
    const b uint64 = BYTES_WORD

    for i := uint64(0); i < WORDS_RATE; i++ {
        c := load64(in[b*i:b*(i+1)])
        store64(out[b*i:b*(i+1)], s[i] ^ c)
        s[i] = c
    }
}

func norx_decrypt_lastblock(state *norx_state_t, out []uint8, in []uint8, inlen uint64) {

    state.s[15] ^= PAYLOAD_TAG
    norx_permute(state)

    var s = state.s[:]
    const n uint64 = BYTES_WORD
    var lastblock [BYTES_RATE]uint8

    for i := uint64(0); i < WORDS_RATE; i++ {
        store64(lastblock[n*i:n*(i+1)],s[i])
    }
    copy(lastblock[:],in[:inlen])
    lastblock[inlen] ^= 0x01
    lastblock[BYTES_RATE - 1] ^= 0x80

    for i := uint64(0); i < WORDS_RATE; i++ {
        c := load64(lastblock[n*i:n*(i+1)])
        store64(lastblock[n*i:n*(i+1)], s[i] ^ c)
        s[i] = c
    }
    copy(out[:inlen],lastblock[:])
    burn8(lastblock[:],BYTES_RATE)
}

func AEAD_encrypt(
    c []uint8, clen *uint64,
    h []uint8, hlen uint64,
    m []uint8, mlen uint64,
    t []uint8, tlen uint64,
    nonce []uint8,
    key []uint8) {

    var state = new(norx_state_t)
    norx_init(state, key, nonce)
    norx_absorb_data(state, h, hlen, HEADER_TAG)
    norx_encrypt_data(state, c, m, mlen)
    norx_absorb_data(state, t, tlen, TRAILER_TAG)
    norx_output_tag(state, c[mlen:])
    *clen = mlen + BYTES_TAG
    burn64(state.s[:], WORDS_STATE)
}

func AEAD_decrypt(
    m []uint8, mlen *uint64,
    h []uint8, hlen uint64,
    c []uint8, clen uint64,
    t []uint8, tlen uint64,
    nonce []uint8,
    key []uint8) int {

    if clen < BYTES_TAG {
      return -1
    }
    var result int = -1
    var tag [BYTES_TAG]uint8
    var state = new(norx_state_t)
    norx_init(state, key, nonce)
    norx_absorb_data(state, h, hlen, HEADER_TAG)
    norx_decrypt_data(state, m, c, clen - BYTES_TAG)
    norx_absorb_data(state, t, tlen, TRAILER_TAG)
    norx_output_tag(state, tag[:])
    *mlen = clen - BYTES_TAG
    result = norx_verify_tag(c[clen - BYTES_TAG:], tag[:])
    if result != 0 {
        burn8(m[:], clen - BYTES_TAG)
    }
    burn64(state.s[:], WORDS_STATE)
    return result
}

<commit_msg>comment<commit_after>/*
    norx.go
    ------

    This file is part of the Go reference implementation of NORX.

    :copyright: (c) 2014, 2015 Philipp Jovanovic <philipp@jovanovic.io>
    :license: CC0, see LICENSE
*/

package aead

const (
    NORX_W      = 64                                // wordsize
    NORX_L      = 4                                 // number of rounds
    NORX_P      = 1                                 // parallelism degree
    NORX_T      = NORX_W * 4                        // tag size
    WORDS_RATE  = 12                                // number of words in the rate
    WORDS_STATE = 16                                // ... in the state
    BYTES_WORD  = NORX_W / 8                        // number of bytes in a word
    BYTES_RATE  = WORDS_RATE * BYTES_WORD           // ... in the rate
    BYTES_TAG   = NORX_T / 8                        // ... in the tag
    HEADER_TAG  = 0x01                              // domain separation constant for header
    PAYLOAD_TAG = 0x02                              // ... for payload
    TRAILER_TAG = 0x04                              // ... for trailer
    FINAL_TAG   = 0x08                              // ... for finalisation
    BRANCH_TAG  = 0x10                              // ... for branching
    MERGE_TAG   = 0x20                              // ... for merging
    R0, R1, R2, R3 = 8, 19, 40, 63                  // rotation offsets
)

type norx_state_t struct {
    s [WORDS_STATE]uint64
}

func load64(in []uint8) uint64 {
    return (uint64(in[0]) <<  0) |
           (uint64(in[1]) <<  8) |
           (uint64(in[2]) << 16) |
           (uint64(in[3]) << 24) |
           (uint64(in[4]) << 32) |
           (uint64(in[5]) << 40) |
           (uint64(in[6]) << 48) |
           (uint64(in[7]) << 56)
}

func store64(out []uint8, in uint64) {
    out[0] = uint8(in >>  0)
    out[1] = uint8(in >>  8)
    out[2] = uint8(in >> 16)
    out[3] = uint8(in >> 24)
    out[4] = uint8(in >> 32)
    out[5] = uint8(in >> 40)
    out[6] = uint8(in >> 48)
    out[7] = uint8(in >> 56)
}

func burn8(x []uint8, xlen uint64) {
    for i := uint64(0); i < xlen; i++ {
        x[i] = 0
    }
}

func burn64(x []uint64, xlen uint64) {
    for i := uint64(0); i < xlen; i++ {
        x[i] = 0
    }
}

func rotr(x,c uint64) uint64 {
    return (x >> c | x << (NORX_W - c))
}

func h(x,y uint64) uint64 {
    return (x ^ y) ^ ((x & y) << 1)
}

func g(a,b,c,d uint64) (uint64,uint64,uint64,uint64) {

    a = h(a,b)
    d = rotr(a ^ d, R0)
    c = h(c,d)
    b = rotr(b ^ c, R1)
    a = h(a,b)
    d = rotr(a ^ d, R2)
    c = h(c,d)
    b = rotr(b ^ c, R3)
    return a,b,c,d
}

func f(s []uint64) {

    // Column step
    s[ 0], s[ 4], s[ 8], s[12] = g(s[ 0], s[ 4], s[ 8], s[12])
    s[ 1], s[ 5], s[ 9], s[13] = g(s[ 1], s[ 5], s[ 9], s[13])
    s[ 2], s[ 6], s[10], s[14] = g(s[ 2], s[ 6], s[10], s[14])
    s[ 3], s[ 7], s[11], s[15] = g(s[ 3], s[ 7], s[11], s[15])
    // Diagonal step
    s[ 0], s[ 5], s[10], s[15] = g(s[ 0], s[ 5], s[10], s[15])
    s[ 1], s[ 6], s[11], s[12] = g(s[ 1], s[ 6], s[11], s[12])
    s[ 2], s[ 7], s[ 8], s[13] = g(s[ 2], s[ 7], s[ 8], s[13])
    s[ 3], s[ 4], s[ 9], s[14] = g(s[ 3], s[ 4], s[ 9], s[14])
}

func norx_permute(state *norx_state_t) {

    var s = state.s[:]
    for i := uint64(0); i < NORX_L; i++ {
        f(s)
    }
}

func norx_init(state *norx_state_t, k []uint8, n []uint8) {

    var s = state.s[:]

    for i := uint64(0); i < 16; i++ {
        s[i] = i
    }

    f(s)
    f(s)

    state.s[ 0] = load64(n[ 0: 8])
    state.s[ 1] = load64(n[ 8:16])

    state.s[ 4] = load64(k[ 0: 8])
    state.s[ 5] = load64(k[ 8:16])
    state.s[ 6] = load64(k[16:24])
    state.s[ 7] = load64(k[24:32])

    state.s[12] ^= NORX_W
    state.s[13] ^= NORX_L
    state.s[14] ^= NORX_P
    state.s[15] ^= NORX_T

    norx_permute(state)
}

func norx_absorb_data(state *norx_state_t, in []uint8, inlen uint64, tag uint64) {

    if inlen > 0 {

        var i uint64 = 0
        const n uint64 = BYTES_RATE

        for i = 0; inlen >= n; inlen, i = inlen-n, i+1 {
            norx_absorb_block(state, in[n*i:n*(i+1)], tag)
        }
        norx_absorb_lastblock(state, in[n*i:n*i+inlen], inlen, tag)
    }
}

func norx_encrypt_data(state *norx_state_t, out []uint8, in []uint8, inlen uint64) {

    if inlen > 0 {

        var i uint64 = 0
        const n uint64 = BYTES_RATE

        for i = 0; inlen >= n; inlen, i = inlen-n, i+1 {
            norx_encrypt_block(state, out[n*i:n*(i+1)], in[n*i:n*(i+1)])
        }
        encrypt_lastblock(state, out[n*i:n*i+inlen], in[n*i:n*i+inlen], inlen)
    }
}

func norx_decrypt_data(state *norx_state_t, out []uint8, in []uint8, inlen uint64) {

    if inlen > 0 {

        var i uint64 = 0
        const n uint64 = BYTES_RATE

        for i = 0; inlen >= n; inlen, i = inlen-n, i+1 {
            norx_decrypt_block(state, out[n*i:n*(i+1)], in[n*i:n*(i+1)])
        }
        norx_decrypt_lastblock(state, out[n*i:n*i+inlen], in[n*i:n*i+inlen], inlen)
    }
}

func norx_output_tag(state *norx_state_t, tag []uint8) {

    state.s[15] ^= FINAL_TAG
    norx_permute(state)
    norx_permute(state)

    var s = state.s[:]
    var lastblock [BYTES_RATE]uint8
    const b uint64 = BYTES_WORD

    for i := uint64(0); i < WORDS_RATE; i++ {
        store64(lastblock[b*i:b*(i+1)], s[i])
    }
    copy(tag[:], lastblock[:])
    burn8(lastblock[:], BYTES_RATE)
}

func norx_verify_tag(tag1 []uint8, tag2 []uint8) int {

    var acc int = 0

    for i := uint64(0); i < BYTES_TAG; i++ {
        acc |= int(tag1[i] ^ tag2[i])
    }
    return (((acc - 1) >> 8) & 1) - 1
}

func norx_pad(out []uint8, in []uint8, inlen uint64) {

    copy(out[:],in[:inlen])
    out[inlen] = 0x01
    out[BYTES_RATE - 1] |= 0x80
}

func norx_absorb_block(state *norx_state_t, in []uint8, tag uint64) {

    state.s[15] ^= tag
    norx_permute(state)

    var s = state.s[:]
    const b uint64 = BYTES_WORD

    for i := uint64(0); i < WORDS_RATE; i++ {
        s[i] ^= load64(in[b*i:b*(i+1)])
    }
}

func norx_absorb_lastblock(state *norx_state_t, in []uint8, inlen uint64, tag uint64) {

    var lastblock [BYTES_RATE]uint8
    norx_pad(lastblock[:], in[:], inlen)
    norx_absorb_block(state, lastblock[:], tag)
    burn8(lastblock[:], BYTES_RATE)
}

func norx_encrypt_block(state *norx_state_t, out []uint8, in []uint8) {

    state.s[15] ^= PAYLOAD_TAG
    norx_permute(state)

    var s = state.s[:]
    const b uint64 = BYTES_WORD

    for i := uint64(0); i < WORDS_RATE; i++ {
        s[i] ^= load64(in[b*i:b*(i+1)])
        store64(out[b*i:b*(i+1)], s[i])
    }
}

func encrypt_lastblock(state *norx_state_t, out []uint8, in []uint8, inlen uint64) {

    var lastblock [BYTES_RATE]uint8
    norx_pad(lastblock[:], in[:], inlen)
    norx_encrypt_block(state, lastblock[:], lastblock[:])
    copy(out[:], lastblock[:])
    burn8(lastblock[:], BYTES_RATE)
}

func norx_decrypt_block(state *norx_state_t, out []uint8, in []uint8) {

    state.s[15] ^= PAYLOAD_TAG
    norx_permute(state)

    var s = state.s[:]
    const b uint64 = BYTES_WORD

    for i := uint64(0); i < WORDS_RATE; i++ {
        c := load64(in[b*i:b*(i+1)])
        store64(out[b*i:b*(i+1)], s[i] ^ c)
        s[i] = c
    }
}

func norx_decrypt_lastblock(state *norx_state_t, out []uint8, in []uint8, inlen uint64) {

    state.s[15] ^= PAYLOAD_TAG
    norx_permute(state)

    var s = state.s[:]
    const n uint64 = BYTES_WORD
    var lastblock [BYTES_RATE]uint8

    for i := uint64(0); i < WORDS_RATE; i++ {
        store64(lastblock[n*i:n*(i+1)],s[i])
    }
    copy(lastblock[:],in[:inlen])
    lastblock[inlen] ^= 0x01
    lastblock[BYTES_RATE - 1] ^= 0x80

    for i := uint64(0); i < WORDS_RATE; i++ {
        c := load64(lastblock[n*i:n*(i+1)])
        store64(lastblock[n*i:n*(i+1)], s[i] ^ c)
        s[i] = c
    }
    copy(out[:inlen],lastblock[:])
    burn8(lastblock[:],BYTES_RATE)
}

func AEAD_encrypt(
    c []uint8, clen *uint64,
    h []uint8, hlen uint64,
    m []uint8, mlen uint64,
    t []uint8, tlen uint64,
    nonce []uint8,
    key []uint8) {

    var state = new(norx_state_t)
    norx_init(state, key, nonce)
    norx_absorb_data(state, h, hlen, HEADER_TAG)
    norx_encrypt_data(state, c, m, mlen)
    norx_absorb_data(state, t, tlen, TRAILER_TAG)
    norx_output_tag(state, c[mlen:])
    *clen = mlen + BYTES_TAG
    burn64(state.s[:], WORDS_STATE)
}

func AEAD_decrypt(
    m []uint8, mlen *uint64,
    h []uint8, hlen uint64,
    c []uint8, clen uint64,
    t []uint8, tlen uint64,
    nonce []uint8,
    key []uint8) int {

    if clen < BYTES_TAG {
      return -1
    }
    var result int = -1
    var tag [BYTES_TAG]uint8
    var state = new(norx_state_t)
    norx_init(state, key, nonce)
    norx_absorb_data(state, h, hlen, HEADER_TAG)
    norx_decrypt_data(state, m, c, clen - BYTES_TAG)
    norx_absorb_data(state, t, tlen, TRAILER_TAG)
    norx_output_tag(state, tag[:])
    *mlen = clen - BYTES_TAG
    result = norx_verify_tag(c[clen - BYTES_TAG:], tag[:])
    if result != 0 {
        burn8(m[:], clen - BYTES_TAG)
    }
    burn64(state.s[:], WORDS_STATE)
    return result
}

<|endoftext|>


<commit_before>package factory_test

import (
	"github.com/concourse/atc"
	"github.com/concourse/atc/scheduler/factory"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Factory Do", func() {
	var (
		buildFactory *factory.BuildFactory

		resources atc.ResourceConfigs
	)

	BeforeEach(func() {
		buildFactory = &factory.BuildFactory{
			PipelineName: "some-pipeline",
		}

		resources = atc.ResourceConfigs{
			{
				Name:   "some-resource",
				Type:   "git",
				Source: atc.Source{"uri": "git://some-resource"},
			},
		}
	})

	Context("when I have a nested do ", func() {
		It("returns the correct plan", func() {

			actual, err := buildFactory.Create(atc.JobConfig{
				Plan: atc.PlanSequence{
					{
						Do: &atc.PlanSequence{
							{
								Task: "some thing",
							},
							{
								Task: "some thing-2",
							},
							{
								Do: &atc.PlanSequence{
									{
										Task: "some other thing",
									},
								},
							},
						},
					},
				},
			}, resources, nil)
			Ω(err).ShouldNot(HaveOccurred())

			expected := atc.Plan{
				OnSuccess: &atc.OnSuccessPlan{
					Step: atc.Plan{
						Location: &atc.Location{
							ParentID:      0,
							ID:            3,
							ParallelGroup: 0,
							SerialGroup:   2,
						},
						Task: &atc.TaskPlan{
							Name: "some thing",
						},
					},
					Next: atc.Plan{
						OnSuccess: &atc.OnSuccessPlan{
							Step: atc.Plan{
								Location: &atc.Location{
									ParentID:      0,
									ID:            4,
									ParallelGroup: 0,
									SerialGroup:   2,
								},
								Task: &atc.TaskPlan{
									Name: "some thing-2",
								},
							},
							Next: atc.Plan{
								Location: &atc.Location{
									ParentID:      2,
									ID:            7,
									ParallelGroup: 0,
									SerialGroup:   6,
								},
								Task: &atc.TaskPlan{
									Name: "some other thing",
								},
							},
						},
					},
				},
			}
			Ω(actual).Should(Equal(expected))
		})
	})

	Context("when I have an aggregate inside a do", func() {
		It("returns the correct plan", func() {

			actual, err := buildFactory.Create(atc.JobConfig{
				Plan: atc.PlanSequence{
					{
						Do: &atc.PlanSequence{
							{
								Task: "some thing",
							},
							{
								Aggregate: &atc.PlanSequence{
									{
										Task: "some other thing",
									},
								},
							},
							{
								Task: "some thing-2",
							},
						},
					},
				},
			}, resources, nil)
			Ω(err).ShouldNot(HaveOccurred())

			expected := atc.Plan{
				OnSuccess: &atc.OnSuccessPlan{
					Step: atc.Plan{
						Location: &atc.Location{
							ParentID:      0,
							ID:            3,
							ParallelGroup: 0,
							SerialGroup:   2,
						},
						Task: &atc.TaskPlan{
							Name: "some thing",
						},
					},
					Next: atc.Plan{
						OnSuccess: &atc.OnSuccessPlan{
							Step: atc.Plan{

								Aggregate: &atc.AggregatePlan{
									{
										Location: &atc.Location{
											ParentID:      2,
											ID:            6,
											ParallelGroup: 5,
											SerialGroup:   0,
										},
										Task: &atc.TaskPlan{
											Name: "some other thing",
										},
									},
								},
							},
							Next: atc.Plan{
								Location: &atc.Location{
									ParentID:      0,
									ID:            7,
									ParallelGroup: 0,
									SerialGroup:   2,
								},
								Task: &atc.TaskPlan{
									Name: "some thing-2",
								},
							},
						},
					},
				},
			}
			Ω(actual).Should(Equal(expected))
		})
	})

	Context("when i have a do inside an aggregate inside a hook", func() {
		FIt("returns the correct plan", func() {

			actual, err := buildFactory.Create(atc.JobConfig{
				Plan: atc.PlanSequence{
					{
						Task: "starting-task",
						Success: &atc.PlanConfig{
							Aggregate: &atc.PlanSequence{
								{
									Task: "some thing",
								},
								{
									Do: &atc.PlanSequence{
										{
											Task: "some other thing",
										},
									},
								},
							},
						},
					},
				},
			}, resources, nil)
			Ω(err).ShouldNot(HaveOccurred())

			expected := atc.Plan{
				OnSuccess: &atc.OnSuccessPlan{
					Step: atc.Plan{
						Location: &atc.Location{
							ParentID:      0,
							ID:            1,
							ParallelGroup: 0,
							SerialGroup:   0,
						},
						Task: &atc.TaskPlan{
							Name: "starting-task",
						},
					},
					Next: atc.Plan{
						Aggregate: &atc.AggregatePlan{
							{
								Location: &atc.Location{
									ParentID:      1,
									ID:            4,
									ParallelGroup: 3,
									SerialGroup:   0,
									Hook:          "success",
								},
								Task: &atc.TaskPlan{
									Name: "some thing",
								},
							},
							{
								Location: &atc.Location{
									ParentID:      3,
									ID:            7,
									ParallelGroup: 0,
									SerialGroup:   6,
								},
								Task: &atc.TaskPlan{
									Name: "some other thing",
								},
							},
						},
					},
				},
			}

			Ω(actual).Should(Equal(expected))
		})
	})

	Context("when I have a do inside an aggregate", func() {
		It("returns the correct plan", func() {

			actual, err := buildFactory.Create(atc.JobConfig{
				Plan: atc.PlanSequence{
					{
						Aggregate: &atc.PlanSequence{
							{
								Task: "some thing",
							},
							{
								Do: &atc.PlanSequence{
									{
										Task: "some other thing",
									},
									{
										Task: "some other thing-2",
									},
								},
							},
							{
								Task: "some thing-2",
							},
						},
					},
				},
			}, resources, nil)
			Ω(err).ShouldNot(HaveOccurred())

			expected := atc.Plan{
				Aggregate: &atc.AggregatePlan{
					{
						Location: &atc.Location{
							ParentID:      0,
							ID:            3,
							ParallelGroup: 2,
							SerialGroup:   0,
						},
						Task: &atc.TaskPlan{
							Name: "some thing",
						},
					},
					{
						OnSuccess: &atc.OnSuccessPlan{
							Step: atc.Plan{
								Location: &atc.Location{
									ParentID:      2,
									ID:            6,
									ParallelGroup: 0,
									SerialGroup:   5,
								},
								Task: &atc.TaskPlan{
									Name: "some other thing",
								},
							},
							Next: atc.Plan{
								Location: &atc.Location{
									ParentID:      2,
									ID:            7,
									ParallelGroup: 0,
									SerialGroup:   5,
								},
								Task: &atc.TaskPlan{
									Name: "some other thing-2",
								},
							},
						},
					},
					{
						Location: &atc.Location{
							ParentID:      0,
							ID:            8,
							ParallelGroup: 2,
							SerialGroup:   0,
						},
						Task: &atc.TaskPlan{
							Name: "some thing-2",
						},
					},
				},
			}

			Ω(actual).Should(Equal(expected))
		})
	})
})
<commit_msg>Remove focused test<commit_after>package factory_test

import (
	"github.com/concourse/atc"
	"github.com/concourse/atc/scheduler/factory"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Factory Do", func() {
	var (
		buildFactory *factory.BuildFactory

		resources atc.ResourceConfigs
	)

	BeforeEach(func() {
		buildFactory = &factory.BuildFactory{
			PipelineName: "some-pipeline",
		}

		resources = atc.ResourceConfigs{
			{
				Name:   "some-resource",
				Type:   "git",
				Source: atc.Source{"uri": "git://some-resource"},
			},
		}
	})

	Context("when I have a nested do ", func() {
		It("returns the correct plan", func() {

			actual, err := buildFactory.Create(atc.JobConfig{
				Plan: atc.PlanSequence{
					{
						Do: &atc.PlanSequence{
							{
								Task: "some thing",
							},
							{
								Task: "some thing-2",
							},
							{
								Do: &atc.PlanSequence{
									{
										Task: "some other thing",
									},
								},
							},
						},
					},
				},
			}, resources, nil)
			Ω(err).ShouldNot(HaveOccurred())

			expected := atc.Plan{
				OnSuccess: &atc.OnSuccessPlan{
					Step: atc.Plan{
						Location: &atc.Location{
							ParentID:      0,
							ID:            3,
							ParallelGroup: 0,
							SerialGroup:   2,
						},
						Task: &atc.TaskPlan{
							Name: "some thing",
						},
					},
					Next: atc.Plan{
						OnSuccess: &atc.OnSuccessPlan{
							Step: atc.Plan{
								Location: &atc.Location{
									ParentID:      0,
									ID:            4,
									ParallelGroup: 0,
									SerialGroup:   2,
								},
								Task: &atc.TaskPlan{
									Name: "some thing-2",
								},
							},
							Next: atc.Plan{
								Location: &atc.Location{
									ParentID:      2,
									ID:            7,
									ParallelGroup: 0,
									SerialGroup:   6,
								},
								Task: &atc.TaskPlan{
									Name: "some other thing",
								},
							},
						},
					},
				},
			}
			Ω(actual).Should(Equal(expected))
		})
	})

	Context("when I have an aggregate inside a do", func() {
		It("returns the correct plan", func() {

			actual, err := buildFactory.Create(atc.JobConfig{
				Plan: atc.PlanSequence{
					{
						Do: &atc.PlanSequence{
							{
								Task: "some thing",
							},
							{
								Aggregate: &atc.PlanSequence{
									{
										Task: "some other thing",
									},
								},
							},
							{
								Task: "some thing-2",
							},
						},
					},
				},
			}, resources, nil)
			Ω(err).ShouldNot(HaveOccurred())

			expected := atc.Plan{
				OnSuccess: &atc.OnSuccessPlan{
					Step: atc.Plan{
						Location: &atc.Location{
							ParentID:      0,
							ID:            3,
							ParallelGroup: 0,
							SerialGroup:   2,
						},
						Task: &atc.TaskPlan{
							Name: "some thing",
						},
					},
					Next: atc.Plan{
						OnSuccess: &atc.OnSuccessPlan{
							Step: atc.Plan{

								Aggregate: &atc.AggregatePlan{
									{
										Location: &atc.Location{
											ParentID:      2,
											ID:            6,
											ParallelGroup: 5,
											SerialGroup:   0,
										},
										Task: &atc.TaskPlan{
											Name: "some other thing",
										},
									},
								},
							},
							Next: atc.Plan{
								Location: &atc.Location{
									ParentID:      0,
									ID:            7,
									ParallelGroup: 0,
									SerialGroup:   2,
								},
								Task: &atc.TaskPlan{
									Name: "some thing-2",
								},
							},
						},
					},
				},
			}
			Ω(actual).Should(Equal(expected))
		})
	})

	Context("when i have a do inside an aggregate inside a hook", func() {
		It("returns the correct plan", func() {

			actual, err := buildFactory.Create(atc.JobConfig{
				Plan: atc.PlanSequence{
					{
						Task: "starting-task",
						Success: &atc.PlanConfig{
							Aggregate: &atc.PlanSequence{
								{
									Task: "some thing",
								},
								{
									Do: &atc.PlanSequence{
										{
											Task: "some other thing",
										},
									},
								},
							},
						},
					},
				},
			}, resources, nil)
			Ω(err).ShouldNot(HaveOccurred())

			expected := atc.Plan{
				OnSuccess: &atc.OnSuccessPlan{
					Step: atc.Plan{
						Location: &atc.Location{
							ParentID:      0,
							ID:            1,
							ParallelGroup: 0,
							SerialGroup:   0,
						},
						Task: &atc.TaskPlan{
							Name: "starting-task",
						},
					},
					Next: atc.Plan{
						Aggregate: &atc.AggregatePlan{
							{
								Location: &atc.Location{
									ParentID:      1,
									ID:            4,
									ParallelGroup: 3,
									SerialGroup:   0,
									Hook:          "success",
								},
								Task: &atc.TaskPlan{
									Name: "some thing",
								},
							},
							{
								Location: &atc.Location{
									ParentID:      3,
									ID:            7,
									ParallelGroup: 0,
									SerialGroup:   6,
								},
								Task: &atc.TaskPlan{
									Name: "some other thing",
								},
							},
						},
					},
				},
			}

			Ω(actual).Should(Equal(expected))
		})
	})

	Context("when I have a do inside an aggregate", func() {
		It("returns the correct plan", func() {

			actual, err := buildFactory.Create(atc.JobConfig{
				Plan: atc.PlanSequence{
					{
						Aggregate: &atc.PlanSequence{
							{
								Task: "some thing",
							},
							{
								Do: &atc.PlanSequence{
									{
										Task: "some other thing",
									},
									{
										Task: "some other thing-2",
									},
								},
							},
							{
								Task: "some thing-2",
							},
						},
					},
				},
			}, resources, nil)
			Ω(err).ShouldNot(HaveOccurred())

			expected := atc.Plan{
				Aggregate: &atc.AggregatePlan{
					{
						Location: &atc.Location{
							ParentID:      0,
							ID:            3,
							ParallelGroup: 2,
							SerialGroup:   0,
						},
						Task: &atc.TaskPlan{
							Name: "some thing",
						},
					},
					{
						OnSuccess: &atc.OnSuccessPlan{
							Step: atc.Plan{
								Location: &atc.Location{
									ParentID:      2,
									ID:            6,
									ParallelGroup: 0,
									SerialGroup:   5,
								},
								Task: &atc.TaskPlan{
									Name: "some other thing",
								},
							},
							Next: atc.Plan{
								Location: &atc.Location{
									ParentID:      2,
									ID:            7,
									ParallelGroup: 0,
									SerialGroup:   5,
								},
								Task: &atc.TaskPlan{
									Name: "some other thing-2",
								},
							},
						},
					},
					{
						Location: &atc.Location{
							ParentID:      0,
							ID:            8,
							ParallelGroup: 2,
							SerialGroup:   0,
						},
						Task: &atc.TaskPlan{
							Name: "some thing-2",
						},
					},
				},
			}

			Ω(actual).Should(Equal(expected))
		})
	})
})
<|endoftext|>


<commit_before>/*
    norx.go
    ------

    This file is part of the Go reference implementation of NORX.

    :copyright: (c) 2014 Philipp Jovanovic <philipp@jovanovic.io>
    :license: BSD (3-Clause), see LICENSE
*/

package aead

const (
    NORX_W = 64              // wordsize
    NORX_R = 4               // number of rounds
    NORX_D = 1               // parallelism degree
    NORX_A = NORX_W * 4      // tag size
    NORX_N = NORX_W * 2      // nonce size
    NORX_K = NORX_W * 4      // key size
    NORX_B = NORX_W * 16     // state size
    NORX_C = NORX_W * 6      // capacity size
    RATE = NORX_B - NORX_C   // rate size
    HEADER_TAG  = 1 << 0
    PAYLOAD_TAG = 1 << 1
    TRAILER_TAG = 1 << 2
    FINAL_TAG   = 1 << 3
    BRANCH_TAG  = 1 << 4
    MERGE_TAG   = 1 << 5
    R0, R1, R2, R3 = 8, 19, 40, 63 // rotation offsets
    u0, u1 = 0x243F6A8885A308D3, 0x13198A2E03707344
    u2, u3 = 0xA4093822299F31D0, 0x082EFA98EC4E6C89
    u4, u5 = 0xAE8858DC339325A1, 0x670A134EE52D7FA6
    u6, u7 = 0xC4316D80CD967541, 0xD21DFBF8B630B762
    u8, u9 = 0x375A18D261E7F892, 0x343D1F187D92285B
)

type state_t struct {
    s [16]uint64
}

func ROTR(x,c uint64) uint64 {
    return (x >> c | x << (NORX_W - c))
}

func H(x,y uint64) uint64 {
    return (x ^ y) ^ ((x & y) << 1)
}

func G(a,b,c,d uint64) (uint64,uint64,uint64,uint64) {

    a = H(a,b)
    d = ROTR(a ^ d, R0)
    c = H(c,d)
    b = ROTR(b ^ c, R1)
    a = H(a,b)
    d = ROTR(a ^ d, R2)
    c = H(c,d)
    b = ROTR(b ^ c, R3)
    return a,b,c,d
}

func F(s []uint64) {

    // Column step
    s[ 0], s[ 4], s[ 8], s[12] = G(s[ 0], s[ 4], s[ 8], s[12])
    s[ 1], s[ 5], s[ 9], s[13] = G(s[ 1], s[ 5], s[ 9], s[13])
    s[ 2], s[ 6], s[10], s[14] = G(s[ 2], s[ 6], s[10], s[14])
    s[ 3], s[ 7], s[11], s[15] = G(s[ 3], s[ 7], s[11], s[15])
    // Diagonal step
    s[ 0], s[ 5], s[10], s[15] = G(s[ 0], s[ 5], s[10], s[15])
    s[ 1], s[ 6], s[11], s[12] = G(s[ 1], s[ 6], s[11], s[12])
    s[ 2], s[ 7], s[ 8], s[13] = G(s[ 2], s[ 7], s[ 8], s[13])
    s[ 3], s[ 4], s[ 9], s[14] = G(s[ 3], s[ 4], s[ 9], s[14])
}

func permute(state *state_t) {

    s := state.s[:]
    for i:=0; i<NORX_R; i++ { F(s) }
}

func setup(state *state_t, k []uint8, n []uint8) {

    s := state.s[:]

    s[ 0] = u0
    s[ 1] = LOAD64(n[ 0: 8])
    s[ 2] = LOAD64(n[ 8:16])
    s[ 3] = u1

    s[ 4] = LOAD64(k[ 0: 8])
    s[ 5] = LOAD64(k[ 8:16])
    s[ 6] = LOAD64(k[16:24])
    s[ 7] = LOAD64(k[24:32])

    s[ 8] = u2
    s[ 9] = u3
    s[10] = u4
    s[11] = u5

    s[12] = u6
    s[13] = u7
    s[14] = u8
    s[15] = u9

    s[14] ^= (NORX_R << 26) | (NORX_D << 18) | (NORX_W << 10) | NORX_A
    permute(state)
}

func process_header(state *state_t, in []uint8, inlen uint64) {

    if inlen > 0 {
        i := uint64(0)
        n := BYTES64(RATE)
        for inlen >= n {
            absorb_block(state, in[n*i:n*(i+1)], HEADER_TAG)
            inlen -= n
            i++
        }
        absorb_lastblock(state, in[n*i:n*i+inlen], inlen, HEADER_TAG)
    }
}

func encrypt_msg(state *state_t, out []uint8, in []uint8, inlen uint64) {

    if inlen > 0 {
        i := uint64(0)
        n := BYTES64(RATE)
        for inlen >= n {
            encrypt_block(state, out[n*i:n*(i+1)], in[n*i:n*(i+1)])
            inlen -= n
            i++
        }
        encrypt_lastblock(state, out[n*i:n*i+inlen], in[n*i:n*i+inlen], inlen)
    }
}

func decrypt_msg(state *state_t, out []uint8, in []uint8, inlen uint64) {

    if inlen > 0 {
        i := uint64(0)
        n := BYTES64(RATE)
        for inlen >= n {
            decrypt_block(state, out[n*i:n*(i+1)], in[n*i:n*(i+1)])
            inlen -= n
            i++
        }
        decrypt_lastblock(state, out[n*i:n*i+inlen], in[n*i:n*i+inlen], inlen)
    }
}

func process_trailer(state *state_t, in []uint8, inlen uint64) {

    if inlen > 0 {
        i := uint64(0)
        n := BYTES64(RATE)
        for inlen >= n {
            absorb_block(state, in[n*i:n*(i+1)], TRAILER_TAG)
            inlen -= n
            i++
        }
        absorb_lastblock(state, in[n*i:n*i+inlen], inlen, TRAILER_TAG)
    }
}

func output_tag(state *state_t, tag []uint8) {

    inject_tag(state, FINAL_TAG)
    permute(state)
    permute(state)

    s := state.s[:]
    lastblock := make([]uint8, BYTES64(RATE))
    b := BYTES64(NORX_W)
    for i:= uint64(0); i < WORDS64(RATE); i++ {
        STORE64(lastblock[b*i:b*(i+1)], s[i])
    }
    copy(tag[:], lastblock[:])
    BURN8(lastblock[:], BYTES64(RATE))
}

func verify_tag(tag1 []uint8, tag2 []uint8) int {

    acc := 0
    for i := uint64(0); i < BYTES64(NORX_A); i++ {
        acc |= int(tag1[i] ^ tag2[i])
    }
    return (((acc - 1) >> 8) & 1) - 1
}

func pad(out []uint8, in []uint8, inlen uint64) {

    copy(out[:],in[:inlen])
    out[inlen] = 0x01
    out[BYTES64(RATE) - 1] |= 0x80
}

func inject_tag(state *state_t, tag uint64) {

    s := state.s[:]
    s[15] ^= tag
}

func absorb_block(state *state_t, in []uint8, tag uint64) {

    inject_tag(state, tag)
    permute(state)

    s := state.s[:]
    b := BYTES64(NORX_W)
    for i:= uint64(0); i < WORDS64(RATE); i++ {
        s[i] ^= LOAD64(in[b*i:b*(i+1)])
    }
}

func absorb_lastblock(state *state_t, in []uint8, inlen uint64, tag uint64) {

    lastblock := make([]uint8, BYTES64(RATE))
    pad(lastblock[:], in[:], inlen)
    absorb_block(state, lastblock[:], tag)
    BURN8(lastblock[:], BYTES64(RATE))
}

func encrypt_block(state *state_t, out []uint8, in []uint8) {

    inject_tag(state, PAYLOAD_TAG)
    permute(state)

    s := state.s[:]
    b := BYTES64(NORX_W)
    for i:= uint64(0); i < WORDS64(RATE); i++ {
        s[i] ^= LOAD64(in[b*i:b*(i+1)])
        STORE64(out[b*i:b*(i+1)], s[i])
    }
}

func encrypt_lastblock(state *state_t, out []uint8, in []uint8, inlen uint64) {

    lastblock := make([]uint8, BYTES64(RATE))
    pad(lastblock[:], in[:], inlen)
    encrypt_block(state, lastblock[:], lastblock[:])
    copy(out[:], lastblock[:])
    BURN8(lastblock[:], BYTES64(RATE))
}

func decrypt_block(state *state_t, out []uint8, in []uint8) {

    inject_tag(state, PAYLOAD_TAG)
    permute(state)

    s := state.s[:]
    b := BYTES64(NORX_W)
    for i:= uint64(0); i < WORDS64(RATE); i++ {
        c := LOAD64(in[b*i:b*(i+1)])
        STORE64(out[b*i:b*(i+1)], s[i] ^ c)
        s[i] = c
    }
}

func decrypt_lastblock(state *state_t, out []uint8, in []uint8, inlen uint64) {

    inject_tag(state, PAYLOAD_TAG)
    permute(state)

    s := state.s[:]
    i := uint64(0)
    n := BYTES64(NORX_W)

    /* undo padding */
    s[inlen / n] ^= uint64(0x01) << (inlen % n * 8)
    s[WORDS64(RATE) - 1] ^= uint64(0x80) << ((BYTES64(RATE) - 1) % n * 8)

    for inlen >= n {
        c := LOAD64(in[n*i:n*(i+1)])
        STORE64(out[n*i:n*(i+1)], s[i] ^ c)
        s[i] = c
        inlen -= n
        i++
    }

    /* decrypt last bytes */
    b := make([]uint8, n)
    copy(b,in[n*i:n*i+inlen])
    x := LOAD64(b)
    STORE64(b, s[i] ^ x)
    copy(out[n*i:n*i+inlen],b)
    s[i] = x
    BURN8(b,n)
}

func AEAD_encrypt(
    c []uint8, clen *uint64,
    h []uint8, hlen uint64,
    m []uint8, mlen uint64,
    t []uint8, tlen uint64,
    nonce []uint8,
    key []uint8) {

    state := new(state_t)
    setup(state, key, nonce)
    process_header(state, h, hlen)
    encrypt_msg(state, c, m, mlen)
    process_trailer(state, t, tlen)
    output_tag(state, c[mlen:])
    *clen = mlen + BYTES64(NORX_A)
    BURN64(state.s[:], WORDS64(NORX_B))
}

func AEAD_decrypt(
    m []uint8, mlen *uint64,
    h []uint8, hlen uint64,
    c []uint8, clen uint64,
    t []uint8, tlen uint64,
    nonce []uint8,
    key []uint8) int {

    if clen < BYTES64(NORX_A) {
      return -1
    }
    result := -1
    tag := make([]uint8, NORX_A)
    state := new(state_t)
    setup(state, key, nonce)
    process_header(state, h, hlen)
    decrypt_msg(state, m, c, clen - BYTES64(NORX_A))
    process_trailer(state, t, tlen)
    output_tag(state, tag)
    *mlen = clen - BYTES64(NORX_A)
    result = verify_tag(c[clen - BYTES64(NORX_A):], tag)
    if result != 0 {
        BURN8(m, clen - BYTES64(NORX_A))
    }
    BURN64(state.s[:], WORDS64(NORX_B))
    return result
}

<commit_msg>bugfix<commit_after>/*
    norx.go
    ------

    This file is part of the Go reference implementation of NORX.

    :copyright: (c) 2014 Philipp Jovanovic <philipp@jovanovic.io>
    :license: BSD (3-Clause), see LICENSE
*/

package aead

const (
    NORX_W = 64              // wordsize
    NORX_R = 4               // number of rounds
    NORX_D = 1               // parallelism degree
    NORX_A = NORX_W * 4      // tag size
    NORX_N = NORX_W * 2      // nonce size
    NORX_K = NORX_W * 4      // key size
    NORX_B = NORX_W * 16     // state size
    NORX_C = NORX_W * 6      // capacity size
    RATE = NORX_B - NORX_C   // rate size
    HEADER_TAG  = 1 << 0
    PAYLOAD_TAG = 1 << 1
    TRAILER_TAG = 1 << 2
    FINAL_TAG   = 1 << 3
    BRANCH_TAG  = 1 << 4
    MERGE_TAG   = 1 << 5
    R0, R1, R2, R3 = 8, 19, 40, 63 // rotation offsets
    u0, u1 = 0x243F6A8885A308D3, 0x13198A2E03707344
    u2, u3 = 0xA4093822299F31D0, 0x082EFA98EC4E6C89
    u4, u5 = 0xAE8858DC339325A1, 0x670A134EE52D7FA6
    u6, u7 = 0xC4316D80CD967541, 0xD21DFBF8B630B762
    u8, u9 = 0x375A18D261E7F892, 0x343D1F187D92285B
)

type state_t struct {
    s [16]uint64
}

func ROTR(x,c uint64) uint64 {
    return (x >> c | x << (NORX_W - c))
}

func H(x,y uint64) uint64 {
    return (x ^ y) ^ ((x & y) << 1)
}

func G(a,b,c,d uint64) (uint64,uint64,uint64,uint64) {

    a = H(a,b)
    d = ROTR(a ^ d, R0)
    c = H(c,d)
    b = ROTR(b ^ c, R1)
    a = H(a,b)
    d = ROTR(a ^ d, R2)
    c = H(c,d)
    b = ROTR(b ^ c, R3)
    return a,b,c,d
}

func F(s []uint64) {

    // Column step
    s[ 0], s[ 4], s[ 8], s[12] = G(s[ 0], s[ 4], s[ 8], s[12])
    s[ 1], s[ 5], s[ 9], s[13] = G(s[ 1], s[ 5], s[ 9], s[13])
    s[ 2], s[ 6], s[10], s[14] = G(s[ 2], s[ 6], s[10], s[14])
    s[ 3], s[ 7], s[11], s[15] = G(s[ 3], s[ 7], s[11], s[15])
    // Diagonal step
    s[ 0], s[ 5], s[10], s[15] = G(s[ 0], s[ 5], s[10], s[15])
    s[ 1], s[ 6], s[11], s[12] = G(s[ 1], s[ 6], s[11], s[12])
    s[ 2], s[ 7], s[ 8], s[13] = G(s[ 2], s[ 7], s[ 8], s[13])
    s[ 3], s[ 4], s[ 9], s[14] = G(s[ 3], s[ 4], s[ 9], s[14])
}

func permute(state *state_t) {

    s := state.s[:]
    for i:=0; i<NORX_R; i++ { F(s) }
}

func setup(state *state_t, k []uint8, n []uint8) {

    s := state.s[:]

    s[ 0] = u0
    s[ 1] = LOAD64(n[ 0: 8])
    s[ 2] = LOAD64(n[ 8:16])
    s[ 3] = u1

    s[ 4] = LOAD64(k[ 0: 8])
    s[ 5] = LOAD64(k[ 8:16])
    s[ 6] = LOAD64(k[16:24])
    s[ 7] = LOAD64(k[24:32])

    s[ 8] = u2
    s[ 9] = u3
    s[10] = u4
    s[11] = u5

    s[12] = u6
    s[13] = u7
    s[14] = u8
    s[15] = u9

    s[14] ^= (NORX_R << 26) | (NORX_D << 18) | (NORX_W << 10) | NORX_A
    permute(state)
}

func process_header(state *state_t, in []uint8, inlen uint64) {

    if inlen > 0 {
        i := uint64(0)
        n := BYTES64(RATE)
        for inlen >= n {
            absorb_block(state, in[n*i:n*(i+1)], HEADER_TAG)
            inlen -= n
            i++
        }
        absorb_lastblock(state, in[n*i:n*i+inlen], inlen, HEADER_TAG)
    }
}

func encrypt_msg(state *state_t, out []uint8, in []uint8, inlen uint64) {

    if inlen > 0 {
        i := uint64(0)
        n := BYTES64(RATE)
        for inlen >= n {
            encrypt_block(state, out[n*i:n*(i+1)], in[n*i:n*(i+1)])
            inlen -= n
            i++
        }
        encrypt_lastblock(state, out[n*i:n*i+inlen], in[n*i:n*i+inlen], inlen)
    }
}

func decrypt_msg(state *state_t, out []uint8, in []uint8, inlen uint64) {

    if inlen > 0 {
        i := uint64(0)
        n := BYTES64(RATE)
        for inlen >= n {
            decrypt_block(state, out[n*i:n*(i+1)], in[n*i:n*(i+1)])
            inlen -= n
            i++
        }
        decrypt_lastblock(state, out[n*i:n*i+inlen], in[n*i:n*i+inlen], inlen)
    }
}

func process_trailer(state *state_t, in []uint8, inlen uint64) {

    if inlen > 0 {
        i := uint64(0)
        n := BYTES64(RATE)
        for inlen >= n {
            absorb_block(state, in[n*i:n*(i+1)], TRAILER_TAG)
            inlen -= n
            i++
        }
        absorb_lastblock(state, in[n*i:n*i+inlen], inlen, TRAILER_TAG)
    }
}

func output_tag(state *state_t, tag []uint8) {

    inject_tag(state, FINAL_TAG)
    permute(state)
    permute(state)

    s := state.s[:]
    lastblock := make([]uint8, BYTES64(RATE))
    b := BYTES64(NORX_W)
    for i:= uint64(0); i < WORDS64(RATE); i++ {
        STORE64(lastblock[b*i:b*(i+1)], s[i])
    }
    copy(tag[:], lastblock[:])
    BURN8(lastblock[:], BYTES64(RATE))
}

func verify_tag(tag1 []uint8, tag2 []uint8) int {

    acc := 0
    for i := uint64(0); i < BYTES64(NORX_A); i++ {
        acc |= int(tag1[i] ^ tag2[i])
    }
    return (((acc - 1) >> 8) & 1) - 1
}

func pad(out []uint8, in []uint8, inlen uint64) {

    copy(out[:],in[:inlen])
    out[inlen] = 0x01
    out[BYTES64(RATE) - 1] |= 0x80
}

func inject_tag(state *state_t, tag uint64) {

    s := state.s[:]
    s[15] ^= tag
}

func absorb_block(state *state_t, in []uint8, tag uint64) {

    inject_tag(state, tag)
    permute(state)

    s := state.s[:]
    b := BYTES64(NORX_W)
    for i:= uint64(0); i < WORDS64(RATE); i++ {
        s[i] ^= LOAD64(in[b*i:b*(i+1)])
    }
}

func absorb_lastblock(state *state_t, in []uint8, inlen uint64, tag uint64) {

    lastblock := make([]uint8, BYTES64(RATE))
    pad(lastblock[:], in[:], inlen)
    absorb_block(state, lastblock[:], tag)
    BURN8(lastblock[:], BYTES64(RATE))
}

func encrypt_block(state *state_t, out []uint8, in []uint8) {

    inject_tag(state, PAYLOAD_TAG)
    permute(state)

    s := state.s[:]
    b := BYTES64(NORX_W)
    for i:= uint64(0); i < WORDS64(RATE); i++ {
        s[i] ^= LOAD64(in[b*i:b*(i+1)])
        STORE64(out[b*i:b*(i+1)], s[i])
    }
}

func encrypt_lastblock(state *state_t, out []uint8, in []uint8, inlen uint64) {

    lastblock := make([]uint8, BYTES64(RATE))
    pad(lastblock[:], in[:], inlen)
    encrypt_block(state, lastblock[:], lastblock[:])
    copy(out[:], lastblock[:])
    BURN8(lastblock[:], BYTES64(RATE))
}

func decrypt_block(state *state_t, out []uint8, in []uint8) {

    inject_tag(state, PAYLOAD_TAG)
    permute(state)

    s := state.s[:]
    b := BYTES64(NORX_W)
    for i:= uint64(0); i < WORDS64(RATE); i++ {
        c := LOAD64(in[b*i:b*(i+1)])
        STORE64(out[b*i:b*(i+1)], s[i] ^ c)
        s[i] = c
    }
}

func decrypt_lastblock(state *state_t, out []uint8, in []uint8, inlen uint64) {

    inject_tag(state, PAYLOAD_TAG)
    permute(state)

    s := state.s[:]
    i := uint64(0)
    n := BYTES64(NORX_W)

    /* undo padding */
    s[inlen / n] ^= uint64(0x01) << (inlen % n * 8)
    s[WORDS64(RATE) - 1] ^= uint64(0x80) << ((BYTES64(RATE) - 1) % n * 8)

    for inlen >= n {
        c := LOAD64(in[n*i:n*(i+1)])
        STORE64(out[n*i:n*(i+1)], s[i] ^ c)
        s[i] = c
        inlen -= n
        i++
    }

    /* decrypt last bytes */
    b := make([]uint8, n)
    STORE64(b,s[i])
    for j := uint64(0); j < inlen; j++ {
        c := in[n*i+j]
        out[n*i+j] = b[j] ^ c
        b[j] = c
    }
    s[i] = LOAD64(b)
    BURN8(b,n)
}

func AEAD_encrypt(
    c []uint8, clen *uint64,
    h []uint8, hlen uint64,
    m []uint8, mlen uint64,
    t []uint8, tlen uint64,
    nonce []uint8,
    key []uint8) {

    state := new(state_t)
    setup(state, key, nonce)
    process_header(state, h, hlen)
    encrypt_msg(state, c, m, mlen)
    process_trailer(state, t, tlen)
    output_tag(state, c[mlen:])
    *clen = mlen + BYTES64(NORX_A)
    BURN64(state.s[:], WORDS64(NORX_B))
}

func AEAD_decrypt(
    m []uint8, mlen *uint64,
    h []uint8, hlen uint64,
    c []uint8, clen uint64,
    t []uint8, tlen uint64,
    nonce []uint8,
    key []uint8) int {

    if clen < BYTES64(NORX_A) {
      return -1
    }
    result := -1
    tag := make([]uint8, NORX_A)
    state := new(state_t)
    setup(state, key, nonce)
    process_header(state, h, hlen)
    decrypt_msg(state, m, c, clen - BYTES64(NORX_A))
    process_trailer(state, t, tlen)
    output_tag(state, tag)
    *mlen = clen - BYTES64(NORX_A)
    result = verify_tag(c[clen - BYTES64(NORX_A):], tag)
    if result != 0 {
        BURN8(m, clen - BYTES64(NORX_A))
    }
    BURN64(state.s[:], WORDS64(NORX_B))
    return result
}

<|endoftext|>


<commit_before>package brdoc

import "testing"

func TestIsCEP(t *testing.T) {
	for i, v := range []struct {
		v string
		u []FederativeUnit
		r bool
	}{
		// Invalid format.
		{"3467875434578764345789654", []FederativeUnit{}, false},
		{"", []FederativeUnit{}, false},
		{"#$%¨&*(ABCDEF", []FederativeUnit{}, false},

		// Invalid Federative Unit.
		{"10000-000", []FederativeUnit{RJ}, false},
		{"25000-000", []FederativeUnit{ES}, false},
		{"29500-000", []FederativeUnit{MG}, false},
		{"35000-000", []FederativeUnit{BA}, false},
		{"45000-000", []FederativeUnit{SE}, false},
		{"49500-000", []FederativeUnit{PE}, false},
		{"53000-000", []FederativeUnit{AL}, false},
		{"57500-000", []FederativeUnit{PB}, false},
		{"58500-000", []FederativeUnit{RN}, false},
		{"59500-000", []FederativeUnit{CE}, false},
		{"62000-000", []FederativeUnit{PI}, false},
		{"64500-000", []FederativeUnit{MA}, false},
		{"65500-000", []FederativeUnit{PA}, false},
		{"67000-000", []FederativeUnit{AP}, false},
		{"68900-000", []FederativeUnit{AM}, false},
		{"69100-000", []FederativeUnit{RR}, false},
		{"69300-000", []FederativeUnit{AM}, false},
		{"69600-000", []FederativeUnit{AC}, false},
		{"69900-000", []FederativeUnit{DF}, false},
		{"71500-000", []FederativeUnit{GO}, false},
		{"72800-000", []FederativeUnit{DF}, false},
		{"73200-000", []FederativeUnit{GO}, false},
		{"74500-000", []FederativeUnit{RO}, false},
		{"76800-000", []FederativeUnit{TO}, false},
		{"77500-000", []FederativeUnit{MT}, false},
		{"78500-000", []FederativeUnit{MS}, false},
		{"79500-000", []FederativeUnit{PR}, false},
		{"84000-000", []FederativeUnit{SC}, false},
		{"89000-000", []FederativeUnit{RS}, false},
		{"95000-000", []FederativeUnit{SP}, false},

		// Valid.
		{"10000-000", []FederativeUnit{SP}, true},
		{"25000-000", []FederativeUnit{RJ}, true},
		{"29500-000", []FederativeUnit{ES}, true},
		{"35000-000", []FederativeUnit{MG}, true},
		{"45000-000", []FederativeUnit{BA}, true},
		{"49500-000", []FederativeUnit{SE}, true},
		{"53000-000", []FederativeUnit{PE}, true},
		{"57500-000", []FederativeUnit{AL}, true},
		{"58500-000", []FederativeUnit{PB}, true},
		{"59500-000", []FederativeUnit{RN}, true},
		{"62000-000", []FederativeUnit{CE}, true},
		{"64500-000", []FederativeUnit{PI}, true},
		{"65500-000", []FederativeUnit{MA}, true},
		{"67000-000", []FederativeUnit{PA}, true},
		{"68900-000", []FederativeUnit{AP}, true},
		{"69100-000", []FederativeUnit{AM}, true},
		{"69300-000", []FederativeUnit{RR}, true},
		{"69600-000", []FederativeUnit{AM}, true},
		{"69900-000", []FederativeUnit{AC}, true},
		{"71500-000", []FederativeUnit{DF}, true},
		{"72800-000", []FederativeUnit{GO}, true},
		{"73200-000", []FederativeUnit{DF}, true},
		{"74500-000", []FederativeUnit{GO}, true},
		{"76800-000", []FederativeUnit{RO}, true},
		{"77500-000", []FederativeUnit{TO}, true},
		{"78500-000", []FederativeUnit{MT}, true},
		{"79500-000", []FederativeUnit{MS}, true},
		{"84000-000", []FederativeUnit{PR}, true},
		{"89000-000", []FederativeUnit{SC}, true},
		{"95000-000", []FederativeUnit{RS}, true},

		// With different sizes of Federative Unit slices.
		{"10000-000", []FederativeUnit{SP, SP, SP}, true},
		{"25000-000", []FederativeUnit{}, true},
		{"00000-000", []FederativeUnit{}, true},
		{"00000-000", []FederativeUnit{SP}, false},
		{"29500-000", []FederativeUnit{MT, MS, MG}, false},
	} {
		t.Logf("#%d CEP validation of %s should return %v: ", i, v.v, v.r)
		if IsCEP(v.v, v.u...) != v.r {
			t.Fatal(ballotX)
		}
		t.Log(checkMark)
	}
}
<commit_msg>Add tests for format validation.<commit_after>package brdoc

import "testing"

func TestIsCEP(t *testing.T) {
	for i, v := range []struct {
		v string
		u []FederativeUnit
		r bool
	}{
		// Invalid format.
		{"3467875434578764345789654", []FederativeUnit{}, false},
		{"", []FederativeUnit{}, false},
		{"#$%¨&*(ABCDEF", []FederativeUnit{}, false},

		// Invalid Federative Unit.
		{"10000-000", []FederativeUnit{RJ}, false},
		{"25000-000", []FederativeUnit{ES}, false},
		{"29500-000", []FederativeUnit{MG}, false},
		{"35000-000", []FederativeUnit{BA}, false},
		{"45000-000", []FederativeUnit{SE}, false},
		{"49500-000", []FederativeUnit{PE}, false},
		{"53000-000", []FederativeUnit{AL}, false},
		{"57500-000", []FederativeUnit{PB}, false},
		{"58500-000", []FederativeUnit{RN}, false},
		{"59500-000", []FederativeUnit{CE}, false},
		{"62000-000", []FederativeUnit{PI}, false},
		{"64500-000", []FederativeUnit{MA}, false},
		{"65500-000", []FederativeUnit{PA}, false},
		{"67000-000", []FederativeUnit{AP}, false},
		{"68900-000", []FederativeUnit{AM}, false},
		{"69100-000", []FederativeUnit{RR}, false},
		{"69300-000", []FederativeUnit{AM}, false},
		{"69600-000", []FederativeUnit{AC}, false},
		{"69900-000", []FederativeUnit{DF}, false},
		{"71500-000", []FederativeUnit{GO}, false},
		{"72800-000", []FederativeUnit{DF}, false},
		{"73200-000", []FederativeUnit{GO}, false},
		{"74500-000", []FederativeUnit{RO}, false},
		{"76800-000", []FederativeUnit{TO}, false},
		{"77500-000", []FederativeUnit{MT}, false},
		{"78500-000", []FederativeUnit{MS}, false},
		{"79500-000", []FederativeUnit{PR}, false},
		{"84000-000", []FederativeUnit{SC}, false},
		{"89000-000", []FederativeUnit{RS}, false},
		{"95000-000", []FederativeUnit{SP}, false},

		// Valid.
		{"10000-000", []FederativeUnit{SP}, true},
		{"25000-000", []FederativeUnit{RJ}, true},
		{"29500-000", []FederativeUnit{ES}, true},
		{"35000-000", []FederativeUnit{MG}, true},
		{"45000-000", []FederativeUnit{BA}, true},
		{"49500-000", []FederativeUnit{SE}, true},
		{"53000-000", []FederativeUnit{PE}, true},
		{"57500-000", []FederativeUnit{AL}, true},
		{"58500-000", []FederativeUnit{PB}, true},
		{"59500-000", []FederativeUnit{RN}, true},
		{"62000-000", []FederativeUnit{CE}, true},
		{"64500-000", []FederativeUnit{PI}, true},
		{"65500-000", []FederativeUnit{MA}, true},
		{"67000-000", []FederativeUnit{PA}, true},
		{"68900-000", []FederativeUnit{AP}, true},
		{"69100-000", []FederativeUnit{AM}, true},
		{"69300-000", []FederativeUnit{RR}, true},
		{"69600-000", []FederativeUnit{AM}, true},
		{"69900-000", []FederativeUnit{AC}, true},
		{"71500-000", []FederativeUnit{DF}, true},
		{"72800-000", []FederativeUnit{GO}, true},
		{"73200-000", []FederativeUnit{DF}, true},
		{"74500-000", []FederativeUnit{GO}, true},
		{"76800-000", []FederativeUnit{RO}, true},
		{"77500-000", []FederativeUnit{TO}, true},
		{"78500-000", []FederativeUnit{MT}, true},
		{"79500-000", []FederativeUnit{MS}, true},
		{"84000-000", []FederativeUnit{PR}, true},
		{"89000-000", []FederativeUnit{SC}, true},
		{"95000-000", []FederativeUnit{RS}, true},

		// With different sizes of Federative Unit slices.
		{"10000-000", []FederativeUnit{SP, SP, SP}, true},
		{"25000-000", []FederativeUnit{}, true},
		{"00000-000", []FederativeUnit{}, true},
		{"00000-000", []FederativeUnit{SP}, false},
		{"29500-000", []FederativeUnit{MT, MS, MG}, false},
	} {
		t.Logf("#%d CEP validation of %s should return %v: ", i, v.v, v.r)
		if IsCEP(v.v, v.u...) != v.r {
			t.Fatal(ballotX)
		}
		t.Log(checkMark)
	}
}

func TestValidateCEPFormat(t *testing.T) {
	for i, v := range []struct {
		v string
		r bool
	}{
		// Invalid.
		{"3467875434578764345789654", false},
		{"", false},
		{"#$%¨&*(ABCDEF", false},
		{"0-0000000", false},
		{"00-000000", false},
		{"000-00000", false},
		{"0000-0000", false},
		{"000000-00", false},
		{"0000000-0", false},
		{"0000x000", false},
		{"0000x-000", false},
		{"0000000x", false},
		{"00000-00x", false},

		// Valid.
		{"00000000", true},
		{"00000-000", true},
		{"12345678", true},
		{"87654-321", true},
		{"99999999", true},
		{"99999-999", true},
	} {
		t.Logf("#%d CEP format validation of %s should return %v: ", i, v.v, v.r)
		if ValidateCEPFormat(v.v) != v.r {
			t.Fatal(ballotX)
		}
		t.Log(checkMark)
	}
}
<|endoftext|>


<commit_before>/*
 * Minio Client (C) 2015 Minio, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package main

import (
	"github.com/fatih/color"
	"github.com/minio/cli"
	"github.com/minio/mc/pkg/console"
	"github.com/minio/minio/pkg/probe"
)

// Help message.
var diffCmd = cli.Command{
	Name:        "diff",
	Usage:       "Compute differences between two files or folders.",
	Description: "NOTE: This command *DOES NOT* check for content similarity, which means objects with same size, but different content will not be spotted.",
	Action:      mainDiff,
	CustomHelpTemplate: `NAME:
   mc {{.Name}} - {{.Usage}}

USAGE:
   mc {{.Name}} FIRST SECOND {{if .Description}}

DESCRIPTION:
   {{.Description}}{{end}}{{if .Flags}}

FLAGS:
   {{range .Flags}}{{.}}
   {{end}}{{ end }}

EXAMPLES:
   1. Compare foo.ogg on a local filesystem with bar.ogg on Amazon AWS cloud storage.
      $ mc {{.Name}} foo.ogg  https://s3.amazonaws.com/jukebox/bar.ogg

   2. Compare two different folders on a local filesystem.
      $ mc {{.Name}} ~/Photos /Media/Backup/Photos

`,
}

// mainDiff - is a handler for mc diff command
func mainDiff(ctx *cli.Context) {
	if len(ctx.Args()) != 2 || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "diff", 1) // last argument is exit code
	}

	console.SetCustomTheme(map[string]*color.Color{
		"DiffMessage":     color.New(color.FgGreen, color.Bold),
		"DiffOnlyInFirst": color.New(color.FgRed, color.Bold),
		"DiffType":        color.New(color.FgYellow, color.Bold),
		"DiffSize":        color.New(color.FgMagenta, color.Bold),
	})

	config := mustGetMcConfig()
	firstArg := ctx.Args().First()
	secondArg := ctx.Args()[1]

	var err *probe.Error
	firstURL, err := getCanonicalizedURL(firstArg, config.Aliases)
	fatalIf(err.Trace(firstArg), "Unable to parse first argument ‘"+firstArg+"’.")

	secondURL, err := getCanonicalizedURL(secondArg, config.Aliases)
	fatalIf(err.Trace(secondArg), "Unable to parse second argument ‘"+secondArg+"’.")

	if isURLRecursive(secondURL) {
		fatalIf(errInvalidArgument().Trace(), "Second argument ‘"+secondURL+"’ cannot be recursive.")
	}
	newFirstURL := stripRecursiveURL(firstURL)
	for diff := range doDiffCmd(newFirstURL, secondURL, isURLRecursive(firstURL)) {
		fatalIf(diff.Error.Trace(newFirstURL, secondURL), "Failed to diff ‘"+firstURL+"’ and ‘"+secondURL+"’.")
		console.Println(diff.String())
	}
}

// doDiffCmd - Execute the diff command
func doDiffCmd(firstURL, secondURL string, recursive bool) <-chan DiffMessage {
	ch := make(chan DiffMessage, 10000)
	go doDiffInRoutine(firstURL, secondURL, recursive, ch)
	return ch
}
<commit_msg>Add checkDiffSyntax() for diff command<commit_after>/*
 * Minio Client (C) 2015 Minio, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package main

import (
	"strings"

	"github.com/fatih/color"
	"github.com/minio/cli"
	"github.com/minio/mc/pkg/console"
)

// Help message.
var diffCmd = cli.Command{
	Name:        "diff",
	Usage:       "Compute differences between two files or folders.",
	Description: "NOTE: This command *DOES NOT* check for content similarity, which means objects with same size, but different content will not be spotted.",
	Action:      mainDiff,
	CustomHelpTemplate: `NAME:
   mc {{.Name}} - {{.Usage}}

USAGE:
   mc {{.Name}} FIRST SECOND {{if .Description}}

DESCRIPTION:
   {{.Description}}{{end}}{{if .Flags}}

FLAGS:
   {{range .Flags}}{{.}}
   {{end}}{{ end }}

EXAMPLES:
   1. Compare foo.ogg on a local filesystem with bar.ogg on Amazon AWS cloud storage.
      $ mc {{.Name}} foo.ogg  https://s3.amazonaws.com/jukebox/bar.ogg

   2. Compare two different folders on a local filesystem.
      $ mc {{.Name}} ~/Photos /Media/Backup/Photos

`,
}

func checkDiffSyntax(ctx *cli.Context) {
	if len(ctx.Args()) != 2 || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "diff", 1) // last argument is exit code
	}
	for _, arg := range ctx.Args() {
		if strings.TrimSpace(arg) == "" {
			fatalIf(errInvalidArgument().Trace(), "Unable to validate empty argument.")
		}
	}
	if isURLRecursive(ctx.Args().Last()) {
		fatalIf(errInvalidArgument().Trace(), "Second argument ‘"+ctx.Args().Last()+"’ cannot be recursive.")
	}
}

// mainDiff - is a handler for mc diff command
func mainDiff(ctx *cli.Context) {
	checkDiffSyntax(ctx)

	console.SetCustomTheme(map[string]*color.Color{
		"DiffMessage":     color.New(color.FgGreen, color.Bold),
		"DiffOnlyInFirst": color.New(color.FgRed, color.Bold),
		"DiffType":        color.New(color.FgYellow, color.Bold),
		"DiffSize":        color.New(color.FgMagenta, color.Bold),
	})

	config := mustGetMcConfig()
	firstArg := ctx.Args().First()
	secondArg := ctx.Args().Last()

	firstURL, err := getCanonicalizedURL(firstArg, config.Aliases)
	fatalIf(err.Trace(firstArg), "Unable to parse first argument ‘"+firstArg+"’.")

	secondURL, err := getCanonicalizedURL(secondArg, config.Aliases)
	fatalIf(err.Trace(secondArg), "Unable to parse second argument ‘"+secondArg+"’.")

	newFirstURL := stripRecursiveURL(firstURL)
	for diff := range doDiffCmd(newFirstURL, secondURL, isURLRecursive(firstURL)) {
		fatalIf(diff.Error.Trace(newFirstURL, secondURL), "Failed to diff ‘"+firstURL+"’ and ‘"+secondURL+"’.")
		console.Println(diff.String())
	}
}

// doDiffCmd - Execute the diff command
func doDiffCmd(firstURL, secondURL string, recursive bool) <-chan DiffMessage {
	ch := make(chan DiffMessage, 10000)
	go doDiffInRoutine(firstURL, secondURL, recursive, ch)
	return ch
}
<|endoftext|>


<commit_before>// Copyright 2016 e-Xpert Solutions SA. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package diff implements diff functions to compare objects.
package diff

import (
	"encoding/json"
	"errors"
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

// A Diff represents the changes between two structures.
type Diff map[string]interface{}

// HasChange report whether the Diff contains some changes.
func (d Diff) HasChange() bool {
	return len(d) > 0
}

// PrettyJSON serializes the Diff into JSON in a indented (hence human readable)
// way.
func (d Diff) PrettyJSON() []byte {
	bs, err := json.MarshalIndent(d, "", "   ")
	if err != nil {
		return []byte{}
	}
	return bs
}

// JSON serializes the Diff into JSON in a compact format (no indentation).
func (d Diff) JSON() []byte {
	bs, err := json.Marshal(d)
	if err != nil {
		return []byte{}
	}
	return bs
}

type ChangeType string

// Possible values for a ChangeType.
const (
	AddType ChangeType = "ADD" // addition
	DelType ChangeType = "DEL" // deletion
	ModType ChangeType = "MOD" // modification
)

type Change struct {
	OldVal interface{} `json:"old_value,omitempty"`
	NewVal interface{} `json:"new_value,omitempty"`
	Type   ChangeType  `json:"type,omitempty"`
}

func Compute(x, y interface{}) (Diff, error) {
	return Engine{}.Compute(x, y)
}

type Engine struct {
	ExcludeFieldList []string
	Recursive        bool
}

func (e Engine) IsIgnored(field string) bool {
	for _, f := range e.ExcludeFieldList {
		if f == field {
			return true
		}
	}
	return false
}

func (e Engine) Compute(x, y interface{}) (Diff, error) {
	vx, vy := reflect.ValueOf(x), reflect.ValueOf(y)
	tx, ty := vx.Type(), vy.Type()

	if !tx.AssignableTo(ty) {
		return nil, errors.New("input objects do not share the same type")
	}

	// since x and y share the same type, there is no need to check them both
	if vx.Kind() != reflect.Struct {
		return nil, errors.New("input values are not struct")
	}

	xNumFields := vx.NumField()

	delta := make(Diff)

	for i := 0; i < xNumFields; i++ {
		fx := vx.Field(i)
		typ := tx.Field(i)

		// skip non-exported fields and the ones that are excluded
		if !isExported(typ.Name) || e.IsIgnored(typ.Name) {
			continue
		}

		fy := vy.FieldByName(typ.Name)

		if d := e.handleValue(fx, fy); d != nil {
			delta[typ.Name] = d
		}
	}

	return delta, nil
}

func (e Engine) handleValue(fx, fy reflect.Value) interface{} {
	switch fx.Kind() {

	case reflect.Struct:
		return e.handleStruct(fx, fy)
	case reflect.Array, reflect.Slice:
		return e.handleSlice(fx, fy)
	case reflect.Map:
		return nil

	case reflect.Ptr:
		if fx.IsNil() {
			if fy.IsNil() {
				return nil
			}
			return Change{OldVal: nil, NewVal: fy.Elem().Interface()}
		} else if fy.IsNil() {
			return Change{OldVal: fx.Elem().Interface(), NewVal: nil, Type: ModType}
		}
		return e.handleValue(fx.Elem(), fy.Elem())

	case reflect.Interface, reflect.Func, reflect.Chan, reflect.Invalid, reflect.UnsafePointer, reflect.Complex64, reflect.Complex128:
		// TODO(gilliek): support complex numbers
		return nil

	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		ix, iy := fx.Int(), fy.Int()
		if ix != iy {
			return Change{OldVal: ix, NewVal: iy, Type: ModType}
		}
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		uix, uiy := fx.Uint(), fy.Uint()
		if uix != uiy {
			return Change{OldVal: uix, NewVal: uiy, Type: ModType}
		}
	case reflect.Float32, reflect.Float64:
		flx, fly := fx.Float(), fy.Float()
		if flx-fly < 0.000001 {
			return Change{OldVal: flx, NewVal: fly, Type: ModType}
		}
	case reflect.String:
		sx, sy := fx.String(), fy.String()
		if sx != sy {
			return Change{OldVal: sx, NewVal: sy, Type: ModType}
		}
	}

	return nil
}

func (e Engine) handleStruct(fx, fy reflect.Value) interface{} {
	if isFullyNonExportedStruct(fx) {
		if !isEqual(fx, fy) {
			return Change{OldVal: fx.Interface(), NewVal: fy.Interface()}
		}
		return nil
	}

	delta := make(Diff)
	numFields := fx.NumField()
	for i := 0; i < numFields; i++ {
		newFx := fx.Field(i)
		typ := fx.Type().Field(i)

		// skip non-exported fields and the ones that are excluded
		if !isExported(typ.Name) || e.IsIgnored(typ.Name) {
			continue
		}

		newFy := fy.FieldByName(typ.Name)

		if d := e.handleValue(newFx, newFy); d != nil {
			delta[typ.Name] = d
		}
	}
	if len(delta) > 0 {
		return delta
	}
	return nil
}

func (e Engine) handleSlice(fx, fy reflect.Value) interface{} {
	xLen, yLen := fx.Len(), fy.Len()

	changes := make(map[string]Change)
	if xLen == 0 {
		if yLen == 0 {
			return nil
		}
		for i := 0; i < yLen; i++ {
			changes[strconv.Itoa(i)] = Change{NewVal: fy.Index(i).Interface(), Type: AddType}
		}
	} else if yLen == 0 {
		for i := 0; i < xLen; i++ {
			changes[strconv.Itoa(i)] = Change{OldVal: fx.Index(i).Interface(), Type: DelType}
		}
	} else {
		var maxLen int
		if xLen > yLen {
			maxLen = yLen
			for i := yLen; i < xLen; i++ {
				changes[strconv.Itoa(i)] = Change{OldVal: fx.Index(i).Interface(), Type: DelType}
			}
		} else if xLen < yLen {
			maxLen = xLen
			for i := xLen; i < yLen; i++ {
				changes[strconv.Itoa(i)] = Change{NewVal: fy.Index(i).Interface(), Type: AddType}
			}
		} else {
			maxLen = xLen
		}
		for i := 0; i < maxLen; i++ {
			if d := e.handleValue(fx.Index(i), fy.Index(i)); d != nil {
				changes[strconv.Itoa(i)] = Change{NewVal: d, Type: ModType}
			}
		}
	}
	if len(changes) > 0 {
		return changes
	}
	return nil
}

func isExported(fieldName string) bool {
	if fieldName == "" {
		return false
	}
	firstLetter := string(fieldName[0])
	return firstLetter != strings.ToLower(firstLetter)
}

func isFullyNonExportedStruct(s reflect.Value) bool {
	if s.Kind() != reflect.Struct {
		return false
	}
	numFields := s.NumField()
	for i := 0; i < numFields; i++ {
		typ := s.Type().Field(i)
		if isExported(typ.Name) {
			return false
		}
	}
	return true
}

func isEqual(x, y reflect.Value) bool {
	return fmt.Sprint(x.Interface()) == fmt.Sprint(y.Interface())
}
<commit_msg>diff: add Val field to Change to be semantically correct<commit_after>// Copyright 2016 e-Xpert Solutions SA. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package diff implements diff functions to compare objects.
package diff

import (
	"encoding/json"
	"errors"
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

// A Diff represents the changes between two structures.
type Diff map[string]interface{}

// HasChange report whether the Diff contains some changes.
func (d Diff) HasChange() bool {
	return len(d) > 0
}

// PrettyJSON serializes the Diff into JSON in a indented (hence human readable)
// way.
func (d Diff) PrettyJSON() []byte {
	bs, err := json.MarshalIndent(d, "", "   ")
	if err != nil {
		return []byte{}
	}
	return bs
}

// JSON serializes the Diff into JSON in a compact format (no indentation).
func (d Diff) JSON() []byte {
	bs, err := json.Marshal(d)
	if err != nil {
		return []byte{}
	}
	return bs
}

type ChangeType string

// Possible values for a ChangeType.
const (
	AddType ChangeType = "ADD" // addition
	DelType ChangeType = "DEL" // deletion
	ModType ChangeType = "MOD" // modification
)

type Change struct {
	OldVal interface{} `json:"old_value,omitempty"`
	NewVal interface{} `json:"new_value,omitempty"`
	Val    interface{} `json:"value,omitempty"`
	Type   ChangeType  `json:"type,omitempty"`
}

func Compute(x, y interface{}) (Diff, error) {
	return Engine{}.Compute(x, y)
}

type Engine struct {
	ExcludeFieldList []string
	Recursive        bool
}

func (e Engine) IsIgnored(field string) bool {
	for _, f := range e.ExcludeFieldList {
		if f == field {
			return true
		}
	}
	return false
}

func (e Engine) Compute(x, y interface{}) (Diff, error) {
	vx, vy := reflect.ValueOf(x), reflect.ValueOf(y)
	tx, ty := vx.Type(), vy.Type()

	if !tx.AssignableTo(ty) {
		return nil, errors.New("input objects do not share the same type")
	}

	// since x and y share the same type, there is no need to check them both
	if vx.Kind() != reflect.Struct {
		return nil, errors.New("input values are not struct")
	}

	xNumFields := vx.NumField()

	delta := make(Diff)

	for i := 0; i < xNumFields; i++ {
		fx := vx.Field(i)
		typ := tx.Field(i)

		// skip non-exported fields and the ones that are excluded
		if !isExported(typ.Name) || e.IsIgnored(typ.Name) {
			continue
		}

		fy := vy.FieldByName(typ.Name)

		if d := e.handleValue(fx, fy); d != nil {
			delta[typ.Name] = d
		}
	}

	return delta, nil
}

func (e Engine) handleValue(fx, fy reflect.Value) interface{} {
	switch fx.Kind() {

	case reflect.Struct:
		return e.handleStruct(fx, fy)
	case reflect.Array, reflect.Slice:
		return e.handleSlice(fx, fy)
	case reflect.Map:
		return nil

	case reflect.Ptr:
		if fx.IsNil() {
			if fy.IsNil() {
				return nil
			}
			return Change{OldVal: nil, NewVal: fy.Elem().Interface()}
		} else if fy.IsNil() {
			return Change{OldVal: fx.Elem().Interface(), NewVal: nil, Type: ModType}
		}
		return e.handleValue(fx.Elem(), fy.Elem())

	case reflect.Interface, reflect.Func, reflect.Chan, reflect.Invalid, reflect.UnsafePointer, reflect.Complex64, reflect.Complex128:
		// TODO(gilliek): support complex numbers
		return nil

	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		ix, iy := fx.Int(), fy.Int()
		if ix != iy {
			return Change{OldVal: ix, NewVal: iy, Type: ModType}
		}
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		uix, uiy := fx.Uint(), fy.Uint()
		if uix != uiy {
			return Change{OldVal: uix, NewVal: uiy, Type: ModType}
		}
	case reflect.Float32, reflect.Float64:
		flx, fly := fx.Float(), fy.Float()
		if flx-fly < 0.000001 {
			return Change{OldVal: flx, NewVal: fly, Type: ModType}
		}
	case reflect.String:
		sx, sy := fx.String(), fy.String()
		if sx != sy {
			return Change{OldVal: sx, NewVal: sy, Type: ModType}
		}
	}

	return nil
}

func (e Engine) handleStruct(fx, fy reflect.Value) interface{} {
	if isFullyNonExportedStruct(fx) {
		if !isEqual(fx, fy) {
			return Change{OldVal: fx.Interface(), NewVal: fy.Interface()}
		}
		return nil
	}

	delta := make(Diff)
	numFields := fx.NumField()
	for i := 0; i < numFields; i++ {
		newFx := fx.Field(i)
		typ := fx.Type().Field(i)

		// skip non-exported fields and the ones that are excluded
		if !isExported(typ.Name) || e.IsIgnored(typ.Name) {
			continue
		}

		newFy := fy.FieldByName(typ.Name)

		if d := e.handleValue(newFx, newFy); d != nil {
			delta[typ.Name] = d
		}
	}
	if len(delta) > 0 {
		return delta
	}
	return nil
}

func (e Engine) handleSlice(fx, fy reflect.Value) interface{} {
	xLen, yLen := fx.Len(), fy.Len()

	changes := make(map[string]Change)
	if xLen == 0 {
		if yLen == 0 {
			return nil
		}
		for i := 0; i < yLen; i++ {
			changes[strconv.Itoa(i)] = Change{NewVal: fy.Index(i).Interface(), Type: AddType}
		}
	} else if yLen == 0 {
		for i := 0; i < xLen; i++ {
			changes[strconv.Itoa(i)] = Change{OldVal: fx.Index(i).Interface(), Type: DelType}
		}
	} else {
		var maxLen int
		if xLen > yLen {
			maxLen = yLen
			for i := yLen; i < xLen; i++ {
				changes[strconv.Itoa(i)] = Change{OldVal: fx.Index(i).Interface(), Type: DelType}
			}
		} else if xLen < yLen {
			maxLen = xLen
			for i := xLen; i < yLen; i++ {
				changes[strconv.Itoa(i)] = Change{NewVal: fy.Index(i).Interface(), Type: AddType}
			}
		} else {
			maxLen = xLen
		}
		for i := 0; i < maxLen; i++ {
			if d := e.handleValue(fx.Index(i), fy.Index(i)); d != nil {
				changes[strconv.Itoa(i)] = Change{Val: d, Type: ModType}
			}
		}
	}
	if len(changes) > 0 {
		return changes
	}
	return nil
}

func isExported(fieldName string) bool {
	if fieldName == "" {
		return false
	}
	firstLetter := string(fieldName[0])
	return firstLetter != strings.ToLower(firstLetter)
}

func isFullyNonExportedStruct(s reflect.Value) bool {
	if s.Kind() != reflect.Struct {
		return false
	}
	numFields := s.NumField()
	for i := 0; i < numFields; i++ {
		typ := s.Type().Field(i)
		if isExported(typ.Name) {
			return false
		}
	}
	return true
}

func isEqual(x, y reflect.Value) bool {
	return fmt.Sprint(x.Interface()) == fmt.Sprint(y.Interface())
}
<|endoftext|>