// Tests a 2-node system func TestBroadcast(t *testing.T) { defer log.AfterTest(t) log.TestOutput(testing.Verbose(), 3) for _, nbrNodes := range []int{3, 10, 14} { local := sda.NewLocalTest() _, _, tree := local.GenTree(nbrNodes, false, true, true) pi, err := local.CreateProtocol(tree, "Broadcast") if err != nil { t.Fatal("Couldn't start protocol:", err) } protocol := pi.(*manage.Broadcast) done := make(chan bool) protocol.RegisterOnDone(func() { done <- true }) protocol.Start() timeout := network.WaitRetry * time.Duration(network.MaxRetry*nbrNodes*2) * time.Millisecond select { case <-done: log.Lvl2("Done with connecting everybody") case <-time.After(timeout): t.Fatal("Didn't finish in time") } local.CloseAll() } }
func TestProtocolHandlers(t *testing.T) { defer log.AfterTest(t) local := sda.NewLocalTest() _, _, tree := local.GenTree(3, false, true, true) defer local.CloseAll() log.Lvl2("Sending to children") IncomingHandlers = make(chan *sda.TreeNodeInstance, 2) p, err := local.CreateProtocol(tree, "ProtocolHandlers") if err != nil { t.Fatal(err) } go p.Start() log.Lvl2("Waiting for responses") child1 := <-IncomingHandlers child2 := <-IncomingHandlers if child1.ServerIdentity().ID == child2.ServerIdentity().ID { t.Fatal("Both entities should be different") } log.Lvl2("Sending to parent") tni := p.(*ProtocolHandlers).TreeNodeInstance child1.SendTo(tni.TreeNode(), &NodeTestAggMsg{}) if len(IncomingHandlers) > 0 { t.Fatal("This should not trigger yet") } child2.SendTo(tni.TreeNode(), &NodeTestAggMsg{}) final := <-IncomingHandlers if final.ServerIdentity().ID != tni.ServerIdentity().ID { t.Fatal("This should be the same ID") } }
func TestNodeChannel(t *testing.T) { defer log.AfterTest(t) local := sda.NewLocalTest() _, _, tree := local.GenTree(2, false, true, true) defer local.CloseAll() p, err := local.CreateProtocol(tree, "ProtocolChannels") if err != nil { t.Fatal("Couldn't create new node:", err) } c := make(chan struct { *sda.TreeNode NodeTestMsg }, 1) tni := p.(*ProtocolChannels).TreeNodeInstance err = tni.RegisterChannel(c) if err != nil { t.Fatal("Couldn't register channel:", err) } err = tni.DispatchChannel([]*sda.ProtocolMsg{&sda.ProtocolMsg{ Msg: NodeTestMsg{3}, MsgType: network.RegisterMessageType(NodeTestMsg{}), From: &sda.Token{ TreeID: tree.ID, TreeNodeID: tree.Root.ID, }}, }) if err != nil { t.Fatal("Couldn't dispatch to channel:", err) } msg := <-c if msg.I != 3 { t.Fatal("Message should contain '3'") } }
// Tests a 2-node system func TestCloseall(t *testing.T) { defer log.AfterTest(t) log.TestOutput(testing.Verbose(), 4) local := sda.NewLocalTest() nbrNodes := 2 _, _, tree := local.GenTree(nbrNodes, false, true, true) defer local.CloseAll() pi, err := local.CreateProtocol(tree, "ExampleChannels") if err != nil { t.Fatal("Couldn't start protocol:", err) } go pi.Start() protocol := pi.(*channels.ProtocolExampleChannels) timeout := network.WaitRetry * time.Duration(network.MaxRetry*nbrNodes*2) * time.Millisecond select { case children := <-protocol.ChildCount: log.Lvl2("Instance 1 is done") if children != nbrNodes { t.Fatal("Didn't get a child-cound of", nbrNodes) } case <-time.After(timeout): t.Fatal("Didn't finish in time") } }
// Tests an n-node system func TestPropagate(t *testing.T) { for _, nbrNodes := range []int{3, 10, 14} { local := sda.NewLocalTest() _, el, _ := local.GenTree(nbrNodes, false, true, true) o := local.Overlays[el.List[0].ID] i := 0 msg := &PropagateMsg{[]byte("propagate")} tree := el.GenerateNaryTreeWithRoot(8, o.ServerIdentity()) log.Lvl2("Starting to propagate", reflect.TypeOf(msg)) pi, err := o.CreateProtocolSDA(tree, "Propagate") log.ErrFatal(err) nodes, err := propagateStartAndWait(pi, msg, 1000, func(m network.Body) { if bytes.Equal(msg.Data, m.(*PropagateMsg).Data) { i++ } else { t.Error("Didn't receive correct data") } }) log.ErrFatal(err) if i != 1 { t.Fatal("Didn't get data-request") } if nodes != nbrNodes { t.Fatal("Not all nodes replied") } local.CloseAll() } }
func TestClient_Send(t *testing.T) { local := sda.NewLocalTest() defer local.CloseAll() // register service sda.RegisterNewService("BackForth", func(c *sda.Context, path string) sda.Service { return &simpleService{ ctx: c, } }) // create hosts hosts, el, _ := local.GenTree(4, true, true, false) client := sda.NewClient("BackForth") r := &simpleRequest{ ServerIdentities: el, Val: 10, } nm, err := client.Send(hosts[0].ServerIdentity, r) log.ErrFatal(err) assert.Equal(t, nm.MsgType, simpleResponseType) resp := nm.Msg.(simpleResponse) assert.Equal(t, resp.Val, 10) }
func TestBftCoSi(t *testing.T) { defer log.AfterTest(t) log.TestOutput(testing.Verbose(), 4) // Register test protocol using BFTCoSi sda.ProtocolRegisterName(TestProtocolName, func(n *sda.TreeNodeInstance) (sda.ProtocolInstance, error) { return NewBFTCoSiProtocol(n, verify) }) for _, nbrHosts := range []int{3, 13} { countMut.Lock() veriCount = 0 countMut.Unlock() log.Lvl2("Running BFTCoSi with", nbrHosts, "hosts") local := sda.NewLocalTest() _, _, tree := local.GenBigTree(nbrHosts, nbrHosts, 3, true, true) done := make(chan bool) // create the message we want to sign for this round msg := []byte("Hello BFTCoSi") // Start the protocol node, err := local.CreateProtocol(tree, TestProtocolName) if err != nil { t.Fatal("Couldn't create new node:", err) } // Register the function generating the protocol instance var root *ProtocolBFTCoSi root = node.(*ProtocolBFTCoSi) root.Msg = msg // function that will be called when protocol is finished by the root root.RegisterOnDone(func() { done <- true }) go node.Start() // are we done yet? wait := time.Second * 3 select { case <-done: countMut.Lock() assert.Equal(t, veriCount, nbrHosts, "Each host should have called verification.") // if assert fails we don't care for unlocking (t.Fail) countMut.Unlock() sig := root.Signature() if err := cosi.VerifyCosiSignatureWithException(root.Suite(), root.AggregatedPublic, msg, sig.Sig, sig.Exceptions); err != nil { t.Fatal(fmt.Sprintf("%s Verification of the signature failed: %s", root.Name(), err.Error())) } case <-time.After(wait): t.Fatal("Waited", wait, "sec for BFTCoSi to finish ...") } local.CloseAll() } }
func TestHostClose2(t *testing.T) { defer log.AfterTest(t) local := sda.NewLocalTest() defer local.CloseAll() _, _, tree := local.GenTree(2, false, true, true) log.Lvl3(tree.Dump()) time.Sleep(time.Millisecond * 100) log.Lvl3("Done") }
// Test propagation of tree - both known and unknown func TestTreePropagation(t *testing.T) { defer log.AfterTest(t) local := sda.NewLocalTest() hosts, el, tree := local.GenTree(2, true, false, false) defer local.CloseAll() h1 := hosts[0] h2 := hosts[1] // Suppose both hosts have the list available, but not the tree h1.AddRoster(el) h2.AddRoster(el) h2.StartProcessMessages() // Check that h2 sends back an empty tree if it is unknown err := h1.SendRaw(h2.ServerIdentity, &sda.RequestTree{TreeID: tree.ID}) if err != nil { t.Fatal("Couldn't send message to h2:", err) } msg := h1.Receive() if msg.MsgType != sda.SendTreeMessageID { network.DumpTypes() t.Fatal("h1 didn't receive SendTree type:", msg.MsgType) } if msg.Msg.(sda.TreeMarshal).RosterID != sda.RosterID(uuid.Nil) { t.Fatal("List should be empty") } // Now add the list to h2 and try again h2.AddTree(tree) err = h1.SendRaw(h2.ServerIdentity, &sda.RequestTree{TreeID: tree.ID}) if err != nil { t.Fatal("Couldn't send message to h2:", err) } msg = h1.Receive() if msg.MsgType != sda.SendTreeMessageID { t.Fatal("h1 didn't receive Tree-type") } if msg.Msg.(sda.TreeMarshal).TreeID != tree.ID { t.Fatal("Tree should be equal to original tree") } // And test whether it gets stored correctly h1.StartProcessMessages() err = h1.SendRaw(h2.ServerIdentity, &sda.RequestTree{TreeID: tree.ID}) if err != nil { t.Fatal("Couldn't send message to h2:", err) } time.Sleep(time.Second) tree2, ok := h1.GetTree(tree.ID) if !ok { t.Fatal("List-id not found") } if !tree.Equal(tree2) { t.Fatal("Trees do not match") } }
// Test propagation of peer-lists - both known and unknown func TestPeerListPropagation(t *testing.T) { defer log.AfterTest(t) local := sda.NewLocalTest() hosts, el, _ := local.GenTree(2, false, false, false) defer local.CloseAll() h1 := hosts[0] h2 := hosts[1] h2.StartProcessMessages() // Check that h2 sends back an empty list if it is unknown err := h1.SendRaw(h2.ServerIdentity, &sda.RequestRoster{ RosterID: el.ID}) if err != nil { t.Fatal("Couldn't send message to h2:", err) } msg := h1.Receive() if msg.MsgType != sda.SendRosterMessageID { t.Fatal("h1 didn't receive Roster type, but", msg.MsgType) } if msg.Msg.(sda.Roster).ID != sda.RosterID(uuid.Nil) { t.Fatal("List should be empty") } // Now add the list to h2 and try again h2.AddRoster(el) err = h1.SendRaw(h2.ServerIdentity, &sda.RequestRoster{RosterID: el.ID}) if err != nil { t.Fatal("Couldn't send message to h2:", err) } msg = h1.Receive() if msg.MsgType != sda.SendRosterMessageID { t.Fatal("h1 didn't receive Roster type") } if msg.Msg.(sda.Roster).ID != el.ID { t.Fatal("List should be equal to original list") } // And test whether it gets stored correctly h1.StartProcessMessages() err = h1.SendRaw(h2.ServerIdentity, &sda.RequestRoster{RosterID: el.ID}) if err != nil { t.Fatal("Couldn't send message to h2:", err) } time.Sleep(time.Second) list, ok := h1.Roster(el.ID) if !ok { t.Fatal("List-id not found") } if list.ID != el.ID { t.Fatal("IDs do not match") } }
func TestNtree(t *testing.T) { defer log.AfterTest(t) log.TestOutput(testing.Verbose(), 4) for _, nbrHosts := range []int{1, 3, 13} { log.Lvl2("Running ntree with", nbrHosts, "hosts") local := sda.NewLocalTest() _, _, tree := local.GenBigTree(nbrHosts, nbrHosts, 3, true, true) done := make(chan bool) // create the message we want to sign for this round msg := []byte("Ntree rocks slowly") // Register the function generating the protocol instance var root *ntree.Protocol // function that will be called when protocol is finished by the root doneFunc := func() bool { done <- true return true } // Start the protocol pi, err := local.CreateProtocol(tree, "NaiveTree") if err != nil { t.Fatal("Couldn't create new node:", err) } root = pi.(*ntree.Protocol) root.Message = msg root.OnDoneCallback(doneFunc) err = pi.Start() if nbrHosts == 1 { if err == nil { t.Fatal("Shouldn't be able to start NTree with 1 node") } } else if err != nil { t.Fatal("Couldn't start protocol:", err) } else { select { case <-done: case <-time.After(time.Second * 2): t.Fatal("Protocol didn't finish in time") } } local.CloseAll() } }
func TestBlocking(t *testing.T) { defer log.AfterTest(t) l := sda.NewLocalTest() _, _, tree := l.GenTree(2, true, true, true) defer l.CloseAll() n1, err := l.StartProtocol("ProtocolBlocking", tree) if err != nil { t.Fatal("Couldn't start protocol") } n2, err := l.StartProtocol("ProtocolBlocking", tree) if err != nil { t.Fatal("Couldn't start protocol") } p1 := n1.(*BlockingProtocol) p2 := n2.(*BlockingProtocol) tn1 := p1.TreeNodeInstance tn2 := p2.TreeNodeInstance go func() { // Send two messages to n1, which blocks the old interface err := l.SendTreeNode("", tn2, tn1, &NodeTestMsg{}) if err != nil { t.Fatal("Couldn't send message:", err) } err = l.SendTreeNode("", tn2, tn1, &NodeTestMsg{}) if err != nil { t.Fatal("Couldn't send message:", err) } // Now send a message to n2, but in the old interface this // blocks. err = l.SendTreeNode("", tn1, tn2, &NodeTestMsg{}) if err != nil { t.Fatal("Couldn't send message:", err) } }() // Release p2 p2.stopBlockChan <- true select { case <-p2.doneChan: log.Lvl2("Node 2 done") p1.stopBlockChan <- true <-p1.doneChan case <-time.After(time.Second): t.Fatal("Node 2 didn't receive") } }
func TestRandHound(t *testing.T) { // Setup parameters var name string = "RandHound" // Protocol name var nodes uint32 = 10 // Number of nodes (peers + leader) var trustees uint32 = 5 // Number of trustees var purpose string = "RandHound test run" // Purpose var shards uint32 = 2 // Number of shards created from the randomness local := sda.NewLocalTest() _, _, tree := local.GenTree(int(nodes), false, true, true) defer local.CloseAll() log.TestOutput(testing.Verbose(), 1) // Setup and Start RandHound log.Printf("RandHound - starting") leader, err := local.CreateProtocol(tree, name) if err != nil { t.Fatal("Couldn't initialise RandHound protocol:", err) } rh := leader.(*randhound.RandHound) err = rh.Setup(nodes, trustees, purpose) if err != nil { t.Fatal("Couldn't initialise RandHound protocol:", err) } log.Printf("RandHound - group config: %d %d %d %d %d %d\n", rh.Group.N, rh.Group.F, rh.Group.L, rh.Group.K, rh.Group.R, rh.Group.T) log.Printf("RandHound - shards: %d\n", shards) leader.Start() select { case <-rh.Leader.Done: log.Printf("RandHound - done") rnd, err := rh.Random() if err != nil { t.Fatal(err) } sharding, err := rh.Shard(rnd, shards) if err != nil { t.Fatal(err) } log.Printf("RandHound - random bytes: %v\n", rnd) log.Printf("RandHound - sharding: %v\n", sharding) case <-time.After(time.Second * 60): t.Fatal("RandHound – time out") } }
// Test when a peer receives a New Roster, it can create the trees that are // waiting on this specific entitiy list, to be constructed. func TestPeerPendingTreeMarshal(t *testing.T) { defer log.AfterTest(t) local := sda.NewLocalTest() hosts, el, tree := local.GenTree(2, false, false, false) defer local.CloseAll() h1 := hosts[0] // Add the marshalled version of the tree local.AddPendingTreeMarshal(h1, tree.MakeTreeMarshal()) if _, ok := h1.GetTree(tree.ID); ok { t.Fatal("host 1 should not have the tree definition yet.") } // Now make it check local.CheckPendingTreeMarshal(h1, el) if _, ok := h1.GetTree(tree.ID); !ok { t.Fatal("Host 1 should have the tree definition now.") } }
// Tests both list- and tree-propagation // basically h1 ask for a tree id // h2 respond with the tree // h1 ask for the entitylist (because it dont know) // h2 respond with the entitylist func TestListTreePropagation(t *testing.T) { defer log.AfterTest(t) local := sda.NewLocalTest() hosts, el, tree := local.GenTree(2, true, true, false) defer local.CloseAll() h1 := hosts[0] h2 := hosts[1] // h2 knows the entity list h2.AddRoster(el) // and the tree h2.AddTree(tree) // make the communcation happen if err := h1.SendRaw(h2.ServerIdentity, &sda.RequestTree{TreeID: tree.ID}); err != nil { t.Fatal("Could not send tree request to host2", err) } var tryTree int var tryServerIdentity int var found bool for tryTree < 5 || tryServerIdentity < 5 { // Sleep a bit time.Sleep(100 * time.Millisecond) // then look if we have both the tree and the entity list if _, ok := h1.GetTree(tree.ID); !ok { tryTree++ continue } // We got the tree that's already something, now do we get the entity // list if _, ok := h1.Roster(el.ID); !ok { tryServerIdentity++ continue } // we got both ! yay found = true break } if !found { t.Fatal("Did not get the tree + entityList from host2") } }
func TestMsgAggregation(t *testing.T) { defer log.AfterTest(t) local := sda.NewLocalTest() _, _, tree := local.GenTree(3, false, true, true) defer local.CloseAll() root, err := local.StartProtocol("ProtocolChannels", tree) if err != nil { t.Fatal("Couldn't create new node:", err) } proto := root.(*ProtocolChannels) // Wait for both children to be up <-Incoming <-Incoming log.Lvl3("Both children are up") child1 := local.GetNodes(tree.Root.Children[0])[0] child2 := local.GetNodes(tree.Root.Children[1])[0] err = local.SendTreeNode("ProtocolChannels", child1, proto.TreeNodeInstance, &NodeTestAggMsg{3}) if err != nil { t.Fatal(err) } if len(proto.IncomingAgg) > 0 { t.Fatal("Messages should NOT be there") } err = local.SendTreeNode("ProtocolChannels", child2, proto.TreeNodeInstance, &NodeTestAggMsg{4}) if err != nil { t.Fatal(err) } select { case msgs := <-proto.IncomingAgg: if msgs[0].I != 3 { t.Fatal("First message should be 3") } if msgs[1].I != 4 { t.Fatal("Second message should be 4") } case <-time.After(time.Second): t.Fatal("Messages should BE there") } }
func TestNodeChannelCreateSlice(t *testing.T) { defer log.AfterTest(t) local := sda.NewLocalTest() _, _, tree := local.GenTree(2, false, true, true) defer local.CloseAll() p, err := local.CreateProtocol(tree, "ProtocolChannels") if err != nil { t.Fatal("Couldn't create new node:", err) } var c chan []struct { *sda.TreeNode NodeTestMsg } tni := p.(*ProtocolChannels).TreeNodeInstance err = tni.RegisterChannel(&c) if err != nil { t.Fatal("Couldn't register channel:", err) } }
func TestSendLimitedTree(t *testing.T) { defer log.AfterTest(t) local := sda.NewLocalTest() _, _, tree := local.GenBigTree(7, 1, 2, true, true) defer local.CloseAll() log.Lvl3(tree.Dump()) root, err := local.StartProtocol("Count", tree) if err != nil { t.Fatal("Couldn't create new node:", err) } // XXX using manage here ... maybe theses are the kind of protocol / // services we want to embed directly into SDA instead of exporting them and // then importing them again in sda_test. If we really need them ... protoCount := root.(*manage.ProtocolCount) count := <-protoCount.Count if count != 7 { t.Fatal("Didn't get a count of 7:", count) } }
func TestServiceBackForthProtocol(t *testing.T) { local := sda.NewLocalTest() defer local.CloseAll() // register service sda.RegisterNewService("BackForth", func(c *sda.Context, path string) sda.Service { return &simpleService{ ctx: c, } }) // create hosts hosts, el, _ := local.GenTree(4, true, true, false) // create client priv, pub := sda.PrivPub() client := network.NewSecureTCPHost(priv, network.NewServerIdentity(pub, "")) c, err := client.Open(hosts[0].ServerIdentity) assert.Nil(t, err) // create request r := &simpleRequest{ ServerIdentities: el, Val: 10, } buff, err := network.MarshalRegisteredType(r) assert.Nil(t, err) req := &sda.ClientRequest{ Service: sda.ServiceFactory.ServiceID("BackForth"), Data: buff, } assert.Nil(t, c.Send(context.TODO(), req)) nm, err := c.Receive(context.TODO()) assert.Nil(t, err) assert.Equal(t, nm.MsgType, simpleResponseType) resp := nm.Msg.(simpleResponse) assert.Equal(t, resp.Val, 10) }
func TestClient_Parallel(t *testing.T) { nbrNodes := 2 nbrParallel := 2 local := sda.NewLocalTest() defer local.CloseAll() // register service sda.RegisterNewService("BackForth", func(c *sda.Context, path string) sda.Service { return &simpleService{ ctx: c, } }) // create hosts hosts, el, _ := local.GenTree(nbrNodes, true, true, false) wg := sync.WaitGroup{} wg.Add(nbrParallel) for i := 0; i < nbrParallel; i++ { go func(i int) { log.Lvl1("Starting message", i) r := &simpleRequest{ ServerIdentities: el, Val: 10 * i, } client := sda.NewClient("BackForth") nm, err := client.Send(hosts[0].ServerIdentity, r) log.ErrFatal(err) assert.Equal(t, nm.MsgType, simpleResponseType) resp := nm.Msg.(simpleResponse) assert.Equal(t, resp.Val, 10*i) log.Lvl1("Done with message", i) wg.Done() }(i) } wg.Wait() }
func TestJVSS(t *testing.T) { // Setup parameters var name string = "JVSS" // Protocol name var nodes uint32 = 5 // Number of nodes var rounds int = 3 // Number of rounds msg := []byte("Hello World!") // Message to-be-signed local := sda.NewLocalTest() _, _, tree := local.GenTree(int(nodes), false, true, true) defer local.CloseAll() log.TestOutput(testing.Verbose(), 1) log.Lvl1("JVSS - starting") leader, err := local.CreateProtocol(tree, name) if err != nil { t.Fatal("Couldn't initialise protocol tree:", err) } jv := leader.(*jvss.JVSS) leader.Start() log.Lvl1("JVSS - setup done") for i := 0; i < rounds; i++ { log.Lvl1("JVSS - starting round", i) log.Lvl1("JVSS - requesting signature") sig, _ := jv.Sign(msg) log.Lvl1("JVSS - signature received") err = jv.Verify(msg, sig) if err != nil { t.Fatal("Error signature verification failed", err) } log.Lvl1("JVSS - signature verification succeded") } }
func TestFlags(t *testing.T) { defer log.AfterTest(t) testType := network.MessageTypeID(uuid.Nil) local := sda.NewLocalTest() _, _, tree := local.GenTree(3, false, false, true) defer local.CloseAll() p, err := local.CreateProtocol(tree, "ProtocolChannels") if err != nil { t.Fatal("Couldn't create node.") } tni := p.(*ProtocolChannels).TreeNodeInstance if tni.HasFlag(testType, sda.AggregateMessages) { t.Fatal("Should NOT have AggregateMessages-flag") } tni.SetFlag(testType, sda.AggregateMessages) if !tni.HasFlag(testType, sda.AggregateMessages) { t.Fatal("Should HAVE AggregateMessages-flag cleared") } tni.ClearFlag(testType, sda.AggregateMessages) if tni.HasFlag(testType, sda.AggregateMessages) { t.Fatal("Should NOT have AggregateMessages-flag") } }