diff --git a/.travis.yml b/.travis.yml index b2385ac2e..febed0f8b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -60,9 +60,10 @@ script: - go list ./... | grep -v github.com/01org/ciao/vendor | xargs go list -f '{{.Dir}}' | xargs gofmt -s -l | wc -l | xargs -I % bash -c "test % -eq 0" - sudo mkdir -p /var/lib/ciao/instances - sudo chmod 0777 /var/lib/ciao/instances - - test-cases -v -timeout 9 -text -coverprofile /tmp/cover.out -short github.com/01org/ciao/ciao-launcher github.com/01org/ciao/ciao-scheduler github.com/01org/ciao/ciao-controller/... github.com/01org/ciao/payloads github.com/01org/ciao/configuration github.com/01org/ciao/testutil github.com/01org/ciao/ssntp/uuid - - export GOROOT=`go env GOROOT` && sudo -E PATH=$PATH:$GOROOT/bin $GOPATH/bin/test-cases -v -timeout 9 -text -coverprofile /tmp/cover.out -append-profile github.com/01org/ciao/ssntp - - export GOROOT=`go env GOROOT` && export SNNET_ENV=198.51.100.0/24 && sudo -E PATH=$PATH:$GOROOT/bin $GOPATH/bin/test-cases -v -timeout 9 -text -short -tags travis -coverprofile /tmp/cover.out -append-profile github.com/01org/ciao/networking/libsnnet + - test-cases -v -timeout 9 -text -coverprofile /tmp/cover.out -short github.com/01org/ciao/ciao-controller/... + - test-cases -v -timeout 9 -text -coverprofile /tmp/cover.out -append-profile -short -race github.com/01org/ciao/ciao-launcher github.com/01org/ciao/ciao-scheduler github.com/01org/ciao/payloads github.com/01org/ciao/configuration github.com/01org/ciao/testutil github.com/01org/ciao/ssntp/uuid + - export GOROOT=`go env GOROOT` && sudo -E PATH=$PATH:$GOROOT/bin $GOPATH/bin/test-cases -v -timeout 9 -text -coverprofile /tmp/cover.out -append-profile -race github.com/01org/ciao/ssntp + - export GOROOT=`go env GOROOT` && export SNNET_ENV=198.51.100.0/24 && sudo -E PATH=$PATH:$GOROOT/bin $GOPATH/bin/test-cases -v -timeout 9 -text -short -tags travis -coverprofile /tmp/cover.out -append-profile -race github.com/01org/ciao/networking/libsnnet after_success: - $GOPATH/bin/goveralls -service=travis-ci -coverprofile=/tmp/cover.out diff --git a/ciao-controller/compute_test.go b/ciao-controller/compute_test.go index 8d3328dac..58cd4cda3 100644 --- a/ciao-controller/compute_test.go +++ b/ciao-controller/compute_test.go @@ -286,7 +286,7 @@ func testDeleteServer(t *testing.T, httpExpectedStatus int, httpExpectedErrorSta if err != nil { t.Fatal(err) } - defer client.Ssntp.Close() + defer client.Shutdown() tURL := testutil.ComputeURL + "/v2.1/" + tenant.ID + "/servers/" @@ -337,7 +337,7 @@ func testServersActionStart(t *testing.T, httpExpectedStatus int, validToken boo if err != nil { t.Fatal(err) } - defer client.Ssntp.Close() + defer client.Shutdown() servers := testCreateServer(t, 1) if servers.TotalServers != 1 { @@ -397,7 +397,7 @@ func testServersActionStop(t *testing.T, httpExpectedStatus int, action string) if err != nil { t.Fatal(err) } - defer client.Ssntp.Close() + defer client.Shutdown() servers := testCreateServer(t, 1) if servers.TotalServers != 1 { @@ -446,7 +446,7 @@ func testServerActionStop(t *testing.T, httpExpectedStatus int, validToken bool) if err != nil { t.Fatal(err) } - defer client.Ssntp.Close() + defer client.Shutdown() servers := testCreateServer(t, 1) if servers.TotalServers != 1 { @@ -483,7 +483,7 @@ func TestServerActionStart(t *testing.T) { if err != nil { t.Fatal(err) } - defer client.Ssntp.Close() + defer client.Shutdown() servers := testCreateServer(t, 1) if servers.TotalServers != 1 { @@ -1124,7 +1124,7 @@ func testListTraces(t *testing.T, httpExpectedStatus int, validToken bool) { var expected payloads.CiaoTracesSummary client := testStartTracedWorkload(t) - defer client.Ssntp.Close() + defer client.Shutdown() sendTraceReportEvent(client, t) @@ -1246,7 +1246,7 @@ func TestClearEventsInvalidToken(t *testing.T) { func testTraceData(t *testing.T, httpExpectedStatus int, validToken bool) { client := testStartTracedWorkload(t) - defer client.Ssntp.Close() + defer client.Shutdown() sendTraceReportEvent(client, t) diff --git a/ciao-controller/controller_test.go b/ciao-controller/controller_test.go index d77779af3..63b9336e9 100644 --- a/ciao-controller/controller_test.go +++ b/ciao-controller/controller_test.go @@ -233,17 +233,17 @@ func TestStartWorkload(t *testing.T) { var reason payloads.StartFailureReason client, _ := testStartWorkload(t, 1, false, reason) - defer client.Ssntp.Close() + defer client.Shutdown() } func TestStartTracedWorkload(t *testing.T) { client := testStartTracedWorkload(t) - defer client.Ssntp.Close() + defer client.Shutdown() } func TestStartWorkloadLaunchCNCI(t *testing.T) { netClient, instances := testStartWorkloadLaunchCNCI(t, 1) - defer netClient.Ssntp.Close() + defer netClient.Shutdown() id := instances[0].TenantID @@ -293,7 +293,7 @@ func TestDeleteInstance(t *testing.T) { var reason payloads.StartFailureReason client, instances := testStartWorkload(t, 1, false, reason) - defer client.Ssntp.Close() + defer client.Shutdown() sendStatsCmd(client, t) @@ -319,7 +319,7 @@ func TestStopInstance(t *testing.T) { var reason payloads.StartFailureReason client, instances := testStartWorkload(t, 1, false, reason) - defer client.Ssntp.Close() + defer client.Shutdown() sendStatsCmd(client, t) @@ -345,7 +345,7 @@ func TestRestartInstance(t *testing.T) { var reason payloads.StartFailureReason client, instances := testStartWorkload(t, 1, false, reason) - defer client.Ssntp.Close() + defer client.Shutdown() time.Sleep(1 * time.Second) @@ -400,7 +400,7 @@ func TestEvacuateNode(t *testing.T) { if err != nil { t.Fatal(err) } - defer client.Ssntp.Close() + defer client.Shutdown() serverCh := server.AddCmdChan(ssntp.EVACUATE) @@ -424,7 +424,7 @@ func TestInstanceDeletedEvent(t *testing.T) { var reason payloads.StartFailureReason client, instances := testStartWorkload(t, 1, false, reason) - defer client.Ssntp.Close() + defer client.Shutdown() sendStatsCmd(client, t) @@ -467,7 +467,7 @@ func TestStartFailure(t *testing.T) { reason := payloads.FullCloud client, _ := testStartWorkload(t, 1, true, reason) - defer client.Ssntp.Close() + defer client.Shutdown() // since we had a start failure, we should confirm that the // instance is no longer pending in the database @@ -479,7 +479,7 @@ func TestStopFailure(t *testing.T) { var reason payloads.StartFailureReason client, instances := testStartWorkload(t, 1, false, reason) - defer client.Ssntp.Close() + defer client.Shutdown() client.StopFail = true client.StopFailReason = payloads.StopNoInstance @@ -527,7 +527,7 @@ func TestRestartFailure(t *testing.T) { var reason payloads.StartFailureReason client, instances := testStartWorkload(t, 1, false, reason) - defer client.Ssntp.Close() + defer client.Shutdown() client.RestartFail = true client.RestartFailReason = payloads.RestartLaunchFailure @@ -601,10 +601,10 @@ func TestNoNetwork(t *testing.T) { var reason payloads.StartFailureReason client, _ := testStartWorkload(t, 1, false, reason) - defer client.Ssntp.Close() + defer client.Shutdown() } -// NOTE: the caller is responsible for calling Ssntp.Close() on the *SsntpTestClient +// NOTE: the caller is responsible for calling Shutdown() on the *SsntpTestClient func testStartTracedWorkload(t *testing.T) *testutil.SsntpTestClient { tenant, err := addTestTenant() if err != nil { @@ -616,7 +616,7 @@ func testStartTracedWorkload(t *testing.T) *testutil.SsntpTestClient { t.Fatal(err) } // caller of TestStartTracedWorkload() owns doing the close - //defer client.Ssntp.Close() + //defer client.Shutdown() wls, err := context.ds.GetWorkloads() if err != nil { @@ -652,7 +652,7 @@ func testStartTracedWorkload(t *testing.T) *testutil.SsntpTestClient { return client } -// NOTE: the caller is responsible for calling Ssntp.Close() on the *SsntpTestClient +// NOTE: the caller is responsible for calling Shutdown() on the *SsntpTestClient func testStartWorkload(t *testing.T, num int, fail bool, reason payloads.StartFailureReason) (*testutil.SsntpTestClient, []*types.Instance) { tenant, err := addTestTenant() if err != nil { @@ -664,7 +664,7 @@ func testStartWorkload(t *testing.T, num int, fail bool, reason payloads.StartFa t.Fatal(err) } // caller of TestStartWorkload() owns doing the close - //defer client.Ssntp.Close() + //defer client.Shutdown() wls, err := context.ds.GetWorkloads() if err != nil { @@ -708,14 +708,14 @@ func testStartWorkload(t *testing.T, num int, fail bool, reason payloads.StartFa return client, instances } -// NOTE: the caller is responsible for calling Ssntp.Close() on the *SsntpTestClient +// NOTE: the caller is responsible for calling Shutdown() 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 - //defer netClient.Ssntp.Close() + //defer netClient.Shutdown() wls, err := context.ds.GetWorkloads() if err != nil { @@ -784,7 +784,7 @@ func testStartWorkloadLaunchCNCI(t *testing.T, num int) (*testutil.SsntpTestClie } // shutdown the test CNCI client - cnciClient.Ssntp.Close() + cnciClient.Shutdown() if result.InstanceUUID != tenantCNCI[0].InstanceID { t.Fatalf("Did not get correct Instance ID, got %s, expected %s", result.InstanceUUID, tenantCNCI[0].InstanceID) @@ -800,13 +800,13 @@ func testStartWorkloadLaunchCNCI(t *testing.T, num int) (*testutil.SsntpTestClie var testClients []*testutil.SsntpTestClient var context *controller -var server testutil.SsntpTestServer +var server *testutil.SsntpTestServer func TestMain(m *testing.M) { flag.Parse() // create fake ssntp server - testutil.StartTestServer(&server) + server = testutil.StartTestServer() context = new(controller) context.ds = new(datastore.Datastore) @@ -863,7 +863,7 @@ func TestMain(m *testing.M) { context.client.Disconnect() context.ds.Exit() id.Close() - server.Ssntp.Stop() + server.Shutdown() os.Remove("./ciao-controller-test.db") os.Remove("./ciao-controller-test.db-shm") diff --git a/test-cases/test-cases.go b/test-cases/test-cases.go index 9f610d200..14cd8e03d 100644 --- a/test-cases/test-cases.go +++ b/test-cases/test-cases.go @@ -141,6 +141,7 @@ var coverageRegexp *regexp.Regexp var cssPath string var textOutput bool var short bool +var race bool var tags string var colour bool var coverProfile string @@ -153,6 +154,7 @@ func init() { flag.StringVar(&cssPath, "css", "", "Full path to CSS file") flag.BoolVar(&textOutput, "text", false, "Output text instead of HTML") flag.BoolVar(&short, "short", false, "If true -short is passed to go test") + flag.BoolVar(&race, "race", false, "If true -race is passed to go test") flag.StringVar(&tags, "tags", "", "Build tags to pass to go test") flag.StringVar(&coverProfile, "coverprofile", "", "Path of coverage profile to be generated") flag.BoolVar(&appendProfile, "append-profile", false, "Append generated coverage profiles an existing file") @@ -382,6 +384,9 @@ func runPackageTests(p *PackageTests, coverFile string, errorOutput *bytes.Buffe if short { args = append(args, "-short") } + if race { + args = append(args, "-race") + } if tags != "" { args = append(args, "-tags", tags) } diff --git a/testutil/agent.go b/testutil/agent.go index 7425bccbe..908568823 100644 --- a/testutil/agent.go +++ b/testutil/agent.go @@ -57,6 +57,12 @@ type SsntpTestClient struct { StatusChansLock *sync.Mutex } +// Shutdown shuts down the testutil.SsntpTestClient and cleans up state +func (client *SsntpTestClient) Shutdown() { + client.Ssntp.Close() + closeClientChans(client) +} + // NewSsntpTestClientConnection creates an SsntpTestClient and dials the server. // Calling with a unique name parameter string for inclusion in the SsntpTestClient.Name // field aides in debugging. The role parameter is mandatory. The uuid string @@ -74,14 +80,11 @@ func NewSsntpTestClientConnection(name string, role ssntp.Role, uuid string) (*S client.UUID = uuid client.Role = role client.StartFail = false - client.CmdChans = make(map[ssntp.Command]chan Result) client.CmdChansLock = &sync.Mutex{} - client.EventChans = make(map[ssntp.Event]chan Result) client.EventChansLock = &sync.Mutex{} - client.ErrorChans = make(map[ssntp.Error]chan Result) client.ErrorChansLock = &sync.Mutex{} - client.StatusChans = make(map[ssntp.Status]chan Result) client.StatusChansLock = &sync.Mutex{} + openClientChans(client) client.instancesLock = &sync.Mutex{} client.tracesLock = &sync.Mutex{} @@ -126,13 +129,15 @@ func (client *SsntpTestClient) GetCmdChanResult(c *chan Result, cmd ssntp.Comman // SendResultAndDelCmdChan deletes an ssntp.Command from the SsntpTestClient command channel func (client *SsntpTestClient) SendResultAndDelCmdChan(cmd ssntp.Command, result Result) { client.CmdChansLock.Lock() - defer client.CmdChansLock.Unlock() c, ok := client.CmdChans[cmd] if ok { delete(client.CmdChans, cmd) + client.CmdChansLock.Unlock() c <- result close(c) + return } + client.CmdChansLock.Unlock() } // AddEventChan adds a ssntp.Event to the SsntpTestClient event channel @@ -163,13 +168,15 @@ func (client *SsntpTestClient) GetEventChanResult(c *chan Result, evt ssntp.Even // SendResultAndDelEventChan deletes an ssntp.Event from the SsntpTestClient event channel func (client *SsntpTestClient) SendResultAndDelEventChan(evt ssntp.Event, result Result) { client.EventChansLock.Lock() - defer client.EventChansLock.Unlock() c, ok := client.EventChans[evt] if ok { delete(client.EventChans, evt) + client.EventChansLock.Unlock() c <- result close(c) + return } + client.EventChansLock.Unlock() } // AddErrorChan adds a ssntp.Error to the SsntpTestClient error channel @@ -200,13 +207,15 @@ func (client *SsntpTestClient) GetErrorChanResult(c *chan Result, error ssntp.Er // SendResultAndDelErrorChan deletes an ssntp.Error from the SsntpTestClient error channel func (client *SsntpTestClient) SendResultAndDelErrorChan(error ssntp.Error, result Result) { client.ErrorChansLock.Lock() - defer client.ErrorChansLock.Unlock() c, ok := client.ErrorChans[error] if ok { delete(client.ErrorChans, error) + client.ErrorChansLock.Unlock() c <- result close(c) + return } + client.ErrorChansLock.Unlock() } // AddStatusChan adds an ssntp.Status to the SsntpTestClient status channel @@ -237,13 +246,63 @@ func (client *SsntpTestClient) GetStatusChanResult(c *chan Result, status ssntp. // SendResultAndDelStatusChan deletes an ssntp.Status from the SsntpTestClient status channel func (client *SsntpTestClient) SendResultAndDelStatusChan(status ssntp.Status, result Result) { client.StatusChansLock.Lock() - defer client.StatusChansLock.Unlock() c, ok := client.StatusChans[status] if ok { delete(client.StatusChans, status) + client.StatusChansLock.Unlock() c <- result close(c) + return + } + client.StatusChansLock.Unlock() +} + +func openClientChans(client *SsntpTestClient) { + client.CmdChansLock.Lock() + client.CmdChans = make(map[ssntp.Command]chan Result) + client.CmdChansLock.Unlock() + + client.EventChansLock.Lock() + client.EventChans = make(map[ssntp.Event]chan Result) + client.EventChansLock.Unlock() + + client.ErrorChansLock.Lock() + client.ErrorChans = make(map[ssntp.Error]chan Result) + client.ErrorChansLock.Unlock() + + client.StatusChansLock.Lock() + client.StatusChans = make(map[ssntp.Status]chan Result) + client.StatusChansLock.Unlock() +} + +func closeClientChans(client *SsntpTestClient) { + client.CmdChansLock.Lock() + for k := range client.CmdChans { + close(client.CmdChans[k]) + delete(client.CmdChans, k) + } + client.CmdChansLock.Unlock() + + client.EventChansLock.Lock() + for k := range client.EventChans { + close(client.EventChans[k]) + delete(client.EventChans, k) + } + client.EventChansLock.Unlock() + + client.ErrorChansLock.Lock() + for k := range client.ErrorChans { + close(client.ErrorChans[k]) + delete(client.ErrorChans, k) + } + client.ErrorChansLock.Unlock() + + client.StatusChansLock.Lock() + for k := range client.StatusChans { + close(client.StatusChans[k]) + delete(client.StatusChans, k) } + client.StatusChansLock.Unlock() } // ConnectNotify implements the SSNTP client ConnectNotify callback for SsntpTestClient diff --git a/testutil/agent_test.go b/testutil/agent_test.go index 9b6957e69..1ef7a869c 100644 --- a/testutil/agent_test.go +++ b/testutil/agent_test.go @@ -151,3 +151,22 @@ func TestAgentCmdChanTimeout(t *testing.T) { t.Fatal(err) } } + +func TestAgentCloseChans(t *testing.T) { + var result Result + + _ = agent.AddCmdChan(ssntp.START) + go agent.SendResultAndDelCmdChan(ssntp.START, result) + + _ = agent.AddEventChan(ssntp.TraceReport) + go agent.SendResultAndDelEventChan(ssntp.TraceReport, result) + + _ = agent.AddErrorChan(ssntp.StopFailure) + go agent.SendResultAndDelErrorChan(ssntp.StopFailure, result) + + _ = agent.AddStatusChan(ssntp.READY) + go agent.SendResultAndDelStatusChan(ssntp.READY, result) + + CloseClientChans(agent) + OpenClientChans(agent) +} diff --git a/testutil/client_server_test.go b/testutil/client_server_test.go index fb1882977..ec34e02c8 100644 --- a/testutil/client_server_test.go +++ b/testutil/client_server_test.go @@ -29,7 +29,7 @@ import ( . "github.com/01org/ciao/testutil" ) -var server SsntpTestServer +var server *SsntpTestServer var controller *SsntpTestController var agent *SsntpTestClient var netAgent *SsntpTestClient @@ -451,7 +451,7 @@ func stopServer() error { netAgentCh := netAgent.AddEventChan(ssntp.NodeDisconnected) agentCh := agent.AddEventChan(ssntp.NodeDisconnected) - server.Ssntp.Stop() + server.Shutdown() _, err := controller.GetEventChanResult(controllerCh, ssntp.NodeDisconnected) if err != nil { @@ -474,7 +474,7 @@ func restartServer() error { agentCh := agent.AddEventChan(ssntp.NodeConnected) cnciAgentCh := cnciAgent.AddEventChan(ssntp.NodeConnected) - StartTestServer(&server) + server = StartTestServer() //MUST be after StartTestServer becase the channels are initialized on start serverCh := server.AddEventChan(ssntp.NodeConnected) @@ -511,6 +511,7 @@ func restartServer() error { } func TestReconnects(t *testing.T) { + fmt.Println("stopping server") err := stopServer() if err != nil { t.Fatal(err) @@ -518,6 +519,7 @@ func TestReconnects(t *testing.T) { time.Sleep(1 * time.Second) + fmt.Println("restarting server") err = restartServer() if err != nil { t.Fatal(err) @@ -564,7 +566,7 @@ func TestMain(m *testing.M) { flag.Parse() // start server - StartTestServer(&server) + server = StartTestServer() // start controller controllerUUID := uuid.Generate().String() @@ -589,16 +591,16 @@ func TestMain(m *testing.M) { // stop everybody time.Sleep(1 * time.Second) - controller.Ssntp.Close() + controller.Shutdown() time.Sleep(1 * time.Second) - netAgent.Ssntp.Close() + netAgent.Shutdown() time.Sleep(1 * time.Second) - agent.Ssntp.Close() + agent.Shutdown() time.Sleep(1 * time.Second) - server.Ssntp.Stop() + server.Shutdown() os.Exit(status) } diff --git a/testutil/controller.go b/testutil/controller.go index 922f23b8b..c16611b97 100644 --- a/testutil/controller.go +++ b/testutil/controller.go @@ -39,6 +39,12 @@ type SsntpTestController struct { ErrorChansLock *sync.Mutex } +// Shutdown shuts down the testutil.SsntpTestClient and cleans up state +func (ctl *SsntpTestController) Shutdown() { + ctl.Ssntp.Close() + closeControllerChans(ctl) +} + // NewSsntpTestControllerConnection creates an SsntpTestController and dials the server. // Calling with a unique name parameter string for inclusion in the // SsntpTestClient.Name field aides in debugging. The uuid string @@ -54,12 +60,10 @@ func NewSsntpTestControllerConnection(name string, uuid string) (*SsntpTestContr UUID: uuid, } - ctl.CmdChans = make(map[ssntp.Command]chan Result) ctl.CmdChansLock = &sync.Mutex{} - ctl.EventChans = make(map[ssntp.Event]chan Result) ctl.EventChansLock = &sync.Mutex{} - ctl.ErrorChans = make(map[ssntp.Error]chan Result) ctl.ErrorChansLock = &sync.Mutex{} + openControllerChans(ctl) config := &ssntp.Config{ URI: "", @@ -103,13 +107,15 @@ func (ctl *SsntpTestController) GetCmdChanResult(c *chan Result, cmd ssntp.Comma // SendResultAndDelCmdChan deletes an ssntp.Command from the SsntpTestController command channel func (ctl *SsntpTestController) SendResultAndDelCmdChan(cmd ssntp.Command, result Result) { ctl.CmdChansLock.Lock() - defer ctl.CmdChansLock.Unlock() c, ok := ctl.CmdChans[cmd] if ok { delete(ctl.CmdChans, cmd) + ctl.CmdChansLock.Unlock() c <- result close(c) + return } + ctl.CmdChansLock.Unlock() } // AddEventChan adds an ssntp.Event to the SsntpTestController event channel @@ -140,13 +146,15 @@ func (ctl *SsntpTestController) GetEventChanResult(c *chan Result, evt ssntp.Eve // SendResultAndDelEventChan deletes an ssntpEvent from the SsntpTestController event channel func (ctl *SsntpTestController) SendResultAndDelEventChan(evt ssntp.Event, result Result) { ctl.EventChansLock.Lock() - defer ctl.EventChansLock.Unlock() c, ok := ctl.EventChans[evt] if ok { delete(ctl.EventChans, evt) + ctl.EventChansLock.Unlock() c <- result close(c) + return } + ctl.EventChansLock.Unlock() } // AddErrorChan adds an ssntp.Error to the SsntpTestController error channel @@ -177,13 +185,52 @@ func (ctl *SsntpTestController) GetErrorChanResult(c *chan Result, error ssntp.E // SendResultAndDelErrorChan deletes an ssntp.Error from the SsntpTestController error channel func (ctl *SsntpTestController) SendResultAndDelErrorChan(error ssntp.Error, result Result) { ctl.ErrorChansLock.Lock() - defer ctl.ErrorChansLock.Unlock() c, ok := ctl.ErrorChans[error] if ok { delete(ctl.ErrorChans, error) + ctl.ErrorChansLock.Unlock() c <- result close(c) + return + } + ctl.ErrorChansLock.Unlock() +} + +func openControllerChans(ctl *SsntpTestController) { + ctl.CmdChansLock.Lock() + ctl.CmdChans = make(map[ssntp.Command]chan Result) + ctl.CmdChansLock.Unlock() + + ctl.EventChansLock.Lock() + ctl.EventChans = make(map[ssntp.Event]chan Result) + ctl.EventChansLock.Unlock() + + ctl.ErrorChansLock.Lock() + ctl.ErrorChans = make(map[ssntp.Error]chan Result) + ctl.ErrorChansLock.Unlock() +} + +func closeControllerChans(ctl *SsntpTestController) { + ctl.CmdChansLock.Lock() + for k := range ctl.CmdChans { + close(ctl.CmdChans[k]) + delete(ctl.CmdChans, k) } + ctl.CmdChansLock.Unlock() + + ctl.EventChansLock.Lock() + for k := range ctl.EventChans { + close(ctl.EventChans[k]) + delete(ctl.EventChans, k) + } + ctl.EventChansLock.Unlock() + + ctl.ErrorChansLock.Lock() + for k := range ctl.ErrorChans { + close(ctl.ErrorChans[k]) + delete(ctl.ErrorChans, k) + } + ctl.ErrorChansLock.Unlock() } // ConnectNotify implements the SSNTP client ConnectNotify callback for SsntpTestController diff --git a/testutil/controller_test.go b/testutil/controller_test.go index 49fa45cac..78ec806f6 100644 --- a/testutil/controller_test.go +++ b/testutil/controller_test.go @@ -117,3 +117,19 @@ func TestControllerCmdChanTimeout(t *testing.T) { t.Fatal(err) } } + +func TestControllerCloseChans(t *testing.T) { + var result Result + + _ = controller.AddCmdChan(ssntp.START) + go controller.SendResultAndDelCmdChan(ssntp.START, result) + + _ = controller.AddEventChan(ssntp.TraceReport) + go controller.SendResultAndDelEventChan(ssntp.TraceReport, result) + + _ = controller.AddErrorChan(ssntp.StopFailure) + go controller.SendResultAndDelErrorChan(ssntp.StopFailure, result) + + CloseControllerChans(controller) + OpenControllerChans(controller) +} diff --git a/testutil/export_test.go b/testutil/export_test.go new file mode 100644 index 000000000..2ce763ff9 --- /dev/null +++ b/testutil/export_test.go @@ -0,0 +1,25 @@ +// +// Copyright (c) 2016 Intel Corporation +// +// 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 testutil + +var OpenControllerChans = openControllerChans +var OpenServerChans = openServerChans +var OpenClientChans = openClientChans + +var CloseControllerChans = closeControllerChans +var CloseServerChans = closeServerChans +var CloseClientChans = closeClientChans diff --git a/testutil/server.go b/testutil/server.go index d4d6c8e99..cb29c595f 100644 --- a/testutil/server.go +++ b/testutil/server.go @@ -74,13 +74,15 @@ func (server *SsntpTestServer) GetCmdChanResult(c *chan Result, cmd ssntp.Comman // SendResultAndDelCmdChan deletes an ssntp.Command from the SsntpTestServer command channel func (server *SsntpTestServer) SendResultAndDelCmdChan(cmd ssntp.Command, result Result) { server.CmdChansLock.Lock() - defer server.CmdChansLock.Unlock() c, ok := server.CmdChans[cmd] if ok { delete(server.CmdChans, cmd) + server.CmdChansLock.Unlock() c <- result close(c) + return } + server.CmdChansLock.Unlock() } // AddEventChan adds an ssntp.Event to the SsntpTestServer event channel @@ -111,13 +113,15 @@ func (server *SsntpTestServer) GetEventChanResult(c *chan Result, evt ssntp.Even // SendResultAndDelEventChan deletes an ssntp.Event from the SsntpTestServer event channel func (server *SsntpTestServer) SendResultAndDelEventChan(evt ssntp.Event, result Result) { server.EventChansLock.Lock() - defer server.EventChansLock.Unlock() c, ok := server.EventChans[evt] if ok { delete(server.EventChans, evt) + server.EventChansLock.Unlock() c <- result close(c) + return } + server.EventChansLock.Unlock() } // AddErrorChan adds an ssntp.Error to the SsntpTestServer error channel @@ -148,13 +152,15 @@ func (server *SsntpTestServer) GetErrorChanResult(c *chan Result, error ssntp.Er // SendResultAndDelErrorChan deletes an ssntp.Error from the SsntpTestServer error channel func (server *SsntpTestServer) SendResultAndDelErrorChan(error ssntp.Error, result Result) { server.ErrorChansLock.Lock() - defer server.ErrorChansLock.Unlock() c, ok := server.ErrorChans[error] if ok { delete(server.ErrorChans, error) + server.ErrorChansLock.Unlock() c <- result close(c) + return } + server.ErrorChansLock.Unlock() } // AddStatusChan adds an ssntp.Status to the SsntpTestServer status channel @@ -185,13 +191,63 @@ func (server *SsntpTestServer) GetStatusChanResult(c *chan Result, status ssntp. // SendResultAndDelStatusChan deletes an ssntp.Status from the SsntpTestServer status channel func (server *SsntpTestServer) SendResultAndDelStatusChan(error ssntp.Status, result Result) { server.StatusChansLock.Lock() - defer server.StatusChansLock.Unlock() c, ok := server.StatusChans[error] if ok { delete(server.StatusChans, error) + server.StatusChansLock.Unlock() c <- result close(c) + return } + server.StatusChansLock.Unlock() +} + +func openServerChans(server *SsntpTestServer) { + server.CmdChansLock.Lock() + server.CmdChans = make(map[ssntp.Command]chan Result) + server.CmdChansLock.Unlock() + + server.EventChansLock.Lock() + server.EventChans = make(map[ssntp.Event]chan Result) + server.EventChansLock.Unlock() + + server.ErrorChansLock.Lock() + server.ErrorChans = make(map[ssntp.Error]chan Result) + server.ErrorChansLock.Unlock() + + server.StatusChansLock.Lock() + server.StatusChans = make(map[ssntp.Status]chan Result) + server.StatusChansLock.Unlock() +} + +func closeServerChans(server *SsntpTestServer) { + server.CmdChansLock.Lock() + for k := range server.CmdChans { + close(server.CmdChans[k]) + delete(server.CmdChans, k) + } + server.CmdChansLock.Unlock() + + server.EventChansLock.Lock() + for k := range server.EventChans { + close(server.EventChans[k]) + delete(server.EventChans, k) + } + server.EventChansLock.Unlock() + + server.ErrorChansLock.Lock() + for k := range server.ErrorChans { + close(server.ErrorChans[k]) + delete(server.ErrorChans, k) + } + server.ErrorChansLock.Unlock() + + server.StatusChansLock.Lock() + for k := range server.StatusChans { + close(server.StatusChans[k]) + delete(server.StatusChans, k) + } + server.StatusChansLock.Unlock() } // ConnectNotify implements an SSNTP ConnectNotify callback for SsntpTestServer @@ -521,23 +577,24 @@ func (server *SsntpTestServer) CommandForward(uuid string, command ssntp.Command return dest } +// Shutdown shuts down the testutil.SsntpTestServer and cleans up state +func (server *SsntpTestServer) Shutdown() { + server.Ssntp.Stop() + closeServerChans(server) +} + // StartTestServer starts a go routine for based on a // testutil.SsntpTestServer configuration with standard ssntp.FrameRorwardRules -func StartTestServer(server *SsntpTestServer) { +func StartTestServer() *SsntpTestServer { + server := new(SsntpTestServer) server.clientsLock = &sync.Mutex{} server.netClientsLock = &sync.Mutex{} - server.CmdChans = make(map[ssntp.Command]chan Result) server.CmdChansLock = &sync.Mutex{} - - server.EventChans = make(map[ssntp.Event]chan Result) server.EventChansLock = &sync.Mutex{} - - server.ErrorChans = make(map[ssntp.Error]chan Result) server.ErrorChansLock = &sync.Mutex{} - - server.StatusChans = make(map[ssntp.Status]chan Result) server.StatusChansLock = &sync.Mutex{} + openServerChans(server) serverConfig := ssntp.Config{ CAcert: ssntp.DefaultCACert, @@ -612,5 +669,5 @@ func StartTestServer(server *SsntpTestServer) { } go server.Ssntp.Serve(&serverConfig, server) - return + return server } diff --git a/testutil/server_test.go b/testutil/server_test.go index d3f1e1460..a4baf5bc7 100644 --- a/testutil/server_test.go +++ b/testutil/server_test.go @@ -139,3 +139,22 @@ func TestServerCmdChanTimeout(t *testing.T) { t.Fatal(err) } } + +func TestServerCloseChans(t *testing.T) { + var result Result + + _ = server.AddCmdChan(ssntp.START) + go server.SendResultAndDelCmdChan(ssntp.START, result) + + _ = server.AddEventChan(ssntp.TraceReport) + go server.SendResultAndDelEventChan(ssntp.TraceReport, result) + + _ = server.AddErrorChan(ssntp.StopFailure) + go server.SendResultAndDelErrorChan(ssntp.StopFailure, result) + + _ = server.AddStatusChan(ssntp.READY) + go server.SendResultAndDelStatusChan(ssntp.READY, result) + + CloseServerChans(server) + OpenServerChans(server) +}