From 3aa405ce83ae0326a7bcea28b6a278f5582f325d Mon Sep 17 00:00:00 2001 From: qiaozhou Date: Fri, 24 Mar 2023 00:20:26 +0800 Subject: [PATCH 1/2] junit5 unit test --- .../cola/test/junit5/AllTestSuites.java | 11 + .../test/junit5/StateMachinePlantUMLTest.java | 196 ++++++++++++++++++ .../cola/test/junit5/StateMachineTest.java | 188 +++++++++++++++++ .../test/junit5/StateMachineUnNormalTest.java | 88 ++++++++ 4 files changed, 483 insertions(+) create mode 100644 cola-components/cola-component-statemachine/src/test/java/com/alibaba/cola/test/junit5/AllTestSuites.java create mode 100644 cola-components/cola-component-statemachine/src/test/java/com/alibaba/cola/test/junit5/StateMachinePlantUMLTest.java create mode 100644 cola-components/cola-component-statemachine/src/test/java/com/alibaba/cola/test/junit5/StateMachineTest.java create mode 100644 cola-components/cola-component-statemachine/src/test/java/com/alibaba/cola/test/junit5/StateMachineUnNormalTest.java diff --git a/cola-components/cola-component-statemachine/src/test/java/com/alibaba/cola/test/junit5/AllTestSuites.java b/cola-components/cola-component-statemachine/src/test/java/com/alibaba/cola/test/junit5/AllTestSuites.java new file mode 100644 index 000000000..fb0f1991a --- /dev/null +++ b/cola-components/cola-component-statemachine/src/test/java/com/alibaba/cola/test/junit5/AllTestSuites.java @@ -0,0 +1,11 @@ +package com.alibaba.cola.test.junit5; + +import org.junit.platform.suite.api.SelectPackages; +import org.junit.platform.suite.api.SuiteDisplayName; +import org.junit.runner.RunWith; + +@RunWith(org.junit.platform.runner.JUnitPlatform.class) +@SuiteDisplayName("suite launcher") +@SelectPackages("com.alibaba.cola.test.junit5") +public class AllTestSuites { +} diff --git a/cola-components/cola-component-statemachine/src/test/java/com/alibaba/cola/test/junit5/StateMachinePlantUMLTest.java b/cola-components/cola-component-statemachine/src/test/java/com/alibaba/cola/test/junit5/StateMachinePlantUMLTest.java new file mode 100644 index 000000000..4173c459b --- /dev/null +++ b/cola-components/cola-component-statemachine/src/test/java/com/alibaba/cola/test/junit5/StateMachinePlantUMLTest.java @@ -0,0 +1,196 @@ +package com.alibaba.cola.test.junit5; + +import com.alibaba.cola.statemachine.Action; +import com.alibaba.cola.statemachine.Condition; +import com.alibaba.cola.statemachine.StateMachine; +import com.alibaba.cola.statemachine.builder.StateMachineBuilder; +import com.alibaba.cola.statemachine.builder.StateMachineBuilderFactory; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.stream.Stream; + +import static com.alibaba.cola.test.junit5.StateMachinePlantUMLTest.PriceAdjustmentTaskEventEnum.*; +import static com.alibaba.cola.test.junit5.StateMachinePlantUMLTest.PriceAdjustmentTaskStatusEnum.*; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * StateMachinePlantUMLTest + * + * @author cookie lin + * @date 2023-03-08 7:53 PM + */ +public class StateMachinePlantUMLTest { + + enum PriceAdjustmentTaskStatusEnum { + /** + * 开始状态 + */ + None, + /** + * 待商家处理 + */ + Supplier_Processing, + /** + * 待控商小二处理 + */ + Supplier_Manager_Processing, + /** + * 待价格管控小二处理 + */ + Price_Manager_Processing, + /** + * 退出 + */ + Closed + } + + enum PriceAdjustmentTaskEventEnum { + + // 系统事件 + Create, + Normal_Update, + /** + * 合理价变更 + */ + P0_Changed, + /** + * 页面价变合理 + */ + Page_Price_changed, + + // 商家事件 + Supplier_Reject, + Supplier_Agree, + Supplier_Timeout, + + // 控商小二事件 + Apply_Over_P0_Sell, + + // 价格小二事件 + Agree_Over_P0_Sell, + Reject_Over_P0_Sell; + + } + + @Test + @DisplayName("test generated content by plantuml") + public void testPlantUML(){ + StateMachineBuilder builder = StateMachineBuilderFactory.create(); + + builder.externalTransition() + .from(None) + .to(Supplier_Processing) + .on(Create) + .when(checkCondition()) + .perform(doAction()); + + // 商家调价 + Stream.of(Supplier_Processing, Supplier_Manager_Processing, Price_Manager_Processing) + .forEach(status -> + builder.externalTransition() + .from(status) + .to(Closed) + .on(Supplier_Agree) + .when(checkCondition()) + .perform(doAction()) + ); + + // 商家 -上升至-> 控商小二 + builder.externalTransition() + .from(Supplier_Processing) + .to(Supplier_Manager_Processing) + .on(Supplier_Reject) + .when(checkCondition()) + .perform(doAction()); + + builder.externalTransition() + .from(Supplier_Processing) + .to(Supplier_Manager_Processing) + .on(Supplier_Timeout) + .when(checkCondition()) + .perform(doAction()); + + // 申请申请高于P0售卖 + builder.externalTransition() + .from(Supplier_Manager_Processing) + .to(Price_Manager_Processing) + .on(Apply_Over_P0_Sell) + .when(checkCondition()) + .perform(doAction()); + + // 同意高于P0价售卖 + builder.externalTransition() + .from(Price_Manager_Processing) + .to(Closed) + .on(Agree_Over_P0_Sell) + .when(checkCondition()) + .perform(doAction()); + + // 拒绝高于P0价售卖 + builder.externalTransition() + .from(Price_Manager_Processing) + .to(Supplier_Manager_Processing) + .on(Reject_Over_P0_Sell) + .when(checkCondition()) + .perform(doAction()); + + // 普通字段更新事件 + Stream.of(Supplier_Processing, Supplier_Manager_Processing, Price_Manager_Processing) + .forEach(status -> builder + .internalTransition() + .within(status) + .on(Normal_Update) + .when(checkCondition()) + .perform(doAction()) + ); + + // P0价变更事件、页面价高于合理价事件 + Stream.of(P0_Changed, Page_Price_changed) + .forEach(event -> builder.externalTransitions() + .fromAmong(Supplier_Processing, Supplier_Manager_Processing, Price_Manager_Processing) + .to(Closed) + .on(event) + .when(checkCondition()) + .perform(doAction())); + + StateMachine stateMachine = builder.build("AdjustPriceTask"); + String plantUML = stateMachine.generatePlantUML(); + + String[] expected = new String[] { + "@startuml", + "Supplier_Processing --> Closed : Supplier_Agree", + "Supplier_Processing --> Closed : P0_Changed", + "Supplier_Processing --> Supplier_Manager_Processing : Supplier_Timeout", + "Supplier_Processing --> Closed : Page_Price_changed", + "Supplier_Processing --> Supplier_Processing : Normal_Update", + "Supplier_Processing --> Supplier_Manager_Processing : Supplier_Reject", + "Price_Manager_Processing --> Closed : Supplier_Agree", + "Price_Manager_Processing --> Closed : P0_Changed", + "Price_Manager_Processing --> Supplier_Manager_Processing : Reject_Over_P0_Sell", + "Price_Manager_Processing --> Closed : Page_Price_changed", + "Price_Manager_Processing --> Closed : Agree_Over_P0_Sell", + "Price_Manager_Processing --> Price_Manager_Processing : Normal_Update", + "None --> Supplier_Processing : Create", + "Supplier_Manager_Processing --> Supplier_Manager_Processing : Normal_Update", + "Supplier_Manager_Processing --> Closed : Page_Price_changed", + "Supplier_Manager_Processing --> Closed : Supplier_Agree", + "Supplier_Manager_Processing --> Price_Manager_Processing : Apply_Over_P0_Sell", + "Supplier_Manager_Processing --> Closed : P0_Changed", + "@enduml" + }; + + for (String s : expected) { + assertTrue(plantUML.contains(s)); + } + + } + + private Condition checkCondition() { + return (ctx) -> true; + } + + private Action doAction() { + return (from, to, event, ctx)-> System.out.println(ctx.operator+" is operating "+ctx.entityId+" from:"+from+" to:"+to+" on:"+event); + } +} diff --git a/cola-components/cola-component-statemachine/src/test/java/com/alibaba/cola/test/junit5/StateMachineTest.java b/cola-components/cola-component-statemachine/src/test/java/com/alibaba/cola/test/junit5/StateMachineTest.java new file mode 100644 index 000000000..b48005071 --- /dev/null +++ b/cola-components/cola-component-statemachine/src/test/java/com/alibaba/cola/test/junit5/StateMachineTest.java @@ -0,0 +1,188 @@ +package com.alibaba.cola.test.junit5; + +import com.alibaba.cola.statemachine.Action; +import com.alibaba.cola.statemachine.Condition; +import com.alibaba.cola.statemachine.StateMachine; +import com.alibaba.cola.statemachine.StateMachineFactory; +import com.alibaba.cola.statemachine.builder.StateMachineBuilder; +import com.alibaba.cola.statemachine.builder.StateMachineBuilderFactory; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * StateMachineTest + * + * @author cookie Lin + * @date 2023-03-08 12:19 PM + */ +public class StateMachineTest { + + static String MACHINE_ID = "TestStateMachine"; + + enum States { + STATE1, STATE2, STATE3, STATE4 + } + + enum Events { + EVENT1, EVENT2, EVENT3, EVENT4, INTERNAL_EVENT + } + + static class Context{ + String operator = "cookie"; + String entityId = "123465"; + } + + @Test + @DisplayName("test whether the state is changed when the condition is met") + public void testExternalNormal(){ + StateMachineBuilder builder = StateMachineBuilderFactory.create(); + builder.externalTransition() + .from(States.STATE1) + .to(States.STATE2) + .on(Events.EVENT1) + .when(checkCondition()) + .perform(doAction()); + + StateMachine stateMachine = builder.build(MACHINE_ID); + States target = stateMachine.fireEvent(States.STATE1, Events.EVENT1, new Context()); + assertEquals(States.STATE2, target); + } + + @Test + @DisplayName("test whether the state is changed when the condition is met and raw state is among multiple states") + public void testExternalTransitionsNormal(){ + StateMachineBuilder builder = StateMachineBuilderFactory.create(); + builder.externalTransitions() + .fromAmong(States.STATE1, States.STATE2, States.STATE3) + .to(States.STATE4) + .on(Events.EVENT1) + .when(checkCondition()) + .perform(doAction()); + + StateMachine stateMachine = builder.build(MACHINE_ID+"1"); + States target = stateMachine.fireEvent(States.STATE2, Events.EVENT1, new Context()); + assertEquals(States.STATE4, target); + } + + @Test + @DisplayName("test whether the state is changed when internal event is fired") + public void testInternalNormal(){ + StateMachineBuilder builder = StateMachineBuilderFactory.create(); + builder.internalTransition() + .within(States.STATE1) + .on(Events.INTERNAL_EVENT) + .when(checkCondition()) + .perform(doAction()); + StateMachine stateMachine = builder.build(MACHINE_ID+"2"); + + stateMachine.fireEvent(States.STATE1, Events.EVENT1, new Context()); + States target = stateMachine.fireEvent(States.STATE1, Events.INTERNAL_EVENT, new Context()); + assertEquals(States.STATE1, target); + } + + @Test + @DisplayName("test whether the state is changed when external and internal event is fired") + public void testExternalInternalNormal(){ + StateMachine stateMachine = buildStateMachine("testExternalInternalNormal"); + + Context context = new Context(); + States target = stateMachine.fireEvent(States.STATE1, Events.EVENT1, context); + assertEquals(States.STATE2, target); + target = stateMachine.fireEvent(States.STATE2, Events.INTERNAL_EVENT, context); + assertEquals(States.STATE2, target); + target = stateMachine.fireEvent(States.STATE2, Events.EVENT2, context); + assertEquals(States.STATE1, target); + target = stateMachine.fireEvent(States.STATE1, Events.EVENT3, context); + assertEquals(States.STATE3, target); + } + + private StateMachine buildStateMachine(String machineId) { + StateMachineBuilder builder = StateMachineBuilderFactory.create(); + builder.externalTransition() + .from(States.STATE1) + .to(States.STATE2) + .on(Events.EVENT1) + .when(checkCondition()) + .perform(doAction()); + + builder.internalTransition() + .within(States.STATE2) + .on(Events.INTERNAL_EVENT) + .when(checkCondition()) + .perform(doAction()); + + builder.externalTransition() + .from(States.STATE2) + .to(States.STATE1) + .on(Events.EVENT2) + .when(checkCondition()) + .perform(doAction()); + + builder.externalTransition() + .from(States.STATE1) + .to(States.STATE3) + .on(Events.EVENT3) + .when(checkCondition()) + .perform(doAction()); + + builder.externalTransitions() + .fromAmong(States.STATE1, States.STATE2, States.STATE3) + .to(States.STATE4) + .on(Events.EVENT4) + .when(checkCondition()) + .perform(doAction()); + + builder.build(machineId); + + StateMachine stateMachine = StateMachineFactory.get(machineId); + stateMachine.showStateMachine(); + return stateMachine; + } + + @Test + @DisplayName("test whether the state is changed when external and internal event is fired by multiple threads") + public void testMultiThread(){ + buildStateMachine("testMultiThread"); + + for(int i=0 ; i<10 ; i++){ + Thread thread = new Thread(()->{ + StateMachine stateMachine = StateMachineFactory.get("testMultiThread"); + States target = stateMachine.fireEvent(States.STATE1, Events.EVENT1, new Context()); + assertEquals(States.STATE2, target); + }); + thread.start(); + } + + + for(int i=0 ; i<10 ; i++) { + Thread thread = new Thread(() -> { + StateMachine stateMachine = StateMachineFactory.get("testMultiThread"); + States target = stateMachine.fireEvent(States.STATE1, Events.EVENT4, new Context()); + assertEquals(States.STATE4, target); + }); + thread.start(); + } + + for(int i=0 ; i<10 ; i++) { + Thread thread = new Thread(() -> { + StateMachine stateMachine = StateMachineFactory.get("testMultiThread"); + States target = stateMachine.fireEvent(States.STATE1, Events.EVENT3, new Context()); + assertEquals(States.STATE3, target); + }); + thread.start(); + } + + } + + + private Condition checkCondition() { + return (ctx) -> true; + } + + private Action doAction() { + return (from, to, event, ctx)-> System.out.println(ctx.operator+" is operating "+ctx.entityId+" from:"+from+" to:"+to+" on:"+event); + } + +} diff --git a/cola-components/cola-component-statemachine/src/test/java/com/alibaba/cola/test/junit5/StateMachineUnNormalTest.java b/cola-components/cola-component-statemachine/src/test/java/com/alibaba/cola/test/junit5/StateMachineUnNormalTest.java new file mode 100644 index 000000000..fe620fc9e --- /dev/null +++ b/cola-components/cola-component-statemachine/src/test/java/com/alibaba/cola/test/junit5/StateMachineUnNormalTest.java @@ -0,0 +1,88 @@ +package com.alibaba.cola.test.junit5; + +import com.alibaba.cola.statemachine.Action; +import com.alibaba.cola.statemachine.Condition; +import com.alibaba.cola.statemachine.StateMachine; +import com.alibaba.cola.statemachine.builder.StateMachineBuilder; +import com.alibaba.cola.statemachine.builder.StateMachineBuilderFactory; +import com.alibaba.cola.statemachine.impl.StateMachineException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +/** + * StateMachineUnNormalTest + * + * @author cookie lin + * @date 2023-03-08 5:52 PM + */ +public class StateMachineUnNormalTest { + + @Test + @DisplayName("the state is unchanged when the condition is no met") + public void testConditionNotMeet(){ + StateMachineBuilder builder = StateMachineBuilderFactory.create(); + builder.externalTransition() + .from(StateMachineTest.States.STATE1) + .to(StateMachineTest.States.STATE2) + .on(StateMachineTest.Events.EVENT1) + .when(checkConditionFalse()) + .perform(doAction()); + + StateMachine stateMachine = builder.build("NotMeetConditionMachine"); + StateMachineTest.States target = stateMachine.fireEvent(StateMachineTest.States.STATE1, StateMachineTest.Events.EVENT1, new StateMachineTest.Context()); + Assertions.assertEquals(StateMachineTest.States.STATE1,target); + } + + + @Test + @DisplayName("StateMachineException is thrown when duplicated transition is defined") + public void testDuplicatedTransition(){ + StateMachineBuilder builder = StateMachineBuilderFactory.create(); + Assertions.assertThrows(StateMachineException.class, () -> { + builder.externalTransition() + .from(StateMachineTest.States.STATE1) + .to(StateMachineTest.States.STATE2) + .on(StateMachineTest.Events.EVENT1) + .when(checkCondition()) + .perform(doAction()); + + builder.externalTransition() + .from(StateMachineTest.States.STATE1) + .to(StateMachineTest.States.STATE2) + .on(StateMachineTest.Events.EVENT1) + .when(checkCondition()) + .perform(doAction()); + }); + + } + + @Test + @DisplayName("StateMachineException is thrown when duplicated statemachine is defined") + public void testDuplicateMachine(){ + StateMachineBuilder builder = StateMachineBuilderFactory.create(); + Assertions.assertThrows(StateMachineException.class, () -> { + builder.externalTransition() + .from(StateMachineTest.States.STATE1) + .to(StateMachineTest.States.STATE2) + .on(StateMachineTest.Events.EVENT1) + .when(checkCondition()) + .perform(doAction()); + + builder.build("DuplicatedMachine"); + builder.build("DuplicatedMachine"); + }); + } + + private Condition checkCondition() { + return (ctx) -> true; + } + + private Condition checkConditionFalse() { + return (ctx) -> false; + } + + private Action doAction() { + return (from, to, event, ctx)-> System.out.println(ctx.operator+" is operating "+ctx.entityId+"from:"+from+" to:"+to+" on:"+event); + } +} From 821cab20d7c4066d57df463137994ffa5bae61e7 Mon Sep 17 00:00:00 2001 From: qiaozhou Date: Fri, 24 Mar 2023 00:24:50 +0800 Subject: [PATCH 2/2] junit5 unit test --- cola-components/pom.xml | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/cola-components/pom.xml b/cola-components/pom.xml index 31073eb2d..d8413093d 100644 --- a/cola-components/pom.xml +++ b/cola-components/pom.xml @@ -84,6 +84,37 @@ junit test + + org.junit.platform + junit-platform-launcher + test + + + org.junit.platform + junit-platform-runner + test + + + org.junit.jupiter + junit-jupiter-params + test + + + org.junit.vintage + junit-vintage-engine + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.assertj + assertj-core + 3.11.1 + test + @@ -95,7 +126,13 @@ pom import - + + org.junit + junit-bom + 5.9.2 + pom + import + com.alibaba