From 5481566d940c5de323a40c027cd01f948d12c476 Mon Sep 17 00:00:00 2001 From: Tim Pepper Date: Fri, 1 Jul 2016 15:51:38 -0700 Subject: [PATCH 01/19] ciao-controller: stop test clients/servers without defers We need to shut down the ssntp and id servers and not via a defer because os.Exit() results in deferred code not running. Signed-off-by: Tim Pepper --- ciao-controller/controller_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ciao-controller/controller_test.go b/ciao-controller/controller_test.go index 46b13cc7a..683e8ad21 100644 --- a/ciao-controller/controller_test.go +++ b/ciao-controller/controller_test.go @@ -763,7 +763,6 @@ func TestMain(m *testing.M) { // create fake ssntp server testutil.StartTestServer(&server) - defer server.Ssntp.Stop() context = new(controller) context.ds = new(datastore.Datastore) @@ -797,7 +796,6 @@ func TestMain(m *testing.M) { } id := testutil.StartIdentityServer(testIdentityConfig) - defer id.Close() idConfig := identityConfig{ endpoint: id.URL, @@ -820,6 +818,8 @@ func TestMain(m *testing.M) { context.client.Disconnect() context.ds.Exit() + id.Close() + server.Ssntp.Stop() os.Remove("./ciao-controller-test.db") os.Remove("./ciao-controller-test.db-shm") From 7b4d8b4868e384ea86096f45da9a4a20dccb9e22 Mon Sep 17 00:00:00 2001 From: Tim Pepper Date: Fri, 8 Jul 2016 15:56:06 -0700 Subject: [PATCH 02/19] ciao-scheduler: thread and wait with prints the test teardown sequence A bug was causing the scheduler test's ssntpTestsTeardown() function to hang. By using subroutines, a waitgroup and adding some printouts it's more clear if and where a hang is happening. Signed-off-by: Tim Pepper --- ciao-scheduler/scheduler_ssntp_test.go | 27 +++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/ciao-scheduler/scheduler_ssntp_test.go b/ciao-scheduler/scheduler_ssntp_test.go index cd250b45e..59c00ad66 100644 --- a/ciao-scheduler/scheduler_ssntp_test.go +++ b/ciao-scheduler/scheduler_ssntp_test.go @@ -503,15 +503,28 @@ func ssntpTestsSetup() error { func ssntpTestsTeardown() { // stop everybody - time.Sleep(1 * time.Second) - controller.Ssntp.Close() + var wg sync.WaitGroup + wg.Add(3) - time.Sleep(1 * time.Second) - netAgent.Ssntp.Close() + go func() { + controller.Ssntp.Close() + wg.Done() + }() - time.Sleep(1 * time.Second) - agent.Ssntp.Close() + go func() { + netAgent.Ssntp.Close() + wg.Done() + }() - time.Sleep(1 * time.Second) + go func() { + agent.Ssntp.Close() + wg.Done() + }() + + fmt.Println("Awaiting clients' shutdown") + wg.Wait() + fmt.Println("Got clients' shutdown") + fmt.Println("Awaiting server shutdown") server.ssntp.Stop() + fmt.Println("Got server shutdown") } From df9c11091949e582690b91485829f8d35a83e6cd Mon Sep 17 00:00:00 2001 From: Tim Pepper Date: Fri, 8 Jul 2016 16:01:34 -0700 Subject: [PATCH 03/19] ciao-controller: add more synchonization points to test The ciao-controller tests have mostly relied on time.Sleep() for "ordering" of events. At least for the portions which flow through a testutil client or server, it's possible to use the event and command channels to see that the expected events have traversed the stack in the expected places. The sleep's can't fully, simply be removed though because the controller does not have a similar mechanism to insure its asynchronous processing has completed before carrying on. Signed-off-by: Tim Pepper --- ciao-controller/compute_test.go | 57 ++------ ciao-controller/controller_test.go | 212 ++++++++++++++++------------- 2 files changed, 130 insertions(+), 139 deletions(-) diff --git a/ciao-controller/compute_test.go b/ciao-controller/compute_test.go index 685957ab7..b7e873859 100644 --- a/ciao-controller/compute_test.go +++ b/ciao-controller/compute_test.go @@ -233,12 +233,7 @@ func TestDeleteServer(t *testing.T) { time.Sleep(2 * time.Second) - c := client.AddCmdChan(ssntp.STATS) - go client.SendStatsCmd() - _, err = client.GetCmdChanResult(c, ssntp.STATS) - if err != nil { - t.Fatal(err) - } + sendStatsCmd(client, t) time.Sleep(2 * time.Second) @@ -280,12 +275,7 @@ func TestServersActionStart(t *testing.T) { time.Sleep(2 * time.Second) - c := client.AddCmdChan(ssntp.STATS) - go client.SendStatsCmd() - _, err = client.GetCmdChanResult(c, ssntp.STATS) - if err != nil { - t.Fatal(err) - } + sendStatsCmd(client, t) time.Sleep(1 * time.Second) @@ -296,12 +286,7 @@ func TestServersActionStart(t *testing.T) { time.Sleep(1 * time.Second) - c = client.AddCmdChan(ssntp.STATS) - go client.SendStatsCmd() - _, err = client.GetCmdChanResult(c, ssntp.STATS) - if err != nil { - t.Fatal(err) - } + sendStatsCmd(client, t) time.Sleep(1 * time.Second) @@ -342,12 +327,7 @@ func TestServersActionStop(t *testing.T) { time.Sleep(2 * time.Second) - c := client.AddCmdChan(ssntp.STATS) - go client.SendStatsCmd() - _, err = client.GetCmdChanResult(c, ssntp.STATS) - if err != nil { - t.Fatal(err) - } + sendStatsCmd(client, t) time.Sleep(1 * time.Second) @@ -388,12 +368,7 @@ func TestServerActionStop(t *testing.T) { time.Sleep(2 * time.Second) - c := client.AddCmdChan(ssntp.STATS) - go client.SendStatsCmd() - _, err = client.GetCmdChanResult(c, ssntp.STATS) - if err != nil { - t.Fatal(err) - } + sendStatsCmd(client, t) time.Sleep(1 * time.Second) @@ -422,35 +397,25 @@ func TestServerActionStart(t *testing.T) { time.Sleep(1 * time.Second) - c := client.AddCmdChan(ssntp.STATS) - go client.SendStatsCmd() - _, err = client.GetCmdChanResult(c, ssntp.STATS) - if err != nil { - t.Fatal(err) - } + sendStatsCmd(client, t) time.Sleep(1 * time.Second) - c = server.AddCmdChan(ssntp.STOP) + serverCh := server.AddCmdChan(ssntp.STOP) err = context.stopInstance(servers.Servers[0].ID) if err != nil { t.Fatal(err) } - _, err = server.GetCmdChanResult(c, ssntp.STOP) + _, err = server.GetCmdChanResult(serverCh, ssntp.STOP) if err != nil { t.Fatal(err) } time.Sleep(1 * time.Second) - c = client.AddCmdChan(ssntp.STATS) - go client.SendStatsCmd() - _, err = client.GetCmdChanResult(c, ssntp.STATS) - if err != nil { - t.Fatal(err) - } + sendStatsCmd(client, t) time.Sleep(1 * time.Second) @@ -924,7 +889,7 @@ func TestListTraces(t *testing.T) { client := testStartTracedWorkload(t) defer client.Ssntp.Close() - client.SendTrace() + sendTraceReportEvent(client, t) time.Sleep(2 * time.Second) @@ -1010,7 +975,7 @@ func TestTraceData(t *testing.T) { client := testStartTracedWorkload(t) defer client.Ssntp.Close() - client.SendTrace() + sendTraceReportEvent(client, t) time.Sleep(2 * time.Second) diff --git a/ciao-controller/controller_test.go b/ciao-controller/controller_test.go index 683e8ad21..564eba643 100644 --- a/ciao-controller/controller_test.go +++ b/ciao-controller/controller_test.go @@ -21,6 +21,7 @@ import ( "fmt" "net" "os" + "sync" "testing" "time" @@ -258,6 +259,34 @@ func TestStartWorkloadLaunchCNCI(t *testing.T) { } +func sendTraceReportEvent(client *testutil.SsntpTestClient, t *testing.T) { + clientCh := client.AddEventChan(ssntp.TraceReport) + serverCh := server.AddEventChan(ssntp.TraceReport) + go client.SendTrace() + _, err := client.GetEventChanResult(clientCh, ssntp.TraceReport) + if err != nil { + t.Fatal(err) + } + _, err = server.GetEventChanResult(serverCh, ssntp.TraceReport) + if err != nil { + t.Fatal(err) + } +} + +func sendStatsCmd(client *testutil.SsntpTestClient, t *testing.T) { + clientCh := client.AddCmdChan(ssntp.STATS) + serverCh := server.AddCmdChan(ssntp.STATS) + go client.SendStatsCmd() + _, err := client.GetCmdChanResult(clientCh, ssntp.STATS) + if err != nil { + t.Fatal(err) + } + _, err = server.GetCmdChanResult(serverCh, ssntp.STATS) + if err != nil { + t.Fatal(err) + } +} + // TBD: for the launch CNCI tests, I really need to create a fake // network node and test that way. @@ -267,11 +296,9 @@ func TestDeleteInstance(t *testing.T) { client, instances := testStartWorkload(t, 1, false, reason) defer client.Ssntp.Close() - time.Sleep(1 * time.Second) + sendStatsCmd(client, t) - client.SendStatsCmd() - - c := server.AddCmdChan(ssntp.DELETE) + serverCh := server.AddCmdChan(ssntp.DELETE) time.Sleep(1 * time.Second) @@ -280,7 +307,7 @@ func TestDeleteInstance(t *testing.T) { t.Fatal(err) } - result, err := server.GetCmdChanResult(c, ssntp.DELETE) + result, err := server.GetCmdChanResult(serverCh, ssntp.DELETE) if err != nil { t.Fatal(err) } @@ -295,11 +322,9 @@ func TestStopInstance(t *testing.T) { client, instances := testStartWorkload(t, 1, false, reason) defer client.Ssntp.Close() - time.Sleep(1 * time.Second) - - client.SendStatsCmd() + sendStatsCmd(client, t) - c := server.AddCmdChan(ssntp.STOP) + serverCh := server.AddCmdChan(ssntp.STOP) time.Sleep(1 * time.Second) @@ -308,7 +333,7 @@ func TestStopInstance(t *testing.T) { t.Fatal(err) } - result, err := server.GetCmdChanResult(c, ssntp.STOP) + result, err := server.GetCmdChanResult(serverCh, ssntp.STOP) if err != nil { t.Fatal(err) } @@ -325,9 +350,10 @@ func TestRestartInstance(t *testing.T) { time.Sleep(1 * time.Second) - client.SendStatsCmd() + sendStatsCmd(client, t) - c := server.AddCmdChan(ssntp.STOP) + serverCh := server.AddCmdChan(ssntp.STOP) + clientCh := client.AddCmdChan(ssntp.STOP) time.Sleep(1 * time.Second) @@ -336,7 +362,11 @@ func TestRestartInstance(t *testing.T) { t.Fatal(err) } - result, err := server.GetCmdChanResult(c, ssntp.STOP) + result, err := server.GetCmdChanResult(serverCh, ssntp.STOP) + if err != nil { + t.Fatal(err) + } + _, err = client.GetCmdChanResult(clientCh, ssntp.STOP) if err != nil { t.Fatal(err) } @@ -345,11 +375,10 @@ func TestRestartInstance(t *testing.T) { } // now attempt to restart - time.Sleep(1 * time.Second) - client.SendStatsCmd() + sendStatsCmd(client, t) - c = server.AddCmdChan(ssntp.RESTART) + serverCh = server.AddCmdChan(ssntp.RESTART) time.Sleep(1 * time.Second) @@ -358,7 +387,7 @@ func TestRestartInstance(t *testing.T) { t.Fatal(err) } - result, err = server.GetCmdChanResult(c, ssntp.RESTART) + result, err = server.GetCmdChanResult(serverCh, ssntp.RESTART) if err != nil { t.Fatal(err) } @@ -374,7 +403,7 @@ func TestEvacuateNode(t *testing.T) { } defer client.Ssntp.Close() - c := server.AddCmdChan(ssntp.EVACUATE) + serverCh := server.AddCmdChan(ssntp.EVACUATE) // ok to not send workload first? @@ -383,7 +412,7 @@ func TestEvacuateNode(t *testing.T) { t.Error(err) } - result, err := server.GetCmdChanResult(c, ssntp.EVACUATE) + result, err := server.GetCmdChanResult(serverCh, ssntp.EVACUATE) if err != nil { t.Fatal(err) } @@ -398,9 +427,9 @@ func TestInstanceDeletedEvent(t *testing.T) { client, instances := testStartWorkload(t, 1, false, reason) defer client.Ssntp.Close() - time.Sleep(1 * time.Second) + sendStatsCmd(client, t) - client.SendStatsCmd() + serverCh := server.AddCmdChan(ssntp.DELETE) time.Sleep(1 * time.Second) @@ -409,53 +438,29 @@ func TestInstanceDeletedEvent(t *testing.T) { t.Fatal(err) } - time.Sleep(1 * time.Second) - - client.SendDeleteEvent(instances[0].ID) - - time.Sleep(1 * time.Second) - - // try to get instance info - _, err = context.ds.GetInstance(instances[0].ID) - if err == nil { - t.Error("Instance not deleted") - } -} - -func TestLaunchCNCI(t *testing.T) { - netClient, err := testutil.NewSsntpTestClientConnection("LaunchCNCI", ssntp.NETAGENT, testutil.NetAgentUUID) + _, err = server.GetCmdChanResult(serverCh, ssntp.DELETE) if err != nil { t.Fatal(err) } - defer netClient.Ssntp.Close() - c := server.AddCmdChan(ssntp.START) - - id := uuid.Generate().String() - - // this blocks till it get success or failure - go context.addTenant(id) - - result, err := server.GetCmdChanResult(c, ssntp.START) + clientEvtCh := client.AddEventChan(ssntp.InstanceDeleted) + serverEvtCh := server.AddEventChan(ssntp.InstanceDeleted) + go client.SendDeleteEvent(instances[0].ID) + _, err = client.GetEventChanResult(clientEvtCh, ssntp.InstanceDeleted) if err != nil { t.Fatal(err) } - if result.TenantUUID != id { - t.Fatal("Did not get correct tenant ID") - } - if !result.CNCI { - t.Fatal("this is not a CNCI launch request") - } - - time.Sleep(2 * time.Second) - - tenant, err := context.ds.GetTenant(id) - if err != nil || tenant == nil { + _, err = server.GetEventChanResult(serverEvtCh, ssntp.InstanceDeleted) + if err != nil { t.Fatal(err) } - if tenant.CNCIIP == "" { - t.Fatal("CNCI Info not updated") + time.Sleep(1 * time.Second) + + // try to get instance info + _, err = context.ds.GetInstance(instances[0].ID) + if err == nil { + t.Error("Instance not deleted") } } @@ -480,13 +485,9 @@ func TestStopFailure(t *testing.T) { client.StopFail = true client.StopFailReason = payloads.StopNoInstance - time.Sleep(1 * time.Second) + sendStatsCmd(client, t) - client.SendStatsCmd() - - time.Sleep(1 * time.Second) - - c := server.AddCmdChan(ssntp.STOP) + serverCh := server.AddCmdChan(ssntp.STOP) time.Sleep(1 * time.Second) @@ -495,7 +496,7 @@ func TestStopFailure(t *testing.T) { t.Fatal(err) } - result, err := server.GetCmdChanResult(c, ssntp.STOP) + result, err := server.GetCmdChanResult(serverCh, ssntp.STOP) if err != nil { t.Fatal(err) } @@ -532,20 +533,23 @@ func TestRestartFailure(t *testing.T) { client.RestartFail = true client.RestartFailReason = payloads.RestartLaunchFailure - time.Sleep(1 * time.Second) - - client.SendStatsCmd() + sendStatsCmd(client, t) time.Sleep(1 * time.Second) - c := server.AddCmdChan(ssntp.STOP) + serverCh := server.AddCmdChan(ssntp.STOP) + clientCh := client.AddCmdChan(ssntp.STOP) err := context.stopInstance(instances[0].ID) if err != nil { t.Fatal(err) } - result, err := server.GetCmdChanResult(c, ssntp.STOP) + _, err = client.GetCmdChanResult(clientCh, ssntp.STOP) + if err != nil { + t.Fatal(err) + } + result, err := server.GetCmdChanResult(serverCh, ssntp.STOP) if err != nil { t.Fatal(err) } @@ -553,20 +557,18 @@ func TestRestartFailure(t *testing.T) { t.Fatal("Did not get correct Instance ID") } - time.Sleep(1 * time.Second) - - client.SendStatsCmd() + sendStatsCmd(client, t) time.Sleep(1 * time.Second) - c = server.AddCmdChan(ssntp.RESTART) + serverCh = server.AddCmdChan(ssntp.RESTART) err = context.restartInstance(instances[0].ID) if err != nil { t.Fatal(err) } - result, err = server.GetCmdChanResult(c, ssntp.RESTART) + result, err = server.GetCmdChanResult(serverCh, ssntp.RESTART) if err != nil { t.Fatal(err) } @@ -625,7 +627,8 @@ func testStartTracedWorkload(t *testing.T) *testutil.SsntpTestClient { t.Fatal("No workloads, expected len(wls) > 0, got len(wls) == 0") } - c := client.AddCmdChan(ssntp.START) + clientCh := client.AddCmdChan(ssntp.START) + serverCh := server.AddCmdChan(ssntp.START) instances, err := context.startWorkload(wls[0].ID, tenant.ID, 1, true, "testtrace1") if err != nil { @@ -635,7 +638,11 @@ func testStartTracedWorkload(t *testing.T) *testutil.SsntpTestClient { t.Fatalf("Wrong number of instances, expected 1, got %d", len(instances)) } - result, err := client.GetCmdChanResult(c, ssntp.START) + _, err = client.GetCmdChanResult(clientCh, ssntp.START) + if err != nil { + t.Fatal(err) + } + result, err := server.GetCmdChanResult(serverCh, ssntp.START) if err != nil { t.Fatal(err) } @@ -668,7 +675,8 @@ func testStartWorkload(t *testing.T, num int, fail bool, reason payloads.StartFa t.Fatal("No workloads, expected len(wls) > 0, got len(wls) == 0") } - c := client.AddCmdChan(ssntp.START) + clientCmdCh := client.AddCmdChan(ssntp.START) + clientErrCh := client.AddErrorChan(ssntp.StartFailure) client.StartFail = fail client.StartFailReason = reason @@ -680,7 +688,14 @@ func testStartWorkload(t *testing.T, num int, fail bool, reason payloads.StartFa t.Fatalf("Wrong number of instances, expected %d, got %d", len(instances), num) } - result, err := client.GetCmdChanResult(c, ssntp.START) + if fail == true { + _, err := client.GetErrorChanResult(clientErrCh, ssntp.StartFailure) + if err == nil { // unexpected success + t.Fatal(err) + } + } + + result, err := client.GetCmdChanResult(clientCmdCh, ssntp.START) if fail == true && err == nil { // unexpected success t.Fatal(err) } @@ -694,14 +709,13 @@ func testStartWorkload(t *testing.T, num int, fail bool, reason payloads.StartFa return client, instances } -// TestStartWorkloadLaunchCNCI starts a test CNCI // NOTE: the caller is responsible for calling Ssntp.Close() on the *SsntpTestClient func testStartWorkloadLaunchCNCI(t *testing.T, num int) (*testutil.SsntpTestClient, []*types.Instance) { netClient, err := testutil.NewSsntpTestClientConnection("StartWorkloadLaunchCNCI", ssntp.NETAGENT, testutil.NetAgentUUID) if err != nil { t.Fatal(err) } - // caller of TestStartWorkloadLaunchCNCI() owns doing the close + // caller of testStartWorkloadLaunchCNCI() owns doing the close //defer netClient.Ssntp.Close() wls, err := context.ds.GetWorkloads() @@ -712,14 +726,20 @@ func testStartWorkloadLaunchCNCI(t *testing.T, num int) (*testutil.SsntpTestClie t.Fatal("No workloads, expected len(wls) > 0, got len(wls) == 0") } - c := server.AddCmdChan(ssntp.START) + serverCmdCh := server.AddCmdChan(ssntp.START) + netClientCmdCh := netClient.AddCmdChan(ssntp.START) - id := uuid.Generate().String() + newTenant := uuid.Generate().String() // random ~= new tenant and thus triggers start of a CNCI + // trigger the START command flow, and await results + // NOTE: "instances" is shared with the go subroutine and we must + // insure consistency between parent and child processes var instances []*types.Instance + var wg sync.WaitGroup + wg.Add(1) go func() { - instances, err = context.startWorkload(wls[0].ID, id, 1, false, "") + instances, err = context.startWorkload(wls[0].ID, newTenant, 1, false, "") if err != nil { t.Fatal(err) } @@ -727,13 +747,19 @@ func testStartWorkloadLaunchCNCI(t *testing.T, num int) (*testutil.SsntpTestClie if len(instances) != 1 { t.Fatalf("Wrong number of instances, expected 1, got %d", len(instances)) } + wg.Done() }() - result, err := server.GetCmdChanResult(c, ssntp.START) + _, err = netClient.GetCmdChanResult(netClientCmdCh, ssntp.START) if err != nil { t.Fatal(err) } - if result.TenantUUID != id { + result, err := server.GetCmdChanResult(serverCmdCh, ssntp.START) + if err != nil { + t.Fatal(err) + } + + if result.TenantUUID != newTenant { t.Fatal("Did not get correct tenant ID") } @@ -741,14 +767,14 @@ func testStartWorkloadLaunchCNCI(t *testing.T, num int) (*testutil.SsntpTestClie t.Fatal("this is not a CNCI launch request") } - c = server.AddCmdChan(ssntp.START) - - result, err = server.GetCmdChanResult(c, ssntp.START) - if err != nil { - t.Fatal(err) + tenantCNCI, _ := context.ds.GetTenantCNCISummary(result.InstanceUUID) + if result.InstanceUUID != tenantCNCI[0].InstanceID { + t.Fatalf("Did not get correct Instance ID, got %s, expected %s", result.InstanceUUID, tenantCNCI[0].InstanceID) } - if result.InstanceUUID != instances[0].ID { - t.Fatal("Did not get correct Instance ID") + + wg.Wait() // for "instances" + if instances == nil { + t.Fatal("did not receive instance") } return netClient, instances From cb8a5edc37218fedddf849886e88d698845b3999 Mon Sep 17 00:00:00 2001 From: Tim Pepper Date: Tue, 28 Jun 2016 17:23:55 -0700 Subject: [PATCH 04/19] testutil: server EventNotify() doesn't handle connect/disconnect The testutil server had conditional handling in EventNotify() for connect/disconnect cases which are already handled by ConnectNotify() and DisconnectNotify(). We can't have duplicate events pushed to the event channels or stale ones hang out from prior tests. Remove the unused code, but note where applicable in comment that the event does not need code there handling it. Signed-off-by: Tim Pepper --- testutil/controller.go | 2 ++ testutil/server.go | 10 ++-------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/testutil/controller.go b/testutil/controller.go index 22cfd4d57..1f1263a5a 100644 --- a/testutil/controller.go +++ b/testutil/controller.go @@ -239,6 +239,8 @@ func (ctl *SsntpTestController) EventNotify(event ssntp.Event, frame *ssntp.Fram var result Result switch event { + // case ssntp.NodeConnected: handled by ConnectNotify() + // case ssntp.NodeDisconnected: handled by DisconnectNotify() case ssntp.InstanceDeleted: var deleteEvent payloads.EventInstanceDeleted diff --git a/testutil/server.go b/testutil/server.go index 7f21f51b3..d51091228 100644 --- a/testutil/server.go +++ b/testutil/server.go @@ -340,14 +340,8 @@ func (server *SsntpTestServer) EventNotify(uuid string, event ssntp.Event, frame payload := frame.Payload switch event { - case ssntp.NodeConnected: - var connectEvent payloads.NodeConnected - - result.Err = yaml.Unmarshal(payload, &connectEvent) - case ssntp.NodeDisconnected: - var disconnectEvent payloads.NodeDisconnected - - result.Err = yaml.Unmarshal(payload, &disconnectEvent) + // case ssntp.NodeConnected: handled by ConnectNotify() + // case ssntp.NodeDisconnected: handled by DisconnectNotify() case ssntp.TraceReport: var traceEvent payloads.Trace From 6c59a508d70803d8def05e61bc80795325474b8b Mon Sep 17 00:00:00 2001 From: Tim Pepper Date: Tue, 28 Jun 2016 17:38:03 -0700 Subject: [PATCH 05/19] testutil: treat server's clients and net clients the same The testutil server implementation has internal structures to track "compute node" clients and "network node" clients. They are needlessly different, with the network nodes' tracking being a lessor implementation. Cleaning this up makes it easier to subsequently add on CNCI related flows. Signed-off-by: Tim Pepper --- testutil/server.go | 112 ++++++++++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 51 deletions(-) diff --git a/testutil/server.go b/testutil/server.go index d51091228..fbd5eb230 100644 --- a/testutil/server.go +++ b/testutil/server.go @@ -29,9 +29,13 @@ import ( // SsntpTestServer is global state for the testutil SSNTP server type SsntpTestServer struct { - Ssntp ssntp.Server - clients []string - clientsLock *sync.Mutex + Ssntp ssntp.Server + + clients []string + clientsLock *sync.Mutex + netClients []string + netClientsLock *sync.Mutex + CmdChans map[ssntp.Command]chan Result CmdChansLock *sync.Mutex EventChans map[ssntp.Event]chan Result @@ -40,9 +44,6 @@ type SsntpTestServer struct { ErrorChansLock *sync.Mutex StatusChans map[ssntp.Status]chan Result StatusChansLock *sync.Mutex - - NetClients map[string]bool - NetClientsLock *sync.RWMutex } // AddCmdChan adds an ssntp.Command to the SsntpTestServer command channel @@ -204,9 +205,9 @@ func (server *SsntpTestServer) ConnectNotify(uuid string, role ssntp.Role) { server.clients = append(server.clients, uuid) case ssntp.NETAGENT: - server.NetClientsLock.Lock() - server.NetClients[uuid] = true - server.NetClientsLock.Unlock() + server.netClientsLock.Lock() + defer server.netClientsLock.Unlock() + server.netClients = append(server.netClients, uuid) } server.SendResultAndDelEventChan(ssntp.NodeConnected, result) @@ -216,20 +217,27 @@ func (server *SsntpTestServer) ConnectNotify(uuid string, role ssntp.Role) { func (server *SsntpTestServer) DisconnectNotify(uuid string, role ssntp.Role) { var result Result - server.clientsLock.Lock() - for index := range server.clients { - if server.clients[index] == uuid { - server.clients = append(server.clients[:index], server.clients[index+1:]...) - break + switch role { + case ssntp.AGENT: + server.clientsLock.Lock() + for index := range server.clients { + if server.clients[index] == uuid { + server.clients = append(server.clients[:index], server.clients[index+1:]...) + break + } } - } - server.clientsLock.Unlock() + server.clientsLock.Unlock() - server.NetClientsLock.Lock() - if server.NetClients[uuid] == true { - delete(server.NetClients, uuid) + case ssntp.NETAGENT: + server.netClientsLock.Lock() + for index := range server.netClients { + if server.netClients[index] == uuid { + server.netClients = append(server.netClients[:index], server.netClients[index+1:]...) + break + } + } + server.netClientsLock.Unlock() } - server.NetClientsLock.Unlock() server.SendResultAndDelEventChan(ssntp.NodeDisconnected, result) } @@ -455,47 +463,51 @@ func (server *SsntpTestServer) ErrorNotify(uuid string, error ssntp.Error, frame server.SendResultAndDelErrorChan(error, result) } -// CommandForward implements an SSNTP CommandForward callback for SsntpTestServer -func (server *SsntpTestServer) CommandForward(uuid string, command ssntp.Command, frame *ssntp.Frame) (dest ssntp.ForwardDestination) { - switch command { - case ssntp.START: - //TODO: move to a workload start function - var startCmd payloads.Start - var nn bool - - payload := frame.Payload +func (server *SsntpTestServer) handleStart(payload []byte) (dest ssntp.ForwardDestination) { + var startCmd payloads.Start + var nn bool - err := yaml.Unmarshal(payload, &startCmd) + err := yaml.Unmarshal(payload, &startCmd) - if err != nil { - return - } + if err != nil { + return + } - resources := startCmd.Start.RequestedResources + resources := startCmd.Start.RequestedResources - for i := range resources { - if resources[i].Type == payloads.NetworkNode { - nn = true - break - } + for i := range resources { + if resources[i].Type == payloads.NetworkNode { + nn = true + break } + } - if nn { - server.NetClientsLock.RLock() - for key := range server.NetClients { - dest.AddRecipient(key) - break - } - server.NetClientsLock.RUnlock() - return + if nn { + server.netClientsLock.Lock() + defer server.netClientsLock.Unlock() + if len(server.netClients) > 0 { + index := rand.Intn(len(server.netClients)) + dest.AddRecipient(server.netClients[index]) } - + } else { server.clientsLock.Lock() defer server.clientsLock.Unlock() if len(server.clients) > 0 { index := rand.Intn(len(server.clients)) dest.AddRecipient(server.clients[index]) } + } + + return dest +} + +// CommandForward implements an SSNTP CommandForward callback for SsntpTestServer +func (server *SsntpTestServer) CommandForward(uuid string, command ssntp.Command, frame *ssntp.Frame) (dest ssntp.ForwardDestination) { + payload := frame.Payload + + switch command { + case ssntp.START: + dest = server.handleStart(payload) case ssntp.EVACUATE: fallthrough case ssntp.STOP: @@ -515,6 +527,7 @@ func (server *SsntpTestServer) CommandForward(uuid string, command ssntp.Command // testutil.SsntpTestServer configuration with standard ssntp.FrameRorwardRules func StartTestServer(server *SsntpTestServer) { server.clientsLock = &sync.Mutex{} + server.netClientsLock = &sync.Mutex{} server.CmdChans = make(map[ssntp.Command]chan Result) server.CmdChansLock = &sync.Mutex{} @@ -528,9 +541,6 @@ func StartTestServer(server *SsntpTestServer) { server.StatusChans = make(map[ssntp.Status]chan Result) server.StatusChansLock = &sync.Mutex{} - server.NetClients = make(map[string]bool) - server.NetClientsLock = &sync.RWMutex{} - serverConfig := ssntp.Config{ CAcert: ssntp.DefaultCACert, Cert: ssntp.RoleToDefaultCertName(ssntp.SERVER), From 4df270ad6aeaad609956aa07a24267fcfc47ffb2 Mon Sep 17 00:00:00 2001 From: Tim Pepper Date: Tue, 28 Jun 2016 17:39:58 -0700 Subject: [PATCH 06/19] testutil: TestStart wait on server response before agent The testutil client-server test's TestStart function waits first on the agent and then on the server. That's technically fine since this is all asynchonous and threaded, but it's illogical. The command first flows through the server so wait on seeing it flow through the server first. Then wait on seeing the command at the agent. Signed-off-by: Tim Pepper --- testutil/client_server_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testutil/client_server_test.go b/testutil/client_server_test.go index fd1a336c6..e1af6fa86 100644 --- a/testutil/client_server_test.go +++ b/testutil/client_server_test.go @@ -61,11 +61,11 @@ func TestStart(t *testing.T) { go controller.Ssntp.SendCommand(ssntp.START, []byte(StartYaml)) - _, err := agent.GetCmdChanResult(agentCh, ssntp.START) + _, err := server.GetCmdChanResult(serverCh, ssntp.START) if err != nil { t.Fatal(err) } - _, err = server.GetCmdChanResult(serverCh, ssntp.START) + _, err = agent.GetCmdChanResult(agentCh, ssntp.START) if err != nil { t.Fatal(err) } From 16556bf97379babae624435a63fc36c0dd6e313e Mon Sep 17 00:00:00 2001 From: Tim Pepper Date: Fri, 8 Jul 2016 16:50:43 -0700 Subject: [PATCH 07/19] testutil: ssntp.ConcentratorInstanceAddedEvent event flows Add ssntp.ConcentratorInstanceAddedEvent event flows to the testutil client-server test. This means adding a cnciAgent client and a test case which simulates the controller requesting via the server that a netAgent start the cnciAgent into the testutil client-server test. Similarly ciao-controller's tests which did a less thorough simulation of the ssntp.ConcentratorInstanceAddedEvent event flow need adjusted. Signed-off-by: Tim Pepper --- ciao-controller/controller_test.go | 22 ++++++++++++++ ciao-scheduler/scheduler_internal_test.go | 8 +++-- testutil/agent.go | 27 +++++++++-------- testutil/client_server_test.go | 37 +++++++++++++++++++++++ testutil/payloads.go | 18 ++++++++++- testutil/server.go | 2 +- 6 files changed, 96 insertions(+), 18 deletions(-) diff --git a/ciao-controller/controller_test.go b/ciao-controller/controller_test.go index 564eba643..85bbd9576 100644 --- a/ciao-controller/controller_test.go +++ b/ciao-controller/controller_test.go @@ -767,7 +767,29 @@ func testStartWorkloadLaunchCNCI(t *testing.T, num int) (*testutil.SsntpTestClie t.Fatal("this is not a CNCI launch request") } + // start a test CNCI client + cnciClient, err := testutil.NewSsntpTestClientConnection("StartWorkloadLaunchCNCI", ssntp.CNCIAGENT, newTenant) + if err != nil { + t.Fatal(err) + } + + // make CNCI send an ssntp.ConcentratorInstanceAdded event, and await results + cnciEventCh := cnciClient.AddEventChan(ssntp.ConcentratorInstanceAdded) + serverEventCh := server.AddEventChan(ssntp.ConcentratorInstanceAdded) tenantCNCI, _ := context.ds.GetTenantCNCISummary(result.InstanceUUID) + go cnciClient.SendConcentratorAddedEvent(result.InstanceUUID, newTenant, testutil.CNCIIP, tenantCNCI[0].MACAddress) + result, err = cnciClient.GetEventChanResult(cnciEventCh, ssntp.ConcentratorInstanceAdded) + if err != nil { + t.Fatal(err) + } + _, err = server.GetEventChanResult(serverEventCh, ssntp.ConcentratorInstanceAdded) + if err != nil { + t.Fatal(err) + } + + // shutdown the test CNCI client + cnciClient.Ssntp.Close() + if result.InstanceUUID != tenantCNCI[0].InstanceID { t.Fatalf("Did not get correct Instance ID, got %s, expected %s", result.InstanceUUID, tenantCNCI[0].InstanceID) } diff --git a/ciao-scheduler/scheduler_internal_test.go b/ciao-scheduler/scheduler_internal_test.go index edd6a973c..9de425ee3 100644 --- a/ciao-scheduler/scheduler_internal_test.go +++ b/ciao-scheduler/scheduler_internal_test.go @@ -579,9 +579,11 @@ func TestStartWorkload(t *testing.T) { fwd, uuid := startWorkload(sched, controllerUUID, []byte(testutil.CNCIStartYaml)) decision := fwd.Decision() recipients := fwd.Recipients() - if decision != ssntp.Forward || - uuid != testutil.CNCIUUID { - t.Errorf("unable to start CNCI, got decision=0x%x, workload uuid=%s", decision, uuid) + if decision != ssntp.Forward { + t.Errorf("bad decision, got 0x%x, expected 0x%x", decision, ssntp.Forward) + } + if uuid != testutil.CNCIInstanceUUID { + t.Errorf("bad uuid, got %s, expected %s", uuid, testutil.CNCIInstanceUUID) } for _, dest = range recipients[:] { if sched.nnMap[dest] == nil { diff --git a/testutil/agent.go b/testutil/agent.go index bf14e4063..45091f338 100644 --- a/testutil/agent.go +++ b/testutil/agent.go @@ -278,12 +278,8 @@ func (client *SsntpTestClient) handleStart(payload []byte) Result { result.TenantUUID = cmd.Start.TenantUUID result.NodeUUID = client.UUID - if client.Role == ssntp.NETAGENT { - networking := cmd.Start.Networking - - client.sendConcentratorAddedEvent(cmd.Start.InstanceUUID, cmd.Start.TenantUUID, networking.VnicMAC) + if client.Role.IsNetAgent() { result.CNCI = true - return result } if client.StartFail == true { @@ -534,20 +530,23 @@ func (client *SsntpTestClient) SendDeleteEvent(uuid string) { _, err = client.Ssntp.SendEvent(ssntp.InstanceDeleted, y) if err != nil { result.Err = err - fmt.Println(err) } } client.SendResultAndDelEventChan(ssntp.InstanceDeleted, result) } -func (client *SsntpTestClient) sendConcentratorAddedEvent(instanceUUID string, tenantUUID string, vnicMAC string) { +// SendConcentratorAddedEvent allows an SsntpTestClient to push an ssntp.ConcentratorInstanceAdded event frame +func (client *SsntpTestClient) SendConcentratorAddedEvent(instanceUUID string, tenantUUID string, ip string, vnicMAC string) { + var result Result + evt := payloads.ConcentratorInstanceAddedEvent{ InstanceUUID: instanceUUID, TenantUUID: tenantUUID, - ConcentratorIP: "192.168.0.1", + ConcentratorIP: ip, ConcentratorMAC: vnicMAC, } + result.InstanceUUID = instanceUUID event := payloads.EventConcentratorInstanceAdded{ CNCIAdded: evt, @@ -555,13 +554,15 @@ func (client *SsntpTestClient) sendConcentratorAddedEvent(instanceUUID string, t y, err := yaml.Marshal(event) if err != nil { - return + result.Err = err + } else { + _, err = client.Ssntp.SendEvent(ssntp.ConcentratorInstanceAdded, y) + if err != nil { + result.Err = err + } } - _, err = client.Ssntp.SendEvent(ssntp.ConcentratorInstanceAdded, y) - if err != nil { - fmt.Println(err) - } + client.SendResultAndDelEventChan(ssntp.ConcentratorInstanceAdded, result) } func (client *SsntpTestClient) sendStartFailure(instanceUUID string, reason payloads.StartFailureReason) { diff --git a/testutil/client_server_test.go b/testutil/client_server_test.go index e1af6fa86..bb7e81613 100644 --- a/testutil/client_server_test.go +++ b/testutil/client_server_test.go @@ -32,6 +32,7 @@ var server SsntpTestServer var controller *SsntpTestController var agent *SsntpTestClient var netAgent *SsntpTestClient +var cnciAgent *SsntpTestClient func TestSendAgentStatus(t *testing.T) { serverCh := server.AddStatusChan(ssntp.READY) @@ -55,6 +56,42 @@ func TestSendNetAgentStatus(t *testing.T) { } } +func TestCNCIStart(t *testing.T) { + serverCh := server.AddCmdChan(ssntp.START) + netAgentCh := netAgent.AddCmdChan(ssntp.START) + + go controller.Ssntp.SendCommand(ssntp.START, []byte(CNCIStartYaml)) + + _, err := server.GetCmdChanResult(serverCh, ssntp.START) + if err != nil { + t.Fatal(err) + } + _, err = netAgent.GetCmdChanResult(netAgentCh, ssntp.START) + if err != nil { + t.Fatal(err) + } + + serverCh = server.AddEventChan(ssntp.ConcentratorInstanceAdded) + controllerCh := controller.AddEventChan(ssntp.ConcentratorInstanceAdded) + + // start CNCI agent + cnciAgent, err = NewSsntpTestClientConnection("CNCI Client", ssntp.CNCIAGENT, CNCIUUID) + if err != nil { + t.Fatal(err) + } + + cnciAgent.SendConcentratorAddedEvent(CNCIInstanceUUID, TenantUUID, CNCIIP, CNCIMAC) + + _, err = server.GetEventChanResult(serverCh, ssntp.ConcentratorInstanceAdded) + if err != nil { + t.Fatal(err) + } + _, err = controller.GetEventChanResult(controllerCh, ssntp.ConcentratorInstanceAdded) + if err != nil { + t.Fatal(err) + } +} + func TestStart(t *testing.T) { serverCh := server.AddCmdChan(ssntp.START) agentCh := agent.AddCmdChan(ssntp.START) diff --git a/testutil/payloads.go b/testutil/payloads.go index 070c86975..51e834e0f 100644 --- a/testutil/payloads.go +++ b/testutil/payloads.go @@ -36,6 +36,9 @@ const InstancePrivateIP = "192.168.1.2" // VNICMAC is a test instance VNIC MAC address const VNICMAC = "aa:bb:cc:01:02:03" +// VNICUUID is a test instance VNIC UUID +const VNICUUID = "7f49d00d-1995-4156-8c79-5f5ab24ce138" + // TenantUUID is a test tenant UUID const TenantUUID = "2491851d-dce9-48d6-b83a-a717417072ce" @@ -90,6 +93,9 @@ const ImageUUID = "59460b8a-5f53-4e3e-b5ce-b71fed8c7e64" // InstanceUUID is an instance UUID for use in start/stop/restart/delete tests const InstanceUUID = "3390740c-dce9-48d6-b83a-a717417072ce" +// CNCIInstanceUUID is a CNCI instance UUID for use in start/stop/restart/delete tests +const CNCIInstanceUUID = "c6beb8b5-0bfc-43fd-9638-7dd788179fd8" + // NetAgentUUID is a network node UUID for coordinated tests const NetAgentUUID = "6be56328-92e2-4ecd-b426-8fe529c04e0c" @@ -138,7 +144,7 @@ const StartYaml = `start: // CNCIStartYaml is a sample CNCI workload START ssntp.Command payload for test cases const CNCIStartYaml = `start: - instance_uuid: ` + CNCIUUID + ` + instance_uuid: ` + CNCIInstanceUUID + ` image_uuid: ` + ImageUUID + ` fw_type: efi persistence: host @@ -153,6 +159,16 @@ const CNCIStartYaml = `start: - type: network_node value: 1 mandatory: true + networking: + vnic_mac: ` + VNICMAC + ` + vnic_uuid: ` + VNICUUID + ` + concentrator_uuid: ` + CNCIUUID + ` + concentrator_ip: ` + CNCIIP + ` + subnet: ` + TenantSubnet + ` + subnet_key: ` + SubnetKey + ` + subnet_uuid: "" + private_ip: "" + public_ip: false ` // PartialStartYaml is a sample minimal workload START ssntp.Command payload for test cases diff --git a/testutil/server.go b/testutil/server.go index fbd5eb230..d55ef7516 100644 --- a/testutil/server.go +++ b/testutil/server.go @@ -365,7 +365,7 @@ func (server *SsntpTestServer) EventNotify(uuid string, event ssntp.Event, frame case ssntp.TenantRemoved: // forwards to CNCI via server.EventForward() case ssntp.PublicIPAssigned: - // forwards to CNCI via server.EventForward() + // forwards from CNCI Controller(s) via server.EventForward() default: fmt.Printf("server unhandled event %s\n", event.String()) } From f6353e3c87a2353c668125984c6478b78ddc7f73 Mon Sep 17 00:00:00 2001 From: Tim Pepper Date: Tue, 28 Jun 2016 17:52:38 -0700 Subject: [PATCH 08/19] ciao-scheduler: ssntp.ConcentratorInstanceAddedEvent event test flows As in testutil, add ssntp.ConcentratorInstanceAddedEvent event test flows to the ciao-scheduler ssntp test cases. The test controller triggers a workload start for the cnci on a network node. Signed-off-by: Tim Pepper --- ciao-scheduler/scheduler_ssntp_test.go | 27 ++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/ciao-scheduler/scheduler_ssntp_test.go b/ciao-scheduler/scheduler_ssntp_test.go index 59c00ad66..58321e2b4 100644 --- a/ciao-scheduler/scheduler_ssntp_test.go +++ b/ciao-scheduler/scheduler_ssntp_test.go @@ -37,6 +37,7 @@ var server *ssntpSchedulerServer var controller *testutil.SsntpTestController var agent *testutil.SsntpTestClient var netAgent *testutil.SsntpTestClient +var cnciAgent *testutil.SsntpTestClient // these status sends need to come early so the agents are marked online // for later ssntp.START's @@ -95,6 +96,32 @@ func TestSendNetAgentStatus(t *testing.T) { server.nnMutex.Unlock() } +func TestCNCIStart(t *testing.T) { + netAgentCh := netAgent.AddCmdChan(ssntp.START) + + go controller.Ssntp.SendCommand(ssntp.START, []byte(testutil.CNCIStartYaml)) + + _, err := netAgent.GetCmdChanResult(netAgentCh, ssntp.START) + if err != nil { + t.Fatal(err) + } + + // start CNCI agent + cnciAgent, err = testutil.NewSsntpTestClientConnection("CNCI Client", ssntp.CNCIAGENT, testutil.CNCIUUID) + if err != nil { + t.Fatal(err) + } + + controllerCh := controller.AddEventChan(ssntp.ConcentratorInstanceAdded) + + cnciAgent.SendConcentratorAddedEvent(testutil.CNCIInstanceUUID, testutil.TenantUUID, testutil.CNCIIP, testutil.CNCIMAC) + + _, err = controller.GetEventChanResult(controllerCh, ssntp.ConcentratorInstanceAdded) + if err != nil { + t.Fatal(err) + } +} + func TestStart(t *testing.T) { agentCh := agent.AddCmdChan(ssntp.START) From 82adc232d41ec0c81872956bac180f38ab0128e1 Mon Sep 17 00:00:00 2001 From: Tim Pepper Date: Fri, 8 Jul 2016 17:23:23 -0700 Subject: [PATCH 09/19] testutil: ssntp.TenantAdded event flows Add testutil ssntp.TenantAdded event flows test coverage. Signed-off-by: Tim Pepper --- testutil/agent.go | 27 +++++++++++++++++++++++++++ testutil/client_server_test.go | 16 ++++++++++++++++ testutil/controller.go | 1 + testutil/server.go | 4 ++++ 4 files changed, 48 insertions(+) diff --git a/testutil/agent.go b/testutil/agent.go index 45091f338..c237d0247 100644 --- a/testutil/agent.go +++ b/testutil/agent.go @@ -434,6 +434,21 @@ func (client *SsntpTestClient) CommandNotify(command ssntp.Command, frame *ssntp // EventNotify is an SSNTP callback stub for SsntpTestClient func (client *SsntpTestClient) EventNotify(event ssntp.Event, frame *ssntp.Frame) { + var result Result + + switch event { + case ssntp.TenantAdded: + var tenantAddedEvent payloads.EventTenantAdded + + err := yaml.Unmarshal(frame.Payload, &tenantAddedEvent) + if err != nil { + result.Err = err + } + default: + fmt.Printf("client unhandled event: %s\n", event.String()) + } + + client.SendResultAndDelEventChan(event, result) } // ErrorNotify is an SSNTP callback stub for SsntpTestClient @@ -536,6 +551,18 @@ func (client *SsntpTestClient) SendDeleteEvent(uuid string) { client.SendResultAndDelEventChan(ssntp.InstanceDeleted, result) } +// SendTenantAddedEvent allows an SsntpTestClient to push an ssntp.TenantAdded event frame +func (client *SsntpTestClient) SendTenantAddedEvent() { + var result Result + + _, err := client.Ssntp.SendEvent(ssntp.TenantAdded, []byte(TenantAddedYaml)) + if err != nil { + result.Err = err + } + + client.SendResultAndDelEventChan(ssntp.TenantAdded, result) +} + // SendConcentratorAddedEvent allows an SsntpTestClient to push an ssntp.ConcentratorInstanceAdded event frame func (client *SsntpTestClient) SendConcentratorAddedEvent(instanceUUID string, tenantUUID string, ip string, vnicMAC string) { var result Result diff --git a/testutil/client_server_test.go b/testutil/client_server_test.go index bb7e81613..56ff27684 100644 --- a/testutil/client_server_test.go +++ b/testutil/client_server_test.go @@ -429,6 +429,22 @@ func TestDeleteFailure(t *testing.T) { } } +func TestTenantAdded(t *testing.T) { + serverCh := server.AddEventChan(ssntp.TenantAdded) + cnciAgentCh := cnciAgent.AddEventChan(ssntp.TenantAdded) + + go agent.SendTenantAddedEvent() + + _, err := server.GetEventChanResult(serverCh, ssntp.TenantAdded) + if err != nil { + t.Fatal(err) + } + _, err = cnciAgent.GetEventChanResult(cnciAgentCh, ssntp.TenantAdded) + if err != nil { + t.Fatal(err) + } +} + func stopServer() error { controllerCh := controller.AddEventChan(ssntp.NodeDisconnected) netAgentCh := netAgent.AddEventChan(ssntp.NodeDisconnected) diff --git a/testutil/controller.go b/testutil/controller.go index 1f1263a5a..d1692f093 100644 --- a/testutil/controller.go +++ b/testutil/controller.go @@ -241,6 +241,7 @@ func (ctl *SsntpTestController) EventNotify(event ssntp.Event, frame *ssntp.Fram switch event { // case ssntp.NodeConnected: handled by ConnectNotify() // case ssntp.NodeDisconnected: handled by DisconnectNotify() + // case ssntp.TenantAdded: does not reach controller case ssntp.InstanceDeleted: var deleteEvent payloads.EventInstanceDeleted diff --git a/testutil/server.go b/testutil/server.go index d55ef7516..decdb4a18 100644 --- a/testutil/server.go +++ b/testutil/server.go @@ -408,6 +408,7 @@ func fwdEventToCNCI(event ssntp.Event, payload []byte) (ssntp.ForwardDestination func (server *SsntpTestServer) EventForward(uuid string, event ssntp.Event, frame *ssntp.Frame) ssntp.ForwardDestination { var err error var dest ssntp.ForwardDestination + var result Result switch event { case ssntp.TenantAdded: @@ -420,8 +421,11 @@ func (server *SsntpTestServer) EventForward(uuid string, event ssntp.Event, fram if err != nil { fmt.Println("server error parsing event yaml for forwarding") + result.Err = err } + server.SendResultAndDelEventChan(event, result) + return dest } From b1af461110ab95b25e38b8e961501d0a722e8100 Mon Sep 17 00:00:00 2001 From: Tim Pepper Date: Fri, 8 Jul 2016 17:36:27 -0700 Subject: [PATCH 10/19] testutil: restart should await any existing test clients There's likely a cnci agent running, and if so the server restart should await its checkin. Same in the ciao-scheduler ssntp test. This was missing. But it highlights the basic need to restart any of the global test clients if they exist at the time of the server restart. Signed-off-by: Tim Pepper --- ciao-scheduler/scheduler_ssntp_test.go | 31 +++++++++++++++++------- testutil/client_server_test.go | 33 ++++++++++++++++++-------- 2 files changed, 45 insertions(+), 19 deletions(-) diff --git a/ciao-scheduler/scheduler_ssntp_test.go b/ciao-scheduler/scheduler_ssntp_test.go index 58321e2b4..1ddfca74d 100644 --- a/ciao-scheduler/scheduler_ssntp_test.go +++ b/ciao-scheduler/scheduler_ssntp_test.go @@ -404,6 +404,7 @@ func restartServer() error { controllerCh := controller.AddEventChan(ssntp.NodeConnected) netAgentCh := netAgent.AddEventChan(ssntp.NodeConnected) agentCh := agent.AddEventChan(ssntp.NodeConnected) + cnciAgentCh := cnciAgent.AddEventChan(ssntp.NodeConnected) server = configSchedulerServer() if server == nil { @@ -412,17 +413,29 @@ func restartServer() error { go server.ssntp.Serve(server.config, server) //go heartBeatLoop(server) ...handy for debugging - _, err := controller.GetEventChanResult(controllerCh, ssntp.NodeConnected) - if err != nil { - return err + if controller != nil { + _, err := controller.GetEventChanResult(controllerCh, ssntp.NodeConnected) + if err != nil { + return err + } } - _, err = netAgent.GetEventChanResult(netAgentCh, ssntp.NodeConnected) - if err != nil { - return err + if netAgent != nil { + _, err := netAgent.GetEventChanResult(netAgentCh, ssntp.NodeConnected) + if err != nil { + return err + } } - _, err = agent.GetEventChanResult(agentCh, ssntp.NodeConnected) - if err != nil { - return err + if agent != nil { + _, err := agent.GetEventChanResult(agentCh, ssntp.NodeConnected) + if err != nil { + return err + } + } + if cnciAgent != nil { + _, err := cnciAgent.GetEventChanResult(cnciAgentCh, ssntp.NodeConnected) + if err != nil { + return err + } } return nil } diff --git a/testutil/client_server_test.go b/testutil/client_server_test.go index 56ff27684..31d903e7e 100644 --- a/testutil/client_server_test.go +++ b/testutil/client_server_test.go @@ -471,25 +471,38 @@ func restartServer() error { controllerCh := controller.AddEventChan(ssntp.NodeConnected) netAgentCh := netAgent.AddEventChan(ssntp.NodeConnected) agentCh := agent.AddEventChan(ssntp.NodeConnected) + cnciAgentCh := cnciAgent.AddEventChan(ssntp.NodeConnected) StartTestServer(&server) //MUST be after StartTestServer becase the channels are initialized on start serverCh := server.AddEventChan(ssntp.NodeConnected) - _, err := controller.GetEventChanResult(controllerCh, ssntp.NodeConnected) - if err != nil { - return err + if controller != nil { + _, err := controller.GetEventChanResult(controllerCh, ssntp.NodeConnected) + if err != nil { + return err + } } - _, err = netAgent.GetEventChanResult(netAgentCh, ssntp.NodeConnected) - if err != nil { - return err + if netAgent != nil { + _, err := netAgent.GetEventChanResult(netAgentCh, ssntp.NodeConnected) + if err != nil { + return err + } } - _, err = agent.GetEventChanResult(agentCh, ssntp.NodeConnected) - if err != nil { - return err + if agent != nil { + _, err := agent.GetEventChanResult(agentCh, ssntp.NodeConnected) + if err != nil { + return err + } + } + if cnciAgent != nil { + _, err := cnciAgent.GetEventChanResult(cnciAgentCh, ssntp.NodeConnected) + if err != nil { + return err + } } - _, err = server.GetEventChanResult(serverCh, ssntp.NodeConnected) + _, err := server.GetEventChanResult(serverCh, ssntp.NodeConnected) if err != nil { return err } From 6ae4054c700d6d0eb67e41ad0b17091b5529e824 Mon Sep 17 00:00:00 2001 From: Tim Pepper Date: Fri, 8 Jul 2016 17:49:32 -0700 Subject: [PATCH 11/19] testutil: ssntp.TenantRemoved event flows Add testutil ssntp.TenantRemoved event flows test coverage. Signed-off-by: Tim Pepper --- testutil/agent.go | 18 ++++++++++++++++++ testutil/client_server_test.go | 15 +++++++++++++++ testutil/controller.go | 1 + 3 files changed, 34 insertions(+) diff --git a/testutil/agent.go b/testutil/agent.go index c237d0247..a25ae158b 100644 --- a/testutil/agent.go +++ b/testutil/agent.go @@ -444,6 +444,13 @@ func (client *SsntpTestClient) EventNotify(event ssntp.Event, frame *ssntp.Frame if err != nil { result.Err = err } + case ssntp.TenantRemoved: + var tenantRemovedEvent payloads.EventTenantRemoved + + err := yaml.Unmarshal(frame.Payload, &tenantRemovedEvent) + if err != nil { + result.Err = err + } default: fmt.Printf("client unhandled event: %s\n", event.String()) } @@ -563,6 +570,17 @@ func (client *SsntpTestClient) SendTenantAddedEvent() { client.SendResultAndDelEventChan(ssntp.TenantAdded, result) } +// SendTenantRemovedEvent allows an SsntpTestClient to push an ssntp.TenantRemoved event frame +func (client *SsntpTestClient) SendTenantRemovedEvent() { + var result Result + + _, err := client.Ssntp.SendEvent(ssntp.TenantRemoved, []byte(TenantRemovedYaml)) + if err != nil { + result.Err = err + } + + client.SendResultAndDelEventChan(ssntp.TenantRemoved, result) +} // SendConcentratorAddedEvent allows an SsntpTestClient to push an ssntp.ConcentratorInstanceAdded event frame func (client *SsntpTestClient) SendConcentratorAddedEvent(instanceUUID string, tenantUUID string, ip string, vnicMAC string) { var result Result diff --git a/testutil/client_server_test.go b/testutil/client_server_test.go index 31d903e7e..a01029dba 100644 --- a/testutil/client_server_test.go +++ b/testutil/client_server_test.go @@ -523,6 +523,21 @@ func TestReconnects(t *testing.T) { } } +func TestTenantRemoved(t *testing.T) { + serverCh := server.AddEventChan(ssntp.TenantRemoved) + cnciAgentCh := cnciAgent.AddEventChan(ssntp.TenantRemoved) + + go agent.SendTenantRemovedEvent() + + _, err := server.GetEventChanResult(serverCh, ssntp.TenantRemoved) + if err != nil { + t.Fatal(err) + } + _, err = cnciAgent.GetEventChanResult(cnciAgentCh, ssntp.TenantRemoved) + if err != nil { + t.Fatal(err) + } +} func TestMain(m *testing.M) { var err error diff --git a/testutil/controller.go b/testutil/controller.go index d1692f093..79e39c8a6 100644 --- a/testutil/controller.go +++ b/testutil/controller.go @@ -242,6 +242,7 @@ func (ctl *SsntpTestController) EventNotify(event ssntp.Event, frame *ssntp.Fram // case ssntp.NodeConnected: handled by ConnectNotify() // case ssntp.NodeDisconnected: handled by DisconnectNotify() // case ssntp.TenantAdded: does not reach controller + // case ssntp.TenantRemoved: does not reach controller case ssntp.InstanceDeleted: var deleteEvent payloads.EventInstanceDeleted From cf8874542e24ef1a4aa2408484926f12f0b17d07 Mon Sep 17 00:00:00 2001 From: Tim Pepper Date: Fri, 8 Jul 2016 17:52:19 -0700 Subject: [PATCH 12/19] testutil: ssntp.PublicIPAssigned event flows Add testutil ssntp.PublicIPAssigned event flows coverage and correct the event forwarding. The public IP assignment event flows from a CNCI to all controllers. Signed-off-by: Tim Pepper --- testutil/agent.go | 13 +++++++++++++ testutil/client_server_test.go | 17 +++++++++++++++++ testutil/controller.go | 7 +++++++ testutil/server.go | 14 ++++---------- 4 files changed, 41 insertions(+), 10 deletions(-) diff --git a/testutil/agent.go b/testutil/agent.go index a25ae158b..24675f00d 100644 --- a/testutil/agent.go +++ b/testutil/agent.go @@ -581,6 +581,19 @@ func (client *SsntpTestClient) SendTenantRemovedEvent() { client.SendResultAndDelEventChan(ssntp.TenantRemoved, result) } + +// SendPublicIPAssignedEvent allows an SsntpTestClient to push an ssntp.PublicIPAssigned event frame +func (client *SsntpTestClient) SendPublicIPAssignedEvent() { + var result Result + + _, err := client.Ssntp.SendEvent(ssntp.PublicIPAssigned, []byte(AssignedIPYaml)) + if err != nil { + result.Err = err + } + + client.SendResultAndDelEventChan(ssntp.PublicIPAssigned, result) +} + // SendConcentratorAddedEvent allows an SsntpTestClient to push an ssntp.ConcentratorInstanceAdded event frame func (client *SsntpTestClient) SendConcentratorAddedEvent(instanceUUID string, tenantUUID string, ip string, vnicMAC string) { var result Result diff --git a/testutil/client_server_test.go b/testutil/client_server_test.go index a01029dba..d02f6fcff 100644 --- a/testutil/client_server_test.go +++ b/testutil/client_server_test.go @@ -538,6 +538,23 @@ func TestTenantRemoved(t *testing.T) { t.Fatal(err) } } + +func TestPublicIPAssigned(t *testing.T) { + serverCh := server.AddEventChan(ssntp.PublicIPAssigned) + controllerCh := controller.AddEventChan(ssntp.PublicIPAssigned) + + go cnciAgent.SendPublicIPAssignedEvent() + + _, err := server.GetEventChanResult(serverCh, ssntp.PublicIPAssigned) + if err != nil { + t.Fatal(err) + } + _, err = controller.GetEventChanResult(controllerCh, ssntp.PublicIPAssigned) + if err != nil { + t.Fatal(err) + } +} + func TestMain(m *testing.M) { var err error diff --git a/testutil/controller.go b/testutil/controller.go index 79e39c8a6..922f23b8b 100644 --- a/testutil/controller.go +++ b/testutil/controller.go @@ -243,6 +243,13 @@ func (ctl *SsntpTestController) EventNotify(event ssntp.Event, frame *ssntp.Fram // case ssntp.NodeDisconnected: handled by DisconnectNotify() // case ssntp.TenantAdded: does not reach controller // case ssntp.TenantRemoved: does not reach controller + case ssntp.PublicIPAssigned: + var publicIPAssignedEvent payloads.EventPublicIPAssigned + + err := yaml.Unmarshal(frame.Payload, &publicIPAssignedEvent) + if err != nil { + result.Err = err + } case ssntp.InstanceDeleted: var deleteEvent payloads.EventInstanceDeleted diff --git a/testutil/server.go b/testutil/server.go index decdb4a18..d4d6c8e99 100644 --- a/testutil/server.go +++ b/testutil/server.go @@ -385,10 +385,6 @@ func getConcentratorUUID(event ssntp.Event, payload []byte) (string, error) { var ev payloads.EventTenantRemoved err := yaml.Unmarshal(payload, &ev) return ev.TenantRemoved.ConcentratorUUID, err - case ssntp.PublicIPAssigned: - var ev payloads.EventPublicIPAssigned - err := yaml.Unmarshal(payload, &ev) - return ev.AssignedIP.ConcentratorUUID, err } } @@ -414,8 +410,6 @@ func (server *SsntpTestServer) EventForward(uuid string, event ssntp.Event, fram case ssntp.TenantAdded: fallthrough case ssntp.TenantRemoved: - fallthrough - case ssntp.PublicIPAssigned: dest, err = fwdEventToCNCI(event, frame.Payload) } @@ -582,6 +576,10 @@ func StartTestServer(server *SsntpTestServer) { Operand: ssntp.DeleteFailure, Dest: ssntp.Controller, }, + { // all PublicIPAssigned events go to all Controllers + Operand: ssntp.PublicIPAssigned, + Dest: ssntp.Controller, + }, { // all START command are processed by the Command forwarder Operand: ssntp.START, CommandForward: server, @@ -610,10 +608,6 @@ func StartTestServer(server *SsntpTestServer) { Operand: ssntp.TenantRemoved, EventForward: server, }, - { // all PublicIPAssigned events are processed by the Event forwarder - Operand: ssntp.PublicIPAssigned, - EventForward: server, - }, }, } From 3af4324d0324750b9bf9aa1a7710eee175c9e527 Mon Sep 17 00:00:00 2001 From: Tim Pepper Date: Fri, 8 Jul 2016 17:53:49 -0700 Subject: [PATCH 13/19] ciao-scheduler: add TenantAdded, TenantRemoved, PublicIPAssigned tests Utilizing the changes as made in testutil, this patch extends the ssntp test coverage of ciao-scheduler to include TenantAdded, TenantRemoved, and PublicIPAssigned event flows. Signed-off-by: Tim Pepper --- ciao-scheduler/scheduler_ssntp_test.go | 33 ++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/ciao-scheduler/scheduler_ssntp_test.go b/ciao-scheduler/scheduler_ssntp_test.go index 1ddfca74d..7a708a8f7 100644 --- a/ciao-scheduler/scheduler_ssntp_test.go +++ b/ciao-scheduler/scheduler_ssntp_test.go @@ -454,6 +454,39 @@ func TestReconnects(t *testing.T) { } } +func TestTenantAdded(t *testing.T) { + cnciAgentCh := cnciAgent.AddEventChan(ssntp.TenantAdded) + + go agent.SendTenantAddedEvent() + + _, err := cnciAgent.GetEventChanResult(cnciAgentCh, ssntp.TenantAdded) + if err != nil { + t.Fatal(err) + } +} + +func TestTenantRemoved(t *testing.T) { + cnciAgentCh := cnciAgent.AddEventChan(ssntp.TenantRemoved) + + go agent.SendTenantRemovedEvent() + + _, err := cnciAgent.GetEventChanResult(cnciAgentCh, ssntp.TenantRemoved) + if err != nil { + t.Fatal(err) + } +} + +func TestPublicIPAssigned(t *testing.T) { + controllerCh := controller.AddEventChan(ssntp.PublicIPAssigned) + + go cnciAgent.SendPublicIPAssignedEvent() + + _, err := controller.GetEventChanResult(controllerCh, ssntp.PublicIPAssigned) + if err != nil { + t.Fatal(err) + } +} + func waitForController(uuid string) { for { server.controllerMutex.Lock() From fcc86457c2bc0142f0f6ba39c7b4e61932a70395 Mon Sep 17 00:00:00 2001 From: Tim Pepper Date: Tue, 28 Jun 2016 18:02:20 -0700 Subject: [PATCH 14/19] ciao-scheduler: bugfixes for ssntp.PublicIPAssigned event forwarding The ssntp.PublicIPAssigned events must flow from a CNCI to all controllers. The code was trying to enable a flow from controller to CNCI (which is more in the direction of what "assign public ip" would do). Signed-off-by: Tim Pepper --- ciao-scheduler/scheduler.go | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/ciao-scheduler/scheduler.go b/ciao-scheduler/scheduler.go index de8637f8d..7627d0202 100644 --- a/ciao-scheduler/scheduler.go +++ b/ciao-scheduler/scheduler.go @@ -480,10 +480,6 @@ func (sched *ssntpSchedulerServer) getConcentratorUUID(event ssntp.Event, payloa var ev payloads.EventTenantRemoved err := yaml.Unmarshal(payload, &ev) return ev.TenantRemoved.ConcentratorUUID, err - case ssntp.PublicIPAssigned: - var ev payloads.EventPublicIPAssigned - err := yaml.Unmarshal(payload, &ev) - return ev.AssignedIP.ConcentratorUUID, err } } @@ -723,8 +719,6 @@ func (sched *ssntpSchedulerServer) EventForward(uuid string, event ssntp.Event, case ssntp.TenantAdded: fallthrough case ssntp.TenantRemoved: - fallthrough - case ssntp.PublicIPAssigned: dest = sched.fwdEventToCNCI(event, payload) } @@ -958,6 +952,10 @@ func setSSNTPForwardRules(sched *ssntpSchedulerServer) { Operand: ssntp.DeleteFailure, Dest: ssntp.Controller, }, + { // all PublicIPAssigned events go to all Controllers + Operand: ssntp.PublicIPAssigned, + Dest: ssntp.Controller, + }, { // all START command are processed by the Command forwarder Operand: ssntp.START, CommandForward: sched, @@ -986,10 +984,6 @@ func setSSNTPForwardRules(sched *ssntpSchedulerServer) { Operand: ssntp.TenantRemoved, EventForward: sched, }, - { // all PublicIPAssigned events are processed by the Event forwarder - Operand: ssntp.PublicIPAssigned, - EventForward: sched, - }, } } From bc2729751906c05024ad15b32fcb3c8272bc651d Mon Sep 17 00:00:00 2001 From: Tim Pepper Date: Fri, 8 Jul 2016 17:56:54 -0700 Subject: [PATCH 15/19] testutil: more verbose client message for unhandled ssntp flows It's useful in debugging to when a client missed an event or command to see if it was the basic agent or the net agent or the cnci agent which encountered something unexpected. We know the role of the client and can String() output it for clarity. Signed-off-by: Tim Pepper --- testutil/agent.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testutil/agent.go b/testutil/agent.go index 24675f00d..7425bccbe 100644 --- a/testutil/agent.go +++ b/testutil/agent.go @@ -426,7 +426,7 @@ func (client *SsntpTestClient) CommandNotify(command ssntp.Command, frame *ssntp result = client.handleDelete(payload) default: - fmt.Printf("client unhandled command %s\n", command.String()) + fmt.Printf("client %s unhandled command %s\n", client.Role.String(), command.String()) } client.SendResultAndDelCmdChan(command, result) @@ -452,7 +452,7 @@ func (client *SsntpTestClient) EventNotify(event ssntp.Event, frame *ssntp.Frame result.Err = err } default: - fmt.Printf("client unhandled event: %s\n", event.String()) + fmt.Printf("client %s unhandled event: %s\n", client.Role.String(), event.String()) } client.SendResultAndDelEventChan(event, result) From e69f9a348adc22ff2901751263784ffd463b8235 Mon Sep 17 00:00:00 2001 From: Tim Pepper Date: Mon, 11 Jul 2016 15:35:25 -0700 Subject: [PATCH 16/19] testutil: comment need to call Close() on server An entity using the testutil identity server needs, after calling StartIdentityServer(), to clean up with a Close() on the httptest.Server returned originally by the server start call. Signed-off-by: Tim Pepper --- testutil/identity.go | 1 + 1 file changed, 1 insertion(+) diff --git a/testutil/identity.go b/testutil/identity.go index 2d1003650..4b68970f7 100644 --- a/testutil/identity.go +++ b/testutil/identity.go @@ -267,6 +267,7 @@ type IdentityConfig struct { } // StartIdentityServer starts a fake keystone service for unit testing ciao. +// Caller must call Close() on the returned *httptest.Server. func StartIdentityServer(config IdentityConfig) *httptest.Server { id := httptest.NewServer(IdentityHandlers()) if id == nil { From ceb9c4a0b4a845ec3594cc78f194b1ef924d9fbd Mon Sep 17 00:00:00 2001 From: Tim Pepper Date: Mon, 11 Jul 2016 16:18:18 -0700 Subject: [PATCH 17/19] ssntp: add stringer tests The test coverage of these stringer functions was about 50% as they happen to be called in some places by some tests. Easy to make it 100% and then if somebody changes the strings it highlights that output may be parsed by things which would break as the result of such changes. Signed-off-by: Tim Pepper --- ssntp/ssntp_test.go | 96 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 2 deletions(-) diff --git a/ssntp/ssntp_test.go b/ssntp/ssntp_test.go index da3fcad3b..d7905c9dc 100644 --- a/ssntp/ssntp_test.go +++ b/ssntp/ssntp_test.go @@ -21,14 +21,15 @@ import ( "encoding/asn1" "flag" "fmt" - . "github.com/01org/ciao/ssntp" - "github.com/01org/ciao/testutil" "io/ioutil" "os" "path" "sync" "testing" "time" + + . "github.com/01org/ciao/ssntp" + "github.com/01org/ciao/testutil" ) const tempCertPath = "/tmp/ssntp-test-certs" @@ -2465,6 +2466,97 @@ var ( payloadSize = flag.Int("payload", 1<<11, "Frames payload size") ) +func TestCommandStringer(t *testing.T) { + var stringTests = []struct { + cmd Command + expected string + }{ + {CONNECT, "CONNECT"}, + {START, "START"}, + {STOP, "STOP"}, + {STATS, "STATISTICS"}, + {EVACUATE, "EVACUATE"}, + {DELETE, "DELETE"}, + {RESTART, "RESTART"}, + {AssignPublicIP, "Assign public IP"}, + {ReleasePublicIP, "Release public IP"}, + {CONFIGURE, "CONFIGURE"}, + } + + for _, test := range stringTests { + str := test.cmd.String() + if str != test.expected { + t.Errorf("expected \"%s\", got \"%s\"", test.expected, str) + } + } +} + +func TestStatusStringer(t *testing.T) { + var stringTests = []struct { + sta Status + expected string + }{ + {CONNECTED, "CONNECTED"}, + {READY, "READY"}, + {FULL, "FULL"}, + {OFFLINE, "OFFLINE"}, + {MAINTENANCE, "MAINTENANCE"}, + } + + for _, test := range stringTests { + str := test.sta.String() + if str != test.expected { + t.Errorf("expected \"%s\", got \"%s\"", test.expected, str) + } + } +} + +func TestEventStringer(t *testing.T) { + var stringTests = []struct { + evt Event + expected string + }{ + {TenantAdded, "Tenant Added"}, + {TenantRemoved, "Tenant Removed"}, + {InstanceDeleted, "Instance Deleted"}, + {ConcentratorInstanceAdded, "Network Concentrator Instance Added"}, + {PublicIPAssigned, "Public IP Assigned"}, + {TraceReport, "Trace Report"}, + {NodeConnected, "Node Connected"}, + {NodeDisconnected, "Node Disconnected"}, + } + + for _, test := range stringTests { + str := test.evt.String() + if str != test.expected { + t.Errorf("expected \"%s\", got \"%s\"", test.expected, str) + } + } +} + +func TestErrorStringer(t *testing.T) { + var stringTests = []struct { + err Error + expected string + }{ + {InvalidFrameType, "Invalid SSNTP frame type"}, + {StartFailure, "Could not start instance"}, + {StopFailure, "Could not stop instance"}, + {ConnectionFailure, "SSNTP Connection failed"}, + {RestartFailure, "Could not restart instance"}, + {DeleteFailure, "Could not delete instance"}, + {ConnectionAborted, "SSNTP Connection aborted"}, + {InvalidConfiguration, "Cluster configuration is invalid"}, + } + + for _, test := range stringTests { + str := test.err.String() + if str != test.expected { + t.Errorf("expected \"%s\", got \"%s\"", test.expected, str) + } + } +} + func TestMain(m *testing.M) { flag.Parse() From 5ecc80dbc78e2e58ab886b2ec9310e2d1a8f6be1 Mon Sep 17 00:00:00 2001 From: Tim Pepper Date: Mon, 11 Jul 2016 16:37:36 -0700 Subject: [PATCH 18/19] ssntp: add unit test for RoleToDefaultCertName() This is a simple table test and intentionally duplicates the const string definitions instead of referencing them by variable name. If somebody changes the const string definition, the test will fail. That hopefully reminds the person that users actually use default values and such a change will break users, which isn't very nice. Signed-off-by: Tim Pepper --- ssntp/ssntp_test.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/ssntp/ssntp_test.go b/ssntp/ssntp_test.go index d7905c9dc..09fec9be9 100644 --- a/ssntp/ssntp_test.go +++ b/ssntp/ssntp_test.go @@ -2557,6 +2557,29 @@ func TestErrorStringer(t *testing.T) { } } +func TestRoleToDefaultCertName(t *testing.T) { + var stringTests = []struct { + r Role + expected string + }{ + {Controller, "/etc/pki/ciao/cert-Controller-localhost.pem"}, + {AGENT, "/etc/pki/ciao/cert-CNAgent-localhost.pem"}, + {CNCIAGENT, "/etc/pki/ciao/cert-CNCIAgent-localhost.pem"}, + {NETAGENT, "/etc/pki/ciao/cert-NetworkingAgent-localhost.pem"}, + {AGENT | NETAGENT, "/etc/pki/ciao/cert-CNAgent-NetworkingAgent-localhost.pem"}, + {SERVER, "/etc/pki/ciao/cert-Server-localhost.pem"}, + {SCHEDULER, "/etc/pki/ciao/cert-Scheduler-localhost.pem"}, + {UNKNOWN, ""}, + } + + for _, test := range stringTests { + certname := RoleToDefaultCertName(test.r) + if certname != test.expected { + t.Errorf("expected \"%s\", got \"%s\"", test.expected, certname) + } + } +} + func TestMain(m *testing.M) { flag.Parse() From b6d25edd3a51177656c919ff6e4b3b03b2742ce4 Mon Sep 17 00:00:00 2001 From: Tim Pepper Date: Mon, 11 Jul 2016 16:47:59 -0700 Subject: [PATCH 19/19] ssntp: add unit test of Role set function Set() The Role setting function supports three usage modes: setting a single value, setting values via successive sequential calls, or providing a comma-separated list. A table test is added for the first case, and a simple pair of calls are added to cover the two ways to set multiple roles. Signed-off-by: Tim Pepper --- ssntp/ssntp_test.go | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/ssntp/ssntp_test.go b/ssntp/ssntp_test.go index 09fec9be9..cacddeafc 100644 --- a/ssntp/ssntp_test.go +++ b/ssntp/ssntp_test.go @@ -2580,6 +2580,46 @@ func TestRoleToDefaultCertName(t *testing.T) { } } +func TestRoleSet(t *testing.T) { + var stringTests = []struct { + r string + expected Role + }{ + {"unknown", UNKNOWN}, + {"server", SERVER}, + {"controller", Controller}, + {"agent", AGENT}, + {"netagent", NETAGENT}, + {"scheduler", SCHEDULER}, + {"cnciagent", CNCIAGENT}, + } + + for _, test := range stringTests { + var role Role + role.Set(test.r) + if role != test.expected { + t.Errorf("expected \"%x\", got \"%x\"", test.expected, role) + } + } + + var role Role + err := role.Set("asdf") + if err == nil { + t.Error("expected \"Unknown role\" error, got nil") + } + + role.Set("agent") + role.Set("netagent") + if role != AGENT|NETAGENT { + t.Error("didn't correctly sequantially assign role") + } + + role.Set("agent, netagent") + if role != AGENT|NETAGENT { + t.Error("didn't correctly multi-assign role") + } +} + func TestMain(m *testing.M) { flag.Parse()