// TestEnvironment tests general environment methods. func TestEnvironment(t *testing.T) { assert := audit.NewTestingAssertion(t, true) envOne := cells.NewEnvironment("part", 1, "of", "env", "ONE") defer envOne.Stop() id := envOne.ID() assert.Equal(id, "part:1:of:env:one") envTwo := cells.NewEnvironment("environment TWO") defer envTwo.Stop() id = envTwo.ID() assert.Equal(id, "environment-two") }
// TestEnvironmentSubscribersDo tests the iteration over // the subscribers. func TestEnvironmentSubscribersDo(t *testing.T) { assert := audit.NewTestingAssertion(t, true) env := cells.NewEnvironment("subscribers-do") defer env.Stop() err := env.StartCell("foo", newCollectBehavior()) assert.Nil(err) err = env.StartCell("bar", newCollectBehavior()) assert.Nil(err) err = env.StartCell("baz", newCollectBehavior()) assert.Nil(err) err = env.Subscribe("foo", "bar", "baz") assert.Nil(err) err = env.EmitNew("foo", iterateTopic, nil) assert.Nil(err) time.Sleep(200 * time.Millisecond) collected, err := env.Request("bar", cells.ProcessedTopic, nil, cells.DefaultTimeout) assert.Nil(err) assert.Length(collected, 1) assert.Contents(`<topic: "love" / payload: <"default": foo loves bar>>`, collected) collected, err = env.Request("baz", cells.ProcessedTopic, nil, cells.DefaultTimeout) assert.Nil(err) assert.Length(collected, 1) assert.Contents(`<topic: "love" / payload: <"default": foo loves baz>>`, collected) }
// TestRateBehavior tests the event rate behavior. func TestRateBehavior(t *testing.T) { assert := audit.NewTestingAssertion(t, true) env := cells.NewEnvironment("rate-behavior") defer env.Stop() matches := func(event cells.Event) bool { return event.Topic() == "now" } topics := []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "now"} env.StartCell("rater", behaviors.NewRateBehavior(matches, 5)) env.StartCell("collector", behaviors.NewCollectorBehavior(1000)) env.Subscribe("rater", "collector") for i := 0; i < 1000; i++ { topic := topics[rand.Intn(len(topics))] env.EmitNew("rater", topic, nil) time.Sleep(time.Duration(rand.Intn(3)) * time.Millisecond) } collected, err := env.Request("collector", cells.CollectedTopic, nil, cells.DefaultTimeout) assert.Nil(err) events := collected.([]behaviors.EventData) assert.True(len(events) <= 1000) for _, event := range events { assert.Equal(event.Topic, "event-rate!") _, ok := event.Payload.GetDuration(behaviors.EventRateAveragePayload) assert.True(ok) _, ok = event.Payload.GetDuration(behaviors.EventRateAveragePayload) assert.True(ok) _, ok = event.Payload.GetDuration(behaviors.EventRateLowPayload) assert.True(ok) } }
// TestConfigurationRead tests the successful reading of a configuration. func TestConfigurationRead(t *testing.T) { assert := audit.NewTestingAssertion(t, true) env := cells.NewEnvironment("configuration-read") defer env.Stop() tempDir, filename := createConfigurationFile(assert, "{etc {foo 42}}") defer tempDir.Restore() sigc := audit.MakeSigChan() spf := func(c cells.Cell, event cells.Event) error { if event.Topic() == behaviors.ConfigurationTopic { cfg := behaviors.Configuration(event) v := cfg.ValueAsString("foo", "0815") assert.Equal(v, "42") sigc <- true } return nil } env.StartCell("configurator", behaviors.NewConfiguratorBehavior(nil)) env.StartCell("simple", behaviors.NewSimpleProcessorBehavior(spf)) env.Subscribe("configurator", "simple") pvs := cells.PayloadValues{ behaviors.ConfigurationFilenamePayload: filename, } env.EmitNew("configurator", behaviors.ReadConfigurationTopic, pvs) assert.Wait(sigc, true, 100*time.Millisecond) }
// TestEnvironmentScenario tests creating and using the // environment in a simple way. func TestEnvironmentScenario(t *testing.T) { assert := audit.NewTestingAssertion(t, true) env := cells.NewEnvironment("scenario") defer env.Stop() err := env.StartCell("foo", newCollectBehavior()) assert.Nil(err) err = env.StartCell("bar", newCollectBehavior()) assert.Nil(err) err = env.StartCell("collector", newCollectBehavior()) assert.Nil(err) err = env.Subscribe("foo", "bar") assert.Nil(err) err = env.Subscribe("bar", "collector") assert.Nil(err) err = env.EmitNew("foo", "lorem", 4711) assert.Nil(err) err = env.EmitNew("foo", "ipsum", 1234) assert.Nil(err) response, err := env.Request("foo", cells.PingTopic, nil, cells.DefaultTimeout) assert.Nil(err) assert.Equal(response, cells.PongResponse) time.Sleep(200 * time.Millisecond) collected, err := env.Request("collector", cells.ProcessedTopic, nil, cells.DefaultTimeout) assert.Nil(err) assert.Length(collected, 2, "two collected events") assert.Contents(`<topic: "lorem" / payload: <"default": 4711>>`, collected) assert.Contents(`<topic: "ipsum" / payload: <"default": 1234>>`, collected) }
// TestRouterBehavior tests the router behavior. func TestRouterBehavior(t *testing.T) { assert := audit.NewTestingAssertion(t, true) env := cells.NewEnvironment("router-behavior") defer env.Stop() rf := func(emitterID, subscriberID string, event cells.Event) (bool, error) { ok := strings.Contains(event.Topic(), subscriberID) return ok, nil } env.StartCell("router", behaviors.NewRouterBehavior(rf)) env.StartCell("test-1", behaviors.NewCollectorBehavior(10)) env.StartCell("test-2", behaviors.NewCollectorBehavior(10)) env.StartCell("test-3", behaviors.NewCollectorBehavior(10)) env.StartCell("test-4", behaviors.NewCollectorBehavior(10)) env.StartCell("test-5", behaviors.NewCollectorBehavior(10)) env.Subscribe("router", "test-1", "test-2", "test-3", "test-4", "test-5") env.EmitNew("router", "test-1:test-2", "a") env.EmitNew("router", "test-1:test-2:test-3", "b") env.EmitNew("router", "test-3:test-4:test-5", "c") time.Sleep(100 * time.Millisecond) test := func(id string, length int) { collected, err := env.Request(id, cells.CollectedTopic, nil, cells.DefaultTimeout) assert.Nil(err) assert.Length(collected, length) } test("test-1", 2) test("test-2", 2) test("test-3", 2) test("test-4", 1) test("test-5", 1) }
// TestCallbackBehavior tests the callback behavior. func TestCallbackBehavior(t *testing.T) { assert := audit.NewTestingAssertion(t, true) env := cells.NewEnvironment("callback-behavior") defer env.Stop() cbdA := []string{} cbfA := func(topic string, payload cells.Payload) error { cbdA = append(cbdA, topic) return nil } cbdB := 0 cbfB := func(topic string, payload cells.Payload) error { cbdB++ return nil } sigc := audit.MakeSigChan() cbfC := func(topic string, payload cells.Payload) error { if topic == "baz" { sigc <- true } return nil } env.StartCell("callback", behaviors.NewCallbackBehavior(cbfA, cbfB, cbfC)) env.EmitNew("callback", "foo", nil) env.EmitNew("callback", "bar", nil) env.EmitNew("callback", "baz", nil) assert.Wait(sigc, true, time.Second) assert.Equal(cbdA, []string{"foo", "bar", "baz"}) assert.Equal(cbdB, 3) }
// TestFilterBehavior tests the filter behavior. func TestFilterBehavior(t *testing.T) { assert := audit.NewTestingAssertion(t, true) env := cells.NewEnvironment("filter-behavior") defer env.Stop() ff := func(id string, event cells.Event) bool { dp, ok := event.Payload().Get(cells.DefaultPayload) if !ok { return false } payload := dp.(string) return event.Topic() == payload } env.StartCell("filter", behaviors.NewFilterBehavior(ff)) env.StartCell("collector", behaviors.NewCollectorBehavior(10)) env.Subscribe("filter", "collector") env.EmitNew("filter", "a", "a") env.EmitNew("filter", "a", "b") env.EmitNew("filter", "b", "b") time.Sleep(100 * time.Millisecond) collected, err := env.Request("collector", cells.CollectedTopic, nil, cells.DefaultTimeout) assert.Nil(err) assert.Length(collected, 2, "two collected events") }
// BenchmarkSmpleEmitStandardMonitoring is a simple emitting to one cell // with the standard monitor. func BenchmarkSmpleEmitStandardMonitoring(b *testing.B) { monitoring.SetBackend(monitoring.NewStandardBackend()) env := cells.NewEnvironment("simple-emit-standard") defer env.Stop() env.StartCell("null", &nullBehavior{}) event, _ := cells.NewEvent("foo", "bar", nil) for i := 0; i < b.N; i++ { env.Emit("null", event) } }
// TestTickerBehavior tests the ticker behavior. func TestTickerBehavior(t *testing.T) { assert := audit.NewTestingAssertion(t, true) env := cells.NewEnvironment("ticker-behavior") defer env.Stop() env.StartCell("ticker", behaviors.NewTickerBehavior(50*time.Millisecond)) env.StartCell("test", behaviors.NewCollectorBehavior(10)) env.Subscribe("ticker", "test") time.Sleep(125 * time.Millisecond) collected, err := env.Request("test", cells.CollectedTopic, nil, cells.DefaultTimeout) assert.Nil(err) assert.Length(collected, 2) }
// TestEnvironmentSubscribeStop subscribing and stopping func TestEnvironmentSubscribeStop(t *testing.T) { assert := audit.NewTestingAssertion(t, true) env := cells.NewEnvironment("subscribe-unsubscribe-stop") defer env.Stop() assert.Nil(env.StartCell("foo", newCollectBehavior())) assert.Nil(env.StartCell("bar", newCollectBehavior())) assert.Nil(env.StartCell("baz", newCollectBehavior())) assert.Nil(env.Subscribe("foo", "bar", "baz")) assert.Nil(env.Subscribe("bar", "foo", "baz")) assert.Nil(env.StopCell("bar")) assert.Nil(env.StopCell("foo")) assert.Nil(env.StopCell("baz")) }
// TestMapperBehavior tests the mapping of events. func TestMapperBehavior(t *testing.T) { assert := audit.NewTestingAssertion(t, true) assertPayload := func(collected interface{}, index int, value string) { eventData, ok := collected.([]behaviors.EventData) assert.True(ok) payload, ok := eventData[index].Payload.(cells.Payload) assert.True(ok) upperText, ok := payload.Get("upper-text") assert.True(ok) assert.Equal(upperText, value) } env := cells.NewEnvironment("mapper-behavior") defer env.Stop() mf := func(id string, event cells.Event) (cells.Event, error) { text, ok := event.Payload().Get(cells.DefaultPayload) if !ok { return event, nil } pv := cells.PayloadValues{ "upper-text": strings.ToUpper(text.(string)), } payload := event.Payload().Apply(pv) return cells.NewEvent(event.Topic(), payload, event.Context()) } env.StartCell("mapper", behaviors.NewMapperBehavior(mf)) env.StartCell("collector", behaviors.NewCollectorBehavior(10)) env.Subscribe("mapper", "collector") env.EmitNew("mapper", "a", "abc") env.EmitNew("mapper", "b", "def") env.EmitNew("mapper", "c", "ghi") time.Sleep(100 * time.Millisecond) collected, err := env.Request("collector", cells.CollectedTopic, nil, cells.DefaultTimeout) assert.Nil(err) assert.Length(collected, 3, "three mapped events") assertPayload(collected, 0, "ABC") assertPayload(collected, 1, "DEF") assertPayload(collected, 2, "GHI") }
// TestBehaviorEmitTimeoutError tests the timeout error handling // when one or more emit need too much time. func TestBehaviorEmitTimeoutError(t *testing.T) { assert := audit.NewTestingAssertion(t, true) env := cells.NewEnvironment("emit-timeout-error") defer env.Stop() err := env.StartCell("emitter", newEmitBehavior()) assert.Nil(err) err = env.StartCell("sleeper", newSleepBehavior()) assert.Nil(err) err = env.Subscribe("emitter", "sleeper") assert.Nil(err) // Emit more events than queue can take while the subscriber works. for i := 0; i < 25; i++ { env.EmitNew("emitter", emitTopic, i) } time.Sleep(2 * time.Second) }
// TestBehaviorEventBufferSize tests the setting of // the event buffer size. func TestBehaviorEventBufferSize(t *testing.T) { assert := audit.NewTestingAssertion(t, true) env := cells.NewEnvironment("event-buffer") defer env.Stop() err := env.StartCell("negative", newEventBufferBehavior(-8)) assert.Nil(err) ci := cells.InspectCell(env, "negative") assert.Equal(ci.EventBufferSize(), cells.MinEventBufferSize) err = env.StartCell("low", newEventBufferBehavior(1)) assert.Nil(err) ci = cells.InspectCell(env, "low") assert.Equal(ci.EventBufferSize(), cells.MinEventBufferSize) err = env.StartCell("high", newEventBufferBehavior(2*cells.MinEventBufferSize)) assert.Nil(err) ci = cells.InspectCell(env, "high") assert.Equal(ci.EventBufferSize(), 2*cells.MinEventBufferSize) }
// TestConfigurationValidation tests the validation of a configuration. func TestConfigurationValidation(t *testing.T) { assert := audit.NewTestingAssertion(t, true) env := cells.NewEnvironment("configuration-validation") defer env.Stop() tempDir, filename := createConfigurationFile(assert, "{etc {foo 42}}") defer tempDir.Restore() sigc := audit.MakeSigChan() spf := func(c cells.Cell, event cells.Event) error { sigc <- true return nil } var key string cv := func(cfg etc.Etc) error { v := cfg.ValueAsString(key, "[-default-]") if v == "[-default-]" { sigc <- false } return nil } env.StartCell("configurator", behaviors.NewConfiguratorBehavior(cv)) env.StartCell("simple", behaviors.NewSimpleProcessorBehavior(spf)) env.Subscribe("configurator", "simple") // First run with success as key has the valid value "foo" pvs := cells.PayloadValues{ behaviors.ConfigurationFilenamePayload: filename, } key = "foo" env.EmitNew("configurator", behaviors.ReadConfigurationTopic, pvs) assert.Wait(sigc, true, 100*time.Millisecond) // Second run also will succeed, even with "bar" as invalid value. // See definition of validator cv above. But validationError is not // nil. key = "bar" env.EmitNew("configurator", behaviors.ReadConfigurationTopic, pvs) assert.Wait(sigc, false, 100*time.Millisecond) }
// TestEnvironmentSubscribeUnsubscribe tests subscribing, // checking and unsubscribing of cells. func TestEnvironmentSubscribeUnsubscribe(t *testing.T) { assert := audit.NewTestingAssertion(t, true) env := cells.NewEnvironment("subscribe-unsubscribe") defer env.Stop() err := env.StartCell("foo", newCollectBehavior()) assert.Nil(err) err = env.StartCell("bar", newCollectBehavior()) assert.Nil(err) err = env.StartCell("baz", newCollectBehavior()) assert.Nil(err) err = env.StartCell("yadda", newCollectBehavior()) assert.Nil(err) err = env.Subscribe("humpf", "foo") assert.True(errors.IsError(err, cells.ErrInvalidID)) err = env.Subscribe("foo", "humpf") assert.True(errors.IsError(err, cells.ErrInvalidID)) err = env.Subscribe("foo", "bar", "baz") assert.Nil(err) subs, err := env.Subscribers("foo") assert.Nil(err) assert.Contents("bar", subs) assert.Contents("baz", subs) err = env.Unsubscribe("foo", "bar") assert.Nil(err) subs, err = env.Subscribers("foo") assert.Nil(err) assert.Contents("baz", subs) err = env.Unsubscribe("foo", "baz") assert.Nil(err) subs, err = env.Subscribers("foo") assert.Nil(err) assert.Empty(subs) }
// TestSimpleBehavior tests the simple processor behavior. func TestSimpleBehavior(t *testing.T) { assert := audit.NewTestingAssertion(t, true) env := cells.NewEnvironment("simple-procesor-behavior") defer env.Stop() topics := []string{} var wg sync.WaitGroup spf := func(c cells.Cell, event cells.Event) error { topics = append(topics, event.Topic()) wg.Done() return nil } env.StartCell("simple", behaviors.NewSimpleProcessorBehavior(spf)) wg.Add(3) env.EmitNew("simple", "foo", "") env.EmitNew("simple", "bar", "") env.EmitNew("simple", "baz", "") wg.Wait() assert.Length(topics, 3) }
// TestRoundRobinBehavior tests the round robin behavior. func TestRoundRobinBehavior(t *testing.T) { assert := audit.NewTestingAssertion(t, true) env := cells.NewEnvironment("round-robin-behavior") defer env.Stop() env.StartCell("round-robin", behaviors.NewRoundRobinBehavior()) env.StartCell("round-robin-1", behaviors.NewCollectorBehavior(10)) env.StartCell("round-robin-2", behaviors.NewCollectorBehavior(10)) env.StartCell("round-robin-3", behaviors.NewCollectorBehavior(10)) env.StartCell("round-robin-4", behaviors.NewCollectorBehavior(10)) env.StartCell("round-robin-5", behaviors.NewCollectorBehavior(10)) env.Subscribe("round-robin", "round-robin-1", "round-robin-2", "round-robin-3", "round-robin-4", "round-robin-5") time.Sleep(100 * time.Millisecond) // Just 23 to let two cells receive less events. for i := 0; i < 25; i++ { err := env.EmitNew("round-robin", "round", i) assert.Nil(err) } time.Sleep(100 * time.Millisecond) test := func(id string) int { collected, err := env.Request(id, cells.CollectedTopic, nil, cells.DefaultTimeout) assert.Nil(err) l := len(collected.([]behaviors.EventData)) assert.Equal(l, 5) return l } l1 := test("round-robin-1") l2 := test("round-robin-2") l3 := test("round-robin-3") l4 := test("round-robin-4") l5 := test("round-robin-5") assert.Equal(l1+l2+l3+l4+l5, 25) }
// TestCounterBehavior tests the counting of events. func TestCounterBehavior(t *testing.T) { assert := audit.NewTestingAssertion(t, true) env := cells.NewEnvironment("counter-behavior") defer env.Stop() cf := func(id string, event cells.Event) []string { payload, ok := event.Payload().Get(cells.DefaultPayload) if !ok { return []string{} } return payload.([]string) } env.StartCell("counter", behaviors.NewCounterBehavior(cf)) env.EmitNew("counter", "count", []string{"a", "b"}) env.EmitNew("counter", "count", []string{"a", "c", "d"}) env.EmitNew("counter", "count", []string{"a", "d"}) time.Sleep(100 * time.Millisecond) counters, err := env.Request("counter", cells.CountersTopic, nil, cells.DefaultTimeout) assert.Nil(err) assert.Length(counters, 4, "four counted events") c := counters.(behaviors.Counters) assert.Equal(c["a"], int64(3)) assert.Equal(c["b"], int64(1)) assert.Equal(c["c"], int64(1)) assert.Equal(c["d"], int64(2)) err = env.EmitNew("counter", cells.ResetTopic, nil) assert.Nil(err) counters, err = env.Request("counter", cells.CountersTopic, nil, cells.DefaultTimeout) assert.Nil(err) assert.Empty(counters, "zero counted events") }
// TestBehaviorEmitTimeoutSetting tests the setting of // the emit timeout. func TestBehaviorEmitTimeoutSetting(t *testing.T) { assert := audit.NewTestingAssertion(t, true) minSeconds := int(cells.MinEmitTimeout.Seconds() / 5) maxSeconds := int(cells.MaxEmitTimeout.Seconds() / 5) env := cells.NewEnvironment("emit-timeout-setting") defer env.Stop() err := env.StartCell("low", newEmitTimeoutBehavior(time.Millisecond)) assert.Nil(err) ci := cells.InspectCell(env, "low") assert.Equal(ci.EmitTimeout(), minSeconds) err = env.StartCell("correct", newEmitTimeoutBehavior(10*time.Second)) assert.Nil(err) ci = cells.InspectCell(env, "correct") assert.Equal(ci.EmitTimeout(), 2) err = env.StartCell("high", newEmitTimeoutBehavior(2*cells.MaxEmitTimeout)) assert.Nil(err) ci = cells.InspectCell(env, "high") assert.Equal(ci.EmitTimeout(), maxSeconds) }
// TestBehaviorRecoveringFrequency tests the setting of // the recovering frequency. func TestBehaviorRecoveringFrequency(t *testing.T) { assert := audit.NewTestingAssertion(t, true) env := cells.NewEnvironment("recovering-frequency") defer env.Stop() err := env.StartCell("negative", newRecoveringFrequencyBehavior(-1, time.Second)) assert.Nil(err) ci := cells.InspectCell(env, "negative") assert.Equal(ci.RecoveringNumber(), cells.MinRecoveringNumber) assert.Equal(ci.RecoveringDuration(), cells.MinRecoveringDuration) err = env.StartCell("low", newRecoveringFrequencyBehavior(10, time.Millisecond)) assert.Nil(err) ci = cells.InspectCell(env, "low") assert.Equal(ci.RecoveringNumber(), cells.MinRecoveringNumber) assert.Equal(ci.RecoveringDuration(), cells.MinRecoveringDuration) err = env.StartCell("high", newRecoveringFrequencyBehavior(12, time.Minute)) assert.Nil(err) ci = cells.InspectCell(env, "high") assert.Equal(ci.RecoveringNumber(), 12) assert.Equal(ci.RecoveringDuration(), time.Minute) }
// TestBroadcasterBehavior tests the broadcast behavior. func TestBroadcasterBehavior(t *testing.T) { assert := audit.NewTestingAssertion(t, true) env := cells.NewEnvironment("broadcaster-behavior") defer env.Stop() env.StartCell("broadcast", behaviors.NewBroadcasterBehavior()) env.StartCell("test-1", behaviors.NewCollectorBehavior(10)) env.StartCell("test-2", behaviors.NewCollectorBehavior(10)) env.Subscribe("broadcast", "test-1", "test-2") env.EmitNew("broadcast", "test", "a") env.EmitNew("broadcast", "test", "b") env.EmitNew("broadcast", "test", "c") time.Sleep(100 * time.Millisecond) collected, err := env.Request("test-1", cells.CollectedTopic, nil, cells.DefaultTimeout) assert.Nil(err) assert.Length(collected, 3) collected, err = env.Request("test-2", cells.CollectedTopic, nil, cells.DefaultTimeout) assert.Nil(err) assert.Length(collected, 3) }
// TestCollectorBehavior tests the collector behavior. func TestCollectorBehavior(t *testing.T) { assert := audit.NewTestingAssertion(t, true) env := cells.NewEnvironment("collector-behavior") defer env.Stop() env.StartCell("collector", behaviors.NewCollectorBehavior(10)) for i := 0; i < 25; i++ { env.EmitNew("collector", "collect", i) } time.Sleep(100 * time.Millisecond) collected, err := env.Request("collector", cells.CollectedTopic, nil, cells.DefaultTimeout) assert.Nil(err) assert.Length(collected, 10) err = env.EmitNew("collector", cells.ResetTopic, nil) assert.Nil(err) collected, err = env.Request("collector", cells.CollectedTopic, nil, cells.DefaultTimeout) assert.Nil(err) assert.Length(collected, 0) }
// TestEnvironmentStartStopCell tests starting, checking and // stopping of cells. func TestEnvironmentStartStopCell(t *testing.T) { assert := audit.NewTestingAssertion(t, true) env := cells.NewEnvironment("start-stop") defer env.Stop() err := env.StartCell("foo", newCollectBehavior()) assert.Nil(err) hasFoo := env.HasCell("foo") assert.True(hasFoo) err = env.StopCell("foo") assert.Nil(err) hasFoo = env.HasCell("foo") assert.False(hasFoo) hasBar := env.HasCell("bar") assert.False(hasBar) err = env.StopCell("bar") assert.True(errors.IsError(err, cells.ErrInvalidID)) hasBar = env.HasCell("bar") assert.False(hasBar) }
// TestEnvironmentStopUnsubscribe tests the unsubscribe of a cell when // it is stopped. func TestEnvironmentStopUnsubscribe(t *testing.T) { assert := audit.NewTestingAssertion(t, true) env := cells.NewEnvironment("stop-unsubscribe") defer env.Stop() err := env.StartCell("foo", newCollectBehavior()) assert.Nil(err) err = env.StartCell("bar", newCollectBehavior()) assert.Nil(err) err = env.StartCell("baz", newCollectBehavior()) assert.Nil(err) err = env.Subscribe("foo", "bar", "baz") assert.Nil(err) err = env.StopCell("bar") assert.Nil(err) // Expect only baz because bar is stopped. response, err := env.Request("foo", subscribersTopic, nil, cells.DefaultTimeout) assert.Nil(err) assert.Equal(response, []string{"baz"}) }
// TestFSMBehavior tests the finite state machine behavior. func TestFSMBehavior(t *testing.T) { assert := audit.NewTestingAssertion(t, true) env := cells.NewEnvironment("fsm-behavior") defer env.Stop() checkCents := func(id string) int { cents, err := env.Request(id, "cents?", nil, cells.DefaultTimeout) assert.Nil(err) return cents.(int) } info := func(id string) string { info, err := env.Request(id, "info?", nil, cells.DefaultTimeout) assert.Nil(err) return info.(string) } grabCents := func() int { cents, err := env.Request("restorer", "grab!", nil, cells.DefaultTimeout) assert.Nil(err) return cents.(int) } lockA := lockMachine{} lockB := lockMachine{} env.StartCell("lock-a", behaviors.NewFSMBehavior(lockA.Locked)) env.StartCell("lock-b", behaviors.NewFSMBehavior(lockB.Locked)) env.StartCell("restorer", newRestorerBehavior()) env.Subscribe("lock-a", "restorer") env.Subscribe("lock-b", "restorer") // 1st run: emit not enough and press button. env.EmitNew("lock-a", "coin!", 20) env.EmitNew("lock-a", "coin!", 20) env.EmitNew("lock-a", "coin!", 20) env.EmitNew("lock-a", "button-press!", nil) time.Sleep(100 * time.Millisecond) assert.Equal(checkCents("lock-a"), 0) assert.Equal(grabCents(), 60) // 2nd run: unlock the lock and lock it again. env.EmitNew("lock-a", "coin!", 50) env.EmitNew("lock-a", "coin!", 20) env.EmitNew("lock-a", "coin!", 50) time.Sleep(100 * time.Millisecond) assert.Equal(info("lock-a"), "state 'unlocked' with 20 cents") env.EmitNew("lock-a", "button-press!", nil) time.Sleep(100 * time.Millisecond) assert.Equal(checkCents("lock-a"), 00) assert.Equal(info("lock-a"), "state 'locked' with 0 cents") assert.Equal(grabCents(), 20) // 3rd run: put a screwdriwer in the lock. env.EmitNew("lock-a", "screwdriver!", nil) time.Sleep(100 * time.Millisecond) status := behaviors.RequestFSMStatus(env, "lock-a") assert.Equal(status.Done, true) assert.Nil(status.Error) // 4th run: try an illegal action. env.EmitNew("lock-b", "chewing-gum", nil) time.Sleep(100 * time.Millisecond) status = behaviors.RequestFSMStatus(env, "lock-b") assert.Equal(status.Done, true) assert.ErrorMatch(status.Error, "illegal topic in state 'locked': chewing-gum") }