Skip to content

Commit

Permalink
core: test
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasmacko committed Jul 4, 2017
1 parent 7877cef commit 71148d2
Show file tree
Hide file tree
Showing 4 changed files with 281 additions and 26 deletions.
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ define test_only
@go test ./messaging/kafka/client
@go test ./messaging/kafka/mux
@go test ./utils/addrs
@go test ./core
@echo "# done"
endef

Expand All @@ -23,9 +24,10 @@ define test_cover_only
@go test -covermode=count -coverprofile=${COVER_DIR}coverage_unit3.out ./messaging/kafka/client
@go test -covermode=count -coverprofile=${COVER_DIR}coverage_unit4.out ./messaging/kafka/mux
@go test -covermode=count -coverprofile=${COVER_DIR}coverage_unit5.out ./utils/addrs
@go test -covermode=count -coverprofile=${COVER_DIR}coverage_unit6.out ./core
@echo "# merging coverage results"
@cd vendor/github.com/wadey/gocovmerge && go install -v
@gocovmerge ${COVER_DIR}coverage_unit1.out ${COVER_DIR}coverage_unit2.out ${COVER_DIR}coverage_unit3.out ${COVER_DIR}coverage_unit4.out ${COVER_DIR}coverage_unit5.out > ${COVER_DIR}coverage.out
@gocovmerge ${COVER_DIR}coverage_unit1.out ${COVER_DIR}coverage_unit2.out ${COVER_DIR}coverage_unit3.out ${COVER_DIR}coverage_unit4.out ${COVER_DIR}coverage_unit5.out ${COVER_DIR}coverage_unit6.out > ${COVER_DIR}coverage.out
@echo "# coverage data generated into ${COVER_DIR}coverage.out"
@echo "# done"
endef
Expand Down
9 changes: 5 additions & 4 deletions core/agent_core.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func NewAgent(logger logging.Logger, maxStartup time.Duration, plugins ...*Named
func (agent *Agent) Start() error {
agent.WithFields(logging.Fields{"BuildVersion": BuildVersion, "BuildDate": BuildDate}).Info("Starting the agent...")

doneChannel := make(chan *struct{}, 0)
doneChannel := make(chan struct{}, 0)
errChannel := make(chan error, 0)

flag.Parse()
Expand All @@ -74,7 +74,7 @@ func (agent *Agent) Start() error {
errChannel <- err
return
}
doneChannel <- &struct{}{}
close(doneChannel)
}()

//block until all Plugins are initialized or timeout expires
Expand All @@ -99,9 +99,10 @@ func (agent *Agent) Stop() error {
err := safeclose.Close(agent.plugins[i].Plugin)
if err != nil {
if len(errMsg) > 0 {
errMsg += "; " + string(agent.plugins[i].PluginName)
errMsg += ": " + err.Error()
errMsg += "; "
}
errMsg += string(agent.plugins[i].PluginName)
errMsg += ": " + err.Error()
}
agent.WithField("pluginName", agent.plugins[i].PluginName).Debug("Stopping plugin end ", err)
}
Expand Down
263 changes: 263 additions & 0 deletions core/core_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
// Copyright (c) 2017 Cisco and/or its affiliates.
//
// 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 core

import (
"fmt"
"github.com/ligato/cn-infra/logging/logrus"
"github.com/onsi/gomega"
"sync"
"testing"
"time"
)

func TestEmptyAgent(t *testing.T) {
gomega.RegisterTestingT(t)

agent := NewAgent(logrus.StandardLogger(), 1*time.Second)
gomega.Expect(agent).NotTo(gomega.BeNil())
err := agent.Start()
gomega.Expect(err).To(gomega.BeNil())
err = agent.Stop()
gomega.Expect(err).To(gomega.BeNil())
}

func TestEventLoopWithInterrupt(t *testing.T) {
gomega.RegisterTestingT(t)

plugins := []*TestPlugin{{}, {}, {}}

namedPlugins := []*NamedPlugin{{"First", plugins[0]},
{"Second", plugins[1]},
{"Third", plugins[2]}}

for _, p := range plugins {
gomega.Expect(p.Initialized()).To(gomega.BeFalse())
gomega.Expect(p.AfterInitialized()).To(gomega.BeFalse())
gomega.Expect(p.Closed()).To(gomega.BeFalse())
}

agent := NewAgent(logrus.StandardLogger(), 100*time.Millisecond, namedPlugins...)
closeCh := make(chan struct{})
errCh := make(chan error)
go func() {
errCh <- EventLoopWithInterrupt(agent, closeCh)
}()

time.Sleep(100 * time.Millisecond)
for _, p := range plugins {
gomega.Expect(p.Initialized()).To(gomega.BeTrue())
gomega.Expect(p.AfterInitialized()).To(gomega.BeTrue())
gomega.Expect(p.Closed()).To(gomega.BeFalse())
}
close(closeCh)

select {
case errCh := <-errCh:
gomega.Expect(errCh).To(gomega.BeNil())
case <-time.After(100 * time.Millisecond):
t.FailNow()
}

for _, p := range plugins {
gomega.Expect(p.Closed()).To(gomega.BeTrue())
}
}

func TestEventLoopFailInit(t *testing.T) {
gomega.RegisterTestingT(t)

plugins := []*TestPlugin{{}, {}, NewTestPlugin(true, false, false)}

namedPlugins := []*NamedPlugin{{"First", plugins[0]},
{"Second", plugins[1]},
{"Third", plugins[2]}}

for _, p := range plugins {
gomega.Expect(p.Initialized()).To(gomega.BeFalse())
gomega.Expect(p.AfterInitialized()).To(gomega.BeFalse())
gomega.Expect(p.Closed()).To(gomega.BeFalse())
}

agent := NewAgent(logrus.StandardLogger(), 100*time.Millisecond, namedPlugins...)
closeCh := make(chan struct{})
errCh := make(chan error)
go func() {
errCh <- EventLoopWithInterrupt(agent, closeCh)
}()

select {
case errCh := <-errCh:
gomega.Expect(errCh).NotTo(gomega.BeNil())
case <-time.After(100 * time.Millisecond):
t.FailNow()
}

for _, p := range plugins {
gomega.Expect(p.Initialized()).To(gomega.BeTrue())
// initialization failed of a plugin failed, afterInit was not called
gomega.Expect(p.AfterInitialized()).To(gomega.BeFalse())
gomega.Expect(p.Closed()).To(gomega.BeTrue())
}
close(closeCh)

}

func TestEventLoopAfterInitFailed(t *testing.T) {
gomega.RegisterTestingT(t)

plugins := []*TestPlugin{{}, NewTestPlugin(false, true, false), {}}

namedPlugins := []*NamedPlugin{{"First", plugins[0]},
{"Second", plugins[1]},
{"Third", plugins[2]}}

for _, p := range plugins {
gomega.Expect(p.Initialized()).To(gomega.BeFalse())
gomega.Expect(p.AfterInitialized()).To(gomega.BeFalse())
gomega.Expect(p.Closed()).To(gomega.BeFalse())
}

agent := NewAgent(logrus.StandardLogger(), 100*time.Millisecond, namedPlugins...)
closeCh := make(chan struct{})
errCh := make(chan error)
go func() {
errCh <- EventLoopWithInterrupt(agent, closeCh)
}()

select {
case errCh := <-errCh:
gomega.Expect(errCh).NotTo(gomega.BeNil())
case <-time.After(100 * time.Millisecond):
t.FailNow()
}

for _, p := range plugins {
gomega.Expect(p.Initialized()).To(gomega.BeTrue())
gomega.Expect(p.Closed()).To(gomega.BeTrue())
}
close(closeCh)

gomega.Expect(plugins[0].AfterInitialized()).To(gomega.BeTrue())
gomega.Expect(plugins[1].AfterInitialized()).To(gomega.BeTrue())
// afterInit of the second plugin failed thus the third was not afterInitialized
gomega.Expect(plugins[2].AfterInitialized()).To(gomega.BeFalse())

}

func TestEventLoopCloseFailed(t *testing.T) {
gomega.RegisterTestingT(t)

plugins := []*TestPlugin{NewTestPlugin(false, false, true), {}, {}}

namedPlugins := []*NamedPlugin{{"First", plugins[0]},
{"Second", plugins[1]},
{"Third", plugins[2]}}

for _, p := range plugins {
gomega.Expect(p.Initialized()).To(gomega.BeFalse())
gomega.Expect(p.AfterInitialized()).To(gomega.BeFalse())
gomega.Expect(p.Closed()).To(gomega.BeFalse())
}

agent := NewAgent(logrus.StandardLogger(), 100*time.Millisecond, namedPlugins...)
closeCh := make(chan struct{})
errCh := make(chan error)
go func() {
errCh <- EventLoopWithInterrupt(agent, closeCh)
}()

time.Sleep(100 * time.Millisecond)
for _, p := range plugins {
gomega.Expect(p.Initialized()).To(gomega.BeTrue())
gomega.Expect(p.AfterInitialized()).To(gomega.BeTrue())
gomega.Expect(p.Closed()).To(gomega.BeFalse())
}

close(closeCh)

select {
case errCh := <-errCh:
gomega.Expect(errCh).NotTo(gomega.BeNil())
case <-time.After(100 * time.Millisecond):
t.FailNow()
}

for _, p := range plugins {
gomega.Expect(p.Closed()).To(gomega.BeTrue())
}

}

type TestPlugin struct {
failInit bool
failAfterInit bool
failClose bool

sync.Mutex
initCalled bool
afterInitCalled bool
closeCalled bool
}

func NewTestPlugin(failInit, failAfterInit, failClose bool) *TestPlugin {
return &TestPlugin{failInit: failInit, failAfterInit: failAfterInit, failClose: failClose}
}

func (p *TestPlugin) Init() error {
p.Lock()
defer p.Unlock()
p.initCalled = true
if p.failInit {
return fmt.Errorf("Init failed")
}
return nil
}
func (p *TestPlugin) AfterInit() error {
p.Lock()
defer p.Unlock()
p.afterInitCalled = true
if p.failAfterInit {
return fmt.Errorf("AfterInit failed")
}
return nil
}
func (p *TestPlugin) Close() error {
p.Lock()
defer p.Unlock()
p.closeCalled = true
if p.failClose {
return fmt.Errorf("Close failed")
}
return nil
}

func (p *TestPlugin) Initialized() bool {
p.Lock()
defer p.Unlock()
return p.initCalled
}

func (p *TestPlugin) AfterInitialized() bool {
p.Lock()
defer p.Unlock()
return p.afterInitCalled
}

func (p *TestPlugin) Closed() bool {
p.Lock()
defer p.Unlock()
return p.closeCalled
}
31 changes: 10 additions & 21 deletions core/event_loop.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,36 +19,25 @@ import (
"os/signal"
)

// EventLoopWithInterrupt initializes Agent with plugins. Agent can be interrupted from outside using public CloseChannel.
func EventLoopWithInterrupt(agent *Agent, closeChan chan *struct{}) {
// EventLoopWithInterrupt initializes Agent with plugins. Agent is stopped when CloseChannel is closed or SIGINT is received.
func EventLoopWithInterrupt(agent *Agent, closeChan chan struct{}) error {
err := agent.Start()
if err != nil {
agent.Error("Error loading core", err)
os.Exit(1)
return err
}
defer func() {
err := agent.Stop()
if err != nil {
agent.Errorf("Agent stop error '%+v'", err)
os.Exit(1)
}
}()

sigChan := make(chan os.Signal, 1)

signal.Notify(sigChan, os.Interrupt)
select {
case <-sigChan:
agent.Println("Interrupt received, returning.")
return
case _, ok := <-closeChan:
if ok {
err := agent.Stop()
if err != nil {
agent.Errorf("Agent stop error '%v'", err)
os.Exit(1)
}
os.Exit(0)
}
case <-closeChan:
}

err = agent.Stop()
if err != nil {
agent.Errorf("Agent stop error '%+v'", err)
}
return err
}

0 comments on commit 71148d2

Please sign in to comment.