| // Copyright (C) 2016 The Android Open Source Project |
| // |
| // 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 fsm_test |
| |
| import ( |
| "testing" |
| "time" |
| |
| "android.googlesource.com/platform/tools/gpu/framework/assert" |
| "android.googlesource.com/platform/tools/gpu/framework/fsm" |
| "android.googlesource.com/platform/tools/gpu/framework/log" |
| "android.googlesource.com/platform/tools/gpu/framework/task" |
| ) |
| |
| func stateChecker(name fsm.StateID) fsm.State { |
| return fsm.Builder(name, func(ctx log.Context, data interface{}) (task.Task, error) { |
| return func(ctx log.Context) error { |
| assert.For(ctx, "state").That(fsm.Get(ctx).State()).Equals(name) |
| return nil |
| }, nil |
| }) |
| } |
| func TestCurrentState(t *testing.T) { |
| ctx := assert.Context(t) |
| fsm.Run(ctx, fsm.MustCompile(fsm.FSM{ |
| States: []fsm.State{ |
| stateChecker("A"), |
| stateChecker("B"), |
| fsm.Exit("C"), |
| }, |
| Transitions: []fsm.Transition{ |
| {From: "A", To: "B"}, |
| {From: "B", To: "C"}, |
| }, |
| })) |
| } |
| |
| func TestTeardown(t *testing.T) { |
| ctx := assert.Context(t) |
| running, release := task.NewSignal() |
| inner, cancel := task.WithCancel(ctx) |
| handle := task.Go(ctx, func(ctx log.Context) error { |
| return fsm.Run(inner, fsm.MustCompile(fsm.FSM{ |
| Controller: func(ctx log.Context) error { |
| release(ctx) |
| return nil |
| }, |
| States: []fsm.State{ |
| fsm.Idle("Init"), |
| }, |
| })) |
| }) |
| running.Wait() |
| cancel() |
| assert.For(ctx, "FSM complete").That(handle.TryWait(time.Second)).Equals(true) |
| } |
| |
| func TestControllerFail(t *testing.T) { |
| ctx := assert.Context(t) |
| handle := task.Go(ctx, func(ctx log.Context) error { |
| return fsm.Run(ctx, fsm.MustCompile(fsm.FSM{ |
| Controller: func(ctx log.Context) error { |
| return ctx.AsError("Controller error") |
| }, |
| States: []fsm.State{ |
| fsm.Idle("Init"), |
| }, |
| })) |
| }) |
| if !handle.TryWait(time.Second) { |
| ctx.Error().Log("FSM did not complete") |
| return |
| } |
| assert.With(ctx).ThatError(handle.Result()).HasMessage("Error:Controller error") |
| } |
| |
| func TestTriggerOverride(t *testing.T) { |
| ctx := assert.Context(t) |
| did := "?" |
| fsm.Run(ctx, fsm.MustCompile(fsm.FSM{ |
| States: []fsm.State{ |
| fsm.Do("A", func(ctx log.Context) error { |
| fsm.Get(ctx).Trigger(ctx, "dob") |
| fsm.Get(ctx).Trigger(ctx, "doc") |
| return nil |
| }), |
| fsm.Do("B", func(ctx log.Context) error { did = "b"; return nil }), |
| fsm.Do("C", func(ctx log.Context) error { did = "c"; return nil }), |
| }, |
| Transitions: []fsm.Transition{ |
| {From: "A", Event: "dob", To: "B"}, |
| {From: "A", Event: "doc", To: "C"}, |
| }, |
| })) |
| assert.With(ctx).That(did).Equals("c") |
| } |
| |
| func TestBadTrigger(t *testing.T) { |
| ctx := assert.Context(t) |
| fsm.Run(ctx, fsm.MustCompile(fsm.FSM{ |
| States: []fsm.State{ |
| fsm.Do("A", func(ctx log.Context) error { |
| _, err := fsm.Get(ctx).Trigger(ctx, "bad") |
| assert.With(ctx).ThatError(err).HasMessage("Error:Invalid event") |
| return nil |
| }), |
| }, |
| })) |
| } |
| |
| func TestNotRunningTrigger(t *testing.T) { |
| ctx := assert.Context(t) |
| var instance *fsm.Instance |
| fsm.Run(ctx, fsm.MustCompile(fsm.FSM{ |
| States: []fsm.State{ |
| fsm.Do("A", func(ctx log.Context) error { |
| instance = fsm.Get(ctx) |
| return nil |
| }), |
| }, |
| })) |
| _, err := instance.Trigger(ctx, nil) |
| assert.With(ctx).ThatError(err).HasMessage("Error:Transition when not running") |
| } |
| |
| func TestData(t *testing.T) { |
| ctx := assert.Context(t) |
| myData := 4 |
| fsm.RunWith(ctx, myData, fsm.MustCompile(fsm.FSM{ |
| States: []fsm.State{ |
| fsm.Do("A", func(ctx log.Context) error { |
| assert.With(ctx).That(fsm.Get(ctx).Data()).Equals(myData) |
| return nil |
| }), |
| }, |
| })) |
| } |