diff --git a/.github/workflows/code_generation_tests.yml b/.github/workflows/code_generation_tests.yml new file mode 100644 index 0000000..2f6b9cd --- /dev/null +++ b/.github/workflows/code_generation_tests.yml @@ -0,0 +1,422 @@ +name: Code Generation Tests + +on: + push: + pull_request: + +jobs: + build-artifacts: + runs-on: ubuntu-latest + steps: + - name: Checkout current repository + uses: actions/checkout@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '8.0.x' + + - name: Run generate python3 + run: | + dotnet run --project src/Stater.CodeGeneration.App artifacts/python/ 0 python3 + + - name: Run generate javascript + run: | + dotnet run --project src/Stater.CodeGeneration.App artifacts/js/ 0 javascript + + - name: Run generate typescript + run: | + dotnet run --project src/Stater.CodeGeneration.App artifacts/ts/ 0 typescript + + - name: Run generate kotlin + run: | + dotnet run --project src/Stater.CodeGeneration.App artifacts/kotlin/ 0 kotlin + + - name: Run generate java + run: | + dotnet run --project src/Stater.CodeGeneration.App artifacts/java/ 0 java + + - name: Run generate csharp + run: | + dotnet run --project src/Stater.CodeGeneration.App artifacts/csharp/ 0 csharp + + - name: Run generate c++ + run: | + dotnet run --project src/Stater.CodeGeneration.App artifacts/cplusplus/ 0 cplusplus + + - name: Save python3 generated files + uses: actions/upload-artifact@v4 + with: + name: python-generated-files + path: artifacts/python/* + + - name: Save js generated files + uses: actions/upload-artifact@v4 + with: + name: js-generated-files + path: artifacts/js/* + + - name: Save ts generated files + uses: actions/upload-artifact@v4 + with: + name: ts-generated-files + path: artifacts/ts/* + + - name: Save kotlin generated files + uses: actions/upload-artifact@v4 + with: + name: kotlin-generated-files + path: artifacts/kotlin/* + + - name: Save java generated files + uses: actions/upload-artifact@v4 + with: + name: java-generated-files + path: artifacts/java/* + + - name: Save csharp generated files + uses: actions/upload-artifact@v4 + with: + name: csharp-generated-files + path: artifacts/csharp/* + + - name: Save c++ generated files + uses: actions/upload-artifact@v4 + with: + name: cplusplus-generated-files + path: artifacts/cplusplus/* + + test-python: + needs: [ build-artifacts ] + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [ '3.9', '3.10', '3.11', '3.12', '3.13' ] + steps: + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + + - name: Install Poetry + run: | + python -m pip install --upgrade pip + pip install poetry + + - name: Checkout specific folder from another repository + uses: actions/checkout@v4 + with: + repository: PhoenixNazarov/stater-fsm-code + + - name: Install dependencies + run: | + cd projects/python + poetry install --no-root + + - name: Install pytest and pytest-cov + run: | + cd projects/python + poetry add --dev pytest pytest-cov + + - name: Download generated files + uses: actions/download-artifact@v4 + with: + name: python-generated-files + path: projects/python/test/ + + - name: Run tests with pytest + run: | + cd projects/python + poetry run pytest --cov --junitxml=junit.xml -o junit_family=legacy + + test-javascript: + needs: [ build-artifacts ] + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [ '16', '18', '20' ] + steps: + - name: Checkout specific folder from another repository + uses: actions/checkout@v4 + with: + repository: PhoenixNazarov/stater-fsm-code + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + cache: 'npm' + cache-dependency-path: projects/js/package-lock.json + + - name: Install dependencies + run: | + cd projects/js + npm ci + + - name: Download generated files + uses: actions/download-artifact@v4 + with: + name: js-generated-files + path: projects/js/src/ + + - name: Run tests with Jest + run: | + cd projects/js + npm test -- --coverage --json --outputFile=test-results.json + + test-typescript: + needs: [ build-artifacts ] + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [ '16', '18', '20' ] + steps: + - name: Checkout specific folder from another repository + uses: actions/checkout@v4 + with: + repository: PhoenixNazarov/stater-fsm-code + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + cache: 'npm' + cache-dependency-path: projects/js/package-lock.json + + - name: Install dependencies + run: | + cd projects/ts + npm ci + + - name: Download generated files + uses: actions/download-artifact@v4 + with: + name: ts-generated-files + path: projects/ts/src/ + + - name: Run tests with Jest + run: | + cd projects/ts + npm test -- --coverage --json --outputFile=test-results.json + + test-kotlin: + needs: [ build-artifacts ] + runs-on: ubuntu-latest + strategy: + matrix: + java-version: [ '17', '21' ] + steps: + - name: Checkout specific folder from another repository + uses: actions/checkout@v4 + with: + repository: PhoenixNazarov/stater-fsm-code + + - name: Download generated files + uses: actions/download-artifact@v4 + with: + name: kotlin-generated-files + path: projects/kotlin/src/ + + - name: Set up JDK + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: ${{ matrix.java-version }} + cache: 'gradle' + + - name: Build project + run: | + cd projects/kotlin + ./gradlew build + + - name: Run tests with coverage + run: | + cd projects/kotlin + ./gradlew test jacocoTestReport --console=plain + + - name: Show test results in console + run: | + cat projects/kotlin/build/test-results/test/TEST-*.xml || true + + - name: Show coverage summary in console + run: | + cd projects/kotlin + ./gradlew jacocoTestCoverageVerification --console=plain || true + + - name: Create JAR + run: | + cd projects/kotlin + ./gradlew jar + + test-java: + needs: [ build-artifacts ] + runs-on: ubuntu-latest + strategy: + matrix: + java-version: [ 17, 21 ] + steps: + - name: Checkout specific folder from another repository + uses: actions/checkout@v4 + with: + repository: PhoenixNazarov/stater-fsm-code + + - name: Download generated files + uses: actions/download-artifact@v4 + with: + name: java-generated-files + path: projects/java/src/ + + - name: Set up JDK + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: ${{ matrix.java-version }} + cache: 'maven' + + - name: Run tests with coverage + run: | + cd projects/java + mvn clean verify -P java${{ matrix.java-version }} + + - name: Create JAR + run: | + cd projects/java + mvn clean package -P java${{ matrix.java-version }} + + test-csharp: + needs: [ build-artifacts ] + runs-on: ubuntu-latest + strategy: + matrix: + dotnet-version: [8.0] + steps: + - name: Checkout specific folder from another repository + uses: actions/checkout@v4 + with: + repository: PhoenixNazarov/stater-fsm-code + + - name: Set up .NET SDK + uses: actions/setup-dotnet@v3 + with: + dotnet-version: ${{ matrix.dotnet-version }} + + - name: Download generated files + uses: actions/download-artifact@v4 + with: + name: csharp-generated-files + path: projects/csharp/Stater.StateMachine.Lib/ + + - name: Restore dependencies + run: | + cd projects/csharp/Stater.StateMachine.Lib + dotnet restore + + - name: Build the project + run: | + cd projects/csharp/Stater.StateMachine.Lib + dotnet build --configuration Release + + - name: Run tests with coverage + run: | + cd projects/csharp/Stater.StateMachine.Lib + dotnet test --configuration Release --collect:"XPlat Code Coverage" + + test-cplusplus: + needs: [ build-artifacts ] + runs-on: ubuntu-latest + strategy: + matrix: + compiler: + - { cc: gcc-11, cxx: g++-11 } + - { cc: gcc-12, cxx: g++-12 } + - { cc: gcc-13, cxx: g++-13 } + - { cc: clang-16, cxx: clang++-16 } + - { cc: clang-17, cxx: clang++-17 } + fail-fast: false + + steps: + - name: Checkout specific folder from another repository + uses: actions/checkout@v4 + with: + repository: PhoenixNazarov/stater-fsm-code + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y lcov cmake + sudo apt-get install -y ${{ matrix.compiler.cc }} ${{ matrix.compiler.cxx }} + if [ "${{ matrix.compiler.cc }}" = "clang-16" ]; then + sudo apt-get install -y llvm-16 + elif [ "${{ matrix.compiler.cc }}" = "clang-17" ]; then + sudo apt-get install -y llvm-17 + fi + pip install gcovr + + - name: Download generated files + uses: actions/download-artifact@v4 + with: + name: cplusplus-generated-files + path: projects/cPlusPlus/ + + - name: Configure CMake + env: + CC: ${{ matrix.compiler.cc }} + CXX: ${{ matrix.compiler.cxx }} + run: | + cd projects/cPlusPlus + sh auto_config_cmake.sh fsm + cmake -B build -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="--coverage" + + - name: Build + env: + CC: ${{ matrix.compiler.cc }} + CXX: ${{ matrix.compiler.cxx }} + run: | + cd projects/cPlusPlus + if [[ "${{ matrix.compiler.cc }}" == clang-* ]]; then + export CFLAGS="-fprofile-instr-generate -fcoverage-mapping" + export CXXFLAGS="-fprofile-instr-generate -fcoverage-mapping" + else + export CFLAGS="--coverage" + export CXXFLAGS="--coverage" + fi + + cmake -B build -S . \ + -DCMAKE_BUILD_TYPE=Debug \ + -DCMAKE_C_COMPILER=${{ matrix.compiler.cc }} \ + -DCMAKE_CXX_COMPILER=${{ matrix.compiler.cxx }} \ + -DCMAKE_C_FLAGS="${CFLAGS}" \ + -DCMAKE_CXX_FLAGS="${CXXFLAGS}" + + cmake --build build + + - name: Run tests + run: | + cd projects/cPlusPlus/build + if [[ "${{ matrix.compiler.cc }}" == clang-* ]]; then + export LLVM_PROFILE_FILE="coverage-%p.profraw" + else + export LLVM_PROFILE_FILE="" + fi + ctest --output-on-failure + + - name: Generate and show detailed coverage + run: | + cd projects/cPlusPlus/build + if [ "${{ matrix.compiler.cc }}" = "clang-16" ]; then + llvm-profdata-16 merge -sparse coverage-*.profraw -o coverage.profdata + llvm-cov-16 report ./generated_test -instr-profile=coverage.profdata --ignore-filename-regex=".*(gtest|nlohmann|CMakeFiles).*" + elif [ "${{ matrix.compiler.cc }}" = "clang-17" ]; then + llvm-profdata-17 merge -sparse coverage-*.profraw -o coverage.profdata + llvm-cov-17 report ./generated_test -instr-profile=coverage.profdata --ignore-filename-regex=".*(gtest|nlohmann|CMakeFiles).*" + else + if [ "${{ matrix.compiler.cc }}" = "gcc-11" ]; then + GCOV_EXEC=gcov-11 + elif [ "${{ matrix.compiler.cc }}" = "gcc-12" ]; then + GCOV_EXEC=gcov-12 + elif [ "${{ matrix.compiler.cc }}" = "gcc-13" ]; then + GCOV_EXEC=gcov-13 + fi + gcovr -r .. --exclude '.*gtest.*' --exclude '.*nlohmann.*' --gcov-executable $GCOV_EXEC --txt + fi + \ No newline at end of file diff --git a/.github/workflows/project_tests.yml b/.github/workflows/project_tests.yml new file mode 100644 index 0000000..6334ea9 --- /dev/null +++ b/.github/workflows/project_tests.yml @@ -0,0 +1,29 @@ +name: c# Tests and Coverage + +on: + push: + pull_request: + +jobs: + build-and-test: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up .NET SDK + uses: actions/setup-dotnet@v3 + with: + dotnet-version: 8.0 + + - name: Restore dependencies + run: | + dotnet restore + + - name: Build the project + run: | + dotnet build --configuration Release + + - name: Run tests with coverage + run: | + dotnet test --configuration Release --collect:"XPlat Code Coverage" diff --git a/.gitignore b/.gitignore index 2583106..74c4596 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,140 @@ TestResults StaterV/bu **/.svn FBDK/FBParser/exp -.vs +.idea +.lib/* +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +[Bb]in/ +[Oo]bj/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.svclog +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml +*.pubxml +*.azurePubxml + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +packages/ +## TODO: If the tool you use requires repositories.config, also uncomment the next line +!packages/repositories.config + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +![Ss]tyle[Cc]op.targets +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml + +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + +# ========================= +# Windows detritus +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac desktop service store files +.DS_Store + +_NCrunch* +.vs= +**.received.** diff --git a/BasePlugin/BasePlugin.csproj b/BasePlugin/BasePlugin.csproj new file mode 100644 index 0000000..3a63532 --- /dev/null +++ b/BasePlugin/BasePlugin.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/BasePlugin/Class1.cs b/BasePlugin/Class1.cs new file mode 100644 index 0000000..83d91b1 --- /dev/null +++ b/BasePlugin/Class1.cs @@ -0,0 +1,5 @@ +namespace BasePlugin; + +public class Class1 +{ +} \ No newline at end of file diff --git a/CFuncGenerator/CFuncGenerator.csproj b/CFuncGenerator1/CFuncGenerator1.csproj similarity index 98% rename from CFuncGenerator/CFuncGenerator.csproj rename to CFuncGenerator1/CFuncGenerator1.csproj index 099ecf0..241f3b6 100644 --- a/CFuncGenerator/CFuncGenerator.csproj +++ b/CFuncGenerator1/CFuncGenerator1.csproj @@ -9,7 +9,7 @@ Library Properties CFuncGenerator - CFuncGenerator + CFuncGenerator1 v4.0 512 diff --git a/CFuncGenerator/CGenerator.cs b/CFuncGenerator1/CGenerator.cs similarity index 99% rename from CFuncGenerator/CGenerator.cs rename to CFuncGenerator1/CGenerator.cs index 1d575a2..ea1177e 100644 --- a/CFuncGenerator/CGenerator.cs +++ b/CFuncGenerator1/CGenerator.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; using PluginData; namespace CFuncGenerator diff --git a/CFuncGenerator/CPlugin.cs b/CFuncGenerator1/CPlugin.cs similarity index 100% rename from CFuncGenerator/CPlugin.cs rename to CFuncGenerator1/CPlugin.cs diff --git a/CFuncGenerator/Properties/AssemblyInfo.cs b/CFuncGenerator1/Properties/AssemblyInfo.cs similarity index 93% rename from CFuncGenerator/Properties/AssemblyInfo.cs rename to CFuncGenerator1/Properties/AssemblyInfo.cs index 82991ee..f298866 100644 --- a/CFuncGenerator/Properties/AssemblyInfo.cs +++ b/CFuncGenerator1/Properties/AssemblyInfo.cs @@ -5,11 +5,11 @@ // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("CFuncGenerator")] +[assembly: AssemblyTitle("CFuncGenerator1")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("CFuncGenerator")] +[assembly: AssemblyProduct("CFuncGenerator1")] [assembly: AssemblyCopyright("Copyright © 2015")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/CSharpCodeGenerator/CSharpCodeGenerator.csproj b/CSharpCodeGenerator1/CSharpCodeGenerator1.csproj similarity index 98% rename from CSharpCodeGenerator/CSharpCodeGenerator.csproj rename to CSharpCodeGenerator1/CSharpCodeGenerator1.csproj index 2b7beb4..254b87c 100644 --- a/CSharpCodeGenerator/CSharpCodeGenerator.csproj +++ b/CSharpCodeGenerator1/CSharpCodeGenerator1.csproj @@ -9,7 +9,7 @@ Library Properties CSharpCodeGenerator - CSharpCodeGenerator + CSharpCodeGenerator1 v4.0 512 diff --git a/CSharpCodeGenerator/CSharpCodeGenerator_vs08.csproj b/CSharpCodeGenerator1/CSharpCodeGenerator_vs08.csproj similarity index 100% rename from CSharpCodeGenerator/CSharpCodeGenerator_vs08.csproj rename to CSharpCodeGenerator1/CSharpCodeGenerator_vs08.csproj diff --git a/CSharpCodeGenerator/Plugin.cs b/CSharpCodeGenerator1/Plugin.cs similarity index 100% rename from CSharpCodeGenerator/Plugin.cs rename to CSharpCodeGenerator1/Plugin.cs diff --git a/CSharpCodeGenerator/Properties/AssemblyInfo.cs b/CSharpCodeGenerator1/Properties/AssemblyInfo.cs similarity index 92% rename from CSharpCodeGenerator/Properties/AssemblyInfo.cs rename to CSharpCodeGenerator1/Properties/AssemblyInfo.cs index a49950f..1cfbf0b 100644 --- a/CSharpCodeGenerator/Properties/AssemblyInfo.cs +++ b/CSharpCodeGenerator1/Properties/AssemblyInfo.cs @@ -5,11 +5,11 @@ // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("CSharpCodeGenerator")] +[assembly: AssemblyTitle("CSharpCodeGenerator1")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Michael Lukin")] -[assembly: AssemblyProduct("CSharpCodeGenerator")] +[assembly: AssemblyProduct("CSharpCodeGenerator1")] [assembly: AssemblyCopyright("Copyright © Michael Lukin")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/README.md b/README.md new file mode 100644 index 0000000..dc4dbc6 --- /dev/null +++ b/README.md @@ -0,0 +1,108 @@ +# Stater: редактор конечного автомата + +Stater — это мощное приложение, разработанное для упрощения создания, управления и выполнения конечных автоматов с использованием фреймворка C# Avalonia. Stater идеально подходит для разработчиков и дизайнеров, которые имеют дело со сложной логикой состояний. Stater предоставляет интуитивно понятный интерфейс для проектирования и управления конечными автоматами для различных приложений. + +## Основные возможности + +- **Управление проектами:** Легкое создание и управление проектами, содержащими несколько конечных автоматов. +- **Редактирование конечного автомата:** Проектирование конечных автоматов с состояниями, переходами и условиями. +- **Моделирование выполнения:** Моделирование переходов состояний и отслеживание изменений в реальном времени. +- **Отмена/повтор действий:** Предоставляет функцию отмены/повтора для легкой навигации по различным этапам проектирования конечного автомата. +- **Поддержка плагинов:** Расширение функциональности с помощью пользовательских плагинов. +- **Ведение журнала и отслеживание переменных:** Мониторинг выполнения и состояний переменных во время моделирования. + +## Установка + +Клонируйте репозиторий и создайте приложение с помощью .NET с фреймворком Avalonia. + +```bash +dotnet build +dotnet run +``` + + +## Использование + +### Основные интерфейсы + +Stater использует несколько ключевых интерфейсов для обеспечения своей функциональности: + +- **`IProjectManager`**: управляет созданием проекта, загрузкой, сохранением и управлением конечными автоматами. +- **`IEditorManager`**: управляет взаимодействием пользователя с компонентами конечного автомата, такими как состояния, переходы и переменные. +- **`IExecutor`**: управляет моделированием выполнения конечных автоматов, включая запуск, остановку и пошаговое прохождение состояний. + +### Пример: создание конечного автомата + +Вот как можно программно создать конечный автомат и добавить состояния и переходы: + +```csharp +var projectManager = new ProjectManager(); +projectManager.CreateProject("Example Project"); +var stateMachine = projectManager.CreateStateMachine(); + +var state1 = projectManager.CreateState(); +var state2 = projectManager.CreateState(); + +var transition = projectManager.CreateTransition(state1, state2); + +projectManager.UpdateStateMachine(stateMachine); +``` + +## Stater.CodeGeneration +Генерация исходного кода из моделей конечных автоматов с использованием шаблонов и языковых адаптеров. + +Этот пакет предоставляет механизм генерации кода для различных языков программирования на основе внутренней модели автомата. Он гибко настраивается с помощью шаблонов и параметров генерации. + +Для каждого сгенерированного кода необходимо установить соответсвующую библиотеку [stater-fsm-code](https://github.com/PhoenixNazarov/stater-fsm-code). + +### Основные компоненты +- `CodeGenerator.cs`. Главная точка входа в процесс генерации. Координирует адаптеры, загрузку шаблонов и вывод итоговых файлов. +- `Entity/`. Модели данных, описывающие параметры генерации: + - `GenerationSettings.cs` — общие настройки генерации (язык, режим, путь и т.д.). + - `Language.cs` — перечисление поддерживаемых языков. + - `Mode.cs` — режимы генерации (например, с тестами / без тестов). +- `LanguageAdapter/`. Адаптеры для различных языков. Каждый из них отвечает за конкретный синтаксис, соглашения и поведение языка. Основаны на базовом классе `BaseLanguageAdapter`. + - `Base/` + - `BaseLanguageAdapter.cs` — абстрактный класс, реализующий общую логику адаптеров. + - `TemplateLoader.cs` — загрузка и обработка шаблонов Scriban. + +### Языковые адаптеры: +- `CSharpAdapter.cs` +- `PythonAdapter.cs` +- `JavaAdapter.cs` +- `JavaScriptAdapter.cs` +- `TypeScriptAdapter.cs` +- `KotlinAdapter.cs` +- `CPlusPlusAdapter.cs` + +`ScenarioFinder.cs`. + +Утилита для нахождения и анализа сценариев в модели автомата — возможно используется для генерации тестов или автоматизации переходов. + +`Stater.CodeGeneration.csproj`. + +Файл проекта .NET с зависимостями, настройками сборки и т.д. + +### Шаблоны: Templates/ +Scriban-шаблоны, используемые при генерации: + +`{language}.scriban` — основной шаблон генерации. + +`{language}-test.scriban` — шаблон для генерации unit-тестов. + +Поддерживаемые языки: + +- `c#`, `python`, `java`, `javascript`, `typescript`, `kotlin`, `c++` + +### Пример генерации +```c# +var settings = new GenerationSettings +{ + Language = Language.CSharp, + OutputDirectory = "./Generated", + Mode = Mode.Full +}; + +var generator = new CodeGenerator(); +generator.Generate(projectModel, settings); +``` diff --git a/SpinVeriff/SpinPlugin.cs b/SpinVeriff/SpinPlugin.cs index f9a6148..f0151ae 100644 --- a/SpinVeriff/SpinPlugin.cs +++ b/SpinVeriff/SpinPlugin.cs @@ -10,6 +10,9 @@ using StaterV.PluginManager; using StaterV.StateMachine; +// TODO: practice NEED + + namespace SpinVeriff { public class SpinPlugin : ButtonPlugin diff --git a/Stater.sln b/Stater.sln index ad663f5..829b841 100644 --- a/Stater.sln +++ b/Stater.sln @@ -1,53 +1,19 @@  Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{1B39C48B-5F4B-4556-A2B3-E4AC50F30B43}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stater", "src\Stater\Stater.csproj", "{EA81CCF1-284B-4E2D-8CB8-AE9C8EACC01E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StaterV", "StaterV\StaterV.csproj", "{B90AF5E3-3BFA-4501-ADAB-CF32D2677DB7}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stater.CodeGeneration.Tests", "src\Stater.CodeGeneration.Tests\Stater.CodeGeneration.Tests.csproj", "{879047E1-76DD-4892-AF8F-8EC562514AD7}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StaterWPF", "StaterWPF\StaterWPF.csproj", "{8506DC5F-90B6-421A-88E8-CB3C33CE0C91}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stater.Domain", "src\Stater.Domain\Stater.Domain.csproj", "{3A09EFE1-C88B-46E6-B0C8-00F7A9D00795}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FirstPlugin", "FirstPlugin\FirstPlugin.csproj", "{5B7A672B-3DB0-4406-9DF1-D1BAE6726BF7}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stater.CodeGeneration", "src\Stater.CodeGeneration\Stater.CodeGeneration.csproj", "{E7786CE3-7E88-456D-ADFE-11035E842ABB}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpCodeGenerator", "CSharpCodeGenerator\CSharpCodeGenerator.csproj", "{B21D8C78-FB92-4C38-8773-6ABB244BF407}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stater.SLXParser", "src\Stater.SLXParser\Stater.SLXParser.csproj", "{1CE08542-B4A2-4632-A066-68462E0BC603}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "Common\Common.csproj", "{542E45C9-9853-42DB-B1C5-1D540FA1700E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stater.CodeGeneration.App", "src\Stater.CodeGeneration.App\Stater.CodeGeneration.App.csproj", "{EA6A952C-2854-4031-94E0-724CCC388807}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CppCodeGenerator", "CppCodeGenerator\CppCodeGenerator.csproj", "{00BCE648-24B5-4523-8180-74841842DD3C}" - ProjectSection(ProjectDependencies) = postProject - {B90AF5E3-3BFA-4501-ADAB-CF32D2677DB7} = {B90AF5E3-3BFA-4501-ADAB-CF32D2677DB7} - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpinVeriff", "SpinVeriff\SpinVeriff.csproj", "{BFBB771A-D679-4C13-885D-BA6425773924}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpinVeriffWPF", "SpinVeriffWPF\SpinVeriffWPF.csproj", "{C4AF1EE4-CD8F-4A7B-9818-CBCBBCC7B2BC}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PluginData", "PluginData\PluginData.csproj", "{41A0B9E4-C529-4F6D-8F69-AB0EE1AE6951}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ind1", "Ind1\Ind1.csproj", "{29B57FE7-013D-49C5-AEBA-A062637D36A3}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSMultyThread", "CSMultyThread\CSMultyThread.csproj", "{FC4128C8-7183-4097-9DFC-1C168D41F42B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TextProcessor", "TextProcessor\TextProcessor.csproj", "{412DC173-85E2-4A92-B886-11F173CB40E4}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StaterVTest", "StaterVTest\StaterVTest.csproj", "{97A35264-A93D-46E4-9DCE-767D427DFA7D}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{16AA45D4-5DC2-4EA5-9016-ED33F6C3F07E}" - ProjectSection(SolutionItems) = preProject - Local.testsettings = Local.testsettings - Stater.vsmdi = Stater.vsmdi - TraceAndTestImpact.testsettings = TraceAndTestImpact.testsettings - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpinVeriffTest", "SpinVeriffTest\SpinVeriffTest.csproj", "{D2D3393E-2248-4406-8065-FF4AEF919AC3}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StateFlow", "StateFlow\StateFlow.csproj", "{2FC95B0A-B404-4E88-8FB0-11F357D2A7C1}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JavaMultyThread", "JavaMultyThread\JavaMultyThread.csproj", "{5E9FF3AA-0784-4B4A-BCD2-9CCBC39D4D66}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FBDK", "FBDK\FBDK.csproj", "{09FED13A-1642-496C-AE3F-F0A2770BE9A2}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CFuncGenerator", "CFuncGenerator\CFuncGenerator.csproj", "{EA67DB8A-BB10-4343-87A0-E91EDD783C8B}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stater.Domain.Tests", "src\Stater.Domain.Tests\Stater.Domain.Tests.csproj", "{D1E2AF9B-55A2-4198-8797-633ABA37AA81}" EndProject Global GlobalSection(TestCaseManagementSettings) = postSolution @@ -58,93 +24,38 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {B90AF5E3-3BFA-4501-ADAB-CF32D2677DB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B90AF5E3-3BFA-4501-ADAB-CF32D2677DB7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B90AF5E3-3BFA-4501-ADAB-CF32D2677DB7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B90AF5E3-3BFA-4501-ADAB-CF32D2677DB7}.Release|Any CPU.Build.0 = Release|Any CPU - {8506DC5F-90B6-421A-88E8-CB3C33CE0C91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8506DC5F-90B6-421A-88E8-CB3C33CE0C91}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8506DC5F-90B6-421A-88E8-CB3C33CE0C91}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8506DC5F-90B6-421A-88E8-CB3C33CE0C91}.Release|Any CPU.Build.0 = Release|Any CPU - {5B7A672B-3DB0-4406-9DF1-D1BAE6726BF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5B7A672B-3DB0-4406-9DF1-D1BAE6726BF7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5B7A672B-3DB0-4406-9DF1-D1BAE6726BF7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5B7A672B-3DB0-4406-9DF1-D1BAE6726BF7}.Release|Any CPU.Build.0 = Release|Any CPU - {B21D8C78-FB92-4C38-8773-6ABB244BF407}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B21D8C78-FB92-4C38-8773-6ABB244BF407}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B21D8C78-FB92-4C38-8773-6ABB244BF407}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B21D8C78-FB92-4C38-8773-6ABB244BF407}.Release|Any CPU.Build.0 = Release|Any CPU - {542E45C9-9853-42DB-B1C5-1D540FA1700E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {542E45C9-9853-42DB-B1C5-1D540FA1700E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {542E45C9-9853-42DB-B1C5-1D540FA1700E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {542E45C9-9853-42DB-B1C5-1D540FA1700E}.Release|Any CPU.Build.0 = Release|Any CPU - {00BCE648-24B5-4523-8180-74841842DD3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {00BCE648-24B5-4523-8180-74841842DD3C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {00BCE648-24B5-4523-8180-74841842DD3C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {00BCE648-24B5-4523-8180-74841842DD3C}.Release|Any CPU.Build.0 = Release|Any CPU - {BFBB771A-D679-4C13-885D-BA6425773924}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BFBB771A-D679-4C13-885D-BA6425773924}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BFBB771A-D679-4C13-885D-BA6425773924}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BFBB771A-D679-4C13-885D-BA6425773924}.Release|Any CPU.Build.0 = Release|Any CPU - {C4AF1EE4-CD8F-4A7B-9818-CBCBBCC7B2BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C4AF1EE4-CD8F-4A7B-9818-CBCBBCC7B2BC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C4AF1EE4-CD8F-4A7B-9818-CBCBBCC7B2BC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C4AF1EE4-CD8F-4A7B-9818-CBCBBCC7B2BC}.Release|Any CPU.Build.0 = Release|Any CPU - {41A0B9E4-C529-4F6D-8F69-AB0EE1AE6951}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {41A0B9E4-C529-4F6D-8F69-AB0EE1AE6951}.Debug|Any CPU.Build.0 = Debug|Any CPU - {41A0B9E4-C529-4F6D-8F69-AB0EE1AE6951}.Release|Any CPU.ActiveCfg = Release|Any CPU - {41A0B9E4-C529-4F6D-8F69-AB0EE1AE6951}.Release|Any CPU.Build.0 = Release|Any CPU - {29B57FE7-013D-49C5-AEBA-A062637D36A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {29B57FE7-013D-49C5-AEBA-A062637D36A3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {29B57FE7-013D-49C5-AEBA-A062637D36A3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {29B57FE7-013D-49C5-AEBA-A062637D36A3}.Release|Any CPU.Build.0 = Release|Any CPU - {FC4128C8-7183-4097-9DFC-1C168D41F42B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FC4128C8-7183-4097-9DFC-1C168D41F42B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FC4128C8-7183-4097-9DFC-1C168D41F42B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FC4128C8-7183-4097-9DFC-1C168D41F42B}.Release|Any CPU.Build.0 = Release|Any CPU - {412DC173-85E2-4A92-B886-11F173CB40E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {412DC173-85E2-4A92-B886-11F173CB40E4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {412DC173-85E2-4A92-B886-11F173CB40E4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {412DC173-85E2-4A92-B886-11F173CB40E4}.Release|Any CPU.Build.0 = Release|Any CPU - {97A35264-A93D-46E4-9DCE-767D427DFA7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {97A35264-A93D-46E4-9DCE-767D427DFA7D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {97A35264-A93D-46E4-9DCE-767D427DFA7D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {97A35264-A93D-46E4-9DCE-767D427DFA7D}.Release|Any CPU.Build.0 = Release|Any CPU - {D2D3393E-2248-4406-8065-FF4AEF919AC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D2D3393E-2248-4406-8065-FF4AEF919AC3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D2D3393E-2248-4406-8065-FF4AEF919AC3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D2D3393E-2248-4406-8065-FF4AEF919AC3}.Release|Any CPU.Build.0 = Release|Any CPU - {2FC95B0A-B404-4E88-8FB0-11F357D2A7C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2FC95B0A-B404-4E88-8FB0-11F357D2A7C1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2FC95B0A-B404-4E88-8FB0-11F357D2A7C1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2FC95B0A-B404-4E88-8FB0-11F357D2A7C1}.Release|Any CPU.Build.0 = Release|Any CPU - {5E9FF3AA-0784-4B4A-BCD2-9CCBC39D4D66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5E9FF3AA-0784-4B4A-BCD2-9CCBC39D4D66}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5E9FF3AA-0784-4B4A-BCD2-9CCBC39D4D66}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5E9FF3AA-0784-4B4A-BCD2-9CCBC39D4D66}.Release|Any CPU.Build.0 = Release|Any CPU - {09FED13A-1642-496C-AE3F-F0A2770BE9A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {09FED13A-1642-496C-AE3F-F0A2770BE9A2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {09FED13A-1642-496C-AE3F-F0A2770BE9A2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {09FED13A-1642-496C-AE3F-F0A2770BE9A2}.Release|Any CPU.Build.0 = Release|Any CPU - {EA67DB8A-BB10-4343-87A0-E91EDD783C8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EA67DB8A-BB10-4343-87A0-E91EDD783C8B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EA67DB8A-BB10-4343-87A0-E91EDD783C8B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EA67DB8A-BB10-4343-87A0-E91EDD783C8B}.Release|Any CPU.Build.0 = Release|Any CPU + {EA81CCF1-284B-4E2D-8CB8-AE9C8EACC01E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EA81CCF1-284B-4E2D-8CB8-AE9C8EACC01E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EA81CCF1-284B-4E2D-8CB8-AE9C8EACC01E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EA81CCF1-284B-4E2D-8CB8-AE9C8EACC01E}.Release|Any CPU.Build.0 = Release|Any CPU + {879047E1-76DD-4892-AF8F-8EC562514AD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {879047E1-76DD-4892-AF8F-8EC562514AD7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {879047E1-76DD-4892-AF8F-8EC562514AD7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {879047E1-76DD-4892-AF8F-8EC562514AD7}.Release|Any CPU.Build.0 = Release|Any CPU + {3A09EFE1-C88B-46E6-B0C8-00F7A9D00795}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3A09EFE1-C88B-46E6-B0C8-00F7A9D00795}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3A09EFE1-C88B-46E6-B0C8-00F7A9D00795}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3A09EFE1-C88B-46E6-B0C8-00F7A9D00795}.Release|Any CPU.Build.0 = Release|Any CPU + {E7786CE3-7E88-456D-ADFE-11035E842ABB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E7786CE3-7E88-456D-ADFE-11035E842ABB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E7786CE3-7E88-456D-ADFE-11035E842ABB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E7786CE3-7E88-456D-ADFE-11035E842ABB}.Release|Any CPU.Build.0 = Release|Any CPU + {1CE08542-B4A2-4632-A066-68462E0BC603}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1CE08542-B4A2-4632-A066-68462E0BC603}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1CE08542-B4A2-4632-A066-68462E0BC603}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1CE08542-B4A2-4632-A066-68462E0BC603}.Release|Any CPU.Build.0 = Release|Any CPU + {EA6A952C-2854-4031-94E0-724CCC388807}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EA6A952C-2854-4031-94E0-724CCC388807}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EA6A952C-2854-4031-94E0-724CCC388807}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EA6A952C-2854-4031-94E0-724CCC388807}.Release|Any CPU.Build.0 = Release|Any CPU + {D1E2AF9B-55A2-4198-8797-633ABA37AA81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D1E2AF9B-55A2-4198-8797-633ABA37AA81}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D1E2AF9B-55A2-4198-8797-633ABA37AA81}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D1E2AF9B-55A2-4198-8797-633ABA37AA81}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {B21D8C78-FB92-4C38-8773-6ABB244BF407} = {1B39C48B-5F4B-4556-A2B3-E4AC50F30B43} - {542E45C9-9853-42DB-B1C5-1D540FA1700E} = {1B39C48B-5F4B-4556-A2B3-E4AC50F30B43} - {00BCE648-24B5-4523-8180-74841842DD3C} = {1B39C48B-5F4B-4556-A2B3-E4AC50F30B43} - {BFBB771A-D679-4C13-885D-BA6425773924} = {1B39C48B-5F4B-4556-A2B3-E4AC50F30B43} - {C4AF1EE4-CD8F-4A7B-9818-CBCBBCC7B2BC} = {1B39C48B-5F4B-4556-A2B3-E4AC50F30B43} - {29B57FE7-013D-49C5-AEBA-A062637D36A3} = {1B39C48B-5F4B-4556-A2B3-E4AC50F30B43} - {FC4128C8-7183-4097-9DFC-1C168D41F42B} = {1B39C48B-5F4B-4556-A2B3-E4AC50F30B43} - {D2D3393E-2248-4406-8065-FF4AEF919AC3} = {1B39C48B-5F4B-4556-A2B3-E4AC50F30B43} - {5E9FF3AA-0784-4B4A-BCD2-9CCBC39D4D66} = {1B39C48B-5F4B-4556-A2B3-E4AC50F30B43} - {09FED13A-1642-496C-AE3F-F0A2770BE9A2} = {1B39C48B-5F4B-4556-A2B3-E4AC50F30B43} - {EA67DB8A-BB10-4343-87A0-E91EDD783C8B} = {1B39C48B-5F4B-4556-A2B3-E4AC50F30B43} EndGlobalSection EndGlobal diff --git a/Stater.sln.DotSettings.user b/Stater.sln.DotSettings.user index 5c6e27c..ed3781e 100644 --- a/Stater.sln.DotSettings.user +++ b/Stater.sln.DotSettings.user @@ -1,8 +1,29 @@  + <AssemblyExplorer> + <Assembly Path="/Users/vnazarov/.nuget/packages/dynamicdata/9.0.4/lib/net8.0/DynamicData.dll" /> +</AssemblyExplorer> False SOLUTION + <SessionState ContinuousTestingMode="0" Name="ConvertToKotlin_ShouldGenerateValidCode" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <Or> + <TestAncestor> + <TestId>xUnit::879047E1-76DD-4892-AF8F-8EC562514AD7::net8.0::Stater.CodeGeneration.Tests.LanguageAdapter.Kotlin.KotlinAdapterDoorTests</TestId> + <TestId>xUnit::879047E1-76DD-4892-AF8F-8EC562514AD7::net8.0::Stater.CodeGeneration.Tests.LanguageAdapter.Python.PythonAdapterDoorTests</TestId> + <TestId>xUnit::879047E1-76DD-4892-AF8F-8EC562514AD7::net8.0::Stater.CodeGeneration.Tests.ScenarioFinderTests.ClazzGenerate</TestId> + <TestId>xUnit::D1E2AF9B-55A2-4198-8797-633ABA37AA81::net8.0::Stater.Domain.Tests.Json.StateMachineJsonAdapterTests.TestToJsonSchema</TestId> + <TestId>xUnit::D1E2AF9B-55A2-4198-8797-633ABA37AA81::net8.0::Stater.Domain.Tests.Json.StateMachineJsonAdapterTests.TestFromJsonSchema</TestId> + </TestAncestor> + <ProjectFile>D1E2AF9B-55A2-4198-8797-633ABA37AA81/d:Json/f:StateMachineJsonAdapterTests.cs</ProjectFile> + <Project Location="/Users/vnazarov/RiderProjects/Stater3/src/Stater.CodeGeneration.Tests" Presentation="&lt;Stater.CodeGeneration.Tests&gt;" /> + </Or> +</SessionState> + <SessionState ContinuousTestingMode="0" IsActive="True" Name="Session" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <Project Location="/Users/vnazarov/RiderProjects/Stater3/src/Stater.CodeGeneration.Tests" Presentation="&lt;Stater.CodeGeneration.Tests&gt;" /> +</SessionState> True True TestArrayW1 - <Session><Elements /></Session> \ No newline at end of file + <Session><Elements /></Session> + + True \ No newline at end of file diff --git a/StaterV/ButtonPlugin.cs b/StaterV/ButtonPlugin.cs index 1fb596e..e6e3b9f 100644 --- a/StaterV/ButtonPlugin.cs +++ b/StaterV/ButtonPlugin.cs @@ -1,8 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using StaterV.PluginManager; +using StaterV.PluginManager; + +// TODO: practice NEED namespace StaterV { diff --git a/StaterV/StaterV.csproj b/StaterV/StaterV.csproj index 6e4ff96..fc3533e 100644 --- a/StaterV/StaterV.csproj +++ b/StaterV/StaterV.csproj @@ -384,14 +384,6 @@ - - {41A0B9E4-C529-4F6D-8F69-AB0EE1AE6951} - PluginData - - - {2FC95B0A-B404-4E88-8FB0-11F357D2A7C1} - StateFlow - {412DC173-85E2-4A92-B886-11F173CB40E4} TextProcessor diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000..f4a0eb4 --- /dev/null +++ b/changelog.md @@ -0,0 +1,16 @@ +# Changelog + +## [Unreleased] + +### Добавления +- Добавлена возможность запуска автомата +- Добавлено окно справа для контрукторов рекдактирования состояний, переходов.. +- Добавлено окно слева для перехода между конечными автоматами + +### Изменения +- Изменена версия C#: C# Framework 4 -> C# net 8 +- Изменена директория с решением проекта, теперь основное решения находитсяв /src/Stater +- Изменен фреймворк для интерфейса Windows Forms -> Avalonia +- Изменена структура приложения, на данный момент приложение использует MVVM архитектуру +- Изменена система UNDO-REDO, раньше каждая команда требовала отдельного написания для класса, сейчас сохраняется каждое изменение StateMachine, что не требует функциональности для REDO +- Изменена система плагинов, на данный момент плагин не является отдельным решением diff --git a/src/Stater.CodeGeneration.App/Program.cs b/src/Stater.CodeGeneration.App/Program.cs new file mode 100644 index 0000000..9396157 --- /dev/null +++ b/src/Stater.CodeGeneration.App/Program.cs @@ -0,0 +1,153 @@ +// See https://aka.ms/new-console-template for more information + + +using Stater.CodeGeneration; +using Stater.CodeGeneration.App; +using Stater.CodeGeneration.Entity; + + +if (args.Length < 3) +{ + Console.WriteLine("Please write: [output-path] [seed] [language]"); +} + +var outputPath = args[0]; +var seed = int.Parse(args[1]); +var language = args[2]; + +if (!Directory.Exists(outputPath)) +{ + Directory.CreateDirectory(outputPath); + Console.WriteLine($"Folder created: {outputPath}"); +} + +var randomStateMachineGenerator = new RandomStateMachineGenerator(seed); + +var states = new List { false, true }; +var codeGenerator = new CodeGenerator(); + +foreach (var generateMode in new List { Mode.Builder, Mode.Clazz }) +{ + foreach (var generateStates in states) + { + foreach (var generateContext in states) + { + foreach (var generateInterface in states) + { + var randomStateMachine = randomStateMachineGenerator.GenerateStateMachine(5, 10, 10, 10, 10); + + var path = outputPath; + var testPath = outputPath; + var languageS = Language.Python3; + switch (language) + { + case "python3": + path += randomStateMachine.Name + ".py"; + testPath += "test_" + randomStateMachine.Name + ".py"; + languageS = Language.Python3; + break; + case "javascript": + path += randomStateMachine.Name + ".js"; + testPath += randomStateMachine.Name + ".test.js"; + languageS = Language.JavaScript; + break; + case "typescript": + path += randomStateMachine.Name + ".ts"; + testPath += randomStateMachine.Name + ".test.ts"; + languageS = Language.TypeScript; + break; + case "kotlin": + path += "main/kotlin/fsm/" + randomStateMachine.Name.ToLower() + "/"; + testPath += "test/kotlin/fsm/" + randomStateMachine.Name.ToLower() + "/"; + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + Console.WriteLine($"Folder created: {path}"); + } + if (!Directory.Exists(testPath)) + { + Directory.CreateDirectory(testPath); + Console.WriteLine($"Folder created: {testPath}"); + } + path += randomStateMachine.Name + ".kt"; + testPath += "Test" + randomStateMachine.Name + ".kt"; + + languageS = Language.Kotlin; + break; + case "java": + path += "main/java/fsm/" + randomStateMachine.Name.ToLower() + "/"; + testPath += "test/java/fsm/" + randomStateMachine.Name.ToLower() + "/"; + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + Console.WriteLine($"Folder created: {path}"); + } + if (!Directory.Exists(testPath)) + { + Directory.CreateDirectory(testPath); + Console.WriteLine($"Folder created: {testPath}"); + } + path += randomStateMachine.Name + ".java"; + testPath += "Test" + randomStateMachine.Name + ".java"; + + languageS = Language.Java; + break; + case "csharp": + path += "/Stater.StateMachine.Lib/fsm/" + randomStateMachine.Name.ToLower() + "/"; + testPath += "/Stater.StateMachine.Lib.Tests/fsm/" + randomStateMachine.Name.ToLower() + "/"; + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + Console.WriteLine($"Folder created: {path}"); + } + if (!Directory.Exists(testPath)) + { + Directory.CreateDirectory(testPath); + Console.WriteLine($"Folder created: {testPath}"); + } + path += randomStateMachine.Name + ".cs"; + testPath += "Test" + randomStateMachine.Name + ".cs"; + + languageS = Language.CSharp; + break; + case "cplusplus": + path += "fsm/" + randomStateMachine.Name + "/"; + testPath += "tests/"; + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + Console.WriteLine($"Folder created: {path}"); + } + if (!Directory.Exists(testPath)) + { + Directory.CreateDirectory(testPath); + Console.WriteLine($"Folder created: {testPath}"); + } + path += randomStateMachine.Name + ".h"; + testPath += "test_" + randomStateMachine.Name + ".cpp"; + + languageS = Language.CPlusPlus; + break; + } + + var settings = new GenerationSettings( + languageS + , generateMode + , GenerateStates: generateStates + , GenerateContext: generateContext + , GenerateInterface: generateInterface + ); + + using var sw = new StreamWriter(path); + var result = codeGenerator.Generate(randomStateMachine, settings); + sw.WriteLine(result); + + + using var swTest = new StreamWriter(testPath); + var results = ScenarioFinder.FindScenarios(randomStateMachine); + var resultTest = codeGenerator.GenerateTests(randomStateMachine, settings, results); + swTest.WriteLine(resultTest); + } + } + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.App/RandomStateMachineGenerator.cs b/src/Stater.CodeGeneration.App/RandomStateMachineGenerator.cs new file mode 100644 index 0000000..d260e12 --- /dev/null +++ b/src/Stater.CodeGeneration.App/RandomStateMachineGenerator.cs @@ -0,0 +1,150 @@ +using Stater.Domain.Models; + +namespace Stater.CodeGeneration.App; + +public class RandomStateMachineGenerator(int seed) +{ + private readonly Random random = new(seed); + + private string RandomString(int length) + { + const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + return new string(Enumerable.Repeat(chars, length) + .Select(s => s[random.Next(s.Length)]).ToArray()); + } + + private State GenerateState() => new( + Guid.NewGuid(), + RandomString(10), + RandomString(20), + StateType.Common, + 0, + 0, + new List(), + new List() + ); + + private Transition GenerateTransition(IReadOnlyList states) => new( + Guid.NewGuid(), + RandomString(15), + states[random.Next(states.Count)].Guid, + states[random.Next(states.Count)].Guid, + null, + null + ); + + private VariableValue.StringVariable GenerateStringVariableValue() => new(RandomString(30)); + private VariableValue.IntVariable GenerateIntVariableValue() => new(random.Next(99999)); + private VariableValue.FloatVariable GenerateFloatVariableValue() => new((float)random.NextDouble()); + private VariableValue.BoolVariable GenerateBoolVariableValue() => new(random.Next(2) == 0); + + private VariableValue GenerateVariableValue() => random.Next(4) switch + { + 0 => GenerateStringVariableValue(), + 1 => GenerateIntVariableValue(), + 2 => GenerateFloatVariableValue(), + 3 => GenerateBoolVariableValue(), + _ => throw new ArgumentOutOfRangeException() + }; + + private VariableValue GenerateVariableValue(VariableValue variableValue) => variableValue switch + { + VariableValue.StringVariable => GenerateStringVariableValue(), + VariableValue.IntVariable => GenerateIntVariableValue(), + VariableValue.FloatVariable => GenerateFloatVariableValue(), + VariableValue.BoolVariable => GenerateBoolVariableValue(), + _ => throw new ArgumentOutOfRangeException() + }; + + private Variable GenerateVariable() => new(Guid.NewGuid(), RandomString(15), GenerateVariableValue()); + + private Event GenerateEvent(IReadOnlyList variables) + { + switch (random.Next(2)) + { + case 0: + var variable = variables[random.Next(variables.Count)]; + return new Event.VariableSet( + variable.Guid, + GenerateVariableValue(variable.StartValue) + ); + case 1: + var variable2 = variables[random.Next(variables.Count)]; + return new Event.VariableMath( + variable2.Guid, + random.Next(4) switch + { + 0 => Event.VariableMath.MathTypeEnum.Sum, + 1 => Event.VariableMath.MathTypeEnum.Div, + 2 => Event.VariableMath.MathTypeEnum.Sub, + 3 => Event.VariableMath.MathTypeEnum.Mul, + _ => throw new ArgumentOutOfRangeException() + }, + GenerateVariableValue(variable2.StartValue) + ); + } + + throw new ArgumentOutOfRangeException(); + } + + private Condition GenerateCondition(IReadOnlyList variables) + { + switch (random.Next(1)) + { + case 0: + var variable1 = variables[random.Next(variables.Count)]; + return new Condition.VariableCondition( + variable1.Guid, + random.Next(6) switch + { + 0 => Condition.VariableCondition.ConditionTypeEnum.Lt, + 1 => Condition.VariableCondition.ConditionTypeEnum.Le, + 2 => Condition.VariableCondition.ConditionTypeEnum.Eq, + 3 => Condition.VariableCondition.ConditionTypeEnum.Ne, + 4 => Condition.VariableCondition.ConditionTypeEnum.Gt, + 5 => Condition.VariableCondition.ConditionTypeEnum.Ge, + _ => throw new ArgumentOutOfRangeException() + }, + GenerateVariableValue(variable1.StartValue) + ); + } + + throw new ArgumentOutOfRangeException(); + } + + public StateMachine GenerateStateMachine( + int countState, + int countTransitions, + int countVariables, + int countEvents, + int countConditions + ) + { + var states = Enumerable.Range(0, countState).Select(_ => GenerateState()).ToList(); + var startStateIndex = random.Next(countState); + states[startStateIndex] = states[startStateIndex] with { Type = StateType.Start }; + var transitions = Enumerable.Range(0, countTransitions).Select(_ => GenerateTransition(states)).ToList(); + var variables = Enumerable.Range(0, countVariables).Select(_ => GenerateVariable()).ToList(); + + for (var i = 0; i < countEvents; i++) + { + var transitionIndex = random.Next(countTransitions); + transitions[transitionIndex] = transitions[transitionIndex] with { Event = GenerateEvent(variables) }; + } + + for (var i = 0; i < countConditions; i++) + { + var transitionIndex = random.Next(countTransitions); + transitions[transitionIndex] = + transitions[transitionIndex] with { Condition = GenerateCondition(variables) }; + } + + return new StateMachine( + Guid.NewGuid(), + RandomString(20), + states, + transitions, + variables + ); + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.App/Stater.CodeGeneration.App.csproj b/src/Stater.CodeGeneration.App/Stater.CodeGeneration.App.csproj new file mode 100644 index 0000000..1fa968a --- /dev/null +++ b/src/Stater.CodeGeneration.App/Stater.CodeGeneration.App.csproj @@ -0,0 +1,13 @@ + + + + Exe + net8.0 + enable + enable + + + + + + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/BaseTestAdapterGenerateDoorTests.cs b/src/Stater.CodeGeneration.Tests/LanguageAdapter/BaseTestAdapterGenerateDoorTests.cs new file mode 100644 index 0000000..c6eedb2 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/BaseTestAdapterGenerateDoorTests.cs @@ -0,0 +1,235 @@ +using Stater.CodeGeneration.Entity; +using Stater.CodeGeneration.LanguageAdapter.Base; + +namespace Stater.CodeGeneration.Tests.LanguageAdapter; + +public abstract class BaseTestAdapterGenerateDoorTests +{ + protected abstract BaseLanguageAdapter Adapter { get; } + protected abstract Language Language { get; } + + + + [Fact] + public Task ClazzGenerate() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var settings = new GenerationSettings( + Language + ); + var result = Adapter.Generate(stateMachine, settings); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task ClazzGenerateWithInterface() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var settings = new GenerationSettings( + Language, + GenerateInterface: true + ); + + var result = Adapter.Generate(stateMachine, settings); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task ClazzStateGenerate() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var settings = new GenerationSettings( + Language, + GenerateStates: true + ); + + var result = Adapter.Generate(stateMachine, settings); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task ClazzStateGenerateWithInterface() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var settings = new GenerationSettings( + Language, + GenerateStates: true, + GenerateInterface: true + ); + + var result = Adapter.Generate(stateMachine, settings); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task ClazzContextGenerate() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var settings = new GenerationSettings( + Language, + GenerateContext: true + ); + + var result = Adapter.Generate(stateMachine, settings); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task ClazzContextGenerateWithInterface() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var settings = new GenerationSettings( + Language, + GenerateContext: true, + GenerateInterface: true + ); + + var result = Adapter.Generate(stateMachine, settings); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task ClazzStateContextGenerate() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var settings = new GenerationSettings( + Language, + GenerateStates: true, + GenerateContext: true + ); + + var result = Adapter.Generate(stateMachine, settings); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task ClazzStateContextGenerateWithInterface() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var settings = new GenerationSettings( + Language, + GenerateStates: true, + GenerateContext: true, + GenerateInterface: true + ); + + var result = Adapter.Generate(stateMachine, settings); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task BuilderGenerate() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var settings = new GenerationSettings( + Language, + Mode.Builder + ); + + var result = Adapter.Generate(stateMachine, settings); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task BuilderGenerateWithInterface() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var settings = new GenerationSettings( + Language, + Mode.Builder, + GenerateInterface: true + ); + + var result = Adapter.Generate(stateMachine, settings); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task BuilderStateGenerate() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var settings = new GenerationSettings( + Language, + Mode.Builder, + GenerateStates: true + ); + + var result = Adapter.Generate(stateMachine, settings); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task BuilderStateGenerateWithInterface() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var settings = new GenerationSettings( + Language, + Mode.Builder, + GenerateStates: true, + GenerateInterface: true + ); + + var result = Adapter.Generate(stateMachine, settings); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task BuilderContextGenerate() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var settings = new GenerationSettings( + Language, + Mode.Builder, + GenerateContext: true + ); + + var result = Adapter.Generate(stateMachine, settings); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task BuilderContextGenerateWithInterface() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var settings = new GenerationSettings( + Language, + Mode.Builder, + GenerateContext: true, + GenerateInterface: true + ); + + var result = Adapter.Generate(stateMachine, settings); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task BuilderStateContextGenerate() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var settings = new GenerationSettings( + Language, + Mode.Builder, + GenerateStates: true, + GenerateContext: true + ); + + var result = Adapter.Generate(stateMachine, settings); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task BuilderStateContextGenerateWithInterface() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var settings = new GenerationSettings( + Language, + Mode.Builder, + GenerateStates: true, + GenerateContext: true, + GenerateInterface: true + ); + + var result = Adapter.Generate(stateMachine, settings); + return Verify(result).UseDirectory(Language.ToString()); + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/BaseTestAdapterGenerateTestsDoorTests.cs b/src/Stater.CodeGeneration.Tests/LanguageAdapter/BaseTestAdapterGenerateTestsDoorTests.cs new file mode 100644 index 0000000..a029e39 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/BaseTestAdapterGenerateTestsDoorTests.cs @@ -0,0 +1,251 @@ +using Stater.CodeGeneration.Entity; +using Stater.CodeGeneration.LanguageAdapter.Base; + +namespace Stater.CodeGeneration.Tests.LanguageAdapter; + +public abstract class BaseTestAdapterGenerateTestsDoorTests +{ + protected abstract BaseLanguageAdapter Adapter { get; } + protected abstract Language Language { get; } + + + + [Fact] + public Task ClazzTestsGenerate() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var scenarios = ScenarioFinder.FindScenarios(stateMachine); + var settings = new GenerationSettings( + Language + ); + var result = Adapter.GenerateTests(stateMachine, settings, scenarios); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task ClazzTestsGenerateWithInterface() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var scenarios = ScenarioFinder.FindScenarios(stateMachine); + var settings = new GenerationSettings( + Language, + GenerateInterface: true + ); + + var result = Adapter.GenerateTests(stateMachine, settings, scenarios); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task ClazzTestsStateGenerate() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var scenarios = ScenarioFinder.FindScenarios(stateMachine); + var settings = new GenerationSettings( + Language, + GenerateStates: true + ); + + var result = Adapter.GenerateTests(stateMachine, settings, scenarios); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task ClazzTestsStateGenerateWithInterface() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var scenarios = ScenarioFinder.FindScenarios(stateMachine); + var settings = new GenerationSettings( + Language, + GenerateStates: true, + GenerateInterface: true + ); + + var result = Adapter.GenerateTests(stateMachine, settings, scenarios); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task ClazzTestsContextGenerate() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var scenarios = ScenarioFinder.FindScenarios(stateMachine); + var settings = new GenerationSettings( + Language, + GenerateContext: true + ); + + var result = Adapter.GenerateTests(stateMachine, settings, scenarios); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task ClazzTestsContextGenerateWithInterface() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var scenarios = ScenarioFinder.FindScenarios(stateMachine); + var settings = new GenerationSettings( + Language, + GenerateContext: true, + GenerateInterface: true + ); + + var result = Adapter.GenerateTests(stateMachine, settings, scenarios); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task ClazzTestsStateContextGenerate() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var scenarios = ScenarioFinder.FindScenarios(stateMachine); + var settings = new GenerationSettings( + Language, + GenerateStates: true, + GenerateContext: true + ); + + var result = Adapter.GenerateTests(stateMachine, settings, scenarios); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task ClazzTestsStateContextGenerateWithInterface() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var scenarios = ScenarioFinder.FindScenarios(stateMachine); + var settings = new GenerationSettings( + Language, + GenerateStates: true, + GenerateContext: true, + GenerateInterface: true + ); + + var result = Adapter.GenerateTests(stateMachine, settings, scenarios); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task BuilderTestsGenerate() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var scenarios = ScenarioFinder.FindScenarios(stateMachine); + var settings = new GenerationSettings( + Language, + Mode.Builder + ); + + var result = Adapter.GenerateTests(stateMachine, settings, scenarios); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task BuilderTestsGenerateWithInterface() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var scenarios = ScenarioFinder.FindScenarios(stateMachine); + var settings = new GenerationSettings( + Language, + Mode.Builder, + GenerateInterface: true + ); + + var result = Adapter.GenerateTests(stateMachine, settings, scenarios); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task BuilderTestsStateGenerate() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var scenarios = ScenarioFinder.FindScenarios(stateMachine); + var settings = new GenerationSettings( + Language, + Mode.Builder, + GenerateStates: true + ); + + var result = Adapter.GenerateTests(stateMachine, settings, scenarios); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task BuilderTestsStateGenerateWithInterface() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var scenarios = ScenarioFinder.FindScenarios(stateMachine); + var settings = new GenerationSettings( + Language, + Mode.Builder, + GenerateStates: true, + GenerateInterface: true + ); + + var result = Adapter.GenerateTests(stateMachine, settings, scenarios); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task BuilderTestsContextGenerate() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var scenarios = ScenarioFinder.FindScenarios(stateMachine); + var settings = new GenerationSettings( + Language, + Mode.Builder, + GenerateContext: true + ); + + var result = Adapter.GenerateTests(stateMachine, settings, scenarios); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task BuilderTestsContextGenerateWithInterface() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var scenarios = ScenarioFinder.FindScenarios(stateMachine); + var settings = new GenerationSettings( + Language, + Mode.Builder, + GenerateContext: true, + GenerateInterface: true + ); + + var result = Adapter.GenerateTests(stateMachine, settings, scenarios); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task BuilderTestsStateContextGenerate() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var scenarios = ScenarioFinder.FindScenarios(stateMachine); + var settings = new GenerationSettings( + Language, + Mode.Builder, + GenerateStates: true, + GenerateContext: true + ); + + var result = Adapter.GenerateTests(stateMachine, settings, scenarios); + return Verify(result).UseDirectory(Language.ToString()); + } + + [Fact] + public Task BuilderTestsStateContextGenerateWithInterface() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var scenarios = ScenarioFinder.FindScenarios(stateMachine); + var settings = new GenerationSettings( + Language, + Mode.Builder, + GenerateStates: true, + GenerateContext: true, + GenerateInterface: true + ); + + var result = Adapter.GenerateTests(stateMachine, settings, scenarios); + return Verify(result).UseDirectory(Language.ToString()); + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.BuilderContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.BuilderContextGenerate.verified.txt new file mode 100644 index 0000000..ff105a5 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.BuilderContextGenerate.verified.txt @@ -0,0 +1,29 @@ +#pragma once + +#include + +class Door_context final : context { +public: + int degreeOfOpening = 0; + bool closeVariable = true; + std::string doorName = "asd"; + float floatVariable = 0f; +}; + +inline stater_state_machine_builder builder_Door_state_machine = stater_state_machine_builder() + .set_start_state("OPEN") + .set_context(new Door_context()) + .add_transition("preOpen", "CLOSE", "AJAR") + .set_transition_event("preOpen", [](Door_context *ctx) { ctx->degreeOfOpening = 1; }) + .add_transition("preClose", "OPEN", "AJAR") + .set_transition_event("preClose", [](Door_context *ctx) { ctx->degreeOfOpening = 99; }) + .add_transition("open", "AJAR", "OPEN") + .set_transition_condition("open", [](Door_context *ctx) { return ctx->degreeOfOpening >= 0; }) + .set_transition_event("open", [](Door_context *ctx) { ctx->degreeOfOpening = 100; }) + .add_transition("close", "AJAR", "CLOSE") + .set_transition_condition("close", [](Door_context *ctx) { return ctx->degreeOfOpening <= 0; }) + .set_transition_event("close", [](Door_context *ctx) { ctx->degreeOfOpening = 0; }) + .add_transition("ajarPlus", "AJAR", "AJAR") + .set_transition_event("ajarPlus", [](Door_context *ctx) { ctx->degreeOfOpening = ctx->degreeOfOpening + 1; }) + .add_transition("ajarMinus", "AJAR", "AJAR") + .set_transition_event("ajarMinus", [](Door_context *ctx) { ctx->degreeOfOpening = ctx->degreeOfOpening - 1; }); \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.BuilderContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.BuilderContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..2a3fab2 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.BuilderContextGenerateWithInterface.verified.txt @@ -0,0 +1,108 @@ +#pragma once + +#include + +class Door_context final : context { +public: + int degreeOfOpening = 0; + bool closeVariable = true; + std::string doorName = "asd"; + float floatVariable = 0f; +}; + +class types_Door_state_machine : public stater_state_machine { +public: + types_Door_state_machine( + const std::vector> &transitions, + Door_context *context, + const std::string &start_state, + const std::unordered_set &states, + const std::unordered_map>> &transition_middlewares, + const std::vector> &transition_all_middlewares, + const std::unordered_map>> &transition_callbacks, + const std::vector> &transition_all_callbacks, + const std::unordered_map>> &state_callbacks, + const std::vector> &state_all_callbacks, + const std::shared_ptr<::context_json_adapter > &context_json_adapter + ) : stater_state_machine( + transitions, + context, + start_state, + states, + transition_middlewares, + transition_all_middlewares, + transition_callbacks, + transition_all_callbacks, + state_callbacks, + state_all_callbacks, + context_json_adapter + ) { + } + + void preOpen() { + transition("preOpen"); + } + + void preClose() { + transition("preClose"); + } + + void open() { + transition("open"); + } + + void close() { + transition("close"); + } + + void ajarPlus() { + transition("ajarPlus"); + } + + void ajarMinus() { + transition("ajarMinus"); + } +}; + +inline state_machine_factory typed_Door_factory = []( + const std::vector > &transitions, + Door_context *context, + std::string start_state, + const std::unordered_set &states, + const std::unordered_map > > & + transition_middleware, + const std::vector > & + transition_all_middlewares, + const std::unordered_map > > & + transition_callbacks, + const std::vector > &transition_all_callbacks, + const std::unordered_map<::std::string, std::vector > > &state_callbacks, + const std::vector > &state_all_callbacks, + const std::shared_ptr >& context_json_adapter_) -> + std::unique_ptr { + return std::make_unique( + transitions, context, start_state, states, + transition_middleware, transition_all_middlewares, + transition_callbacks, transition_all_callbacks, + state_callbacks, state_all_callbacks, context_json_adapter_); +}; + + +inline stater_state_machine_builder builder_Door_state_machine = stater_state_machine_builder() + .set_start_state("OPEN") + .set_context(new Door_context()) + .set_factory(typed_Door_factory) + .add_transition("preOpen", "CLOSE", "AJAR") + .set_transition_event("preOpen", [](Door_context *ctx) { ctx->degreeOfOpening = 1; }) + .add_transition("preClose", "OPEN", "AJAR") + .set_transition_event("preClose", [](Door_context *ctx) { ctx->degreeOfOpening = 99; }) + .add_transition("open", "AJAR", "OPEN") + .set_transition_condition("open", [](Door_context *ctx) { return ctx->degreeOfOpening >= 0; }) + .set_transition_event("open", [](Door_context *ctx) { ctx->degreeOfOpening = 100; }) + .add_transition("close", "AJAR", "CLOSE") + .set_transition_condition("close", [](Door_context *ctx) { return ctx->degreeOfOpening <= 0; }) + .set_transition_event("close", [](Door_context *ctx) { ctx->degreeOfOpening = 0; }) + .add_transition("ajarPlus", "AJAR", "AJAR") + .set_transition_event("ajarPlus", [](Door_context *ctx) { ctx->degreeOfOpening = ctx->degreeOfOpening + 1; }) + .add_transition("ajarMinus", "AJAR", "AJAR") + .set_transition_event("ajarMinus", [](Door_context *ctx) { ctx->degreeOfOpening = ctx->degreeOfOpening - 1; }); \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.BuilderGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.BuilderGenerate.verified.txt new file mode 100644 index 0000000..e040396 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.BuilderGenerate.verified.txt @@ -0,0 +1,13 @@ +#pragma once + +#include + +inline stater_state_machine_builder builder_Door_state_machine = stater_state_machine_builder() + .set_start_state("OPEN") + .set_context(new empty_context()) + .add_transition("preOpen", "CLOSE", "AJAR") + .add_transition("preClose", "OPEN", "AJAR") + .add_transition("open", "AJAR", "OPEN") + .add_transition("close", "AJAR", "CLOSE") + .add_transition("ajarPlus", "AJAR", "AJAR") + .add_transition("ajarMinus", "AJAR", "AJAR"); \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.BuilderGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.BuilderGenerateWithInterface.verified.txt new file mode 100644 index 0000000..a83f586 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.BuilderGenerateWithInterface.verified.txt @@ -0,0 +1,92 @@ +#pragma once + +#include + +class types_Door_state_machine : public stater_state_machine { +public: + types_Door_state_machine( + const std::vector> &transitions, + empty_context *context, + const std::string &start_state, + const std::unordered_set &states, + const std::unordered_map>> &transition_middlewares, + const std::vector> &transition_all_middlewares, + const std::unordered_map>> &transition_callbacks, + const std::vector> &transition_all_callbacks, + const std::unordered_map>> &state_callbacks, + const std::vector> &state_all_callbacks, + const std::shared_ptr<::context_json_adapter > &context_json_adapter + ) : stater_state_machine( + transitions, + context, + start_state, + states, + transition_middlewares, + transition_all_middlewares, + transition_callbacks, + transition_all_callbacks, + state_callbacks, + state_all_callbacks, + context_json_adapter + ) { + } + + void preOpen() { + transition("preOpen"); + } + + void preClose() { + transition("preClose"); + } + + void open() { + transition("open"); + } + + void close() { + transition("close"); + } + + void ajarPlus() { + transition("ajarPlus"); + } + + void ajarMinus() { + transition("ajarMinus"); + } +}; + +inline state_machine_factory typed_Door_factory = []( + const std::vector > &transitions, + empty_context *context, + std::string start_state, + const std::unordered_set &states, + const std::unordered_map > > & + transition_middleware, + const std::vector > & + transition_all_middlewares, + const std::unordered_map > > & + transition_callbacks, + const std::vector > &transition_all_callbacks, + const std::unordered_map<::std::string, std::vector > > &state_callbacks, + const std::vector > &state_all_callbacks, + const std::shared_ptr >& context_json_adapter_) -> + std::unique_ptr { + return std::make_unique( + transitions, context, start_state, states, + transition_middleware, transition_all_middlewares, + transition_callbacks, transition_all_callbacks, + state_callbacks, state_all_callbacks, context_json_adapter_); +}; + + +inline stater_state_machine_builder builder_Door_state_machine = stater_state_machine_builder() + .set_start_state("OPEN") + .set_context(new empty_context()) + .set_factory(typed_Door_factory) + .add_transition("preOpen", "CLOSE", "AJAR") + .add_transition("preClose", "OPEN", "AJAR") + .add_transition("open", "AJAR", "OPEN") + .add_transition("close", "AJAR", "CLOSE") + .add_transition("ajarPlus", "AJAR", "AJAR") + .add_transition("ajarMinus", "AJAR", "AJAR"); \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.BuilderStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.BuilderStateContextGenerate.verified.txt new file mode 100644 index 0000000..1c67b15 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.BuilderStateContextGenerate.verified.txt @@ -0,0 +1,54 @@ +#pragma once + +#include + +enum class e_Door_states { + OPEN, + AJAR, + CLOSE +}; + +inline void to_json(nlohmann::json &j, const e_Door_states &e) { + switch (e) { + case e_Door_states::OPEN: j = "OPEN"; + break; + case e_Door_states::AJAR: j = "AJAR"; + break; + case e_Door_states::CLOSE: j = "CLOSE"; + break; + } +} + +inline void from_json(const nlohmann::json &j, e_Door_states &e) { + std::string state_str = j.get(); + + if (state_str == "OPEN") e = e_Door_states::OPEN; + else if (state_str == "AJAR") e = e_Door_states::AJAR; + else if (state_str == "CLOSE") e = e_Door_states::CLOSE; +} + +class Door_context final : context { +public: + int degreeOfOpening = 0; + bool closeVariable = true; + std::string doorName = "asd"; + float floatVariable = 0f; +}; + +inline stater_state_machine_builder builder_Door_state_machine = stater_state_machine_builder() + .set_start_state(e_Door_states::OPEN) + .set_context(new Door_context()) + .add_transition("preOpen", e_Door_states::CLOSE, e_Door_states::AJAR) + .set_transition_event("preOpen", [](Door_context *ctx) { ctx->degreeOfOpening = 1; }) + .add_transition("preClose", e_Door_states::OPEN, e_Door_states::AJAR) + .set_transition_event("preClose", [](Door_context *ctx) { ctx->degreeOfOpening = 99; }) + .add_transition("open", e_Door_states::AJAR, e_Door_states::OPEN) + .set_transition_condition("open", [](Door_context *ctx) { return ctx->degreeOfOpening >= 0; }) + .set_transition_event("open", [](Door_context *ctx) { ctx->degreeOfOpening = 100; }) + .add_transition("close", e_Door_states::AJAR, e_Door_states::CLOSE) + .set_transition_condition("close", [](Door_context *ctx) { return ctx->degreeOfOpening <= 0; }) + .set_transition_event("close", [](Door_context *ctx) { ctx->degreeOfOpening = 0; }) + .add_transition("ajarPlus", e_Door_states::AJAR, e_Door_states::AJAR) + .set_transition_event("ajarPlus", [](Door_context *ctx) { ctx->degreeOfOpening = ctx->degreeOfOpening + 1; }) + .add_transition("ajarMinus", e_Door_states::AJAR, e_Door_states::AJAR) + .set_transition_event("ajarMinus", [](Door_context *ctx) { ctx->degreeOfOpening = ctx->degreeOfOpening - 1; }); \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.BuilderStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.BuilderStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..76428e9 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.BuilderStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,133 @@ +#pragma once + +#include + +enum class e_Door_states { + OPEN, + AJAR, + CLOSE +}; + +inline void to_json(nlohmann::json &j, const e_Door_states &e) { + switch (e) { + case e_Door_states::OPEN: j = "OPEN"; + break; + case e_Door_states::AJAR: j = "AJAR"; + break; + case e_Door_states::CLOSE: j = "CLOSE"; + break; + } +} + +inline void from_json(const nlohmann::json &j, e_Door_states &e) { + std::string state_str = j.get(); + + if (state_str == "OPEN") e = e_Door_states::OPEN; + else if (state_str == "AJAR") e = e_Door_states::AJAR; + else if (state_str == "CLOSE") e = e_Door_states::CLOSE; +} + +class Door_context final : context { +public: + int degreeOfOpening = 0; + bool closeVariable = true; + std::string doorName = "asd"; + float floatVariable = 0f; +}; + +class types_Door_state_machine : public stater_state_machine { +public: + types_Door_state_machine( + const std::vector> &transitions, + Door_context *context, + const e_Door_states &start_state, + const std::unordered_set &states, + const std::unordered_map>> &transition_middlewares, + const std::vector> &transition_all_middlewares, + const std::unordered_map>> &transition_callbacks, + const std::vector> &transition_all_callbacks, + const std::unordered_map>> &state_callbacks, + const std::vector> &state_all_callbacks, + const std::shared_ptr<::context_json_adapter > &context_json_adapter + ) : stater_state_machine( + transitions, + context, + start_state, + states, + transition_middlewares, + transition_all_middlewares, + transition_callbacks, + transition_all_callbacks, + state_callbacks, + state_all_callbacks, + context_json_adapter + ) { + } + + void preOpen() { + transition("preOpen"); + } + + void preClose() { + transition("preClose"); + } + + void open() { + transition("open"); + } + + void close() { + transition("close"); + } + + void ajarPlus() { + transition("ajarPlus"); + } + + void ajarMinus() { + transition("ajarMinus"); + } +}; + +inline state_machine_factory typed_Door_factory = []( + const std::vector > &transitions, + Door_context *context, + e_Door_states start_state, + const std::unordered_set &states, + const std::unordered_map > > & + transition_middleware, + const std::vector > & + transition_all_middlewares, + const std::unordered_map > > & + transition_callbacks, + const std::vector > &transition_all_callbacks, + const std::unordered_map<::e_Door_states, std::vector > > &state_callbacks, + const std::vector > &state_all_callbacks, + const std::shared_ptr >& context_json_adapter_) -> + std::unique_ptr { + return std::make_unique( + transitions, context, start_state, states, + transition_middleware, transition_all_middlewares, + transition_callbacks, transition_all_callbacks, + state_callbacks, state_all_callbacks, context_json_adapter_); +}; + + +inline stater_state_machine_builder builder_Door_state_machine = stater_state_machine_builder() + .set_start_state(e_Door_states::OPEN) + .set_context(new Door_context()) + .set_factory(typed_Door_factory) + .add_transition("preOpen", e_Door_states::CLOSE, e_Door_states::AJAR) + .set_transition_event("preOpen", [](Door_context *ctx) { ctx->degreeOfOpening = 1; }) + .add_transition("preClose", e_Door_states::OPEN, e_Door_states::AJAR) + .set_transition_event("preClose", [](Door_context *ctx) { ctx->degreeOfOpening = 99; }) + .add_transition("open", e_Door_states::AJAR, e_Door_states::OPEN) + .set_transition_condition("open", [](Door_context *ctx) { return ctx->degreeOfOpening >= 0; }) + .set_transition_event("open", [](Door_context *ctx) { ctx->degreeOfOpening = 100; }) + .add_transition("close", e_Door_states::AJAR, e_Door_states::CLOSE) + .set_transition_condition("close", [](Door_context *ctx) { return ctx->degreeOfOpening <= 0; }) + .set_transition_event("close", [](Door_context *ctx) { ctx->degreeOfOpening = 0; }) + .add_transition("ajarPlus", e_Door_states::AJAR, e_Door_states::AJAR) + .set_transition_event("ajarPlus", [](Door_context *ctx) { ctx->degreeOfOpening = ctx->degreeOfOpening + 1; }) + .add_transition("ajarMinus", e_Door_states::AJAR, e_Door_states::AJAR) + .set_transition_event("ajarMinus", [](Door_context *ctx) { ctx->degreeOfOpening = ctx->degreeOfOpening - 1; }); \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.BuilderStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.BuilderStateGenerate.verified.txt new file mode 100644 index 0000000..c12c426 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.BuilderStateGenerate.verified.txt @@ -0,0 +1,38 @@ +#pragma once + +#include + +enum class e_Door_states { + OPEN, + AJAR, + CLOSE +}; + +inline void to_json(nlohmann::json &j, const e_Door_states &e) { + switch (e) { + case e_Door_states::OPEN: j = "OPEN"; + break; + case e_Door_states::AJAR: j = "AJAR"; + break; + case e_Door_states::CLOSE: j = "CLOSE"; + break; + } +} + +inline void from_json(const nlohmann::json &j, e_Door_states &e) { + std::string state_str = j.get(); + + if (state_str == "OPEN") e = e_Door_states::OPEN; + else if (state_str == "AJAR") e = e_Door_states::AJAR; + else if (state_str == "CLOSE") e = e_Door_states::CLOSE; +} + +inline stater_state_machine_builder builder_Door_state_machine = stater_state_machine_builder() + .set_start_state(e_Door_states::OPEN) + .set_context(new empty_context()) + .add_transition("preOpen", e_Door_states::CLOSE, e_Door_states::AJAR) + .add_transition("preClose", e_Door_states::OPEN, e_Door_states::AJAR) + .add_transition("open", e_Door_states::AJAR, e_Door_states::OPEN) + .add_transition("close", e_Door_states::AJAR, e_Door_states::CLOSE) + .add_transition("ajarPlus", e_Door_states::AJAR, e_Door_states::AJAR) + .add_transition("ajarMinus", e_Door_states::AJAR, e_Door_states::AJAR); \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.BuilderStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.BuilderStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..d6398dd --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.BuilderStateGenerateWithInterface.verified.txt @@ -0,0 +1,117 @@ +#pragma once + +#include + +enum class e_Door_states { + OPEN, + AJAR, + CLOSE +}; + +inline void to_json(nlohmann::json &j, const e_Door_states &e) { + switch (e) { + case e_Door_states::OPEN: j = "OPEN"; + break; + case e_Door_states::AJAR: j = "AJAR"; + break; + case e_Door_states::CLOSE: j = "CLOSE"; + break; + } +} + +inline void from_json(const nlohmann::json &j, e_Door_states &e) { + std::string state_str = j.get(); + + if (state_str == "OPEN") e = e_Door_states::OPEN; + else if (state_str == "AJAR") e = e_Door_states::AJAR; + else if (state_str == "CLOSE") e = e_Door_states::CLOSE; +} + +class types_Door_state_machine : public stater_state_machine { +public: + types_Door_state_machine( + const std::vector> &transitions, + empty_context *context, + const e_Door_states &start_state, + const std::unordered_set &states, + const std::unordered_map>> &transition_middlewares, + const std::vector> &transition_all_middlewares, + const std::unordered_map>> &transition_callbacks, + const std::vector> &transition_all_callbacks, + const std::unordered_map>> &state_callbacks, + const std::vector> &state_all_callbacks, + const std::shared_ptr<::context_json_adapter > &context_json_adapter + ) : stater_state_machine( + transitions, + context, + start_state, + states, + transition_middlewares, + transition_all_middlewares, + transition_callbacks, + transition_all_callbacks, + state_callbacks, + state_all_callbacks, + context_json_adapter + ) { + } + + void preOpen() { + transition("preOpen"); + } + + void preClose() { + transition("preClose"); + } + + void open() { + transition("open"); + } + + void close() { + transition("close"); + } + + void ajarPlus() { + transition("ajarPlus"); + } + + void ajarMinus() { + transition("ajarMinus"); + } +}; + +inline state_machine_factory typed_Door_factory = []( + const std::vector > &transitions, + empty_context *context, + e_Door_states start_state, + const std::unordered_set &states, + const std::unordered_map > > & + transition_middleware, + const std::vector > & + transition_all_middlewares, + const std::unordered_map > > & + transition_callbacks, + const std::vector > &transition_all_callbacks, + const std::unordered_map<::e_Door_states, std::vector > > &state_callbacks, + const std::vector > &state_all_callbacks, + const std::shared_ptr >& context_json_adapter_) -> + std::unique_ptr { + return std::make_unique( + transitions, context, start_state, states, + transition_middleware, transition_all_middlewares, + transition_callbacks, transition_all_callbacks, + state_callbacks, state_all_callbacks, context_json_adapter_); +}; + + +inline stater_state_machine_builder builder_Door_state_machine = stater_state_machine_builder() + .set_start_state(e_Door_states::OPEN) + .set_context(new empty_context()) + .set_factory(typed_Door_factory) + .add_transition("preOpen", e_Door_states::CLOSE, e_Door_states::AJAR) + .add_transition("preClose", e_Door_states::OPEN, e_Door_states::AJAR) + .add_transition("open", e_Door_states::AJAR, e_Door_states::OPEN) + .add_transition("close", e_Door_states::AJAR, e_Door_states::CLOSE) + .add_transition("ajarPlus", e_Door_states::AJAR, e_Door_states::AJAR) + .add_transition("ajarMinus", e_Door_states::AJAR, e_Door_states::AJAR); \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.ClazzContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.ClazzContextGenerate.verified.txt new file mode 100644 index 0000000..fed2f33 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.ClazzContextGenerate.verified.txt @@ -0,0 +1,65 @@ +#pragma once + +#include + +class Door_context final : context { +public: + int degreeOfOpening = 0; + bool closeVariable = true; + std::string doorName = "asd"; + float floatVariable = 0f; +}; + +class Door_state_machine : public stater_state_machine { +public: + Door_state_machine() : stater_state_machine ( + { + transition_t<::std::string, Door_context>( + "preOpen", + "CLOSE", + "AJAR", + [](Door_context *ctx) { return true; }, + [](Door_context *ctx) { ctx->degreeOfOpening = 1; } + ), + transition_t<::std::string, Door_context>( + "preClose", + "OPEN", + "AJAR", + [](Door_context *ctx) { return true; }, + [](Door_context *ctx) { ctx->degreeOfOpening = 99; } + ), + transition_t<::std::string, Door_context>( + "open", + "AJAR", + "OPEN", + [](Door_context *ctx) { return ctx->degreeOfOpening >= 0; }, + [](Door_context *ctx) { ctx->degreeOfOpening = 100; } + ), + transition_t<::std::string, Door_context>( + "close", + "AJAR", + "CLOSE", + [](Door_context *ctx) { return ctx->degreeOfOpening <= 0; }, + [](Door_context *ctx) { ctx->degreeOfOpening = 0; } + ), + transition_t<::std::string, Door_context>( + "ajarPlus", + "AJAR", + "AJAR", + [](Door_context *ctx) { return true; }, + [](Door_context *ctx) { ctx->degreeOfOpening = ctx->degreeOfOpening + 1; } + ), + transition_t<::std::string, Door_context>( + "ajarMinus", + "AJAR", + "AJAR", + [](Door_context *ctx) { return true; }, + [](Door_context *ctx) { ctx->degreeOfOpening = ctx->degreeOfOpening - 1; } + ) + }, + new Door_context(), + "OPEN" + ) { + } + +}; \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.ClazzContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.ClazzContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..f1aa929 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.ClazzContextGenerateWithInterface.verified.txt @@ -0,0 +1,88 @@ +#pragma once + +#include + +class Door_context final : context { +public: + int degreeOfOpening = 0; + bool closeVariable = true; + std::string doorName = "asd"; + float floatVariable = 0f; +}; + +class Door_state_machine : public stater_state_machine { +public: + Door_state_machine() : stater_state_machine ( + { + transition_t<::std::string, Door_context>( + "preOpen", + "CLOSE", + "AJAR", + [](Door_context *ctx) { return true; }, + [](Door_context *ctx) { ctx->degreeOfOpening = 1; } + ), + transition_t<::std::string, Door_context>( + "preClose", + "OPEN", + "AJAR", + [](Door_context *ctx) { return true; }, + [](Door_context *ctx) { ctx->degreeOfOpening = 99; } + ), + transition_t<::std::string, Door_context>( + "open", + "AJAR", + "OPEN", + [](Door_context *ctx) { return ctx->degreeOfOpening >= 0; }, + [](Door_context *ctx) { ctx->degreeOfOpening = 100; } + ), + transition_t<::std::string, Door_context>( + "close", + "AJAR", + "CLOSE", + [](Door_context *ctx) { return ctx->degreeOfOpening <= 0; }, + [](Door_context *ctx) { ctx->degreeOfOpening = 0; } + ), + transition_t<::std::string, Door_context>( + "ajarPlus", + "AJAR", + "AJAR", + [](Door_context *ctx) { return true; }, + [](Door_context *ctx) { ctx->degreeOfOpening = ctx->degreeOfOpening + 1; } + ), + transition_t<::std::string, Door_context>( + "ajarMinus", + "AJAR", + "AJAR", + [](Door_context *ctx) { return true; }, + [](Door_context *ctx) { ctx->degreeOfOpening = ctx->degreeOfOpening - 1; } + ) + }, + new Door_context(), + "OPEN" + ) { + } + + void preOpen() { + transition("preOpen"); + } + + void preClose() { + transition("preClose"); + } + + void open() { + transition("open"); + } + + void close() { + transition("close"); + } + + void ajarPlus() { + transition("ajarPlus"); + } + + void ajarMinus() { + transition("ajarMinus"); + } +}; \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.ClazzGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.ClazzGenerate.verified.txt new file mode 100644 index 0000000..324f61b --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.ClazzGenerate.verified.txt @@ -0,0 +1,57 @@ +#pragma once + +#include + +class Door_state_machine : public stater_state_machine { +public: + Door_state_machine() : stater_state_machine ( + { + transition_t<::std::string, empty_context>( + "preOpen", + "CLOSE", + "AJAR", + [](empty_context *ctx) { return true; }, + [](empty_context *ctx) { } + ), + transition_t<::std::string, empty_context>( + "preClose", + "OPEN", + "AJAR", + [](empty_context *ctx) { return true; }, + [](empty_context *ctx) { } + ), + transition_t<::std::string, empty_context>( + "open", + "AJAR", + "OPEN", + [](empty_context *ctx) { return true; }, + [](empty_context *ctx) { } + ), + transition_t<::std::string, empty_context>( + "close", + "AJAR", + "CLOSE", + [](empty_context *ctx) { return true; }, + [](empty_context *ctx) { } + ), + transition_t<::std::string, empty_context>( + "ajarPlus", + "AJAR", + "AJAR", + [](empty_context *ctx) { return true; }, + [](empty_context *ctx) { } + ), + transition_t<::std::string, empty_context>( + "ajarMinus", + "AJAR", + "AJAR", + [](empty_context *ctx) { return true; }, + [](empty_context *ctx) { } + ) + }, + new empty_context(), + "OPEN" + ) { + } + +}; \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.ClazzGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.ClazzGenerateWithInterface.verified.txt new file mode 100644 index 0000000..2df84f0 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.ClazzGenerateWithInterface.verified.txt @@ -0,0 +1,80 @@ +#pragma once + +#include + +class Door_state_machine : public stater_state_machine { +public: + Door_state_machine() : stater_state_machine ( + { + transition_t<::std::string, empty_context>( + "preOpen", + "CLOSE", + "AJAR", + [](empty_context *ctx) { return true; }, + [](empty_context *ctx) { } + ), + transition_t<::std::string, empty_context>( + "preClose", + "OPEN", + "AJAR", + [](empty_context *ctx) { return true; }, + [](empty_context *ctx) { } + ), + transition_t<::std::string, empty_context>( + "open", + "AJAR", + "OPEN", + [](empty_context *ctx) { return true; }, + [](empty_context *ctx) { } + ), + transition_t<::std::string, empty_context>( + "close", + "AJAR", + "CLOSE", + [](empty_context *ctx) { return true; }, + [](empty_context *ctx) { } + ), + transition_t<::std::string, empty_context>( + "ajarPlus", + "AJAR", + "AJAR", + [](empty_context *ctx) { return true; }, + [](empty_context *ctx) { } + ), + transition_t<::std::string, empty_context>( + "ajarMinus", + "AJAR", + "AJAR", + [](empty_context *ctx) { return true; }, + [](empty_context *ctx) { } + ) + }, + new empty_context(), + "OPEN" + ) { + } + + void preOpen() { + transition("preOpen"); + } + + void preClose() { + transition("preClose"); + } + + void open() { + transition("open"); + } + + void close() { + transition("close"); + } + + void ajarPlus() { + transition("ajarPlus"); + } + + void ajarMinus() { + transition("ajarMinus"); + } +}; \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.ClazzStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.ClazzStateContextGenerate.verified.txt new file mode 100644 index 0000000..93712ec --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.ClazzStateContextGenerate.verified.txt @@ -0,0 +1,90 @@ +#pragma once + +#include + +enum class e_Door_states { + OPEN, + AJAR, + CLOSE +}; + +inline void to_json(nlohmann::json &j, const e_Door_states &e) { + switch (e) { + case e_Door_states::OPEN: j = "OPEN"; + break; + case e_Door_states::AJAR: j = "AJAR"; + break; + case e_Door_states::CLOSE: j = "CLOSE"; + break; + } +} + +inline void from_json(const nlohmann::json &j, e_Door_states &e) { + std::string state_str = j.get(); + + if (state_str == "OPEN") e = e_Door_states::OPEN; + else if (state_str == "AJAR") e = e_Door_states::AJAR; + else if (state_str == "CLOSE") e = e_Door_states::CLOSE; +} + +class Door_context final : context { +public: + int degreeOfOpening = 0; + bool closeVariable = true; + std::string doorName = "asd"; + float floatVariable = 0f; +}; + +class Door_state_machine : public stater_state_machine { +public: + Door_state_machine() : stater_state_machine ( + { + transition_t<::e_Door_states, Door_context>( + "preOpen", + e_Door_states::CLOSE, + e_Door_states::AJAR, + [](Door_context *ctx) { return true; }, + [](Door_context *ctx) { ctx->degreeOfOpening = 1; } + ), + transition_t<::e_Door_states, Door_context>( + "preClose", + e_Door_states::OPEN, + e_Door_states::AJAR, + [](Door_context *ctx) { return true; }, + [](Door_context *ctx) { ctx->degreeOfOpening = 99; } + ), + transition_t<::e_Door_states, Door_context>( + "open", + e_Door_states::AJAR, + e_Door_states::OPEN, + [](Door_context *ctx) { return ctx->degreeOfOpening >= 0; }, + [](Door_context *ctx) { ctx->degreeOfOpening = 100; } + ), + transition_t<::e_Door_states, Door_context>( + "close", + e_Door_states::AJAR, + e_Door_states::CLOSE, + [](Door_context *ctx) { return ctx->degreeOfOpening <= 0; }, + [](Door_context *ctx) { ctx->degreeOfOpening = 0; } + ), + transition_t<::e_Door_states, Door_context>( + "ajarPlus", + e_Door_states::AJAR, + e_Door_states::AJAR, + [](Door_context *ctx) { return true; }, + [](Door_context *ctx) { ctx->degreeOfOpening = ctx->degreeOfOpening + 1; } + ), + transition_t<::e_Door_states, Door_context>( + "ajarMinus", + e_Door_states::AJAR, + e_Door_states::AJAR, + [](Door_context *ctx) { return true; }, + [](Door_context *ctx) { ctx->degreeOfOpening = ctx->degreeOfOpening - 1; } + ) + }, + new Door_context(), + e_Door_states::OPEN + ) { + } + +}; \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.ClazzStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.ClazzStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..065cb21 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.ClazzStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,113 @@ +#pragma once + +#include + +enum class e_Door_states { + OPEN, + AJAR, + CLOSE +}; + +inline void to_json(nlohmann::json &j, const e_Door_states &e) { + switch (e) { + case e_Door_states::OPEN: j = "OPEN"; + break; + case e_Door_states::AJAR: j = "AJAR"; + break; + case e_Door_states::CLOSE: j = "CLOSE"; + break; + } +} + +inline void from_json(const nlohmann::json &j, e_Door_states &e) { + std::string state_str = j.get(); + + if (state_str == "OPEN") e = e_Door_states::OPEN; + else if (state_str == "AJAR") e = e_Door_states::AJAR; + else if (state_str == "CLOSE") e = e_Door_states::CLOSE; +} + +class Door_context final : context { +public: + int degreeOfOpening = 0; + bool closeVariable = true; + std::string doorName = "asd"; + float floatVariable = 0f; +}; + +class Door_state_machine : public stater_state_machine { +public: + Door_state_machine() : stater_state_machine ( + { + transition_t<::e_Door_states, Door_context>( + "preOpen", + e_Door_states::CLOSE, + e_Door_states::AJAR, + [](Door_context *ctx) { return true; }, + [](Door_context *ctx) { ctx->degreeOfOpening = 1; } + ), + transition_t<::e_Door_states, Door_context>( + "preClose", + e_Door_states::OPEN, + e_Door_states::AJAR, + [](Door_context *ctx) { return true; }, + [](Door_context *ctx) { ctx->degreeOfOpening = 99; } + ), + transition_t<::e_Door_states, Door_context>( + "open", + e_Door_states::AJAR, + e_Door_states::OPEN, + [](Door_context *ctx) { return ctx->degreeOfOpening >= 0; }, + [](Door_context *ctx) { ctx->degreeOfOpening = 100; } + ), + transition_t<::e_Door_states, Door_context>( + "close", + e_Door_states::AJAR, + e_Door_states::CLOSE, + [](Door_context *ctx) { return ctx->degreeOfOpening <= 0; }, + [](Door_context *ctx) { ctx->degreeOfOpening = 0; } + ), + transition_t<::e_Door_states, Door_context>( + "ajarPlus", + e_Door_states::AJAR, + e_Door_states::AJAR, + [](Door_context *ctx) { return true; }, + [](Door_context *ctx) { ctx->degreeOfOpening = ctx->degreeOfOpening + 1; } + ), + transition_t<::e_Door_states, Door_context>( + "ajarMinus", + e_Door_states::AJAR, + e_Door_states::AJAR, + [](Door_context *ctx) { return true; }, + [](Door_context *ctx) { ctx->degreeOfOpening = ctx->degreeOfOpening - 1; } + ) + }, + new Door_context(), + e_Door_states::OPEN + ) { + } + + void preOpen() { + transition("preOpen"); + } + + void preClose() { + transition("preClose"); + } + + void open() { + transition("open"); + } + + void close() { + transition("close"); + } + + void ajarPlus() { + transition("ajarPlus"); + } + + void ajarMinus() { + transition("ajarMinus"); + } +}; \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.ClazzStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.ClazzStateGenerate.verified.txt new file mode 100644 index 0000000..b2a15f6 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.ClazzStateGenerate.verified.txt @@ -0,0 +1,82 @@ +#pragma once + +#include + +enum class e_Door_states { + OPEN, + AJAR, + CLOSE +}; + +inline void to_json(nlohmann::json &j, const e_Door_states &e) { + switch (e) { + case e_Door_states::OPEN: j = "OPEN"; + break; + case e_Door_states::AJAR: j = "AJAR"; + break; + case e_Door_states::CLOSE: j = "CLOSE"; + break; + } +} + +inline void from_json(const nlohmann::json &j, e_Door_states &e) { + std::string state_str = j.get(); + + if (state_str == "OPEN") e = e_Door_states::OPEN; + else if (state_str == "AJAR") e = e_Door_states::AJAR; + else if (state_str == "CLOSE") e = e_Door_states::CLOSE; +} + +class Door_state_machine : public stater_state_machine { +public: + Door_state_machine() : stater_state_machine ( + { + transition_t<::e_Door_states, empty_context>( + "preOpen", + e_Door_states::CLOSE, + e_Door_states::AJAR, + [](empty_context *ctx) { return true; }, + [](empty_context *ctx) { } + ), + transition_t<::e_Door_states, empty_context>( + "preClose", + e_Door_states::OPEN, + e_Door_states::AJAR, + [](empty_context *ctx) { return true; }, + [](empty_context *ctx) { } + ), + transition_t<::e_Door_states, empty_context>( + "open", + e_Door_states::AJAR, + e_Door_states::OPEN, + [](empty_context *ctx) { return true; }, + [](empty_context *ctx) { } + ), + transition_t<::e_Door_states, empty_context>( + "close", + e_Door_states::AJAR, + e_Door_states::CLOSE, + [](empty_context *ctx) { return true; }, + [](empty_context *ctx) { } + ), + transition_t<::e_Door_states, empty_context>( + "ajarPlus", + e_Door_states::AJAR, + e_Door_states::AJAR, + [](empty_context *ctx) { return true; }, + [](empty_context *ctx) { } + ), + transition_t<::e_Door_states, empty_context>( + "ajarMinus", + e_Door_states::AJAR, + e_Door_states::AJAR, + [](empty_context *ctx) { return true; }, + [](empty_context *ctx) { } + ) + }, + new empty_context(), + e_Door_states::OPEN + ) { + } + +}; \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.ClazzStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.ClazzStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..322b8d0 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateDoorTests.ClazzStateGenerateWithInterface.verified.txt @@ -0,0 +1,105 @@ +#pragma once + +#include + +enum class e_Door_states { + OPEN, + AJAR, + CLOSE +}; + +inline void to_json(nlohmann::json &j, const e_Door_states &e) { + switch (e) { + case e_Door_states::OPEN: j = "OPEN"; + break; + case e_Door_states::AJAR: j = "AJAR"; + break; + case e_Door_states::CLOSE: j = "CLOSE"; + break; + } +} + +inline void from_json(const nlohmann::json &j, e_Door_states &e) { + std::string state_str = j.get(); + + if (state_str == "OPEN") e = e_Door_states::OPEN; + else if (state_str == "AJAR") e = e_Door_states::AJAR; + else if (state_str == "CLOSE") e = e_Door_states::CLOSE; +} + +class Door_state_machine : public stater_state_machine { +public: + Door_state_machine() : stater_state_machine ( + { + transition_t<::e_Door_states, empty_context>( + "preOpen", + e_Door_states::CLOSE, + e_Door_states::AJAR, + [](empty_context *ctx) { return true; }, + [](empty_context *ctx) { } + ), + transition_t<::e_Door_states, empty_context>( + "preClose", + e_Door_states::OPEN, + e_Door_states::AJAR, + [](empty_context *ctx) { return true; }, + [](empty_context *ctx) { } + ), + transition_t<::e_Door_states, empty_context>( + "open", + e_Door_states::AJAR, + e_Door_states::OPEN, + [](empty_context *ctx) { return true; }, + [](empty_context *ctx) { } + ), + transition_t<::e_Door_states, empty_context>( + "close", + e_Door_states::AJAR, + e_Door_states::CLOSE, + [](empty_context *ctx) { return true; }, + [](empty_context *ctx) { } + ), + transition_t<::e_Door_states, empty_context>( + "ajarPlus", + e_Door_states::AJAR, + e_Door_states::AJAR, + [](empty_context *ctx) { return true; }, + [](empty_context *ctx) { } + ), + transition_t<::e_Door_states, empty_context>( + "ajarMinus", + e_Door_states::AJAR, + e_Door_states::AJAR, + [](empty_context *ctx) { return true; }, + [](empty_context *ctx) { } + ) + }, + new empty_context(), + e_Door_states::OPEN + ) { + } + + void preOpen() { + transition("preOpen"); + } + + void preClose() { + transition("preClose"); + } + + void open() { + transition("open"); + } + + void close() { + transition("close"); + } + + void ajarPlus() { + transition("ajarPlus"); + } + + void ajarMinus() { + transition("ajarMinus"); + } +}; \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.BuilderTestsContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.BuilderTestsContextGenerate.verified.txt new file mode 100644 index 0000000..707e61f --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.BuilderTestsContextGenerate.verified.txt @@ -0,0 +1,254 @@ +#include + +#include + + + +TEST(Door_state_machine_test, test_init) { + builder_Door_state_machine.build(); +} + + +TEST(Door_state_machine_test, test_scenario_0) { + const auto sm = builder_Door_state_machine.build(); + sm->disable_events(); + + + sm->transition("preClose"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("close"); + ASSERT_EQ(sm->get_state(), "CLOSE"); + + sm->transition("preOpen"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("ajarPlus"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("open"); + ASSERT_EQ(sm->get_state(), "OPEN"); +} + +TEST(Door_state_machine_test, test_scenario_1) { + const auto sm = builder_Door_state_machine.build(); + sm->disable_events(); + + + sm->transition("preClose"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("ajarPlus"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("close"); + ASSERT_EQ(sm->get_state(), "CLOSE"); + + sm->transition("preOpen"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("open"); + ASSERT_EQ(sm->get_state(), "OPEN"); +} + +TEST(Door_state_machine_test, test_scenario_2) { + const auto sm = builder_Door_state_machine.build(); + sm->disable_events(); + + + sm->transition("preClose"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("close"); + ASSERT_EQ(sm->get_state(), "CLOSE"); + + sm->transition("preOpen"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("open"); + ASSERT_EQ(sm->get_state(), "OPEN"); +} + +TEST(Door_state_machine_test, test_json_schema) { + auto sm = builder_Door_state_machine.build(); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +})"), nlohmann::json::parse(sm->to_json_schema())); +} + +TEST(Door_state_machine_test, test_system_append_state_transition) { + auto sm_builder = builder_Door_state_machine; + + sm_builder = sm_builder.add_state("__test_state_1__"); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +})"), nlohmann::json::parse(sm_builder.build()->to_json_schema())); + + sm_builder = sm_builder.add_state("__test_state_2__"); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +})"), nlohmann::json::parse(sm_builder.build()->to_json_schema())); + + sm_builder = sm_builder.add_transition("__test_transition__", "__test_state_1__", "__test_state_2__"); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] +})"), nlohmann::json::parse(sm_builder.build()->to_json_schema())); +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.BuilderTestsContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.BuilderTestsContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..f7a80a3 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.BuilderTestsContextGenerateWithInterface.verified.txt @@ -0,0 +1,259 @@ +#include + +#include + + + +TEST(Door_state_machine_test, test_init) { + const auto st = builder_Door_state_machine.build(); + dynamic_cast(st.get()); +} + + +TEST(Door_state_machine_test, test_scenario_0) { + const auto st = builder_Door_state_machine.build(); + const auto sm = dynamic_cast(st.get()); + sm->disable_events(); + + + sm->preClose(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->close(); + ASSERT_EQ(sm->get_state(), "CLOSE"); + + sm->preOpen(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->ajarPlus(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->open(); + ASSERT_EQ(sm->get_state(), "OPEN"); +} + +TEST(Door_state_machine_test, test_scenario_1) { + const auto st = builder_Door_state_machine.build(); + const auto sm = dynamic_cast(st.get()); + sm->disable_events(); + + + sm->preClose(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->ajarPlus(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->close(); + ASSERT_EQ(sm->get_state(), "CLOSE"); + + sm->preOpen(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->open(); + ASSERT_EQ(sm->get_state(), "OPEN"); +} + +TEST(Door_state_machine_test, test_scenario_2) { + const auto st = builder_Door_state_machine.build(); + const auto sm = dynamic_cast(st.get()); + sm->disable_events(); + + + sm->preClose(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->close(); + ASSERT_EQ(sm->get_state(), "CLOSE"); + + sm->preOpen(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->open(); + ASSERT_EQ(sm->get_state(), "OPEN"); +} + +TEST(Door_state_machine_test, test_json_schema) { + const auto st = builder_Door_state_machine.build(); + auto sm = dynamic_cast(st.get()); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +})"), nlohmann::json::parse(sm->to_json_schema())); +} + +TEST(Door_state_machine_test, test_system_append_state_transition) { + auto sm_builder = builder_Door_state_machine; + + sm_builder = sm_builder.add_state("__test_state_1__"); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +})"), nlohmann::json::parse(sm_builder.build()->to_json_schema())); + + sm_builder = sm_builder.add_state("__test_state_2__"); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +})"), nlohmann::json::parse(sm_builder.build()->to_json_schema())); + + sm_builder = sm_builder.add_transition("__test_transition__", "__test_state_1__", "__test_state_2__"); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] +})"), nlohmann::json::parse(sm_builder.build()->to_json_schema())); +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.BuilderTestsGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.BuilderTestsGenerate.verified.txt new file mode 100644 index 0000000..707e61f --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.BuilderTestsGenerate.verified.txt @@ -0,0 +1,254 @@ +#include + +#include + + + +TEST(Door_state_machine_test, test_init) { + builder_Door_state_machine.build(); +} + + +TEST(Door_state_machine_test, test_scenario_0) { + const auto sm = builder_Door_state_machine.build(); + sm->disable_events(); + + + sm->transition("preClose"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("close"); + ASSERT_EQ(sm->get_state(), "CLOSE"); + + sm->transition("preOpen"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("ajarPlus"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("open"); + ASSERT_EQ(sm->get_state(), "OPEN"); +} + +TEST(Door_state_machine_test, test_scenario_1) { + const auto sm = builder_Door_state_machine.build(); + sm->disable_events(); + + + sm->transition("preClose"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("ajarPlus"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("close"); + ASSERT_EQ(sm->get_state(), "CLOSE"); + + sm->transition("preOpen"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("open"); + ASSERT_EQ(sm->get_state(), "OPEN"); +} + +TEST(Door_state_machine_test, test_scenario_2) { + const auto sm = builder_Door_state_machine.build(); + sm->disable_events(); + + + sm->transition("preClose"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("close"); + ASSERT_EQ(sm->get_state(), "CLOSE"); + + sm->transition("preOpen"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("open"); + ASSERT_EQ(sm->get_state(), "OPEN"); +} + +TEST(Door_state_machine_test, test_json_schema) { + auto sm = builder_Door_state_machine.build(); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +})"), nlohmann::json::parse(sm->to_json_schema())); +} + +TEST(Door_state_machine_test, test_system_append_state_transition) { + auto sm_builder = builder_Door_state_machine; + + sm_builder = sm_builder.add_state("__test_state_1__"); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +})"), nlohmann::json::parse(sm_builder.build()->to_json_schema())); + + sm_builder = sm_builder.add_state("__test_state_2__"); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +})"), nlohmann::json::parse(sm_builder.build()->to_json_schema())); + + sm_builder = sm_builder.add_transition("__test_transition__", "__test_state_1__", "__test_state_2__"); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] +})"), nlohmann::json::parse(sm_builder.build()->to_json_schema())); +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.BuilderTestsGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.BuilderTestsGenerateWithInterface.verified.txt new file mode 100644 index 0000000..f7a80a3 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.BuilderTestsGenerateWithInterface.verified.txt @@ -0,0 +1,259 @@ +#include + +#include + + + +TEST(Door_state_machine_test, test_init) { + const auto st = builder_Door_state_machine.build(); + dynamic_cast(st.get()); +} + + +TEST(Door_state_machine_test, test_scenario_0) { + const auto st = builder_Door_state_machine.build(); + const auto sm = dynamic_cast(st.get()); + sm->disable_events(); + + + sm->preClose(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->close(); + ASSERT_EQ(sm->get_state(), "CLOSE"); + + sm->preOpen(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->ajarPlus(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->open(); + ASSERT_EQ(sm->get_state(), "OPEN"); +} + +TEST(Door_state_machine_test, test_scenario_1) { + const auto st = builder_Door_state_machine.build(); + const auto sm = dynamic_cast(st.get()); + sm->disable_events(); + + + sm->preClose(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->ajarPlus(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->close(); + ASSERT_EQ(sm->get_state(), "CLOSE"); + + sm->preOpen(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->open(); + ASSERT_EQ(sm->get_state(), "OPEN"); +} + +TEST(Door_state_machine_test, test_scenario_2) { + const auto st = builder_Door_state_machine.build(); + const auto sm = dynamic_cast(st.get()); + sm->disable_events(); + + + sm->preClose(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->close(); + ASSERT_EQ(sm->get_state(), "CLOSE"); + + sm->preOpen(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->open(); + ASSERT_EQ(sm->get_state(), "OPEN"); +} + +TEST(Door_state_machine_test, test_json_schema) { + const auto st = builder_Door_state_machine.build(); + auto sm = dynamic_cast(st.get()); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +})"), nlohmann::json::parse(sm->to_json_schema())); +} + +TEST(Door_state_machine_test, test_system_append_state_transition) { + auto sm_builder = builder_Door_state_machine; + + sm_builder = sm_builder.add_state("__test_state_1__"); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +})"), nlohmann::json::parse(sm_builder.build()->to_json_schema())); + + sm_builder = sm_builder.add_state("__test_state_2__"); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +})"), nlohmann::json::parse(sm_builder.build()->to_json_schema())); + + sm_builder = sm_builder.add_transition("__test_transition__", "__test_state_1__", "__test_state_2__"); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] +})"), nlohmann::json::parse(sm_builder.build()->to_json_schema())); +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerate.verified.txt new file mode 100644 index 0000000..a238513 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerate.verified.txt @@ -0,0 +1,114 @@ +#include + +#include + + + +TEST(Door_state_machine_test, test_init) { + builder_Door_state_machine.build(); +} + + +TEST(Door_state_machine_test, test_scenario_0) { + const auto sm = builder_Door_state_machine.build(); + sm->disable_events(); + + + sm->transition("preClose"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("close"); + ASSERT_EQ(sm->get_state(), e_Door_states::CLOSE); + + sm->transition("preOpen"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("ajarPlus"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("open"); + ASSERT_EQ(sm->get_state(), e_Door_states::OPEN); +} + +TEST(Door_state_machine_test, test_scenario_1) { + const auto sm = builder_Door_state_machine.build(); + sm->disable_events(); + + + sm->transition("preClose"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("ajarPlus"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("close"); + ASSERT_EQ(sm->get_state(), e_Door_states::CLOSE); + + sm->transition("preOpen"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("open"); + ASSERT_EQ(sm->get_state(), e_Door_states::OPEN); +} + +TEST(Door_state_machine_test, test_scenario_2) { + const auto sm = builder_Door_state_machine.build(); + sm->disable_events(); + + + sm->transition("preClose"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("close"); + ASSERT_EQ(sm->get_state(), e_Door_states::CLOSE); + + sm->transition("preOpen"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("open"); + ASSERT_EQ(sm->get_state(), e_Door_states::OPEN); +} + +TEST(Door_state_machine_test, test_json_schema) { + auto sm = builder_Door_state_machine.build(); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +})"), nlohmann::json::parse(sm->to_json_schema())); +} diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..73c17ac --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,119 @@ +#include + +#include + + + +TEST(Door_state_machine_test, test_init) { + const auto st = builder_Door_state_machine.build(); + dynamic_cast(st.get()); +} + + +TEST(Door_state_machine_test, test_scenario_0) { + const auto st = builder_Door_state_machine.build(); + const auto sm = dynamic_cast(st.get()); + sm->disable_events(); + + + sm->preClose(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->close(); + ASSERT_EQ(sm->get_state(), e_Door_states::CLOSE); + + sm->preOpen(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->ajarPlus(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->open(); + ASSERT_EQ(sm->get_state(), e_Door_states::OPEN); +} + +TEST(Door_state_machine_test, test_scenario_1) { + const auto st = builder_Door_state_machine.build(); + const auto sm = dynamic_cast(st.get()); + sm->disable_events(); + + + sm->preClose(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->ajarPlus(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->close(); + ASSERT_EQ(sm->get_state(), e_Door_states::CLOSE); + + sm->preOpen(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->open(); + ASSERT_EQ(sm->get_state(), e_Door_states::OPEN); +} + +TEST(Door_state_machine_test, test_scenario_2) { + const auto st = builder_Door_state_machine.build(); + const auto sm = dynamic_cast(st.get()); + sm->disable_events(); + + + sm->preClose(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->close(); + ASSERT_EQ(sm->get_state(), e_Door_states::CLOSE); + + sm->preOpen(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->open(); + ASSERT_EQ(sm->get_state(), e_Door_states::OPEN); +} + +TEST(Door_state_machine_test, test_json_schema) { + const auto st = builder_Door_state_machine.build(); + auto sm = dynamic_cast(st.get()); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +})"), nlohmann::json::parse(sm->to_json_schema())); +} diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.BuilderTestsStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.BuilderTestsStateGenerate.verified.txt new file mode 100644 index 0000000..a238513 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.BuilderTestsStateGenerate.verified.txt @@ -0,0 +1,114 @@ +#include + +#include + + + +TEST(Door_state_machine_test, test_init) { + builder_Door_state_machine.build(); +} + + +TEST(Door_state_machine_test, test_scenario_0) { + const auto sm = builder_Door_state_machine.build(); + sm->disable_events(); + + + sm->transition("preClose"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("close"); + ASSERT_EQ(sm->get_state(), e_Door_states::CLOSE); + + sm->transition("preOpen"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("ajarPlus"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("open"); + ASSERT_EQ(sm->get_state(), e_Door_states::OPEN); +} + +TEST(Door_state_machine_test, test_scenario_1) { + const auto sm = builder_Door_state_machine.build(); + sm->disable_events(); + + + sm->transition("preClose"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("ajarPlus"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("close"); + ASSERT_EQ(sm->get_state(), e_Door_states::CLOSE); + + sm->transition("preOpen"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("open"); + ASSERT_EQ(sm->get_state(), e_Door_states::OPEN); +} + +TEST(Door_state_machine_test, test_scenario_2) { + const auto sm = builder_Door_state_machine.build(); + sm->disable_events(); + + + sm->transition("preClose"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("close"); + ASSERT_EQ(sm->get_state(), e_Door_states::CLOSE); + + sm->transition("preOpen"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("open"); + ASSERT_EQ(sm->get_state(), e_Door_states::OPEN); +} + +TEST(Door_state_machine_test, test_json_schema) { + auto sm = builder_Door_state_machine.build(); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +})"), nlohmann::json::parse(sm->to_json_schema())); +} diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.BuilderTestsStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.BuilderTestsStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..73c17ac --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.BuilderTestsStateGenerateWithInterface.verified.txt @@ -0,0 +1,119 @@ +#include + +#include + + + +TEST(Door_state_machine_test, test_init) { + const auto st = builder_Door_state_machine.build(); + dynamic_cast(st.get()); +} + + +TEST(Door_state_machine_test, test_scenario_0) { + const auto st = builder_Door_state_machine.build(); + const auto sm = dynamic_cast(st.get()); + sm->disable_events(); + + + sm->preClose(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->close(); + ASSERT_EQ(sm->get_state(), e_Door_states::CLOSE); + + sm->preOpen(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->ajarPlus(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->open(); + ASSERT_EQ(sm->get_state(), e_Door_states::OPEN); +} + +TEST(Door_state_machine_test, test_scenario_1) { + const auto st = builder_Door_state_machine.build(); + const auto sm = dynamic_cast(st.get()); + sm->disable_events(); + + + sm->preClose(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->ajarPlus(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->close(); + ASSERT_EQ(sm->get_state(), e_Door_states::CLOSE); + + sm->preOpen(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->open(); + ASSERT_EQ(sm->get_state(), e_Door_states::OPEN); +} + +TEST(Door_state_machine_test, test_scenario_2) { + const auto st = builder_Door_state_machine.build(); + const auto sm = dynamic_cast(st.get()); + sm->disable_events(); + + + sm->preClose(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->close(); + ASSERT_EQ(sm->get_state(), e_Door_states::CLOSE); + + sm->preOpen(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->open(); + ASSERT_EQ(sm->get_state(), e_Door_states::OPEN); +} + +TEST(Door_state_machine_test, test_json_schema) { + const auto st = builder_Door_state_machine.build(); + auto sm = dynamic_cast(st.get()); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +})"), nlohmann::json::parse(sm->to_json_schema())); +} diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.ClazzTestsContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.ClazzTestsContextGenerate.verified.txt new file mode 100644 index 0000000..b2df42c --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.ClazzTestsContextGenerate.verified.txt @@ -0,0 +1,114 @@ +#include + +#include + + + +TEST(Door_state_machine_test, test_init) { + new Door_state_machine(); +} + + +TEST(Door_state_machine_test, test_scenario_0) { + const auto sm = new Door_state_machine(); + sm->disable_events(); + + + sm->transition("preClose"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("close"); + ASSERT_EQ(sm->get_state(), "CLOSE"); + + sm->transition("preOpen"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("ajarPlus"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("open"); + ASSERT_EQ(sm->get_state(), "OPEN"); +} + +TEST(Door_state_machine_test, test_scenario_1) { + const auto sm = new Door_state_machine(); + sm->disable_events(); + + + sm->transition("preClose"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("ajarPlus"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("close"); + ASSERT_EQ(sm->get_state(), "CLOSE"); + + sm->transition("preOpen"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("open"); + ASSERT_EQ(sm->get_state(), "OPEN"); +} + +TEST(Door_state_machine_test, test_scenario_2) { + const auto sm = new Door_state_machine(); + sm->disable_events(); + + + sm->transition("preClose"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("close"); + ASSERT_EQ(sm->get_state(), "CLOSE"); + + sm->transition("preOpen"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("open"); + ASSERT_EQ(sm->get_state(), "OPEN"); +} + +TEST(Door_state_machine_test, test_json_schema) { + auto sm = new Door_state_machine(); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +})"), nlohmann::json::parse(sm->to_json_schema())); +} diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.ClazzTestsContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.ClazzTestsContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..47d878a --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.ClazzTestsContextGenerateWithInterface.verified.txt @@ -0,0 +1,114 @@ +#include + +#include + + + +TEST(Door_state_machine_test, test_init) { + new Door_state_machine(); +} + + +TEST(Door_state_machine_test, test_scenario_0) { + const auto sm = new Door_state_machine(); + sm->disable_events(); + + + sm->preClose(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->close(); + ASSERT_EQ(sm->get_state(), "CLOSE"); + + sm->preOpen(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->ajarPlus(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->open(); + ASSERT_EQ(sm->get_state(), "OPEN"); +} + +TEST(Door_state_machine_test, test_scenario_1) { + const auto sm = new Door_state_machine(); + sm->disable_events(); + + + sm->preClose(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->ajarPlus(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->close(); + ASSERT_EQ(sm->get_state(), "CLOSE"); + + sm->preOpen(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->open(); + ASSERT_EQ(sm->get_state(), "OPEN"); +} + +TEST(Door_state_machine_test, test_scenario_2) { + const auto sm = new Door_state_machine(); + sm->disable_events(); + + + sm->preClose(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->close(); + ASSERT_EQ(sm->get_state(), "CLOSE"); + + sm->preOpen(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->open(); + ASSERT_EQ(sm->get_state(), "OPEN"); +} + +TEST(Door_state_machine_test, test_json_schema) { + auto sm = new Door_state_machine(); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +})"), nlohmann::json::parse(sm->to_json_schema())); +} diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.ClazzTestsGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.ClazzTestsGenerate.verified.txt new file mode 100644 index 0000000..b2df42c --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.ClazzTestsGenerate.verified.txt @@ -0,0 +1,114 @@ +#include + +#include + + + +TEST(Door_state_machine_test, test_init) { + new Door_state_machine(); +} + + +TEST(Door_state_machine_test, test_scenario_0) { + const auto sm = new Door_state_machine(); + sm->disable_events(); + + + sm->transition("preClose"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("close"); + ASSERT_EQ(sm->get_state(), "CLOSE"); + + sm->transition("preOpen"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("ajarPlus"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("open"); + ASSERT_EQ(sm->get_state(), "OPEN"); +} + +TEST(Door_state_machine_test, test_scenario_1) { + const auto sm = new Door_state_machine(); + sm->disable_events(); + + + sm->transition("preClose"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("ajarPlus"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("close"); + ASSERT_EQ(sm->get_state(), "CLOSE"); + + sm->transition("preOpen"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("open"); + ASSERT_EQ(sm->get_state(), "OPEN"); +} + +TEST(Door_state_machine_test, test_scenario_2) { + const auto sm = new Door_state_machine(); + sm->disable_events(); + + + sm->transition("preClose"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("close"); + ASSERT_EQ(sm->get_state(), "CLOSE"); + + sm->transition("preOpen"); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->transition("open"); + ASSERT_EQ(sm->get_state(), "OPEN"); +} + +TEST(Door_state_machine_test, test_json_schema) { + auto sm = new Door_state_machine(); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +})"), nlohmann::json::parse(sm->to_json_schema())); +} diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.ClazzTestsGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.ClazzTestsGenerateWithInterface.verified.txt new file mode 100644 index 0000000..47d878a --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.ClazzTestsGenerateWithInterface.verified.txt @@ -0,0 +1,114 @@ +#include + +#include + + + +TEST(Door_state_machine_test, test_init) { + new Door_state_machine(); +} + + +TEST(Door_state_machine_test, test_scenario_0) { + const auto sm = new Door_state_machine(); + sm->disable_events(); + + + sm->preClose(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->close(); + ASSERT_EQ(sm->get_state(), "CLOSE"); + + sm->preOpen(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->ajarPlus(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->open(); + ASSERT_EQ(sm->get_state(), "OPEN"); +} + +TEST(Door_state_machine_test, test_scenario_1) { + const auto sm = new Door_state_machine(); + sm->disable_events(); + + + sm->preClose(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->ajarPlus(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->close(); + ASSERT_EQ(sm->get_state(), "CLOSE"); + + sm->preOpen(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->open(); + ASSERT_EQ(sm->get_state(), "OPEN"); +} + +TEST(Door_state_machine_test, test_scenario_2) { + const auto sm = new Door_state_machine(); + sm->disable_events(); + + + sm->preClose(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->close(); + ASSERT_EQ(sm->get_state(), "CLOSE"); + + sm->preOpen(); + ASSERT_EQ(sm->get_state(), "AJAR"); + + sm->open(); + ASSERT_EQ(sm->get_state(), "OPEN"); +} + +TEST(Door_state_machine_test, test_json_schema) { + auto sm = new Door_state_machine(); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +})"), nlohmann::json::parse(sm->to_json_schema())); +} diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerate.verified.txt new file mode 100644 index 0000000..8bf2ac3 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerate.verified.txt @@ -0,0 +1,114 @@ +#include + +#include + + + +TEST(Door_state_machine_test, test_init) { + new Door_state_machine(); +} + + +TEST(Door_state_machine_test, test_scenario_0) { + const auto sm = new Door_state_machine(); + sm->disable_events(); + + + sm->transition("preClose"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("close"); + ASSERT_EQ(sm->get_state(), e_Door_states::CLOSE); + + sm->transition("preOpen"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("ajarPlus"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("open"); + ASSERT_EQ(sm->get_state(), e_Door_states::OPEN); +} + +TEST(Door_state_machine_test, test_scenario_1) { + const auto sm = new Door_state_machine(); + sm->disable_events(); + + + sm->transition("preClose"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("ajarPlus"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("close"); + ASSERT_EQ(sm->get_state(), e_Door_states::CLOSE); + + sm->transition("preOpen"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("open"); + ASSERT_EQ(sm->get_state(), e_Door_states::OPEN); +} + +TEST(Door_state_machine_test, test_scenario_2) { + const auto sm = new Door_state_machine(); + sm->disable_events(); + + + sm->transition("preClose"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("close"); + ASSERT_EQ(sm->get_state(), e_Door_states::CLOSE); + + sm->transition("preOpen"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("open"); + ASSERT_EQ(sm->get_state(), e_Door_states::OPEN); +} + +TEST(Door_state_machine_test, test_json_schema) { + auto sm = new Door_state_machine(); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +})"), nlohmann::json::parse(sm->to_json_schema())); +} diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..6da3797 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,114 @@ +#include + +#include + + + +TEST(Door_state_machine_test, test_init) { + new Door_state_machine(); +} + + +TEST(Door_state_machine_test, test_scenario_0) { + const auto sm = new Door_state_machine(); + sm->disable_events(); + + + sm->preClose(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->close(); + ASSERT_EQ(sm->get_state(), e_Door_states::CLOSE); + + sm->preOpen(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->ajarPlus(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->open(); + ASSERT_EQ(sm->get_state(), e_Door_states::OPEN); +} + +TEST(Door_state_machine_test, test_scenario_1) { + const auto sm = new Door_state_machine(); + sm->disable_events(); + + + sm->preClose(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->ajarPlus(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->close(); + ASSERT_EQ(sm->get_state(), e_Door_states::CLOSE); + + sm->preOpen(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->open(); + ASSERT_EQ(sm->get_state(), e_Door_states::OPEN); +} + +TEST(Door_state_machine_test, test_scenario_2) { + const auto sm = new Door_state_machine(); + sm->disable_events(); + + + sm->preClose(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->close(); + ASSERT_EQ(sm->get_state(), e_Door_states::CLOSE); + + sm->preOpen(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->open(); + ASSERT_EQ(sm->get_state(), e_Door_states::OPEN); +} + +TEST(Door_state_machine_test, test_json_schema) { + auto sm = new Door_state_machine(); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +})"), nlohmann::json::parse(sm->to_json_schema())); +} diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.ClazzTestsStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.ClazzTestsStateGenerate.verified.txt new file mode 100644 index 0000000..8bf2ac3 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.ClazzTestsStateGenerate.verified.txt @@ -0,0 +1,114 @@ +#include + +#include + + + +TEST(Door_state_machine_test, test_init) { + new Door_state_machine(); +} + + +TEST(Door_state_machine_test, test_scenario_0) { + const auto sm = new Door_state_machine(); + sm->disable_events(); + + + sm->transition("preClose"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("close"); + ASSERT_EQ(sm->get_state(), e_Door_states::CLOSE); + + sm->transition("preOpen"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("ajarPlus"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("open"); + ASSERT_EQ(sm->get_state(), e_Door_states::OPEN); +} + +TEST(Door_state_machine_test, test_scenario_1) { + const auto sm = new Door_state_machine(); + sm->disable_events(); + + + sm->transition("preClose"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("ajarPlus"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("close"); + ASSERT_EQ(sm->get_state(), e_Door_states::CLOSE); + + sm->transition("preOpen"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("open"); + ASSERT_EQ(sm->get_state(), e_Door_states::OPEN); +} + +TEST(Door_state_machine_test, test_scenario_2) { + const auto sm = new Door_state_machine(); + sm->disable_events(); + + + sm->transition("preClose"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("close"); + ASSERT_EQ(sm->get_state(), e_Door_states::CLOSE); + + sm->transition("preOpen"); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->transition("open"); + ASSERT_EQ(sm->get_state(), e_Door_states::OPEN); +} + +TEST(Door_state_machine_test, test_json_schema) { + auto sm = new Door_state_machine(); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +})"), nlohmann::json::parse(sm->to_json_schema())); +} diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.ClazzTestsStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.ClazzTestsStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..6da3797 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlus/CPlusPlusAdapterGenerateTestsDoorTests.ClazzTestsStateGenerateWithInterface.verified.txt @@ -0,0 +1,114 @@ +#include + +#include + + + +TEST(Door_state_machine_test, test_init) { + new Door_state_machine(); +} + + +TEST(Door_state_machine_test, test_scenario_0) { + const auto sm = new Door_state_machine(); + sm->disable_events(); + + + sm->preClose(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->close(); + ASSERT_EQ(sm->get_state(), e_Door_states::CLOSE); + + sm->preOpen(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->ajarPlus(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->open(); + ASSERT_EQ(sm->get_state(), e_Door_states::OPEN); +} + +TEST(Door_state_machine_test, test_scenario_1) { + const auto sm = new Door_state_machine(); + sm->disable_events(); + + + sm->preClose(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->ajarPlus(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->close(); + ASSERT_EQ(sm->get_state(), e_Door_states::CLOSE); + + sm->preOpen(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->open(); + ASSERT_EQ(sm->get_state(), e_Door_states::OPEN); +} + +TEST(Door_state_machine_test, test_scenario_2) { + const auto sm = new Door_state_machine(); + sm->disable_events(); + + + sm->preClose(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->close(); + ASSERT_EQ(sm->get_state(), e_Door_states::CLOSE); + + sm->preOpen(); + ASSERT_EQ(sm->get_state(), e_Door_states::AJAR); + + sm->open(); + ASSERT_EQ(sm->get_state(), e_Door_states::OPEN); +} + +TEST(Door_state_machine_test, test_json_schema) { + auto sm = new Door_state_machine(); + ASSERT_EQ(nlohmann::json::parse(R"({ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +})"), nlohmann::json::parse(sm->to_json_schema())); +} diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlusAdapterGenerateDoorTests.cs b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlusAdapterGenerateDoorTests.cs new file mode 100644 index 0000000..9c80bfb --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CPlusPlusAdapterGenerateDoorTests.cs @@ -0,0 +1,20 @@ +using Stater.CodeGeneration.Entity; +using Stater.CodeGeneration.LanguageAdapter.Base; +using Stater.CodeGeneration.LanguageAdapter.CPlusPlus; +using Stater.CodeGeneration.LanguageAdapter.CSharp; +using Stater.CodeGeneration.LanguageAdapter.Java; +using Stater.CodeGeneration.LanguageAdapter.Kotlin; + +namespace Stater.CodeGeneration.Tests.LanguageAdapter; + +public class CPlusPlusAdapterGenerateDoorTests : BaseTestAdapterGenerateDoorTests +{ + protected override BaseLanguageAdapter Adapter => new CPlusPlusAdapter(); + protected override Language Language => Language.CPlusPlus; +} + +public class CPlusPlusAdapterGenerateTestsDoorTests : BaseTestAdapterGenerateTestsDoorTests +{ + protected override BaseLanguageAdapter Adapter => new CPlusPlusAdapter(); + protected override Language Language => Language.CPlusPlus; +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.BuilderContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.BuilderContextGenerate.verified.txt new file mode 100644 index 0000000..f3772d1 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.BuilderContextGenerate.verified.txt @@ -0,0 +1,30 @@ +namespace fsm.door; + +using Stater.StateMachine.Lib; + +public class DoorFSMContext : IContext{ + public int degreeOfOpening = 0; + public bool closeVariable = true; + public string doorName = "asd"; + public float floatVariable = 0f; +} + +public class Door { + public static StaterStateMachineBuilder BuilderDoorStateMachine = new StaterStateMachineBuilder() + .SetStartState("OPEN") + .SetContext(new DoorFSMContext()) + .AddTransition("preOpen", "CLOSE", "AJAR") + .SetTransitionEvent("preOpen", ctx => ctx.degreeOfOpening = 1) + .AddTransition("preClose", "OPEN", "AJAR") + .SetTransitionEvent("preClose", ctx => ctx.degreeOfOpening = 99) + .AddTransition("open", "AJAR", "OPEN") + .SetTransitionCondition("open", ctx => ctx.degreeOfOpening >= 0) + .SetTransitionEvent("open", ctx => ctx.degreeOfOpening = 100) + .AddTransition("close", "AJAR", "CLOSE") + .SetTransitionCondition("close", ctx => ctx.degreeOfOpening <= 0) + .SetTransitionEvent("close", ctx => ctx.degreeOfOpening = 0) + .AddTransition("ajarPlus", "AJAR", "AJAR") + .SetTransitionEvent("ajarPlus", ctx => ctx.degreeOfOpening = ctx.degreeOfOpening + 1) + .AddTransition("ajarMinus", "AJAR", "AJAR") + .SetTransitionEvent("ajarMinus", ctx => ctx.degreeOfOpening = ctx.degreeOfOpening - 1); +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.BuilderContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.BuilderContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..e5fc93c --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.BuilderContextGenerateWithInterface.verified.txt @@ -0,0 +1,114 @@ +namespace fsm.door; + +using Stater.StateMachine.Lib; + +public class DoorFSMContext : IContext{ + public int degreeOfOpening = 0; + public bool closeVariable = true; + public string doorName = "asd"; + public float floatVariable = 0f; +} + +public class Door { + public class TypesDoorStateMachine( + List> transitions, + DoorFSMContext context, + String startState, + HashSet states, + Dictionary>> transitionMiddlewares, + List> transitionAllMiddlewares, + Dictionary>> transitionCallbacks, + List> transitionAllCallbacks, + Dictionary>> stateCallbacks, + List> stateAllCallbacks, + IContextJsonAdapter contextJsonAdapter + ) : StaterStateMachine( + transitions, + context, + startState, + states, + transitionMiddlewares, + transitionAllMiddlewares, + transitionCallbacks, + transitionAllCallbacks, + stateCallbacks, + stateAllCallbacks, + contextJsonAdapter + ) + { + public void preOpen() + { + Transition("preOpen"); + } + + public void preClose() + { + Transition("preClose"); + } + + public void open() + { + Transition("open"); + } + + public void close() + { + Transition("close"); + } + + public void ajarPlus() + { + Transition("ajarPlus"); + } + + public void ajarMinus() + { + Transition("ajarMinus"); + } + } + private static StateMachineFactory TypedDoorFactory = ( + transitionsA, + contextA, + startStateA, + statesA, + transitionMiddlewaresA, + transitionAllMiddlewaresA, + transitionCallbacksA, + transitionAllCallbacksA, + stateCallbacksA, + stateAllCallbacksA, + contextJsonAdapterA + ) => new TypesDoorStateMachine( + transitionsA, + contextA, + startStateA, + statesA, + transitionMiddlewaresA, + transitionAllMiddlewaresA, + transitionCallbacksA, + transitionAllCallbacksA, + stateCallbacksA, + stateAllCallbacksA, + contextJsonAdapterA + ); + + + public static StaterStateMachineBuilder BuilderDoorStateMachine = new StaterStateMachineBuilder() + .SetStartState("OPEN") + .SetContext(new DoorFSMContext()) + .SetFactory(TypedDoorFactory) + .AddTransition("preOpen", "CLOSE", "AJAR") + .SetTransitionEvent("preOpen", ctx => ctx.degreeOfOpening = 1) + .AddTransition("preClose", "OPEN", "AJAR") + .SetTransitionEvent("preClose", ctx => ctx.degreeOfOpening = 99) + .AddTransition("open", "AJAR", "OPEN") + .SetTransitionCondition("open", ctx => ctx.degreeOfOpening >= 0) + .SetTransitionEvent("open", ctx => ctx.degreeOfOpening = 100) + .AddTransition("close", "AJAR", "CLOSE") + .SetTransitionCondition("close", ctx => ctx.degreeOfOpening <= 0) + .SetTransitionEvent("close", ctx => ctx.degreeOfOpening = 0) + .AddTransition("ajarPlus", "AJAR", "AJAR") + .SetTransitionEvent("ajarPlus", ctx => ctx.degreeOfOpening = ctx.degreeOfOpening + 1) + .AddTransition("ajarMinus", "AJAR", "AJAR") + .SetTransitionEvent("ajarMinus", ctx => ctx.degreeOfOpening = ctx.degreeOfOpening - 1); +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.BuilderGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.BuilderGenerate.verified.txt new file mode 100644 index 0000000..f654445 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.BuilderGenerate.verified.txt @@ -0,0 +1,15 @@ +namespace fsm.door; + +using Stater.StateMachine.Lib; + +public class Door { + public static StaterStateMachineBuilder BuilderDoorStateMachine = new StaterStateMachineBuilder() + .SetStartState("OPEN") + .SetContext(new EmptyContext()) + .AddTransition("preOpen", "CLOSE", "AJAR") + .AddTransition("preClose", "OPEN", "AJAR") + .AddTransition("open", "AJAR", "OPEN") + .AddTransition("close", "AJAR", "CLOSE") + .AddTransition("ajarPlus", "AJAR", "AJAR") + .AddTransition("ajarMinus", "AJAR", "AJAR"); +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.BuilderGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.BuilderGenerateWithInterface.verified.txt new file mode 100644 index 0000000..9452f85 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.BuilderGenerateWithInterface.verified.txt @@ -0,0 +1,99 @@ +namespace fsm.door; + +using Stater.StateMachine.Lib; + +public class Door { + public class TypesDoorStateMachine( + List> transitions, + EmptyContext context, + String startState, + HashSet states, + Dictionary>> transitionMiddlewares, + List> transitionAllMiddlewares, + Dictionary>> transitionCallbacks, + List> transitionAllCallbacks, + Dictionary>> stateCallbacks, + List> stateAllCallbacks, + IContextJsonAdapter contextJsonAdapter + ) : StaterStateMachine( + transitions, + context, + startState, + states, + transitionMiddlewares, + transitionAllMiddlewares, + transitionCallbacks, + transitionAllCallbacks, + stateCallbacks, + stateAllCallbacks, + contextJsonAdapter + ) + { + public void preOpen() + { + Transition("preOpen"); + } + + public void preClose() + { + Transition("preClose"); + } + + public void open() + { + Transition("open"); + } + + public void close() + { + Transition("close"); + } + + public void ajarPlus() + { + Transition("ajarPlus"); + } + + public void ajarMinus() + { + Transition("ajarMinus"); + } + } + private static StateMachineFactory TypedDoorFactory = ( + transitionsA, + contextA, + startStateA, + statesA, + transitionMiddlewaresA, + transitionAllMiddlewaresA, + transitionCallbacksA, + transitionAllCallbacksA, + stateCallbacksA, + stateAllCallbacksA, + contextJsonAdapterA + ) => new TypesDoorStateMachine( + transitionsA, + contextA, + startStateA, + statesA, + transitionMiddlewaresA, + transitionAllMiddlewaresA, + transitionCallbacksA, + transitionAllCallbacksA, + stateCallbacksA, + stateAllCallbacksA, + contextJsonAdapterA + ); + + + public static StaterStateMachineBuilder BuilderDoorStateMachine = new StaterStateMachineBuilder() + .SetStartState("OPEN") + .SetContext(new EmptyContext()) + .SetFactory(TypedDoorFactory) + .AddTransition("preOpen", "CLOSE", "AJAR") + .AddTransition("preClose", "OPEN", "AJAR") + .AddTransition("open", "AJAR", "OPEN") + .AddTransition("close", "AJAR", "CLOSE") + .AddTransition("ajarPlus", "AJAR", "AJAR") + .AddTransition("ajarMinus", "AJAR", "AJAR"); +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.BuilderStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.BuilderStateContextGenerate.verified.txt new file mode 100644 index 0000000..ff7b863 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.BuilderStateContextGenerate.verified.txt @@ -0,0 +1,36 @@ +namespace fsm.door; + +using Stater.StateMachine.Lib; + +public enum States { + OPEN, + AJAR, + CLOSE +} + +public class DoorFSMContext : IContext{ + public int degreeOfOpening = 0; + public bool closeVariable = true; + public string doorName = "asd"; + public float floatVariable = 0f; +} + +public class Door { + public static StaterStateMachineBuilder BuilderDoorStateMachine = new StaterStateMachineBuilder() + .SetStartState(States.OPEN) + .SetContext(new DoorFSMContext()) + .AddTransition("preOpen", States.CLOSE, States.AJAR) + .SetTransitionEvent("preOpen", ctx => ctx.degreeOfOpening = 1) + .AddTransition("preClose", States.OPEN, States.AJAR) + .SetTransitionEvent("preClose", ctx => ctx.degreeOfOpening = 99) + .AddTransition("open", States.AJAR, States.OPEN) + .SetTransitionCondition("open", ctx => ctx.degreeOfOpening >= 0) + .SetTransitionEvent("open", ctx => ctx.degreeOfOpening = 100) + .AddTransition("close", States.AJAR, States.CLOSE) + .SetTransitionCondition("close", ctx => ctx.degreeOfOpening <= 0) + .SetTransitionEvent("close", ctx => ctx.degreeOfOpening = 0) + .AddTransition("ajarPlus", States.AJAR, States.AJAR) + .SetTransitionEvent("ajarPlus", ctx => ctx.degreeOfOpening = ctx.degreeOfOpening + 1) + .AddTransition("ajarMinus", States.AJAR, States.AJAR) + .SetTransitionEvent("ajarMinus", ctx => ctx.degreeOfOpening = ctx.degreeOfOpening - 1); +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.BuilderStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.BuilderStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..e3e9312 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.BuilderStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,120 @@ +namespace fsm.door; + +using Stater.StateMachine.Lib; + +public enum States { + OPEN, + AJAR, + CLOSE +} + +public class DoorFSMContext : IContext{ + public int degreeOfOpening = 0; + public bool closeVariable = true; + public string doorName = "asd"; + public float floatVariable = 0f; +} + +public class Door { + public class TypesDoorStateMachine( + List> transitions, + DoorFSMContext context, + States startState, + HashSet states, + Dictionary>> transitionMiddlewares, + List> transitionAllMiddlewares, + Dictionary>> transitionCallbacks, + List> transitionAllCallbacks, + Dictionary>> stateCallbacks, + List> stateAllCallbacks, + IContextJsonAdapter contextJsonAdapter + ) : StaterStateMachine( + transitions, + context, + startState, + states, + transitionMiddlewares, + transitionAllMiddlewares, + transitionCallbacks, + transitionAllCallbacks, + stateCallbacks, + stateAllCallbacks, + contextJsonAdapter + ) + { + public void preOpen() + { + Transition("preOpen"); + } + + public void preClose() + { + Transition("preClose"); + } + + public void open() + { + Transition("open"); + } + + public void close() + { + Transition("close"); + } + + public void ajarPlus() + { + Transition("ajarPlus"); + } + + public void ajarMinus() + { + Transition("ajarMinus"); + } + } + private static StateMachineFactory TypedDoorFactory = ( + transitionsA, + contextA, + startStateA, + statesA, + transitionMiddlewaresA, + transitionAllMiddlewaresA, + transitionCallbacksA, + transitionAllCallbacksA, + stateCallbacksA, + stateAllCallbacksA, + contextJsonAdapterA + ) => new TypesDoorStateMachine( + transitionsA, + contextA, + startStateA, + statesA, + transitionMiddlewaresA, + transitionAllMiddlewaresA, + transitionCallbacksA, + transitionAllCallbacksA, + stateCallbacksA, + stateAllCallbacksA, + contextJsonAdapterA + ); + + + public static StaterStateMachineBuilder BuilderDoorStateMachine = new StaterStateMachineBuilder() + .SetStartState(States.OPEN) + .SetContext(new DoorFSMContext()) + .SetFactory(TypedDoorFactory) + .AddTransition("preOpen", States.CLOSE, States.AJAR) + .SetTransitionEvent("preOpen", ctx => ctx.degreeOfOpening = 1) + .AddTransition("preClose", States.OPEN, States.AJAR) + .SetTransitionEvent("preClose", ctx => ctx.degreeOfOpening = 99) + .AddTransition("open", States.AJAR, States.OPEN) + .SetTransitionCondition("open", ctx => ctx.degreeOfOpening >= 0) + .SetTransitionEvent("open", ctx => ctx.degreeOfOpening = 100) + .AddTransition("close", States.AJAR, States.CLOSE) + .SetTransitionCondition("close", ctx => ctx.degreeOfOpening <= 0) + .SetTransitionEvent("close", ctx => ctx.degreeOfOpening = 0) + .AddTransition("ajarPlus", States.AJAR, States.AJAR) + .SetTransitionEvent("ajarPlus", ctx => ctx.degreeOfOpening = ctx.degreeOfOpening + 1) + .AddTransition("ajarMinus", States.AJAR, States.AJAR) + .SetTransitionEvent("ajarMinus", ctx => ctx.degreeOfOpening = ctx.degreeOfOpening - 1); +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.BuilderStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.BuilderStateGenerate.verified.txt new file mode 100644 index 0000000..2ce669b --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.BuilderStateGenerate.verified.txt @@ -0,0 +1,21 @@ +namespace fsm.door; + +using Stater.StateMachine.Lib; + +public enum States { + OPEN, + AJAR, + CLOSE +} + +public class Door { + public static StaterStateMachineBuilder BuilderDoorStateMachine = new StaterStateMachineBuilder() + .SetStartState(States.OPEN) + .SetContext(new EmptyContext()) + .AddTransition("preOpen", States.CLOSE, States.AJAR) + .AddTransition("preClose", States.OPEN, States.AJAR) + .AddTransition("open", States.AJAR, States.OPEN) + .AddTransition("close", States.AJAR, States.CLOSE) + .AddTransition("ajarPlus", States.AJAR, States.AJAR) + .AddTransition("ajarMinus", States.AJAR, States.AJAR); +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.BuilderStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.BuilderStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..cba52d6 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.BuilderStateGenerateWithInterface.verified.txt @@ -0,0 +1,105 @@ +namespace fsm.door; + +using Stater.StateMachine.Lib; + +public enum States { + OPEN, + AJAR, + CLOSE +} + +public class Door { + public class TypesDoorStateMachine( + List> transitions, + EmptyContext context, + States startState, + HashSet states, + Dictionary>> transitionMiddlewares, + List> transitionAllMiddlewares, + Dictionary>> transitionCallbacks, + List> transitionAllCallbacks, + Dictionary>> stateCallbacks, + List> stateAllCallbacks, + IContextJsonAdapter contextJsonAdapter + ) : StaterStateMachine( + transitions, + context, + startState, + states, + transitionMiddlewares, + transitionAllMiddlewares, + transitionCallbacks, + transitionAllCallbacks, + stateCallbacks, + stateAllCallbacks, + contextJsonAdapter + ) + { + public void preOpen() + { + Transition("preOpen"); + } + + public void preClose() + { + Transition("preClose"); + } + + public void open() + { + Transition("open"); + } + + public void close() + { + Transition("close"); + } + + public void ajarPlus() + { + Transition("ajarPlus"); + } + + public void ajarMinus() + { + Transition("ajarMinus"); + } + } + private static StateMachineFactory TypedDoorFactory = ( + transitionsA, + contextA, + startStateA, + statesA, + transitionMiddlewaresA, + transitionAllMiddlewaresA, + transitionCallbacksA, + transitionAllCallbacksA, + stateCallbacksA, + stateAllCallbacksA, + contextJsonAdapterA + ) => new TypesDoorStateMachine( + transitionsA, + contextA, + startStateA, + statesA, + transitionMiddlewaresA, + transitionAllMiddlewaresA, + transitionCallbacksA, + transitionAllCallbacksA, + stateCallbacksA, + stateAllCallbacksA, + contextJsonAdapterA + ); + + + public static StaterStateMachineBuilder BuilderDoorStateMachine = new StaterStateMachineBuilder() + .SetStartState(States.OPEN) + .SetContext(new EmptyContext()) + .SetFactory(TypedDoorFactory) + .AddTransition("preOpen", States.CLOSE, States.AJAR) + .AddTransition("preClose", States.OPEN, States.AJAR) + .AddTransition("open", States.AJAR, States.OPEN) + .AddTransition("close", States.AJAR, States.CLOSE) + .AddTransition("ajarPlus", States.AJAR, States.AJAR) + .AddTransition("ajarMinus", States.AJAR, States.AJAR); +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.ClazzContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.ClazzContextGenerate.verified.txt new file mode 100644 index 0000000..7b16d80 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.ClazzContextGenerate.verified.txt @@ -0,0 +1,62 @@ +namespace fsm.door; + +using Stater.StateMachine.Lib; + +public class DoorFSMContext : IContext{ + public int degreeOfOpening = 0; + public bool closeVariable = true; + public string doorName = "asd"; + public float floatVariable = 0f; +} + +public class DoorStateMachine() : StaterStateMachine( + new List> + { + new( + "preOpen", + "CLOSE", + "AJAR", + ctx => true, + ctx => ctx.degreeOfOpening = 1 + ), + new( + "preClose", + "OPEN", + "AJAR", + ctx => true, + ctx => ctx.degreeOfOpening = 99 + ), + new( + "open", + "AJAR", + "OPEN", + ctx => ctx.degreeOfOpening >= 0, + ctx => ctx.degreeOfOpening = 100 + ), + new( + "close", + "AJAR", + "CLOSE", + ctx => ctx.degreeOfOpening <= 0, + ctx => ctx.degreeOfOpening = 0 + ), + new( + "ajarPlus", + "AJAR", + "AJAR", + ctx => true, + ctx => ctx.degreeOfOpening = ctx.degreeOfOpening + 1 + ), + new( + "ajarMinus", + "AJAR", + "AJAR", + ctx => true, + ctx => ctx.degreeOfOpening = ctx.degreeOfOpening - 1 + ) + }, + new DoorFSMContext(), + "OPEN" +) +{ +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.ClazzContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.ClazzContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..6470034 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.ClazzContextGenerateWithInterface.verified.txt @@ -0,0 +1,91 @@ +namespace fsm.door; + +using Stater.StateMachine.Lib; + +public class DoorFSMContext : IContext{ + public int degreeOfOpening = 0; + public bool closeVariable = true; + public string doorName = "asd"; + public float floatVariable = 0f; +} + +public class DoorStateMachine() : StaterStateMachine( + new List> + { + new( + "preOpen", + "CLOSE", + "AJAR", + ctx => true, + ctx => ctx.degreeOfOpening = 1 + ), + new( + "preClose", + "OPEN", + "AJAR", + ctx => true, + ctx => ctx.degreeOfOpening = 99 + ), + new( + "open", + "AJAR", + "OPEN", + ctx => ctx.degreeOfOpening >= 0, + ctx => ctx.degreeOfOpening = 100 + ), + new( + "close", + "AJAR", + "CLOSE", + ctx => ctx.degreeOfOpening <= 0, + ctx => ctx.degreeOfOpening = 0 + ), + new( + "ajarPlus", + "AJAR", + "AJAR", + ctx => true, + ctx => ctx.degreeOfOpening = ctx.degreeOfOpening + 1 + ), + new( + "ajarMinus", + "AJAR", + "AJAR", + ctx => true, + ctx => ctx.degreeOfOpening = ctx.degreeOfOpening - 1 + ) + }, + new DoorFSMContext(), + "OPEN" +) +{ + public void preOpen() + { + Transition("preOpen"); + } + + public void preClose() + { + Transition("preClose"); + } + + public void open() + { + Transition("open"); + } + + public void close() + { + Transition("close"); + } + + public void ajarPlus() + { + Transition("ajarPlus"); + } + + public void ajarMinus() + { + Transition("ajarMinus"); + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.ClazzGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.ClazzGenerate.verified.txt new file mode 100644 index 0000000..c39540a --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.ClazzGenerate.verified.txt @@ -0,0 +1,55 @@ +namespace fsm.door; + +using Stater.StateMachine.Lib; + +public class DoorStateMachine() : StaterStateMachine( + new List> + { + new( + "preOpen", + "CLOSE", + "AJAR", + ctx => true, + ctx => { } + ), + new( + "preClose", + "OPEN", + "AJAR", + ctx => true, + ctx => { } + ), + new( + "open", + "AJAR", + "OPEN", + ctx => true, + ctx => { } + ), + new( + "close", + "AJAR", + "CLOSE", + ctx => true, + ctx => { } + ), + new( + "ajarPlus", + "AJAR", + "AJAR", + ctx => true, + ctx => { } + ), + new( + "ajarMinus", + "AJAR", + "AJAR", + ctx => true, + ctx => { } + ) + }, + new EmptyContext(), + "OPEN" +) +{ +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.ClazzGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.ClazzGenerateWithInterface.verified.txt new file mode 100644 index 0000000..a01817a --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.ClazzGenerateWithInterface.verified.txt @@ -0,0 +1,84 @@ +namespace fsm.door; + +using Stater.StateMachine.Lib; + +public class DoorStateMachine() : StaterStateMachine( + new List> + { + new( + "preOpen", + "CLOSE", + "AJAR", + ctx => true, + ctx => { } + ), + new( + "preClose", + "OPEN", + "AJAR", + ctx => true, + ctx => { } + ), + new( + "open", + "AJAR", + "OPEN", + ctx => true, + ctx => { } + ), + new( + "close", + "AJAR", + "CLOSE", + ctx => true, + ctx => { } + ), + new( + "ajarPlus", + "AJAR", + "AJAR", + ctx => true, + ctx => { } + ), + new( + "ajarMinus", + "AJAR", + "AJAR", + ctx => true, + ctx => { } + ) + }, + new EmptyContext(), + "OPEN" +) +{ + public void preOpen() + { + Transition("preOpen"); + } + + public void preClose() + { + Transition("preClose"); + } + + public void open() + { + Transition("open"); + } + + public void close() + { + Transition("close"); + } + + public void ajarPlus() + { + Transition("ajarPlus"); + } + + public void ajarMinus() + { + Transition("ajarMinus"); + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.ClazzStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.ClazzStateContextGenerate.verified.txt new file mode 100644 index 0000000..633a73a --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.ClazzStateContextGenerate.verified.txt @@ -0,0 +1,68 @@ +namespace fsm.door; + +using Stater.StateMachine.Lib; + +public enum States { + OPEN, + AJAR, + CLOSE +} + +public class DoorFSMContext : IContext{ + public int degreeOfOpening = 0; + public bool closeVariable = true; + public string doorName = "asd"; + public float floatVariable = 0f; +} + +public class DoorStateMachine() : StaterStateMachine( + new List> + { + new( + "preOpen", + States.CLOSE, + States.AJAR, + ctx => true, + ctx => ctx.degreeOfOpening = 1 + ), + new( + "preClose", + States.OPEN, + States.AJAR, + ctx => true, + ctx => ctx.degreeOfOpening = 99 + ), + new( + "open", + States.AJAR, + States.OPEN, + ctx => ctx.degreeOfOpening >= 0, + ctx => ctx.degreeOfOpening = 100 + ), + new( + "close", + States.AJAR, + States.CLOSE, + ctx => ctx.degreeOfOpening <= 0, + ctx => ctx.degreeOfOpening = 0 + ), + new( + "ajarPlus", + States.AJAR, + States.AJAR, + ctx => true, + ctx => ctx.degreeOfOpening = ctx.degreeOfOpening + 1 + ), + new( + "ajarMinus", + States.AJAR, + States.AJAR, + ctx => true, + ctx => ctx.degreeOfOpening = ctx.degreeOfOpening - 1 + ) + }, + new DoorFSMContext(), + States.OPEN +) +{ +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.ClazzStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.ClazzStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..77a7aee --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.ClazzStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,97 @@ +namespace fsm.door; + +using Stater.StateMachine.Lib; + +public enum States { + OPEN, + AJAR, + CLOSE +} + +public class DoorFSMContext : IContext{ + public int degreeOfOpening = 0; + public bool closeVariable = true; + public string doorName = "asd"; + public float floatVariable = 0f; +} + +public class DoorStateMachine() : StaterStateMachine( + new List> + { + new( + "preOpen", + States.CLOSE, + States.AJAR, + ctx => true, + ctx => ctx.degreeOfOpening = 1 + ), + new( + "preClose", + States.OPEN, + States.AJAR, + ctx => true, + ctx => ctx.degreeOfOpening = 99 + ), + new( + "open", + States.AJAR, + States.OPEN, + ctx => ctx.degreeOfOpening >= 0, + ctx => ctx.degreeOfOpening = 100 + ), + new( + "close", + States.AJAR, + States.CLOSE, + ctx => ctx.degreeOfOpening <= 0, + ctx => ctx.degreeOfOpening = 0 + ), + new( + "ajarPlus", + States.AJAR, + States.AJAR, + ctx => true, + ctx => ctx.degreeOfOpening = ctx.degreeOfOpening + 1 + ), + new( + "ajarMinus", + States.AJAR, + States.AJAR, + ctx => true, + ctx => ctx.degreeOfOpening = ctx.degreeOfOpening - 1 + ) + }, + new DoorFSMContext(), + States.OPEN +) +{ + public void preOpen() + { + Transition("preOpen"); + } + + public void preClose() + { + Transition("preClose"); + } + + public void open() + { + Transition("open"); + } + + public void close() + { + Transition("close"); + } + + public void ajarPlus() + { + Transition("ajarPlus"); + } + + public void ajarMinus() + { + Transition("ajarMinus"); + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.ClazzStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.ClazzStateGenerate.verified.txt new file mode 100644 index 0000000..6300b25 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.ClazzStateGenerate.verified.txt @@ -0,0 +1,61 @@ +namespace fsm.door; + +using Stater.StateMachine.Lib; + +public enum States { + OPEN, + AJAR, + CLOSE +} + +public class DoorStateMachine() : StaterStateMachine( + new List> + { + new( + "preOpen", + States.CLOSE, + States.AJAR, + ctx => true, + ctx => { } + ), + new( + "preClose", + States.OPEN, + States.AJAR, + ctx => true, + ctx => { } + ), + new( + "open", + States.AJAR, + States.OPEN, + ctx => true, + ctx => { } + ), + new( + "close", + States.AJAR, + States.CLOSE, + ctx => true, + ctx => { } + ), + new( + "ajarPlus", + States.AJAR, + States.AJAR, + ctx => true, + ctx => { } + ), + new( + "ajarMinus", + States.AJAR, + States.AJAR, + ctx => true, + ctx => { } + ) + }, + new EmptyContext(), + States.OPEN +) +{ +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.ClazzStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.ClazzStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..b45c5f5 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateDoorTests.ClazzStateGenerateWithInterface.verified.txt @@ -0,0 +1,90 @@ +namespace fsm.door; + +using Stater.StateMachine.Lib; + +public enum States { + OPEN, + AJAR, + CLOSE +} + +public class DoorStateMachine() : StaterStateMachine( + new List> + { + new( + "preOpen", + States.CLOSE, + States.AJAR, + ctx => true, + ctx => { } + ), + new( + "preClose", + States.OPEN, + States.AJAR, + ctx => true, + ctx => { } + ), + new( + "open", + States.AJAR, + States.OPEN, + ctx => true, + ctx => { } + ), + new( + "close", + States.AJAR, + States.CLOSE, + ctx => true, + ctx => { } + ), + new( + "ajarPlus", + States.AJAR, + States.AJAR, + ctx => true, + ctx => { } + ), + new( + "ajarMinus", + States.AJAR, + States.AJAR, + ctx => true, + ctx => { } + ) + }, + new EmptyContext(), + States.OPEN +) +{ + public void preOpen() + { + Transition("preOpen"); + } + + public void preClose() + { + Transition("preClose"); + } + + public void open() + { + Transition("open"); + } + + public void close() + { + Transition("close"); + } + + public void ajarPlus() + { + Transition("ajarPlus"); + } + + public void ajarMinus() + { + Transition("ajarMinus"); + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.BuilderTestsContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.BuilderTestsContextGenerate.verified.txt new file mode 100644 index 0000000..cb025ef --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.BuilderTestsContextGenerate.verified.txt @@ -0,0 +1,278 @@ +namespace fsm.door; + +using Newtonsoft.Json.Linq; + +[Collection("Door Auto Generated Tests")] +public class TestDoor { + [Fact] + private void TestInit() + { + _ = Door.BuilderDoorStateMachine.Build(); + } + + + [Fact] + private void TestScenario0() + { + var sm = Door.BuilderDoorStateMachine.Build(); + sm.DisableEvents(); + + + sm.Transition("preClose"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("close"); + Assert.Equal("CLOSE", sm.GetState()); + + sm.Transition("preOpen"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("ajarPlus"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("open"); + Assert.Equal("OPEN", sm.GetState()); + + } + [Fact] + private void TestScenario1() + { + var sm = Door.BuilderDoorStateMachine.Build(); + sm.DisableEvents(); + + + sm.Transition("preClose"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("ajarPlus"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("close"); + Assert.Equal("CLOSE", sm.GetState()); + + sm.Transition("preOpen"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("open"); + Assert.Equal("OPEN", sm.GetState()); + + } + [Fact] + private void TestScenario2() + { + var sm = Door.BuilderDoorStateMachine.Build(); + sm.DisableEvents(); + + + sm.Transition("preClose"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("close"); + Assert.Equal("CLOSE", sm.GetState()); + + sm.Transition("preOpen"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("open"); + Assert.Equal("OPEN", sm.GetState()); + + } + + [Fact] + private void TestJsonSchema() + { + var sm = Door.BuilderDoorStateMachine.Build(); + Assert.Equal(JObject.Parse(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), JObject.Parse(sm.ToJsonSchema())); + } + + + [Fact] + private void TestSystemAppendStateTransition() + { + var smBuilder = Door.BuilderDoorStateMachine.Copy(); + + smBuilder = smBuilder.AddState("__test_state_1__"); + Assert.Equal(JObject.Parse(""" + { + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """), JObject.Parse(smBuilder.Build().ToJsonSchema())); + + smBuilder = smBuilder.AddState("__test_state_2__"); + Assert.Equal(JObject.Parse(""" + { + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """), JObject.Parse(smBuilder.Build().ToJsonSchema())); + + smBuilder = smBuilder.AddTransition("__test_transition__", "__test_state_1__", "__test_state_2__"); + Assert.Equal(JObject.Parse(""" + { + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] + } + """), JObject.Parse(smBuilder.Build().ToJsonSchema())); + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.BuilderTestsContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.BuilderTestsContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..58aee24 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.BuilderTestsContextGenerateWithInterface.verified.txt @@ -0,0 +1,278 @@ +namespace fsm.door; + +using Newtonsoft.Json.Linq; + +[Collection("Door Auto Generated Tests")] +public class TestDoor { + [Fact] + private void TestInit() + { + _ = Door.BuilderDoorStateMachine.Build() as Door.TypesDoorStateMachine; + } + + + [Fact] + private void TestScenario0() + { + var sm = Door.BuilderDoorStateMachine.Build() as Door.TypesDoorStateMachine; + sm.DisableEvents(); + + + sm.preClose(); + Assert.Equal("AJAR", sm.GetState()); + + sm.close(); + Assert.Equal("CLOSE", sm.GetState()); + + sm.preOpen(); + Assert.Equal("AJAR", sm.GetState()); + + sm.ajarPlus(); + Assert.Equal("AJAR", sm.GetState()); + + sm.open(); + Assert.Equal("OPEN", sm.GetState()); + + } + [Fact] + private void TestScenario1() + { + var sm = Door.BuilderDoorStateMachine.Build() as Door.TypesDoorStateMachine; + sm.DisableEvents(); + + + sm.preClose(); + Assert.Equal("AJAR", sm.GetState()); + + sm.ajarPlus(); + Assert.Equal("AJAR", sm.GetState()); + + sm.close(); + Assert.Equal("CLOSE", sm.GetState()); + + sm.preOpen(); + Assert.Equal("AJAR", sm.GetState()); + + sm.open(); + Assert.Equal("OPEN", sm.GetState()); + + } + [Fact] + private void TestScenario2() + { + var sm = Door.BuilderDoorStateMachine.Build() as Door.TypesDoorStateMachine; + sm.DisableEvents(); + + + sm.preClose(); + Assert.Equal("AJAR", sm.GetState()); + + sm.close(); + Assert.Equal("CLOSE", sm.GetState()); + + sm.preOpen(); + Assert.Equal("AJAR", sm.GetState()); + + sm.open(); + Assert.Equal("OPEN", sm.GetState()); + + } + + [Fact] + private void TestJsonSchema() + { + var sm = Door.BuilderDoorStateMachine.Build() as Door.TypesDoorStateMachine; + Assert.Equal(JObject.Parse(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), JObject.Parse(sm.ToJsonSchema())); + } + + + [Fact] + private void TestSystemAppendStateTransition() + { + var smBuilder = Door.BuilderDoorStateMachine.Copy(); + + smBuilder = smBuilder.AddState("__test_state_1__"); + Assert.Equal(JObject.Parse(""" + { + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """), JObject.Parse(smBuilder.Build().ToJsonSchema())); + + smBuilder = smBuilder.AddState("__test_state_2__"); + Assert.Equal(JObject.Parse(""" + { + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """), JObject.Parse(smBuilder.Build().ToJsonSchema())); + + smBuilder = smBuilder.AddTransition("__test_transition__", "__test_state_1__", "__test_state_2__"); + Assert.Equal(JObject.Parse(""" + { + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] + } + """), JObject.Parse(smBuilder.Build().ToJsonSchema())); + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.BuilderTestsGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.BuilderTestsGenerate.verified.txt new file mode 100644 index 0000000..cb025ef --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.BuilderTestsGenerate.verified.txt @@ -0,0 +1,278 @@ +namespace fsm.door; + +using Newtonsoft.Json.Linq; + +[Collection("Door Auto Generated Tests")] +public class TestDoor { + [Fact] + private void TestInit() + { + _ = Door.BuilderDoorStateMachine.Build(); + } + + + [Fact] + private void TestScenario0() + { + var sm = Door.BuilderDoorStateMachine.Build(); + sm.DisableEvents(); + + + sm.Transition("preClose"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("close"); + Assert.Equal("CLOSE", sm.GetState()); + + sm.Transition("preOpen"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("ajarPlus"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("open"); + Assert.Equal("OPEN", sm.GetState()); + + } + [Fact] + private void TestScenario1() + { + var sm = Door.BuilderDoorStateMachine.Build(); + sm.DisableEvents(); + + + sm.Transition("preClose"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("ajarPlus"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("close"); + Assert.Equal("CLOSE", sm.GetState()); + + sm.Transition("preOpen"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("open"); + Assert.Equal("OPEN", sm.GetState()); + + } + [Fact] + private void TestScenario2() + { + var sm = Door.BuilderDoorStateMachine.Build(); + sm.DisableEvents(); + + + sm.Transition("preClose"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("close"); + Assert.Equal("CLOSE", sm.GetState()); + + sm.Transition("preOpen"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("open"); + Assert.Equal("OPEN", sm.GetState()); + + } + + [Fact] + private void TestJsonSchema() + { + var sm = Door.BuilderDoorStateMachine.Build(); + Assert.Equal(JObject.Parse(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), JObject.Parse(sm.ToJsonSchema())); + } + + + [Fact] + private void TestSystemAppendStateTransition() + { + var smBuilder = Door.BuilderDoorStateMachine.Copy(); + + smBuilder = smBuilder.AddState("__test_state_1__"); + Assert.Equal(JObject.Parse(""" + { + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """), JObject.Parse(smBuilder.Build().ToJsonSchema())); + + smBuilder = smBuilder.AddState("__test_state_2__"); + Assert.Equal(JObject.Parse(""" + { + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """), JObject.Parse(smBuilder.Build().ToJsonSchema())); + + smBuilder = smBuilder.AddTransition("__test_transition__", "__test_state_1__", "__test_state_2__"); + Assert.Equal(JObject.Parse(""" + { + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] + } + """), JObject.Parse(smBuilder.Build().ToJsonSchema())); + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.BuilderTestsGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.BuilderTestsGenerateWithInterface.verified.txt new file mode 100644 index 0000000..58aee24 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.BuilderTestsGenerateWithInterface.verified.txt @@ -0,0 +1,278 @@ +namespace fsm.door; + +using Newtonsoft.Json.Linq; + +[Collection("Door Auto Generated Tests")] +public class TestDoor { + [Fact] + private void TestInit() + { + _ = Door.BuilderDoorStateMachine.Build() as Door.TypesDoorStateMachine; + } + + + [Fact] + private void TestScenario0() + { + var sm = Door.BuilderDoorStateMachine.Build() as Door.TypesDoorStateMachine; + sm.DisableEvents(); + + + sm.preClose(); + Assert.Equal("AJAR", sm.GetState()); + + sm.close(); + Assert.Equal("CLOSE", sm.GetState()); + + sm.preOpen(); + Assert.Equal("AJAR", sm.GetState()); + + sm.ajarPlus(); + Assert.Equal("AJAR", sm.GetState()); + + sm.open(); + Assert.Equal("OPEN", sm.GetState()); + + } + [Fact] + private void TestScenario1() + { + var sm = Door.BuilderDoorStateMachine.Build() as Door.TypesDoorStateMachine; + sm.DisableEvents(); + + + sm.preClose(); + Assert.Equal("AJAR", sm.GetState()); + + sm.ajarPlus(); + Assert.Equal("AJAR", sm.GetState()); + + sm.close(); + Assert.Equal("CLOSE", sm.GetState()); + + sm.preOpen(); + Assert.Equal("AJAR", sm.GetState()); + + sm.open(); + Assert.Equal("OPEN", sm.GetState()); + + } + [Fact] + private void TestScenario2() + { + var sm = Door.BuilderDoorStateMachine.Build() as Door.TypesDoorStateMachine; + sm.DisableEvents(); + + + sm.preClose(); + Assert.Equal("AJAR", sm.GetState()); + + sm.close(); + Assert.Equal("CLOSE", sm.GetState()); + + sm.preOpen(); + Assert.Equal("AJAR", sm.GetState()); + + sm.open(); + Assert.Equal("OPEN", sm.GetState()); + + } + + [Fact] + private void TestJsonSchema() + { + var sm = Door.BuilderDoorStateMachine.Build() as Door.TypesDoorStateMachine; + Assert.Equal(JObject.Parse(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), JObject.Parse(sm.ToJsonSchema())); + } + + + [Fact] + private void TestSystemAppendStateTransition() + { + var smBuilder = Door.BuilderDoorStateMachine.Copy(); + + smBuilder = smBuilder.AddState("__test_state_1__"); + Assert.Equal(JObject.Parse(""" + { + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """), JObject.Parse(smBuilder.Build().ToJsonSchema())); + + smBuilder = smBuilder.AddState("__test_state_2__"); + Assert.Equal(JObject.Parse(""" + { + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """), JObject.Parse(smBuilder.Build().ToJsonSchema())); + + smBuilder = smBuilder.AddTransition("__test_transition__", "__test_state_1__", "__test_state_2__"); + Assert.Equal(JObject.Parse(""" + { + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] + } + """), JObject.Parse(smBuilder.Build().ToJsonSchema())); + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerate.verified.txt new file mode 100644 index 0000000..d645422 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerate.verified.txt @@ -0,0 +1,131 @@ +namespace fsm.door; + +using Newtonsoft.Json.Linq; + +[Collection("Door Auto Generated Tests")] +public class TestDoor { + [Fact] + private void TestInit() + { + _ = Door.BuilderDoorStateMachine.Build(); + } + + + [Fact] + private void TestScenario0() + { + var sm = Door.BuilderDoorStateMachine.Build(); + sm.DisableEvents(); + + + sm.Transition("preClose"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("close"); + Assert.Equal(States.CLOSE, sm.GetState()); + + sm.Transition("preOpen"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("ajarPlus"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("open"); + Assert.Equal(States.OPEN, sm.GetState()); + + } + [Fact] + private void TestScenario1() + { + var sm = Door.BuilderDoorStateMachine.Build(); + sm.DisableEvents(); + + + sm.Transition("preClose"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("ajarPlus"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("close"); + Assert.Equal(States.CLOSE, sm.GetState()); + + sm.Transition("preOpen"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("open"); + Assert.Equal(States.OPEN, sm.GetState()); + + } + [Fact] + private void TestScenario2() + { + var sm = Door.BuilderDoorStateMachine.Build(); + sm.DisableEvents(); + + + sm.Transition("preClose"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("close"); + Assert.Equal(States.CLOSE, sm.GetState()); + + sm.Transition("preOpen"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("open"); + Assert.Equal(States.OPEN, sm.GetState()); + + } + + [Fact] + private void TestJsonSchema() + { + var sm = Door.BuilderDoorStateMachine.Build(); + Assert.Equal(JObject.Parse(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), JObject.Parse(sm.ToJsonSchema())); + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..01c26b2 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,131 @@ +namespace fsm.door; + +using Newtonsoft.Json.Linq; + +[Collection("Door Auto Generated Tests")] +public class TestDoor { + [Fact] + private void TestInit() + { + _ = Door.BuilderDoorStateMachine.Build() as Door.TypesDoorStateMachine; + } + + + [Fact] + private void TestScenario0() + { + var sm = Door.BuilderDoorStateMachine.Build() as Door.TypesDoorStateMachine; + sm.DisableEvents(); + + + sm.preClose(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.close(); + Assert.Equal(States.CLOSE, sm.GetState()); + + sm.preOpen(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.ajarPlus(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.open(); + Assert.Equal(States.OPEN, sm.GetState()); + + } + [Fact] + private void TestScenario1() + { + var sm = Door.BuilderDoorStateMachine.Build() as Door.TypesDoorStateMachine; + sm.DisableEvents(); + + + sm.preClose(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.ajarPlus(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.close(); + Assert.Equal(States.CLOSE, sm.GetState()); + + sm.preOpen(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.open(); + Assert.Equal(States.OPEN, sm.GetState()); + + } + [Fact] + private void TestScenario2() + { + var sm = Door.BuilderDoorStateMachine.Build() as Door.TypesDoorStateMachine; + sm.DisableEvents(); + + + sm.preClose(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.close(); + Assert.Equal(States.CLOSE, sm.GetState()); + + sm.preOpen(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.open(); + Assert.Equal(States.OPEN, sm.GetState()); + + } + + [Fact] + private void TestJsonSchema() + { + var sm = Door.BuilderDoorStateMachine.Build() as Door.TypesDoorStateMachine; + Assert.Equal(JObject.Parse(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), JObject.Parse(sm.ToJsonSchema())); + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.BuilderTestsStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.BuilderTestsStateGenerate.verified.txt new file mode 100644 index 0000000..d645422 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.BuilderTestsStateGenerate.verified.txt @@ -0,0 +1,131 @@ +namespace fsm.door; + +using Newtonsoft.Json.Linq; + +[Collection("Door Auto Generated Tests")] +public class TestDoor { + [Fact] + private void TestInit() + { + _ = Door.BuilderDoorStateMachine.Build(); + } + + + [Fact] + private void TestScenario0() + { + var sm = Door.BuilderDoorStateMachine.Build(); + sm.DisableEvents(); + + + sm.Transition("preClose"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("close"); + Assert.Equal(States.CLOSE, sm.GetState()); + + sm.Transition("preOpen"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("ajarPlus"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("open"); + Assert.Equal(States.OPEN, sm.GetState()); + + } + [Fact] + private void TestScenario1() + { + var sm = Door.BuilderDoorStateMachine.Build(); + sm.DisableEvents(); + + + sm.Transition("preClose"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("ajarPlus"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("close"); + Assert.Equal(States.CLOSE, sm.GetState()); + + sm.Transition("preOpen"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("open"); + Assert.Equal(States.OPEN, sm.GetState()); + + } + [Fact] + private void TestScenario2() + { + var sm = Door.BuilderDoorStateMachine.Build(); + sm.DisableEvents(); + + + sm.Transition("preClose"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("close"); + Assert.Equal(States.CLOSE, sm.GetState()); + + sm.Transition("preOpen"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("open"); + Assert.Equal(States.OPEN, sm.GetState()); + + } + + [Fact] + private void TestJsonSchema() + { + var sm = Door.BuilderDoorStateMachine.Build(); + Assert.Equal(JObject.Parse(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), JObject.Parse(sm.ToJsonSchema())); + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.BuilderTestsStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.BuilderTestsStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..01c26b2 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.BuilderTestsStateGenerateWithInterface.verified.txt @@ -0,0 +1,131 @@ +namespace fsm.door; + +using Newtonsoft.Json.Linq; + +[Collection("Door Auto Generated Tests")] +public class TestDoor { + [Fact] + private void TestInit() + { + _ = Door.BuilderDoorStateMachine.Build() as Door.TypesDoorStateMachine; + } + + + [Fact] + private void TestScenario0() + { + var sm = Door.BuilderDoorStateMachine.Build() as Door.TypesDoorStateMachine; + sm.DisableEvents(); + + + sm.preClose(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.close(); + Assert.Equal(States.CLOSE, sm.GetState()); + + sm.preOpen(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.ajarPlus(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.open(); + Assert.Equal(States.OPEN, sm.GetState()); + + } + [Fact] + private void TestScenario1() + { + var sm = Door.BuilderDoorStateMachine.Build() as Door.TypesDoorStateMachine; + sm.DisableEvents(); + + + sm.preClose(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.ajarPlus(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.close(); + Assert.Equal(States.CLOSE, sm.GetState()); + + sm.preOpen(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.open(); + Assert.Equal(States.OPEN, sm.GetState()); + + } + [Fact] + private void TestScenario2() + { + var sm = Door.BuilderDoorStateMachine.Build() as Door.TypesDoorStateMachine; + sm.DisableEvents(); + + + sm.preClose(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.close(); + Assert.Equal(States.CLOSE, sm.GetState()); + + sm.preOpen(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.open(); + Assert.Equal(States.OPEN, sm.GetState()); + + } + + [Fact] + private void TestJsonSchema() + { + var sm = Door.BuilderDoorStateMachine.Build() as Door.TypesDoorStateMachine; + Assert.Equal(JObject.Parse(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), JObject.Parse(sm.ToJsonSchema())); + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.ClazzTestsContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.ClazzTestsContextGenerate.verified.txt new file mode 100644 index 0000000..7bbe63c --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.ClazzTestsContextGenerate.verified.txt @@ -0,0 +1,131 @@ +namespace fsm.door; + +using Newtonsoft.Json.Linq; + +[Collection("Door Auto Generated Tests")] +public class TestDoor { + [Fact] + private void TestInit() + { + _ = new DoorStateMachine(); + } + + + [Fact] + private void TestScenario0() + { + var sm = new DoorStateMachine(); + sm.DisableEvents(); + + + sm.Transition("preClose"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("close"); + Assert.Equal("CLOSE", sm.GetState()); + + sm.Transition("preOpen"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("ajarPlus"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("open"); + Assert.Equal("OPEN", sm.GetState()); + + } + [Fact] + private void TestScenario1() + { + var sm = new DoorStateMachine(); + sm.DisableEvents(); + + + sm.Transition("preClose"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("ajarPlus"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("close"); + Assert.Equal("CLOSE", sm.GetState()); + + sm.Transition("preOpen"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("open"); + Assert.Equal("OPEN", sm.GetState()); + + } + [Fact] + private void TestScenario2() + { + var sm = new DoorStateMachine(); + sm.DisableEvents(); + + + sm.Transition("preClose"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("close"); + Assert.Equal("CLOSE", sm.GetState()); + + sm.Transition("preOpen"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("open"); + Assert.Equal("OPEN", sm.GetState()); + + } + + [Fact] + private void TestJsonSchema() + { + var sm = new DoorStateMachine(); + Assert.Equal(JObject.Parse(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), JObject.Parse(sm.ToJsonSchema())); + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.ClazzTestsContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.ClazzTestsContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..0a1d5db --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.ClazzTestsContextGenerateWithInterface.verified.txt @@ -0,0 +1,131 @@ +namespace fsm.door; + +using Newtonsoft.Json.Linq; + +[Collection("Door Auto Generated Tests")] +public class TestDoor { + [Fact] + private void TestInit() + { + _ = new DoorStateMachine(); + } + + + [Fact] + private void TestScenario0() + { + var sm = new DoorStateMachine(); + sm.DisableEvents(); + + + sm.preClose(); + Assert.Equal("AJAR", sm.GetState()); + + sm.close(); + Assert.Equal("CLOSE", sm.GetState()); + + sm.preOpen(); + Assert.Equal("AJAR", sm.GetState()); + + sm.ajarPlus(); + Assert.Equal("AJAR", sm.GetState()); + + sm.open(); + Assert.Equal("OPEN", sm.GetState()); + + } + [Fact] + private void TestScenario1() + { + var sm = new DoorStateMachine(); + sm.DisableEvents(); + + + sm.preClose(); + Assert.Equal("AJAR", sm.GetState()); + + sm.ajarPlus(); + Assert.Equal("AJAR", sm.GetState()); + + sm.close(); + Assert.Equal("CLOSE", sm.GetState()); + + sm.preOpen(); + Assert.Equal("AJAR", sm.GetState()); + + sm.open(); + Assert.Equal("OPEN", sm.GetState()); + + } + [Fact] + private void TestScenario2() + { + var sm = new DoorStateMachine(); + sm.DisableEvents(); + + + sm.preClose(); + Assert.Equal("AJAR", sm.GetState()); + + sm.close(); + Assert.Equal("CLOSE", sm.GetState()); + + sm.preOpen(); + Assert.Equal("AJAR", sm.GetState()); + + sm.open(); + Assert.Equal("OPEN", sm.GetState()); + + } + + [Fact] + private void TestJsonSchema() + { + var sm = new DoorStateMachine(); + Assert.Equal(JObject.Parse(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), JObject.Parse(sm.ToJsonSchema())); + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.ClazzTestsGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.ClazzTestsGenerate.verified.txt new file mode 100644 index 0000000..7bbe63c --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.ClazzTestsGenerate.verified.txt @@ -0,0 +1,131 @@ +namespace fsm.door; + +using Newtonsoft.Json.Linq; + +[Collection("Door Auto Generated Tests")] +public class TestDoor { + [Fact] + private void TestInit() + { + _ = new DoorStateMachine(); + } + + + [Fact] + private void TestScenario0() + { + var sm = new DoorStateMachine(); + sm.DisableEvents(); + + + sm.Transition("preClose"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("close"); + Assert.Equal("CLOSE", sm.GetState()); + + sm.Transition("preOpen"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("ajarPlus"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("open"); + Assert.Equal("OPEN", sm.GetState()); + + } + [Fact] + private void TestScenario1() + { + var sm = new DoorStateMachine(); + sm.DisableEvents(); + + + sm.Transition("preClose"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("ajarPlus"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("close"); + Assert.Equal("CLOSE", sm.GetState()); + + sm.Transition("preOpen"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("open"); + Assert.Equal("OPEN", sm.GetState()); + + } + [Fact] + private void TestScenario2() + { + var sm = new DoorStateMachine(); + sm.DisableEvents(); + + + sm.Transition("preClose"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("close"); + Assert.Equal("CLOSE", sm.GetState()); + + sm.Transition("preOpen"); + Assert.Equal("AJAR", sm.GetState()); + + sm.Transition("open"); + Assert.Equal("OPEN", sm.GetState()); + + } + + [Fact] + private void TestJsonSchema() + { + var sm = new DoorStateMachine(); + Assert.Equal(JObject.Parse(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), JObject.Parse(sm.ToJsonSchema())); + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.ClazzTestsGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.ClazzTestsGenerateWithInterface.verified.txt new file mode 100644 index 0000000..0a1d5db --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.ClazzTestsGenerateWithInterface.verified.txt @@ -0,0 +1,131 @@ +namespace fsm.door; + +using Newtonsoft.Json.Linq; + +[Collection("Door Auto Generated Tests")] +public class TestDoor { + [Fact] + private void TestInit() + { + _ = new DoorStateMachine(); + } + + + [Fact] + private void TestScenario0() + { + var sm = new DoorStateMachine(); + sm.DisableEvents(); + + + sm.preClose(); + Assert.Equal("AJAR", sm.GetState()); + + sm.close(); + Assert.Equal("CLOSE", sm.GetState()); + + sm.preOpen(); + Assert.Equal("AJAR", sm.GetState()); + + sm.ajarPlus(); + Assert.Equal("AJAR", sm.GetState()); + + sm.open(); + Assert.Equal("OPEN", sm.GetState()); + + } + [Fact] + private void TestScenario1() + { + var sm = new DoorStateMachine(); + sm.DisableEvents(); + + + sm.preClose(); + Assert.Equal("AJAR", sm.GetState()); + + sm.ajarPlus(); + Assert.Equal("AJAR", sm.GetState()); + + sm.close(); + Assert.Equal("CLOSE", sm.GetState()); + + sm.preOpen(); + Assert.Equal("AJAR", sm.GetState()); + + sm.open(); + Assert.Equal("OPEN", sm.GetState()); + + } + [Fact] + private void TestScenario2() + { + var sm = new DoorStateMachine(); + sm.DisableEvents(); + + + sm.preClose(); + Assert.Equal("AJAR", sm.GetState()); + + sm.close(); + Assert.Equal("CLOSE", sm.GetState()); + + sm.preOpen(); + Assert.Equal("AJAR", sm.GetState()); + + sm.open(); + Assert.Equal("OPEN", sm.GetState()); + + } + + [Fact] + private void TestJsonSchema() + { + var sm = new DoorStateMachine(); + Assert.Equal(JObject.Parse(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), JObject.Parse(sm.ToJsonSchema())); + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerate.verified.txt new file mode 100644 index 0000000..901953b --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerate.verified.txt @@ -0,0 +1,131 @@ +namespace fsm.door; + +using Newtonsoft.Json.Linq; + +[Collection("Door Auto Generated Tests")] +public class TestDoor { + [Fact] + private void TestInit() + { + _ = new DoorStateMachine(); + } + + + [Fact] + private void TestScenario0() + { + var sm = new DoorStateMachine(); + sm.DisableEvents(); + + + sm.Transition("preClose"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("close"); + Assert.Equal(States.CLOSE, sm.GetState()); + + sm.Transition("preOpen"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("ajarPlus"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("open"); + Assert.Equal(States.OPEN, sm.GetState()); + + } + [Fact] + private void TestScenario1() + { + var sm = new DoorStateMachine(); + sm.DisableEvents(); + + + sm.Transition("preClose"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("ajarPlus"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("close"); + Assert.Equal(States.CLOSE, sm.GetState()); + + sm.Transition("preOpen"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("open"); + Assert.Equal(States.OPEN, sm.GetState()); + + } + [Fact] + private void TestScenario2() + { + var sm = new DoorStateMachine(); + sm.DisableEvents(); + + + sm.Transition("preClose"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("close"); + Assert.Equal(States.CLOSE, sm.GetState()); + + sm.Transition("preOpen"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("open"); + Assert.Equal(States.OPEN, sm.GetState()); + + } + + [Fact] + private void TestJsonSchema() + { + var sm = new DoorStateMachine(); + Assert.Equal(JObject.Parse(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), JObject.Parse(sm.ToJsonSchema())); + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..650cd06 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,131 @@ +namespace fsm.door; + +using Newtonsoft.Json.Linq; + +[Collection("Door Auto Generated Tests")] +public class TestDoor { + [Fact] + private void TestInit() + { + _ = new DoorStateMachine(); + } + + + [Fact] + private void TestScenario0() + { + var sm = new DoorStateMachine(); + sm.DisableEvents(); + + + sm.preClose(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.close(); + Assert.Equal(States.CLOSE, sm.GetState()); + + sm.preOpen(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.ajarPlus(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.open(); + Assert.Equal(States.OPEN, sm.GetState()); + + } + [Fact] + private void TestScenario1() + { + var sm = new DoorStateMachine(); + sm.DisableEvents(); + + + sm.preClose(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.ajarPlus(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.close(); + Assert.Equal(States.CLOSE, sm.GetState()); + + sm.preOpen(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.open(); + Assert.Equal(States.OPEN, sm.GetState()); + + } + [Fact] + private void TestScenario2() + { + var sm = new DoorStateMachine(); + sm.DisableEvents(); + + + sm.preClose(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.close(); + Assert.Equal(States.CLOSE, sm.GetState()); + + sm.preOpen(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.open(); + Assert.Equal(States.OPEN, sm.GetState()); + + } + + [Fact] + private void TestJsonSchema() + { + var sm = new DoorStateMachine(); + Assert.Equal(JObject.Parse(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), JObject.Parse(sm.ToJsonSchema())); + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.ClazzTestsStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.ClazzTestsStateGenerate.verified.txt new file mode 100644 index 0000000..901953b --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.ClazzTestsStateGenerate.verified.txt @@ -0,0 +1,131 @@ +namespace fsm.door; + +using Newtonsoft.Json.Linq; + +[Collection("Door Auto Generated Tests")] +public class TestDoor { + [Fact] + private void TestInit() + { + _ = new DoorStateMachine(); + } + + + [Fact] + private void TestScenario0() + { + var sm = new DoorStateMachine(); + sm.DisableEvents(); + + + sm.Transition("preClose"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("close"); + Assert.Equal(States.CLOSE, sm.GetState()); + + sm.Transition("preOpen"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("ajarPlus"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("open"); + Assert.Equal(States.OPEN, sm.GetState()); + + } + [Fact] + private void TestScenario1() + { + var sm = new DoorStateMachine(); + sm.DisableEvents(); + + + sm.Transition("preClose"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("ajarPlus"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("close"); + Assert.Equal(States.CLOSE, sm.GetState()); + + sm.Transition("preOpen"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("open"); + Assert.Equal(States.OPEN, sm.GetState()); + + } + [Fact] + private void TestScenario2() + { + var sm = new DoorStateMachine(); + sm.DisableEvents(); + + + sm.Transition("preClose"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("close"); + Assert.Equal(States.CLOSE, sm.GetState()); + + sm.Transition("preOpen"); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.Transition("open"); + Assert.Equal(States.OPEN, sm.GetState()); + + } + + [Fact] + private void TestJsonSchema() + { + var sm = new DoorStateMachine(); + Assert.Equal(JObject.Parse(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), JObject.Parse(sm.ToJsonSchema())); + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.ClazzTestsStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.ClazzTestsStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..650cd06 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharp/CShaprAdapterGenerateTestsDoorTests.ClazzTestsStateGenerateWithInterface.verified.txt @@ -0,0 +1,131 @@ +namespace fsm.door; + +using Newtonsoft.Json.Linq; + +[Collection("Door Auto Generated Tests")] +public class TestDoor { + [Fact] + private void TestInit() + { + _ = new DoorStateMachine(); + } + + + [Fact] + private void TestScenario0() + { + var sm = new DoorStateMachine(); + sm.DisableEvents(); + + + sm.preClose(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.close(); + Assert.Equal(States.CLOSE, sm.GetState()); + + sm.preOpen(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.ajarPlus(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.open(); + Assert.Equal(States.OPEN, sm.GetState()); + + } + [Fact] + private void TestScenario1() + { + var sm = new DoorStateMachine(); + sm.DisableEvents(); + + + sm.preClose(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.ajarPlus(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.close(); + Assert.Equal(States.CLOSE, sm.GetState()); + + sm.preOpen(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.open(); + Assert.Equal(States.OPEN, sm.GetState()); + + } + [Fact] + private void TestScenario2() + { + var sm = new DoorStateMachine(); + sm.DisableEvents(); + + + sm.preClose(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.close(); + Assert.Equal(States.CLOSE, sm.GetState()); + + sm.preOpen(); + Assert.Equal(States.AJAR, sm.GetState()); + + sm.open(); + Assert.Equal(States.OPEN, sm.GetState()); + + } + + [Fact] + private void TestJsonSchema() + { + var sm = new DoorStateMachine(); + Assert.Equal(JObject.Parse(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), JObject.Parse(sm.ToJsonSchema())); + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharpAdapterDoorTests.cs b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharpAdapterDoorTests.cs new file mode 100644 index 0000000..2d3b9dd --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/CSharpAdapterDoorTests.cs @@ -0,0 +1,19 @@ +using Stater.CodeGeneration.Entity; +using Stater.CodeGeneration.LanguageAdapter.Base; +using Stater.CodeGeneration.LanguageAdapter.CSharp; +using Stater.CodeGeneration.LanguageAdapter.Java; +using Stater.CodeGeneration.LanguageAdapter.Kotlin; + +namespace Stater.CodeGeneration.Tests.LanguageAdapter; + +public class CShaprAdapterGenerateDoorTests : BaseTestAdapterGenerateDoorTests +{ + protected override BaseLanguageAdapter Adapter => new CSharpAdapter(); + protected override Language Language => Language.CSharp; +} + +public class CShaprAdapterGenerateTestsDoorTests : BaseTestAdapterGenerateTestsDoorTests +{ + protected override BaseLanguageAdapter Adapter => new CSharpAdapter(); + protected override Language Language => Language.CSharp; +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/DoorStateMachineTestData.cs b/src/Stater.CodeGeneration.Tests/LanguageAdapter/DoorStateMachineTestData.cs new file mode 100644 index 0000000..2fad03e --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/DoorStateMachineTestData.cs @@ -0,0 +1,146 @@ +using Stater.Domain.Models; + +namespace Stater.CodeGeneration.Tests.LanguageAdapter; + +public static class DoorStateMachineTestData +{ + public static StateMachine CreateDoorStateMachine() + { + var open = new State( + Guid.NewGuid(), + "OPEN", + "Open door", + StateType.Start, + 0, + 0, + new List(), + new List() + ); + + var close = new State( + Guid.NewGuid(), + "CLOSE", + "Close door", + StateType.End, + 0, + 0, + new List(), + new List() + ); + + var ajar = new State( + Guid.NewGuid(), + "AJAR", + "Ajar door", + StateType.Common, + 0, + 0, + new List(), + new List() + ); + + var states = new List + { + open, ajar, close + }; + + var degreeOfOpening = new Variable( + Guid.NewGuid(), + "degreeOfOpening", + new VariableValue.IntVariable(0) + ); + var closeVariable = new Variable( + Guid.NewGuid(), + "closeVariable", + new VariableValue.BoolVariable(false) + ); + var nameVariable = new Variable( + Guid.NewGuid(), + "doorName", + new VariableValue.StringVariable("asd") + ); + var degreeOfOpeningFloat = new Variable( + Guid.NewGuid(), + "floatVariable", + new VariableValue.FloatVariable(0) + ); + + + var preOpen = new Transition( + Guid.NewGuid(), + "preOpen", + close.Guid, + ajar.Guid, + null, + new Event.VariableSet(degreeOfOpening.Guid, new VariableValue.IntVariable(1)) + ); + + var preClose = new Transition( + Guid.NewGuid(), + "preClose", + open.Guid, + ajar.Guid, + null, + new Event.VariableSet(degreeOfOpening.Guid, new VariableValue.IntVariable(99)) + ); + + var openEvent = new Transition( + Guid.NewGuid(), + "open", + ajar.Guid, + open.Guid, + new Condition.VariableCondition(degreeOfOpening.Guid, Condition.VariableCondition.ConditionTypeEnum.Ge, + new VariableValue.IntVariable(99)), + new Event.VariableSet(degreeOfOpening.Guid, new VariableValue.IntVariable(100)) + ); + + var closeEvent = new Transition( + Guid.NewGuid(), + "close", + ajar.Guid, + close.Guid, + new Condition.VariableCondition(degreeOfOpening.Guid, Condition.VariableCondition.ConditionTypeEnum.Le, + new VariableValue.IntVariable(1)), + new Event.VariableSet(degreeOfOpening.Guid, new VariableValue.IntVariable(0)) + ); + + var ajarPlus = new Transition( + Guid.NewGuid(), + "ajarPlus", + ajar.Guid, + ajar.Guid, + null, // TODO + new Event.VariableMath(degreeOfOpening.Guid, Event.VariableMath.MathTypeEnum.Sum, + new VariableValue.IntVariable(1)) + ); + + var ajarMinus = new Transition( + Guid.NewGuid(), + "ajarMinus", + ajar.Guid, + ajar.Guid, + null, // TODO + new Event.VariableMath(degreeOfOpening.Guid, Event.VariableMath.MathTypeEnum.Sub, + new VariableValue.IntVariable(1)) + ); + + + var transitions = new List + { + preOpen, + preClose, + openEvent, + closeEvent, + ajarPlus, + ajarMinus + }; + + return new StateMachine( + Guid.NewGuid(), + "Door", + states, + transitions, + new List { degreeOfOpening, closeVariable, nameVariable, degreeOfOpeningFloat } + ); + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.BuilderContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.BuilderContextGenerate.verified.txt new file mode 100644 index 0000000..751ce1e --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.BuilderContextGenerate.verified.txt @@ -0,0 +1,31 @@ +package fsm.door; + +import com.stater.statemachine.java.*; +import java.util.*; + +class Door { + static class DoorFSMContext implements Context{ + int degreeOfOpening = 0; + boolean closeVariable = true; + String doorName = "asd"; + float floatVariable = 0f; + } + + static public final StaterStateMachineBuilder builderDoorStateMachine = new StaterStateMachineBuilder() + .setStartState("OPEN") + .setContext(new DoorFSMContext()) + .addTransition("preOpen", "CLOSE", "AJAR") + .setTransitionEvent("preOpen", ctx -> ctx.degreeOfOpening = 1) + .addTransition("preClose", "OPEN", "AJAR") + .setTransitionEvent("preClose", ctx -> ctx.degreeOfOpening = 99) + .addTransition("open", "AJAR", "OPEN") + .setTransitionCondition("open", ctx -> ctx.degreeOfOpening >= 0) + .setTransitionEvent("open", ctx -> ctx.degreeOfOpening = 100) + .addTransition("close", "AJAR", "CLOSE") + .setTransitionCondition("close", ctx -> ctx.degreeOfOpening <= 0) + .setTransitionEvent("close", ctx -> ctx.degreeOfOpening = 0) + .addTransition("ajarPlus", "AJAR", "AJAR") + .setTransitionEvent("ajarPlus", ctx -> ctx.degreeOfOpening = ctx.degreeOfOpening + 1) + .addTransition("ajarMinus", "AJAR", "AJAR") + .setTransitionEvent("ajarMinus", ctx -> ctx.degreeOfOpening = ctx.degreeOfOpening - 1); +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.BuilderContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.BuilderContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..068457f --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.BuilderContextGenerateWithInterface.verified.txt @@ -0,0 +1,89 @@ +package fsm.door; + +import com.stater.statemachine.java.*; +import java.util.*; + +class Door { + static class DoorFSMContext implements Context{ + int degreeOfOpening = 0; + boolean closeVariable = true; + String doorName = "asd"; + float floatVariable = 0f; + } + + static class TypesDoorStateMachine extends StaterStateMachine { + public TypesDoorStateMachine( + List> transitions, + DoorFSMContext context, + String startState, + Set states, + Map>> transitionMiddlewares, + List> transitionAllMiddlewares, + Map>> transitionCallbacks, + List> transitionAllCallbacks, + Map>> stateCallbacks, + List> stateAllCallbacks, + ContextJsonAdapter contextJsonAdapter + ) { + super( + transitions, + context, + startState, + states, + transitionMiddlewares, + transitionAllMiddlewares, + transitionCallbacks, + transitionAllCallbacks, + stateCallbacks, + stateAllCallbacks, + contextJsonAdapter + ); + } + + void preOpen() { + transition("preOpen"); + } + + void preClose() { + transition("preClose"); + } + + void open() { + transition("open"); + } + + void close() { + transition("close"); + } + + void ajarPlus() { + transition("ajarPlus"); + } + + void ajarMinus() { + transition("ajarMinus"); + } + } + + static private final StateMachineFactory typedDoorFactory = TypesDoorStateMachine::new; + + + static public final StaterStateMachineBuilder builderDoorStateMachine = new StaterStateMachineBuilder() + .setStartState("OPEN") + .setContext(new DoorFSMContext()) + .setFactory(typedDoorFactory) + .addTransition("preOpen", "CLOSE", "AJAR") + .setTransitionEvent("preOpen", ctx -> ctx.degreeOfOpening = 1) + .addTransition("preClose", "OPEN", "AJAR") + .setTransitionEvent("preClose", ctx -> ctx.degreeOfOpening = 99) + .addTransition("open", "AJAR", "OPEN") + .setTransitionCondition("open", ctx -> ctx.degreeOfOpening >= 0) + .setTransitionEvent("open", ctx -> ctx.degreeOfOpening = 100) + .addTransition("close", "AJAR", "CLOSE") + .setTransitionCondition("close", ctx -> ctx.degreeOfOpening <= 0) + .setTransitionEvent("close", ctx -> ctx.degreeOfOpening = 0) + .addTransition("ajarPlus", "AJAR", "AJAR") + .setTransitionEvent("ajarPlus", ctx -> ctx.degreeOfOpening = ctx.degreeOfOpening + 1) + .addTransition("ajarMinus", "AJAR", "AJAR") + .setTransitionEvent("ajarMinus", ctx -> ctx.degreeOfOpening = ctx.degreeOfOpening - 1); +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.BuilderGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.BuilderGenerate.verified.txt new file mode 100644 index 0000000..0c26998 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.BuilderGenerate.verified.txt @@ -0,0 +1,16 @@ +package fsm.door; + +import com.stater.statemachine.java.*; +import java.util.*; + +class Door { + static public final StaterStateMachineBuilder builderDoorStateMachine = new StaterStateMachineBuilder() + .setStartState("OPEN") + .setContext(new EmptyContext()) + .addTransition("preOpen", "CLOSE", "AJAR") + .addTransition("preClose", "OPEN", "AJAR") + .addTransition("open", "AJAR", "OPEN") + .addTransition("close", "AJAR", "CLOSE") + .addTransition("ajarPlus", "AJAR", "AJAR") + .addTransition("ajarMinus", "AJAR", "AJAR"); +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.BuilderGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.BuilderGenerateWithInterface.verified.txt new file mode 100644 index 0000000..1cada91 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.BuilderGenerateWithInterface.verified.txt @@ -0,0 +1,74 @@ +package fsm.door; + +import com.stater.statemachine.java.*; +import java.util.*; + +class Door { + static class TypesDoorStateMachine extends StaterStateMachine { + public TypesDoorStateMachine( + List> transitions, + EmptyContext context, + String startState, + Set states, + Map>> transitionMiddlewares, + List> transitionAllMiddlewares, + Map>> transitionCallbacks, + List> transitionAllCallbacks, + Map>> stateCallbacks, + List> stateAllCallbacks, + ContextJsonAdapter contextJsonAdapter + ) { + super( + transitions, + context, + startState, + states, + transitionMiddlewares, + transitionAllMiddlewares, + transitionCallbacks, + transitionAllCallbacks, + stateCallbacks, + stateAllCallbacks, + contextJsonAdapter + ); + } + + void preOpen() { + transition("preOpen"); + } + + void preClose() { + transition("preClose"); + } + + void open() { + transition("open"); + } + + void close() { + transition("close"); + } + + void ajarPlus() { + transition("ajarPlus"); + } + + void ajarMinus() { + transition("ajarMinus"); + } + } + + static private final StateMachineFactory typedDoorFactory = TypesDoorStateMachine::new; + + + static public final StaterStateMachineBuilder builderDoorStateMachine = new StaterStateMachineBuilder() + .setStartState("OPEN") + .setContext(new EmptyContext()) + .setFactory(typedDoorFactory) + .addTransition("preOpen", "CLOSE", "AJAR") + .addTransition("preClose", "OPEN", "AJAR") + .addTransition("open", "AJAR", "OPEN") + .addTransition("close", "AJAR", "CLOSE") + .addTransition("ajarPlus", "AJAR", "AJAR") + .addTransition("ajarMinus", "AJAR", "AJAR"); +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.BuilderStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.BuilderStateContextGenerate.verified.txt new file mode 100644 index 0000000..88b6798 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.BuilderStateContextGenerate.verified.txt @@ -0,0 +1,37 @@ +package fsm.door; + +import com.stater.statemachine.java.*; +import java.util.*; + +class Door { + static enum States { + OPEN, + AJAR, + CLOSE + } + + static class DoorFSMContext implements Context{ + int degreeOfOpening = 0; + boolean closeVariable = true; + String doorName = "asd"; + float floatVariable = 0f; + } + + static public final StaterStateMachineBuilder builderDoorStateMachine = new StaterStateMachineBuilder() + .setStartState(States.OPEN) + .setContext(new DoorFSMContext()) + .addTransition("preOpen", States.CLOSE, States.AJAR) + .setTransitionEvent("preOpen", ctx -> ctx.degreeOfOpening = 1) + .addTransition("preClose", States.OPEN, States.AJAR) + .setTransitionEvent("preClose", ctx -> ctx.degreeOfOpening = 99) + .addTransition("open", States.AJAR, States.OPEN) + .setTransitionCondition("open", ctx -> ctx.degreeOfOpening >= 0) + .setTransitionEvent("open", ctx -> ctx.degreeOfOpening = 100) + .addTransition("close", States.AJAR, States.CLOSE) + .setTransitionCondition("close", ctx -> ctx.degreeOfOpening <= 0) + .setTransitionEvent("close", ctx -> ctx.degreeOfOpening = 0) + .addTransition("ajarPlus", States.AJAR, States.AJAR) + .setTransitionEvent("ajarPlus", ctx -> ctx.degreeOfOpening = ctx.degreeOfOpening + 1) + .addTransition("ajarMinus", States.AJAR, States.AJAR) + .setTransitionEvent("ajarMinus", ctx -> ctx.degreeOfOpening = ctx.degreeOfOpening - 1); +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.BuilderStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.BuilderStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..60e1cd3 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.BuilderStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,95 @@ +package fsm.door; + +import com.stater.statemachine.java.*; +import java.util.*; + +class Door { + static enum States { + OPEN, + AJAR, + CLOSE + } + + static class DoorFSMContext implements Context{ + int degreeOfOpening = 0; + boolean closeVariable = true; + String doorName = "asd"; + float floatVariable = 0f; + } + + static class TypesDoorStateMachine extends StaterStateMachine { + public TypesDoorStateMachine( + List> transitions, + DoorFSMContext context, + States startState, + Set states, + Map>> transitionMiddlewares, + List> transitionAllMiddlewares, + Map>> transitionCallbacks, + List> transitionAllCallbacks, + Map>> stateCallbacks, + List> stateAllCallbacks, + ContextJsonAdapter contextJsonAdapter + ) { + super( + transitions, + context, + startState, + states, + transitionMiddlewares, + transitionAllMiddlewares, + transitionCallbacks, + transitionAllCallbacks, + stateCallbacks, + stateAllCallbacks, + contextJsonAdapter + ); + } + + void preOpen() { + transition("preOpen"); + } + + void preClose() { + transition("preClose"); + } + + void open() { + transition("open"); + } + + void close() { + transition("close"); + } + + void ajarPlus() { + transition("ajarPlus"); + } + + void ajarMinus() { + transition("ajarMinus"); + } + } + + static private final StateMachineFactory typedDoorFactory = TypesDoorStateMachine::new; + + + static public final StaterStateMachineBuilder builderDoorStateMachine = new StaterStateMachineBuilder() + .setStartState(States.OPEN) + .setContext(new DoorFSMContext()) + .setFactory(typedDoorFactory) + .addTransition("preOpen", States.CLOSE, States.AJAR) + .setTransitionEvent("preOpen", ctx -> ctx.degreeOfOpening = 1) + .addTransition("preClose", States.OPEN, States.AJAR) + .setTransitionEvent("preClose", ctx -> ctx.degreeOfOpening = 99) + .addTransition("open", States.AJAR, States.OPEN) + .setTransitionCondition("open", ctx -> ctx.degreeOfOpening >= 0) + .setTransitionEvent("open", ctx -> ctx.degreeOfOpening = 100) + .addTransition("close", States.AJAR, States.CLOSE) + .setTransitionCondition("close", ctx -> ctx.degreeOfOpening <= 0) + .setTransitionEvent("close", ctx -> ctx.degreeOfOpening = 0) + .addTransition("ajarPlus", States.AJAR, States.AJAR) + .setTransitionEvent("ajarPlus", ctx -> ctx.degreeOfOpening = ctx.degreeOfOpening + 1) + .addTransition("ajarMinus", States.AJAR, States.AJAR) + .setTransitionEvent("ajarMinus", ctx -> ctx.degreeOfOpening = ctx.degreeOfOpening - 1); +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.BuilderStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.BuilderStateGenerate.verified.txt new file mode 100644 index 0000000..2fefcc7 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.BuilderStateGenerate.verified.txt @@ -0,0 +1,22 @@ +package fsm.door; + +import com.stater.statemachine.java.*; +import java.util.*; + +class Door { + static enum States { + OPEN, + AJAR, + CLOSE + } + + static public final StaterStateMachineBuilder builderDoorStateMachine = new StaterStateMachineBuilder() + .setStartState(States.OPEN) + .setContext(new EmptyContext()) + .addTransition("preOpen", States.CLOSE, States.AJAR) + .addTransition("preClose", States.OPEN, States.AJAR) + .addTransition("open", States.AJAR, States.OPEN) + .addTransition("close", States.AJAR, States.CLOSE) + .addTransition("ajarPlus", States.AJAR, States.AJAR) + .addTransition("ajarMinus", States.AJAR, States.AJAR); +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.BuilderStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.BuilderStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..27c37c1 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.BuilderStateGenerateWithInterface.verified.txt @@ -0,0 +1,80 @@ +package fsm.door; + +import com.stater.statemachine.java.*; +import java.util.*; + +class Door { + static enum States { + OPEN, + AJAR, + CLOSE + } + + static class TypesDoorStateMachine extends StaterStateMachine { + public TypesDoorStateMachine( + List> transitions, + EmptyContext context, + States startState, + Set states, + Map>> transitionMiddlewares, + List> transitionAllMiddlewares, + Map>> transitionCallbacks, + List> transitionAllCallbacks, + Map>> stateCallbacks, + List> stateAllCallbacks, + ContextJsonAdapter contextJsonAdapter + ) { + super( + transitions, + context, + startState, + states, + transitionMiddlewares, + transitionAllMiddlewares, + transitionCallbacks, + transitionAllCallbacks, + stateCallbacks, + stateAllCallbacks, + contextJsonAdapter + ); + } + + void preOpen() { + transition("preOpen"); + } + + void preClose() { + transition("preClose"); + } + + void open() { + transition("open"); + } + + void close() { + transition("close"); + } + + void ajarPlus() { + transition("ajarPlus"); + } + + void ajarMinus() { + transition("ajarMinus"); + } + } + + static private final StateMachineFactory typedDoorFactory = TypesDoorStateMachine::new; + + + static public final StaterStateMachineBuilder builderDoorStateMachine = new StaterStateMachineBuilder() + .setStartState(States.OPEN) + .setContext(new EmptyContext()) + .setFactory(typedDoorFactory) + .addTransition("preOpen", States.CLOSE, States.AJAR) + .addTransition("preClose", States.OPEN, States.AJAR) + .addTransition("open", States.AJAR, States.OPEN) + .addTransition("close", States.AJAR, States.CLOSE) + .addTransition("ajarPlus", States.AJAR, States.AJAR) + .addTransition("ajarMinus", States.AJAR, States.AJAR); +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.ClazzContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.ClazzContextGenerate.verified.txt new file mode 100644 index 0000000..a529085 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.ClazzContextGenerate.verified.txt @@ -0,0 +1,66 @@ +package fsm.door; + +import com.stater.statemachine.java.*; +import java.util.*; + +class Door { + static class DoorFSMContext implements Context{ + int degreeOfOpening = 0; + boolean closeVariable = true; + String doorName = "asd"; + float floatVariable = 0f; + } + + static class DoorStateMachine extends StaterStateMachine{ + public DoorStateMachine() { + super( + List.of( + new Transition<>( + "preOpen", + "CLOSE", + "AJAR", + ctx -> true, + ctx -> ctx.degreeOfOpening = 1 + ), + new Transition<>( + "preClose", + "OPEN", + "AJAR", + ctx -> true, + ctx -> ctx.degreeOfOpening = 99 + ), + new Transition<>( + "open", + "AJAR", + "OPEN", + ctx -> ctx.degreeOfOpening >= 0, + ctx -> ctx.degreeOfOpening = 100 + ), + new Transition<>( + "close", + "AJAR", + "CLOSE", + ctx -> ctx.degreeOfOpening <= 0, + ctx -> ctx.degreeOfOpening = 0 + ), + new Transition<>( + "ajarPlus", + "AJAR", + "AJAR", + ctx -> true, + ctx -> ctx.degreeOfOpening = ctx.degreeOfOpening + 1 + ), + new Transition<>( + "ajarMinus", + "AJAR", + "AJAR", + ctx -> true, + ctx -> ctx.degreeOfOpening = ctx.degreeOfOpening - 1 + ) + ), + new DoorFSMContext(), + "OPEN" + ); + } + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.ClazzContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.ClazzContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..5df87cb --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.ClazzContextGenerateWithInterface.verified.txt @@ -0,0 +1,90 @@ +package fsm.door; + +import com.stater.statemachine.java.*; +import java.util.*; + +class Door { + static class DoorFSMContext implements Context{ + int degreeOfOpening = 0; + boolean closeVariable = true; + String doorName = "asd"; + float floatVariable = 0f; + } + + static class DoorStateMachine extends StaterStateMachine{ + public DoorStateMachine() { + super( + List.of( + new Transition<>( + "preOpen", + "CLOSE", + "AJAR", + ctx -> true, + ctx -> ctx.degreeOfOpening = 1 + ), + new Transition<>( + "preClose", + "OPEN", + "AJAR", + ctx -> true, + ctx -> ctx.degreeOfOpening = 99 + ), + new Transition<>( + "open", + "AJAR", + "OPEN", + ctx -> ctx.degreeOfOpening >= 0, + ctx -> ctx.degreeOfOpening = 100 + ), + new Transition<>( + "close", + "AJAR", + "CLOSE", + ctx -> ctx.degreeOfOpening <= 0, + ctx -> ctx.degreeOfOpening = 0 + ), + new Transition<>( + "ajarPlus", + "AJAR", + "AJAR", + ctx -> true, + ctx -> ctx.degreeOfOpening = ctx.degreeOfOpening + 1 + ), + new Transition<>( + "ajarMinus", + "AJAR", + "AJAR", + ctx -> true, + ctx -> ctx.degreeOfOpening = ctx.degreeOfOpening - 1 + ) + ), + new DoorFSMContext(), + "OPEN" + ); + } + + void preOpen() { + transition("preOpen"); + } + + void preClose() { + transition("preClose"); + } + + void open() { + transition("open"); + } + + void close() { + transition("close"); + } + + void ajarPlus() { + transition("ajarPlus"); + } + + void ajarMinus() { + transition("ajarMinus"); + } + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.ClazzGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.ClazzGenerate.verified.txt new file mode 100644 index 0000000..96f622f --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.ClazzGenerate.verified.txt @@ -0,0 +1,59 @@ +package fsm.door; + +import com.stater.statemachine.java.*; +import java.util.*; + +class Door { + static class DoorStateMachine extends StaterStateMachine{ + public DoorStateMachine() { + super( + List.of( + new Transition<>( + "preOpen", + "CLOSE", + "AJAR", + ctx -> true, + ctx -> {} + ), + new Transition<>( + "preClose", + "OPEN", + "AJAR", + ctx -> true, + ctx -> {} + ), + new Transition<>( + "open", + "AJAR", + "OPEN", + ctx -> true, + ctx -> {} + ), + new Transition<>( + "close", + "AJAR", + "CLOSE", + ctx -> true, + ctx -> {} + ), + new Transition<>( + "ajarPlus", + "AJAR", + "AJAR", + ctx -> true, + ctx -> {} + ), + new Transition<>( + "ajarMinus", + "AJAR", + "AJAR", + ctx -> true, + ctx -> {} + ) + ), + new EmptyContext(), + "OPEN" + ); + } + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.ClazzGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.ClazzGenerateWithInterface.verified.txt new file mode 100644 index 0000000..44330ea --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.ClazzGenerateWithInterface.verified.txt @@ -0,0 +1,83 @@ +package fsm.door; + +import com.stater.statemachine.java.*; +import java.util.*; + +class Door { + static class DoorStateMachine extends StaterStateMachine{ + public DoorStateMachine() { + super( + List.of( + new Transition<>( + "preOpen", + "CLOSE", + "AJAR", + ctx -> true, + ctx -> {} + ), + new Transition<>( + "preClose", + "OPEN", + "AJAR", + ctx -> true, + ctx -> {} + ), + new Transition<>( + "open", + "AJAR", + "OPEN", + ctx -> true, + ctx -> {} + ), + new Transition<>( + "close", + "AJAR", + "CLOSE", + ctx -> true, + ctx -> {} + ), + new Transition<>( + "ajarPlus", + "AJAR", + "AJAR", + ctx -> true, + ctx -> {} + ), + new Transition<>( + "ajarMinus", + "AJAR", + "AJAR", + ctx -> true, + ctx -> {} + ) + ), + new EmptyContext(), + "OPEN" + ); + } + + void preOpen() { + transition("preOpen"); + } + + void preClose() { + transition("preClose"); + } + + void open() { + transition("open"); + } + + void close() { + transition("close"); + } + + void ajarPlus() { + transition("ajarPlus"); + } + + void ajarMinus() { + transition("ajarMinus"); + } + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.ClazzStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.ClazzStateContextGenerate.verified.txt new file mode 100644 index 0000000..410d51e --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.ClazzStateContextGenerate.verified.txt @@ -0,0 +1,72 @@ +package fsm.door; + +import com.stater.statemachine.java.*; +import java.util.*; + +class Door { + static enum States { + OPEN, + AJAR, + CLOSE + } + + static class DoorFSMContext implements Context{ + int degreeOfOpening = 0; + boolean closeVariable = true; + String doorName = "asd"; + float floatVariable = 0f; + } + + static class DoorStateMachine extends StaterStateMachine{ + public DoorStateMachine() { + super( + List.of( + new Transition<>( + "preOpen", + States.CLOSE, + States.AJAR, + ctx -> true, + ctx -> ctx.degreeOfOpening = 1 + ), + new Transition<>( + "preClose", + States.OPEN, + States.AJAR, + ctx -> true, + ctx -> ctx.degreeOfOpening = 99 + ), + new Transition<>( + "open", + States.AJAR, + States.OPEN, + ctx -> ctx.degreeOfOpening >= 0, + ctx -> ctx.degreeOfOpening = 100 + ), + new Transition<>( + "close", + States.AJAR, + States.CLOSE, + ctx -> ctx.degreeOfOpening <= 0, + ctx -> ctx.degreeOfOpening = 0 + ), + new Transition<>( + "ajarPlus", + States.AJAR, + States.AJAR, + ctx -> true, + ctx -> ctx.degreeOfOpening = ctx.degreeOfOpening + 1 + ), + new Transition<>( + "ajarMinus", + States.AJAR, + States.AJAR, + ctx -> true, + ctx -> ctx.degreeOfOpening = ctx.degreeOfOpening - 1 + ) + ), + new DoorFSMContext(), + States.OPEN + ); + } + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.ClazzStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.ClazzStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..f9c0377 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.ClazzStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,96 @@ +package fsm.door; + +import com.stater.statemachine.java.*; +import java.util.*; + +class Door { + static enum States { + OPEN, + AJAR, + CLOSE + } + + static class DoorFSMContext implements Context{ + int degreeOfOpening = 0; + boolean closeVariable = true; + String doorName = "asd"; + float floatVariable = 0f; + } + + static class DoorStateMachine extends StaterStateMachine{ + public DoorStateMachine() { + super( + List.of( + new Transition<>( + "preOpen", + States.CLOSE, + States.AJAR, + ctx -> true, + ctx -> ctx.degreeOfOpening = 1 + ), + new Transition<>( + "preClose", + States.OPEN, + States.AJAR, + ctx -> true, + ctx -> ctx.degreeOfOpening = 99 + ), + new Transition<>( + "open", + States.AJAR, + States.OPEN, + ctx -> ctx.degreeOfOpening >= 0, + ctx -> ctx.degreeOfOpening = 100 + ), + new Transition<>( + "close", + States.AJAR, + States.CLOSE, + ctx -> ctx.degreeOfOpening <= 0, + ctx -> ctx.degreeOfOpening = 0 + ), + new Transition<>( + "ajarPlus", + States.AJAR, + States.AJAR, + ctx -> true, + ctx -> ctx.degreeOfOpening = ctx.degreeOfOpening + 1 + ), + new Transition<>( + "ajarMinus", + States.AJAR, + States.AJAR, + ctx -> true, + ctx -> ctx.degreeOfOpening = ctx.degreeOfOpening - 1 + ) + ), + new DoorFSMContext(), + States.OPEN + ); + } + + void preOpen() { + transition("preOpen"); + } + + void preClose() { + transition("preClose"); + } + + void open() { + transition("open"); + } + + void close() { + transition("close"); + } + + void ajarPlus() { + transition("ajarPlus"); + } + + void ajarMinus() { + transition("ajarMinus"); + } + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.ClazzStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.ClazzStateGenerate.verified.txt new file mode 100644 index 0000000..04bb91b --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.ClazzStateGenerate.verified.txt @@ -0,0 +1,65 @@ +package fsm.door; + +import com.stater.statemachine.java.*; +import java.util.*; + +class Door { + static enum States { + OPEN, + AJAR, + CLOSE + } + + static class DoorStateMachine extends StaterStateMachine{ + public DoorStateMachine() { + super( + List.of( + new Transition<>( + "preOpen", + States.CLOSE, + States.AJAR, + ctx -> true, + ctx -> {} + ), + new Transition<>( + "preClose", + States.OPEN, + States.AJAR, + ctx -> true, + ctx -> {} + ), + new Transition<>( + "open", + States.AJAR, + States.OPEN, + ctx -> true, + ctx -> {} + ), + new Transition<>( + "close", + States.AJAR, + States.CLOSE, + ctx -> true, + ctx -> {} + ), + new Transition<>( + "ajarPlus", + States.AJAR, + States.AJAR, + ctx -> true, + ctx -> {} + ), + new Transition<>( + "ajarMinus", + States.AJAR, + States.AJAR, + ctx -> true, + ctx -> {} + ) + ), + new EmptyContext(), + States.OPEN + ); + } + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.ClazzStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.ClazzStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..1733222 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaAdapterGenerateDoorTests.ClazzStateGenerateWithInterface.verified.txt @@ -0,0 +1,89 @@ +package fsm.door; + +import com.stater.statemachine.java.*; +import java.util.*; + +class Door { + static enum States { + OPEN, + AJAR, + CLOSE + } + + static class DoorStateMachine extends StaterStateMachine{ + public DoorStateMachine() { + super( + List.of( + new Transition<>( + "preOpen", + States.CLOSE, + States.AJAR, + ctx -> true, + ctx -> {} + ), + new Transition<>( + "preClose", + States.OPEN, + States.AJAR, + ctx -> true, + ctx -> {} + ), + new Transition<>( + "open", + States.AJAR, + States.OPEN, + ctx -> true, + ctx -> {} + ), + new Transition<>( + "close", + States.AJAR, + States.CLOSE, + ctx -> true, + ctx -> {} + ), + new Transition<>( + "ajarPlus", + States.AJAR, + States.AJAR, + ctx -> true, + ctx -> {} + ), + new Transition<>( + "ajarMinus", + States.AJAR, + States.AJAR, + ctx -> true, + ctx -> {} + ) + ), + new EmptyContext(), + States.OPEN + ); + } + + void preOpen() { + transition("preOpen"); + } + + void preClose() { + transition("preClose"); + } + + void open() { + transition("open"); + } + + void close() { + transition("close"); + } + + void ajarPlus() { + transition("ajarPlus"); + } + + void ajarMinus() { + transition("ajarMinus"); + } + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.BuilderTestsContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.BuilderTestsContextGenerate.verified.txt new file mode 100644 index 0000000..68b3604 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.BuilderTestsContextGenerate.verified.txt @@ -0,0 +1,270 @@ +package fsm.door; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; +import com.fasterxml.jackson.databind.ObjectMapper; + +class TestDoor { + @Test + void testInit() { + var fsm = Door.builderDoorStateMachine.build(); + } + + + @Test + void testScenario0() { + var sm = Door.builderDoorStateMachine.build(); + sm.disableEvents(); + + + sm.transition("preClose"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("close"); + assertEquals(sm.getState(), "CLOSE"); + + sm.transition("preOpen"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("ajarPlus"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("open"); + assertEquals(sm.getState(), "OPEN"); + + } + @Test + void testScenario1() { + var sm = Door.builderDoorStateMachine.build(); + sm.disableEvents(); + + + sm.transition("preClose"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("ajarPlus"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("close"); + assertEquals(sm.getState(), "CLOSE"); + + sm.transition("preOpen"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("open"); + assertEquals(sm.getState(), "OPEN"); + + } + @Test + void testScenario2() { + var sm = Door.builderDoorStateMachine.build(); + sm.disableEvents(); + + + sm.transition("preClose"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("close"); + assertEquals(sm.getState(), "CLOSE"); + + sm.transition("preOpen"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("open"); + assertEquals(sm.getState(), "OPEN"); + + } + + @Test + void testJsonSchema() throws Exception { + var sm = Door.builderDoorStateMachine.build(); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), new ObjectMapper().readTree(sm.toJsonSchema())); + } + + + @Test + void testSystemAppendStateTransition() throws Exception { + var smBuilder = Door.builderDoorStateMachine; + + smBuilder = smBuilder.addState("__test_state_1__"); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + }"""), new ObjectMapper().readTree(smBuilder.build().toJsonSchema())); + + smBuilder = smBuilder.addState("__test_state_2__"); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + }"""), new ObjectMapper().readTree(smBuilder.build().toJsonSchema())); + + smBuilder = smBuilder.addTransition("__test_transition__", "__test_state_1__", "__test_state_2__"); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] + }"""), new ObjectMapper().readTree(smBuilder.build().toJsonSchema())); + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.BuilderTestsContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.BuilderTestsContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..cfed5ef --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.BuilderTestsContextGenerateWithInterface.verified.txt @@ -0,0 +1,270 @@ +package fsm.door; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; +import com.fasterxml.jackson.databind.ObjectMapper; + +class TestDoor { + @Test + void testInit() { + var fsm = (Door.TypesDoorStateMachine)Door.builderDoorStateMachine.build(); + } + + + @Test + void testScenario0() { + var sm = (Door.TypesDoorStateMachine)Door.builderDoorStateMachine.build(); + sm.disableEvents(); + + + sm.preClose(); + assertEquals(sm.getState(), "AJAR"); + + sm.close(); + assertEquals(sm.getState(), "CLOSE"); + + sm.preOpen(); + assertEquals(sm.getState(), "AJAR"); + + sm.ajarPlus(); + assertEquals(sm.getState(), "AJAR"); + + sm.open(); + assertEquals(sm.getState(), "OPEN"); + + } + @Test + void testScenario1() { + var sm = (Door.TypesDoorStateMachine)Door.builderDoorStateMachine.build(); + sm.disableEvents(); + + + sm.preClose(); + assertEquals(sm.getState(), "AJAR"); + + sm.ajarPlus(); + assertEquals(sm.getState(), "AJAR"); + + sm.close(); + assertEquals(sm.getState(), "CLOSE"); + + sm.preOpen(); + assertEquals(sm.getState(), "AJAR"); + + sm.open(); + assertEquals(sm.getState(), "OPEN"); + + } + @Test + void testScenario2() { + var sm = (Door.TypesDoorStateMachine)Door.builderDoorStateMachine.build(); + sm.disableEvents(); + + + sm.preClose(); + assertEquals(sm.getState(), "AJAR"); + + sm.close(); + assertEquals(sm.getState(), "CLOSE"); + + sm.preOpen(); + assertEquals(sm.getState(), "AJAR"); + + sm.open(); + assertEquals(sm.getState(), "OPEN"); + + } + + @Test + void testJsonSchema() throws Exception { + var sm = (Door.TypesDoorStateMachine)Door.builderDoorStateMachine.build(); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), new ObjectMapper().readTree(sm.toJsonSchema())); + } + + + @Test + void testSystemAppendStateTransition() throws Exception { + var smBuilder = Door.builderDoorStateMachine; + + smBuilder = smBuilder.addState("__test_state_1__"); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + }"""), new ObjectMapper().readTree(smBuilder.build().toJsonSchema())); + + smBuilder = smBuilder.addState("__test_state_2__"); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + }"""), new ObjectMapper().readTree(smBuilder.build().toJsonSchema())); + + smBuilder = smBuilder.addTransition("__test_transition__", "__test_state_1__", "__test_state_2__"); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] + }"""), new ObjectMapper().readTree(smBuilder.build().toJsonSchema())); + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.BuilderTestsGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.BuilderTestsGenerate.verified.txt new file mode 100644 index 0000000..68b3604 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.BuilderTestsGenerate.verified.txt @@ -0,0 +1,270 @@ +package fsm.door; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; +import com.fasterxml.jackson.databind.ObjectMapper; + +class TestDoor { + @Test + void testInit() { + var fsm = Door.builderDoorStateMachine.build(); + } + + + @Test + void testScenario0() { + var sm = Door.builderDoorStateMachine.build(); + sm.disableEvents(); + + + sm.transition("preClose"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("close"); + assertEquals(sm.getState(), "CLOSE"); + + sm.transition("preOpen"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("ajarPlus"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("open"); + assertEquals(sm.getState(), "OPEN"); + + } + @Test + void testScenario1() { + var sm = Door.builderDoorStateMachine.build(); + sm.disableEvents(); + + + sm.transition("preClose"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("ajarPlus"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("close"); + assertEquals(sm.getState(), "CLOSE"); + + sm.transition("preOpen"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("open"); + assertEquals(sm.getState(), "OPEN"); + + } + @Test + void testScenario2() { + var sm = Door.builderDoorStateMachine.build(); + sm.disableEvents(); + + + sm.transition("preClose"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("close"); + assertEquals(sm.getState(), "CLOSE"); + + sm.transition("preOpen"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("open"); + assertEquals(sm.getState(), "OPEN"); + + } + + @Test + void testJsonSchema() throws Exception { + var sm = Door.builderDoorStateMachine.build(); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), new ObjectMapper().readTree(sm.toJsonSchema())); + } + + + @Test + void testSystemAppendStateTransition() throws Exception { + var smBuilder = Door.builderDoorStateMachine; + + smBuilder = smBuilder.addState("__test_state_1__"); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + }"""), new ObjectMapper().readTree(smBuilder.build().toJsonSchema())); + + smBuilder = smBuilder.addState("__test_state_2__"); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + }"""), new ObjectMapper().readTree(smBuilder.build().toJsonSchema())); + + smBuilder = smBuilder.addTransition("__test_transition__", "__test_state_1__", "__test_state_2__"); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] + }"""), new ObjectMapper().readTree(smBuilder.build().toJsonSchema())); + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.BuilderTestsGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.BuilderTestsGenerateWithInterface.verified.txt new file mode 100644 index 0000000..cfed5ef --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.BuilderTestsGenerateWithInterface.verified.txt @@ -0,0 +1,270 @@ +package fsm.door; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; +import com.fasterxml.jackson.databind.ObjectMapper; + +class TestDoor { + @Test + void testInit() { + var fsm = (Door.TypesDoorStateMachine)Door.builderDoorStateMachine.build(); + } + + + @Test + void testScenario0() { + var sm = (Door.TypesDoorStateMachine)Door.builderDoorStateMachine.build(); + sm.disableEvents(); + + + sm.preClose(); + assertEquals(sm.getState(), "AJAR"); + + sm.close(); + assertEquals(sm.getState(), "CLOSE"); + + sm.preOpen(); + assertEquals(sm.getState(), "AJAR"); + + sm.ajarPlus(); + assertEquals(sm.getState(), "AJAR"); + + sm.open(); + assertEquals(sm.getState(), "OPEN"); + + } + @Test + void testScenario1() { + var sm = (Door.TypesDoorStateMachine)Door.builderDoorStateMachine.build(); + sm.disableEvents(); + + + sm.preClose(); + assertEquals(sm.getState(), "AJAR"); + + sm.ajarPlus(); + assertEquals(sm.getState(), "AJAR"); + + sm.close(); + assertEquals(sm.getState(), "CLOSE"); + + sm.preOpen(); + assertEquals(sm.getState(), "AJAR"); + + sm.open(); + assertEquals(sm.getState(), "OPEN"); + + } + @Test + void testScenario2() { + var sm = (Door.TypesDoorStateMachine)Door.builderDoorStateMachine.build(); + sm.disableEvents(); + + + sm.preClose(); + assertEquals(sm.getState(), "AJAR"); + + sm.close(); + assertEquals(sm.getState(), "CLOSE"); + + sm.preOpen(); + assertEquals(sm.getState(), "AJAR"); + + sm.open(); + assertEquals(sm.getState(), "OPEN"); + + } + + @Test + void testJsonSchema() throws Exception { + var sm = (Door.TypesDoorStateMachine)Door.builderDoorStateMachine.build(); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), new ObjectMapper().readTree(sm.toJsonSchema())); + } + + + @Test + void testSystemAppendStateTransition() throws Exception { + var smBuilder = Door.builderDoorStateMachine; + + smBuilder = smBuilder.addState("__test_state_1__"); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + }"""), new ObjectMapper().readTree(smBuilder.build().toJsonSchema())); + + smBuilder = smBuilder.addState("__test_state_2__"); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + }"""), new ObjectMapper().readTree(smBuilder.build().toJsonSchema())); + + smBuilder = smBuilder.addTransition("__test_transition__", "__test_state_1__", "__test_state_2__"); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] + }"""), new ObjectMapper().readTree(smBuilder.build().toJsonSchema())); + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.BuilderTestsStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.BuilderTestsStateContextGenerate.verified.txt new file mode 100644 index 0000000..e83ade8 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.BuilderTestsStateContextGenerate.verified.txt @@ -0,0 +1,127 @@ +package fsm.door; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; +import com.fasterxml.jackson.databind.ObjectMapper; + +class TestDoor { + @Test + void testInit() { + var fsm = Door.builderDoorStateMachine.build(); + } + + + @Test + void testScenario0() { + var sm = Door.builderDoorStateMachine.build(); + sm.disableEvents(); + + + sm.transition("preClose"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("close"); + assertEquals(sm.getState(), Door.States.CLOSE); + + sm.transition("preOpen"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("ajarPlus"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("open"); + assertEquals(sm.getState(), Door.States.OPEN); + + } + @Test + void testScenario1() { + var sm = Door.builderDoorStateMachine.build(); + sm.disableEvents(); + + + sm.transition("preClose"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("ajarPlus"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("close"); + assertEquals(sm.getState(), Door.States.CLOSE); + + sm.transition("preOpen"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("open"); + assertEquals(sm.getState(), Door.States.OPEN); + + } + @Test + void testScenario2() { + var sm = Door.builderDoorStateMachine.build(); + sm.disableEvents(); + + + sm.transition("preClose"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("close"); + assertEquals(sm.getState(), Door.States.CLOSE); + + sm.transition("preOpen"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("open"); + assertEquals(sm.getState(), Door.States.OPEN); + + } + + @Test + void testJsonSchema() throws Exception { + var sm = Door.builderDoorStateMachine.build(); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), new ObjectMapper().readTree(sm.toJsonSchema())); + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.BuilderTestsStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.BuilderTestsStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..da9ad4a --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.BuilderTestsStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,127 @@ +package fsm.door; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; +import com.fasterxml.jackson.databind.ObjectMapper; + +class TestDoor { + @Test + void testInit() { + var fsm = (Door.TypesDoorStateMachine)Door.builderDoorStateMachine.build(); + } + + + @Test + void testScenario0() { + var sm = (Door.TypesDoorStateMachine)Door.builderDoorStateMachine.build(); + sm.disableEvents(); + + + sm.preClose(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.close(); + assertEquals(sm.getState(), Door.States.CLOSE); + + sm.preOpen(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.ajarPlus(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.open(); + assertEquals(sm.getState(), Door.States.OPEN); + + } + @Test + void testScenario1() { + var sm = (Door.TypesDoorStateMachine)Door.builderDoorStateMachine.build(); + sm.disableEvents(); + + + sm.preClose(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.ajarPlus(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.close(); + assertEquals(sm.getState(), Door.States.CLOSE); + + sm.preOpen(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.open(); + assertEquals(sm.getState(), Door.States.OPEN); + + } + @Test + void testScenario2() { + var sm = (Door.TypesDoorStateMachine)Door.builderDoorStateMachine.build(); + sm.disableEvents(); + + + sm.preClose(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.close(); + assertEquals(sm.getState(), Door.States.CLOSE); + + sm.preOpen(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.open(); + assertEquals(sm.getState(), Door.States.OPEN); + + } + + @Test + void testJsonSchema() throws Exception { + var sm = (Door.TypesDoorStateMachine)Door.builderDoorStateMachine.build(); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), new ObjectMapper().readTree(sm.toJsonSchema())); + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.BuilderTestsStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.BuilderTestsStateGenerate.verified.txt new file mode 100644 index 0000000..e83ade8 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.BuilderTestsStateGenerate.verified.txt @@ -0,0 +1,127 @@ +package fsm.door; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; +import com.fasterxml.jackson.databind.ObjectMapper; + +class TestDoor { + @Test + void testInit() { + var fsm = Door.builderDoorStateMachine.build(); + } + + + @Test + void testScenario0() { + var sm = Door.builderDoorStateMachine.build(); + sm.disableEvents(); + + + sm.transition("preClose"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("close"); + assertEquals(sm.getState(), Door.States.CLOSE); + + sm.transition("preOpen"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("ajarPlus"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("open"); + assertEquals(sm.getState(), Door.States.OPEN); + + } + @Test + void testScenario1() { + var sm = Door.builderDoorStateMachine.build(); + sm.disableEvents(); + + + sm.transition("preClose"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("ajarPlus"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("close"); + assertEquals(sm.getState(), Door.States.CLOSE); + + sm.transition("preOpen"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("open"); + assertEquals(sm.getState(), Door.States.OPEN); + + } + @Test + void testScenario2() { + var sm = Door.builderDoorStateMachine.build(); + sm.disableEvents(); + + + sm.transition("preClose"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("close"); + assertEquals(sm.getState(), Door.States.CLOSE); + + sm.transition("preOpen"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("open"); + assertEquals(sm.getState(), Door.States.OPEN); + + } + + @Test + void testJsonSchema() throws Exception { + var sm = Door.builderDoorStateMachine.build(); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), new ObjectMapper().readTree(sm.toJsonSchema())); + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.BuilderTestsStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.BuilderTestsStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..da9ad4a --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.BuilderTestsStateGenerateWithInterface.verified.txt @@ -0,0 +1,127 @@ +package fsm.door; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; +import com.fasterxml.jackson.databind.ObjectMapper; + +class TestDoor { + @Test + void testInit() { + var fsm = (Door.TypesDoorStateMachine)Door.builderDoorStateMachine.build(); + } + + + @Test + void testScenario0() { + var sm = (Door.TypesDoorStateMachine)Door.builderDoorStateMachine.build(); + sm.disableEvents(); + + + sm.preClose(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.close(); + assertEquals(sm.getState(), Door.States.CLOSE); + + sm.preOpen(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.ajarPlus(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.open(); + assertEquals(sm.getState(), Door.States.OPEN); + + } + @Test + void testScenario1() { + var sm = (Door.TypesDoorStateMachine)Door.builderDoorStateMachine.build(); + sm.disableEvents(); + + + sm.preClose(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.ajarPlus(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.close(); + assertEquals(sm.getState(), Door.States.CLOSE); + + sm.preOpen(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.open(); + assertEquals(sm.getState(), Door.States.OPEN); + + } + @Test + void testScenario2() { + var sm = (Door.TypesDoorStateMachine)Door.builderDoorStateMachine.build(); + sm.disableEvents(); + + + sm.preClose(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.close(); + assertEquals(sm.getState(), Door.States.CLOSE); + + sm.preOpen(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.open(); + assertEquals(sm.getState(), Door.States.OPEN); + + } + + @Test + void testJsonSchema() throws Exception { + var sm = (Door.TypesDoorStateMachine)Door.builderDoorStateMachine.build(); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), new ObjectMapper().readTree(sm.toJsonSchema())); + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.ClazzTestsContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.ClazzTestsContextGenerate.verified.txt new file mode 100644 index 0000000..8665347 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.ClazzTestsContextGenerate.verified.txt @@ -0,0 +1,127 @@ +package fsm.door; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; +import com.fasterxml.jackson.databind.ObjectMapper; + +class TestDoor { + @Test + void testInit() { + var fsm = new Door.DoorStateMachine(); + } + + + @Test + void testScenario0() { + var sm = new Door.DoorStateMachine(); + sm.disableEvents(); + + + sm.transition("preClose"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("close"); + assertEquals(sm.getState(), "CLOSE"); + + sm.transition("preOpen"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("ajarPlus"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("open"); + assertEquals(sm.getState(), "OPEN"); + + } + @Test + void testScenario1() { + var sm = new Door.DoorStateMachine(); + sm.disableEvents(); + + + sm.transition("preClose"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("ajarPlus"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("close"); + assertEquals(sm.getState(), "CLOSE"); + + sm.transition("preOpen"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("open"); + assertEquals(sm.getState(), "OPEN"); + + } + @Test + void testScenario2() { + var sm = new Door.DoorStateMachine(); + sm.disableEvents(); + + + sm.transition("preClose"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("close"); + assertEquals(sm.getState(), "CLOSE"); + + sm.transition("preOpen"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("open"); + assertEquals(sm.getState(), "OPEN"); + + } + + @Test + void testJsonSchema() throws Exception { + var sm = new Door.DoorStateMachine(); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), new ObjectMapper().readTree(sm.toJsonSchema())); + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.ClazzTestsContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.ClazzTestsContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..6c11e6b --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.ClazzTestsContextGenerateWithInterface.verified.txt @@ -0,0 +1,127 @@ +package fsm.door; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; +import com.fasterxml.jackson.databind.ObjectMapper; + +class TestDoor { + @Test + void testInit() { + var fsm = new Door.DoorStateMachine(); + } + + + @Test + void testScenario0() { + var sm = new Door.DoorStateMachine(); + sm.disableEvents(); + + + sm.preClose(); + assertEquals(sm.getState(), "AJAR"); + + sm.close(); + assertEquals(sm.getState(), "CLOSE"); + + sm.preOpen(); + assertEquals(sm.getState(), "AJAR"); + + sm.ajarPlus(); + assertEquals(sm.getState(), "AJAR"); + + sm.open(); + assertEquals(sm.getState(), "OPEN"); + + } + @Test + void testScenario1() { + var sm = new Door.DoorStateMachine(); + sm.disableEvents(); + + + sm.preClose(); + assertEquals(sm.getState(), "AJAR"); + + sm.ajarPlus(); + assertEquals(sm.getState(), "AJAR"); + + sm.close(); + assertEquals(sm.getState(), "CLOSE"); + + sm.preOpen(); + assertEquals(sm.getState(), "AJAR"); + + sm.open(); + assertEquals(sm.getState(), "OPEN"); + + } + @Test + void testScenario2() { + var sm = new Door.DoorStateMachine(); + sm.disableEvents(); + + + sm.preClose(); + assertEquals(sm.getState(), "AJAR"); + + sm.close(); + assertEquals(sm.getState(), "CLOSE"); + + sm.preOpen(); + assertEquals(sm.getState(), "AJAR"); + + sm.open(); + assertEquals(sm.getState(), "OPEN"); + + } + + @Test + void testJsonSchema() throws Exception { + var sm = new Door.DoorStateMachine(); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), new ObjectMapper().readTree(sm.toJsonSchema())); + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.ClazzTestsGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.ClazzTestsGenerate.verified.txt new file mode 100644 index 0000000..8665347 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.ClazzTestsGenerate.verified.txt @@ -0,0 +1,127 @@ +package fsm.door; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; +import com.fasterxml.jackson.databind.ObjectMapper; + +class TestDoor { + @Test + void testInit() { + var fsm = new Door.DoorStateMachine(); + } + + + @Test + void testScenario0() { + var sm = new Door.DoorStateMachine(); + sm.disableEvents(); + + + sm.transition("preClose"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("close"); + assertEquals(sm.getState(), "CLOSE"); + + sm.transition("preOpen"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("ajarPlus"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("open"); + assertEquals(sm.getState(), "OPEN"); + + } + @Test + void testScenario1() { + var sm = new Door.DoorStateMachine(); + sm.disableEvents(); + + + sm.transition("preClose"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("ajarPlus"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("close"); + assertEquals(sm.getState(), "CLOSE"); + + sm.transition("preOpen"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("open"); + assertEquals(sm.getState(), "OPEN"); + + } + @Test + void testScenario2() { + var sm = new Door.DoorStateMachine(); + sm.disableEvents(); + + + sm.transition("preClose"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("close"); + assertEquals(sm.getState(), "CLOSE"); + + sm.transition("preOpen"); + assertEquals(sm.getState(), "AJAR"); + + sm.transition("open"); + assertEquals(sm.getState(), "OPEN"); + + } + + @Test + void testJsonSchema() throws Exception { + var sm = new Door.DoorStateMachine(); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), new ObjectMapper().readTree(sm.toJsonSchema())); + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.ClazzTestsGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.ClazzTestsGenerateWithInterface.verified.txt new file mode 100644 index 0000000..6c11e6b --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.ClazzTestsGenerateWithInterface.verified.txt @@ -0,0 +1,127 @@ +package fsm.door; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; +import com.fasterxml.jackson.databind.ObjectMapper; + +class TestDoor { + @Test + void testInit() { + var fsm = new Door.DoorStateMachine(); + } + + + @Test + void testScenario0() { + var sm = new Door.DoorStateMachine(); + sm.disableEvents(); + + + sm.preClose(); + assertEquals(sm.getState(), "AJAR"); + + sm.close(); + assertEquals(sm.getState(), "CLOSE"); + + sm.preOpen(); + assertEquals(sm.getState(), "AJAR"); + + sm.ajarPlus(); + assertEquals(sm.getState(), "AJAR"); + + sm.open(); + assertEquals(sm.getState(), "OPEN"); + + } + @Test + void testScenario1() { + var sm = new Door.DoorStateMachine(); + sm.disableEvents(); + + + sm.preClose(); + assertEquals(sm.getState(), "AJAR"); + + sm.ajarPlus(); + assertEquals(sm.getState(), "AJAR"); + + sm.close(); + assertEquals(sm.getState(), "CLOSE"); + + sm.preOpen(); + assertEquals(sm.getState(), "AJAR"); + + sm.open(); + assertEquals(sm.getState(), "OPEN"); + + } + @Test + void testScenario2() { + var sm = new Door.DoorStateMachine(); + sm.disableEvents(); + + + sm.preClose(); + assertEquals(sm.getState(), "AJAR"); + + sm.close(); + assertEquals(sm.getState(), "CLOSE"); + + sm.preOpen(); + assertEquals(sm.getState(), "AJAR"); + + sm.open(); + assertEquals(sm.getState(), "OPEN"); + + } + + @Test + void testJsonSchema() throws Exception { + var sm = new Door.DoorStateMachine(); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), new ObjectMapper().readTree(sm.toJsonSchema())); + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.ClazzTestsStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.ClazzTestsStateContextGenerate.verified.txt new file mode 100644 index 0000000..1cfdbeb --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.ClazzTestsStateContextGenerate.verified.txt @@ -0,0 +1,127 @@ +package fsm.door; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; +import com.fasterxml.jackson.databind.ObjectMapper; + +class TestDoor { + @Test + void testInit() { + var fsm = new Door.DoorStateMachine(); + } + + + @Test + void testScenario0() { + var sm = new Door.DoorStateMachine(); + sm.disableEvents(); + + + sm.transition("preClose"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("close"); + assertEquals(sm.getState(), Door.States.CLOSE); + + sm.transition("preOpen"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("ajarPlus"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("open"); + assertEquals(sm.getState(), Door.States.OPEN); + + } + @Test + void testScenario1() { + var sm = new Door.DoorStateMachine(); + sm.disableEvents(); + + + sm.transition("preClose"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("ajarPlus"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("close"); + assertEquals(sm.getState(), Door.States.CLOSE); + + sm.transition("preOpen"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("open"); + assertEquals(sm.getState(), Door.States.OPEN); + + } + @Test + void testScenario2() { + var sm = new Door.DoorStateMachine(); + sm.disableEvents(); + + + sm.transition("preClose"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("close"); + assertEquals(sm.getState(), Door.States.CLOSE); + + sm.transition("preOpen"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("open"); + assertEquals(sm.getState(), Door.States.OPEN); + + } + + @Test + void testJsonSchema() throws Exception { + var sm = new Door.DoorStateMachine(); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), new ObjectMapper().readTree(sm.toJsonSchema())); + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.ClazzTestsStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.ClazzTestsStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..a665230 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.ClazzTestsStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,127 @@ +package fsm.door; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; +import com.fasterxml.jackson.databind.ObjectMapper; + +class TestDoor { + @Test + void testInit() { + var fsm = new Door.DoorStateMachine(); + } + + + @Test + void testScenario0() { + var sm = new Door.DoorStateMachine(); + sm.disableEvents(); + + + sm.preClose(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.close(); + assertEquals(sm.getState(), Door.States.CLOSE); + + sm.preOpen(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.ajarPlus(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.open(); + assertEquals(sm.getState(), Door.States.OPEN); + + } + @Test + void testScenario1() { + var sm = new Door.DoorStateMachine(); + sm.disableEvents(); + + + sm.preClose(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.ajarPlus(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.close(); + assertEquals(sm.getState(), Door.States.CLOSE); + + sm.preOpen(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.open(); + assertEquals(sm.getState(), Door.States.OPEN); + + } + @Test + void testScenario2() { + var sm = new Door.DoorStateMachine(); + sm.disableEvents(); + + + sm.preClose(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.close(); + assertEquals(sm.getState(), Door.States.CLOSE); + + sm.preOpen(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.open(); + assertEquals(sm.getState(), Door.States.OPEN); + + } + + @Test + void testJsonSchema() throws Exception { + var sm = new Door.DoorStateMachine(); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), new ObjectMapper().readTree(sm.toJsonSchema())); + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.ClazzTestsStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.ClazzTestsStateGenerate.verified.txt new file mode 100644 index 0000000..1cfdbeb --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.ClazzTestsStateGenerate.verified.txt @@ -0,0 +1,127 @@ +package fsm.door; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; +import com.fasterxml.jackson.databind.ObjectMapper; + +class TestDoor { + @Test + void testInit() { + var fsm = new Door.DoorStateMachine(); + } + + + @Test + void testScenario0() { + var sm = new Door.DoorStateMachine(); + sm.disableEvents(); + + + sm.transition("preClose"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("close"); + assertEquals(sm.getState(), Door.States.CLOSE); + + sm.transition("preOpen"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("ajarPlus"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("open"); + assertEquals(sm.getState(), Door.States.OPEN); + + } + @Test + void testScenario1() { + var sm = new Door.DoorStateMachine(); + sm.disableEvents(); + + + sm.transition("preClose"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("ajarPlus"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("close"); + assertEquals(sm.getState(), Door.States.CLOSE); + + sm.transition("preOpen"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("open"); + assertEquals(sm.getState(), Door.States.OPEN); + + } + @Test + void testScenario2() { + var sm = new Door.DoorStateMachine(); + sm.disableEvents(); + + + sm.transition("preClose"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("close"); + assertEquals(sm.getState(), Door.States.CLOSE); + + sm.transition("preOpen"); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.transition("open"); + assertEquals(sm.getState(), Door.States.OPEN); + + } + + @Test + void testJsonSchema() throws Exception { + var sm = new Door.DoorStateMachine(); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), new ObjectMapper().readTree(sm.toJsonSchema())); + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.ClazzTestsStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.ClazzTestsStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..a665230 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Java/JavaTestsAdapterGenerateDoorTests.ClazzTestsStateGenerateWithInterface.verified.txt @@ -0,0 +1,127 @@ +package fsm.door; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; +import com.fasterxml.jackson.databind.ObjectMapper; + +class TestDoor { + @Test + void testInit() { + var fsm = new Door.DoorStateMachine(); + } + + + @Test + void testScenario0() { + var sm = new Door.DoorStateMachine(); + sm.disableEvents(); + + + sm.preClose(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.close(); + assertEquals(sm.getState(), Door.States.CLOSE); + + sm.preOpen(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.ajarPlus(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.open(); + assertEquals(sm.getState(), Door.States.OPEN); + + } + @Test + void testScenario1() { + var sm = new Door.DoorStateMachine(); + sm.disableEvents(); + + + sm.preClose(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.ajarPlus(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.close(); + assertEquals(sm.getState(), Door.States.CLOSE); + + sm.preOpen(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.open(); + assertEquals(sm.getState(), Door.States.OPEN); + + } + @Test + void testScenario2() { + var sm = new Door.DoorStateMachine(); + sm.disableEvents(); + + + sm.preClose(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.close(); + assertEquals(sm.getState(), Door.States.CLOSE); + + sm.preOpen(); + assertEquals(sm.getState(), Door.States.AJAR); + + sm.open(); + assertEquals(sm.getState(), Door.States.OPEN); + + } + + @Test + void testJsonSchema() throws Exception { + var sm = new Door.DoorStateMachine(); + assertEquals(new ObjectMapper().readTree(""" + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """ + ), new ObjectMapper().readTree(sm.toJsonSchema())); + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaAdapterGenerateDoorTests.cs b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaAdapterGenerateDoorTests.cs new file mode 100644 index 0000000..855dc0c --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaAdapterGenerateDoorTests.cs @@ -0,0 +1,18 @@ +using Stater.CodeGeneration.Entity; +using Stater.CodeGeneration.LanguageAdapter.Base; +using Stater.CodeGeneration.LanguageAdapter.Java; +using Stater.CodeGeneration.LanguageAdapter.Kotlin; + +namespace Stater.CodeGeneration.Tests.LanguageAdapter; + +public class JavaAdapterGenerateDoorTests : BaseTestAdapterGenerateDoorTests +{ + protected override BaseLanguageAdapter Adapter => new JavaAdapter(); + protected override Language Language => Language.Java; +} + +public class JavaTestsAdapterGenerateDoorTests : BaseTestAdapterGenerateTestsDoorTests +{ + protected override BaseLanguageAdapter Adapter => new JavaAdapter(); + protected override Language Language => Language.Java; +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.BuilderContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.BuilderContextGenerate.verified.txt new file mode 100644 index 0000000..9860945 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.BuilderContextGenerate.verified.txt @@ -0,0 +1,29 @@ +import {StaterStateMachineBuilder} from "./index.js"; + +const buildDoorFSMContext = () => { + return { + degreeOfOpening: 0, + closeVariable: true, + doorName: "asd", + floatVariable: 0 + } +} + + +export const builderDoorStateMachine = new StaterStateMachineBuilder() + .setStartState("OPEN") + .setContext(buildDoorFSMContext()) + .addTransition("preOpen", "CLOSE", "AJAR") + .setTransitionEvent("preOpen", (ctx) => { ctx.degreeOfOpening = 1 }) + .addTransition("preClose", "OPEN", "AJAR") + .setTransitionEvent("preClose", (ctx) => { ctx.degreeOfOpening = 99 }) + .addTransition("open", "AJAR", "OPEN") + .setTransitionCondition("open", (ctx) => ctx.degreeOfOpening >= 0) + .setTransitionEvent("open", (ctx) => { ctx.degreeOfOpening = 100 }) + .addTransition("close", "AJAR", "CLOSE") + .setTransitionCondition("close", (ctx) => ctx.degreeOfOpening <= 0) + .setTransitionEvent("close", (ctx) => { ctx.degreeOfOpening = 0 }) + .addTransition("ajarPlus", "AJAR", "AJAR") + .setTransitionEvent("ajarPlus", (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening + 1 }) + .addTransition("ajarMinus", "AJAR", "AJAR") + .setTransitionEvent("ajarMinus", (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening - 1 }) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.BuilderContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.BuilderContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..a7527d9 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.BuilderContextGenerateWithInterface.verified.txt @@ -0,0 +1,59 @@ +import {StaterStateMachine} from "./index.js"; +import {StaterStateMachineBuilder} from "./index.js"; + +const buildDoorFSMContext = () => { + return { + degreeOfOpening: 0, + closeVariable: true, + doorName: "asd", + floatVariable: 0 + } +} + + +class TypesDoorStateMachine extends StaterStateMachine { + preOpen() { + this.transition("preOpen") + } + + preClose() { + this.transition("preClose") + } + + open() { + this.transition("open") + } + + close() { + this.transition("close") + } + + ajarPlus() { + this.transition("ajarPlus") + } + + ajarMinus() { + this.transition("ajarMinus") + } +} + +const typedDoorFactory = (...args) => new TypesDoorStateMachine(...args); + +export const builderDoorStateMachine = new StaterStateMachineBuilder() + .setStartState("OPEN") + .setContext(buildDoorFSMContext()) + .setFactory(typedDoorFactory) + .addTransition("preOpen", "CLOSE", "AJAR") + .setTransitionEvent("preOpen", (ctx) => { ctx.degreeOfOpening = 1 }) + .addTransition("preClose", "OPEN", "AJAR") + .setTransitionEvent("preClose", (ctx) => { ctx.degreeOfOpening = 99 }) + .addTransition("open", "AJAR", "OPEN") + .setTransitionCondition("open", (ctx) => ctx.degreeOfOpening >= 0) + .setTransitionEvent("open", (ctx) => { ctx.degreeOfOpening = 100 }) + .addTransition("close", "AJAR", "CLOSE") + .setTransitionCondition("close", (ctx) => ctx.degreeOfOpening <= 0) + .setTransitionEvent("close", (ctx) => { ctx.degreeOfOpening = 0 }) + .addTransition("ajarPlus", "AJAR", "AJAR") + .setTransitionEvent("ajarPlus", (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening + 1 }) + .addTransition("ajarMinus", "AJAR", "AJAR") + .setTransitionEvent("ajarMinus", (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening - 1 }) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.BuilderGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.BuilderGenerate.verified.txt new file mode 100644 index 0000000..6d55837 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.BuilderGenerate.verified.txt @@ -0,0 +1,11 @@ +import {StaterStateMachineBuilder} from "./index.js"; + +export const builderDoorStateMachine = new StaterStateMachineBuilder() + .setStartState("OPEN") + .setContext({}) + .addTransition("preOpen", "CLOSE", "AJAR") + .addTransition("preClose", "OPEN", "AJAR") + .addTransition("open", "AJAR", "OPEN") + .addTransition("close", "AJAR", "CLOSE") + .addTransition("ajarPlus", "AJAR", "AJAR") + .addTransition("ajarMinus", "AJAR", "AJAR") \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.BuilderGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.BuilderGenerateWithInterface.verified.txt new file mode 100644 index 0000000..76d856b --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.BuilderGenerateWithInterface.verified.txt @@ -0,0 +1,41 @@ +import {StaterStateMachine} from "./index.js"; +import {StaterStateMachineBuilder} from "./index.js"; + +class TypesDoorStateMachine extends StaterStateMachine { + preOpen() { + this.transition("preOpen") + } + + preClose() { + this.transition("preClose") + } + + open() { + this.transition("open") + } + + close() { + this.transition("close") + } + + ajarPlus() { + this.transition("ajarPlus") + } + + ajarMinus() { + this.transition("ajarMinus") + } +} + +const typedDoorFactory = (...args) => new TypesDoorStateMachine(...args); + +export const builderDoorStateMachine = new StaterStateMachineBuilder() + .setStartState("OPEN") + .setContext({}) + .setFactory(typedDoorFactory) + .addTransition("preOpen", "CLOSE", "AJAR") + .addTransition("preClose", "OPEN", "AJAR") + .addTransition("open", "AJAR", "OPEN") + .addTransition("close", "AJAR", "CLOSE") + .addTransition("ajarPlus", "AJAR", "AJAR") + .addTransition("ajarMinus", "AJAR", "AJAR") \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.BuilderStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.BuilderStateContextGenerate.verified.txt new file mode 100644 index 0000000..9d83a9d --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.BuilderStateContextGenerate.verified.txt @@ -0,0 +1,35 @@ +import {StaterStateMachineBuilder} from "./index.js"; + +export const States = Object.freeze({ + OPEN: "OPEN", + AJAR: "AJAR", + CLOSE: "CLOSE" +}); + +const buildDoorFSMContext = () => { + return { + degreeOfOpening: 0, + closeVariable: true, + doorName: "asd", + floatVariable: 0 + } +} + + +export const builderDoorStateMachine = new StaterStateMachineBuilder() + .setStartState(States.OPEN) + .setContext(buildDoorFSMContext()) + .addTransition("preOpen", States.CLOSE, States.AJAR) + .setTransitionEvent("preOpen", (ctx) => { ctx.degreeOfOpening = 1 }) + .addTransition("preClose", States.OPEN, States.AJAR) + .setTransitionEvent("preClose", (ctx) => { ctx.degreeOfOpening = 99 }) + .addTransition("open", States.AJAR, States.OPEN) + .setTransitionCondition("open", (ctx) => ctx.degreeOfOpening >= 0) + .setTransitionEvent("open", (ctx) => { ctx.degreeOfOpening = 100 }) + .addTransition("close", States.AJAR, States.CLOSE) + .setTransitionCondition("close", (ctx) => ctx.degreeOfOpening <= 0) + .setTransitionEvent("close", (ctx) => { ctx.degreeOfOpening = 0 }) + .addTransition("ajarPlus", States.AJAR, States.AJAR) + .setTransitionEvent("ajarPlus", (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening + 1 }) + .addTransition("ajarMinus", States.AJAR, States.AJAR) + .setTransitionEvent("ajarMinus", (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening - 1 }) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.BuilderStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.BuilderStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..f0a01d3 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.BuilderStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,65 @@ +import {StaterStateMachine} from "./index.js"; +import {StaterStateMachineBuilder} from "./index.js"; + +export const States = Object.freeze({ + OPEN: "OPEN", + AJAR: "AJAR", + CLOSE: "CLOSE" +}); + +const buildDoorFSMContext = () => { + return { + degreeOfOpening: 0, + closeVariable: true, + doorName: "asd", + floatVariable: 0 + } +} + + +class TypesDoorStateMachine extends StaterStateMachine { + preOpen() { + this.transition("preOpen") + } + + preClose() { + this.transition("preClose") + } + + open() { + this.transition("open") + } + + close() { + this.transition("close") + } + + ajarPlus() { + this.transition("ajarPlus") + } + + ajarMinus() { + this.transition("ajarMinus") + } +} + +const typedDoorFactory = (...args) => new TypesDoorStateMachine(...args); + +export const builderDoorStateMachine = new StaterStateMachineBuilder() + .setStartState(States.OPEN) + .setContext(buildDoorFSMContext()) + .setFactory(typedDoorFactory) + .addTransition("preOpen", States.CLOSE, States.AJAR) + .setTransitionEvent("preOpen", (ctx) => { ctx.degreeOfOpening = 1 }) + .addTransition("preClose", States.OPEN, States.AJAR) + .setTransitionEvent("preClose", (ctx) => { ctx.degreeOfOpening = 99 }) + .addTransition("open", States.AJAR, States.OPEN) + .setTransitionCondition("open", (ctx) => ctx.degreeOfOpening >= 0) + .setTransitionEvent("open", (ctx) => { ctx.degreeOfOpening = 100 }) + .addTransition("close", States.AJAR, States.CLOSE) + .setTransitionCondition("close", (ctx) => ctx.degreeOfOpening <= 0) + .setTransitionEvent("close", (ctx) => { ctx.degreeOfOpening = 0 }) + .addTransition("ajarPlus", States.AJAR, States.AJAR) + .setTransitionEvent("ajarPlus", (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening + 1 }) + .addTransition("ajarMinus", States.AJAR, States.AJAR) + .setTransitionEvent("ajarMinus", (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening - 1 }) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.BuilderStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.BuilderStateGenerate.verified.txt new file mode 100644 index 0000000..294d90c --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.BuilderStateGenerate.verified.txt @@ -0,0 +1,17 @@ +import {StaterStateMachineBuilder} from "./index.js"; + +export const States = Object.freeze({ + OPEN: "OPEN", + AJAR: "AJAR", + CLOSE: "CLOSE" +}); + +export const builderDoorStateMachine = new StaterStateMachineBuilder() + .setStartState(States.OPEN) + .setContext({}) + .addTransition("preOpen", States.CLOSE, States.AJAR) + .addTransition("preClose", States.OPEN, States.AJAR) + .addTransition("open", States.AJAR, States.OPEN) + .addTransition("close", States.AJAR, States.CLOSE) + .addTransition("ajarPlus", States.AJAR, States.AJAR) + .addTransition("ajarMinus", States.AJAR, States.AJAR) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.BuilderStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.BuilderStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..368db9e --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.BuilderStateGenerateWithInterface.verified.txt @@ -0,0 +1,47 @@ +import {StaterStateMachine} from "./index.js"; +import {StaterStateMachineBuilder} from "./index.js"; + +export const States = Object.freeze({ + OPEN: "OPEN", + AJAR: "AJAR", + CLOSE: "CLOSE" +}); + +class TypesDoorStateMachine extends StaterStateMachine { + preOpen() { + this.transition("preOpen") + } + + preClose() { + this.transition("preClose") + } + + open() { + this.transition("open") + } + + close() { + this.transition("close") + } + + ajarPlus() { + this.transition("ajarPlus") + } + + ajarMinus() { + this.transition("ajarMinus") + } +} + +const typedDoorFactory = (...args) => new TypesDoorStateMachine(...args); + +export const builderDoorStateMachine = new StaterStateMachineBuilder() + .setStartState(States.OPEN) + .setContext({}) + .setFactory(typedDoorFactory) + .addTransition("preOpen", States.CLOSE, States.AJAR) + .addTransition("preClose", States.OPEN, States.AJAR) + .addTransition("open", States.AJAR, States.OPEN) + .addTransition("close", States.AJAR, States.CLOSE) + .addTransition("ajarPlus", States.AJAR, States.AJAR) + .addTransition("ajarMinus", States.AJAR, States.AJAR) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.ClazzContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.ClazzContextGenerate.verified.txt new file mode 100644 index 0000000..33712dc --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.ClazzContextGenerate.verified.txt @@ -0,0 +1,61 @@ +import {StaterStateMachine} from "./index.js"; + + +const buildDoorFSMContext = () => { + return { + degreeOfOpening: 0, + closeVariable: true, + doorName: "asd", + floatVariable: 0 + } +} + + +export class DoorStateMachine extends StaterStateMachine { + constructor() { + super( + [ + { + name: "preOpen", + start: "CLOSE", + end: "AJAR", + event: (ctx) => { ctx.degreeOfOpening = 1 } + }, + { + name: "preClose", + start: "OPEN", + end: "AJAR", + event: (ctx) => { ctx.degreeOfOpening = 99 } + }, + { + name: "open", + start: "AJAR", + end: "OPEN", + condition: (ctx) => ctx.degreeOfOpening >= 0, + event: (ctx) => { ctx.degreeOfOpening = 100 } + }, + { + name: "close", + start: "AJAR", + end: "CLOSE", + condition: (ctx) => ctx.degreeOfOpening <= 0, + event: (ctx) => { ctx.degreeOfOpening = 0 } + }, + { + name: "ajarPlus", + start: "AJAR", + end: "AJAR", + event: (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening + 1 } + }, + { + name: "ajarMinus", + start: "AJAR", + end: "AJAR", + event: (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening - 1 } + } + ], + buildDoorFSMContext(), + "OPEN", + ) + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.ClazzContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.ClazzContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..bb1eb45 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.ClazzContextGenerateWithInterface.verified.txt @@ -0,0 +1,85 @@ +import {StaterStateMachine} from "./index.js"; + + +const buildDoorFSMContext = () => { + return { + degreeOfOpening: 0, + closeVariable: true, + doorName: "asd", + floatVariable: 0 + } +} + + +export class DoorStateMachine extends StaterStateMachine { + constructor() { + super( + [ + { + name: "preOpen", + start: "CLOSE", + end: "AJAR", + event: (ctx) => { ctx.degreeOfOpening = 1 } + }, + { + name: "preClose", + start: "OPEN", + end: "AJAR", + event: (ctx) => { ctx.degreeOfOpening = 99 } + }, + { + name: "open", + start: "AJAR", + end: "OPEN", + condition: (ctx) => ctx.degreeOfOpening >= 0, + event: (ctx) => { ctx.degreeOfOpening = 100 } + }, + { + name: "close", + start: "AJAR", + end: "CLOSE", + condition: (ctx) => ctx.degreeOfOpening <= 0, + event: (ctx) => { ctx.degreeOfOpening = 0 } + }, + { + name: "ajarPlus", + start: "AJAR", + end: "AJAR", + event: (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening + 1 } + }, + { + name: "ajarMinus", + start: "AJAR", + end: "AJAR", + event: (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening - 1 } + } + ], + buildDoorFSMContext(), + "OPEN", + ) + } + + preOpen() { + this.transition("preOpen") + } + + preClose() { + this.transition("preClose") + } + + open() { + this.transition("open") + } + + close() { + this.transition("close") + } + + ajarPlus() { + this.transition("ajarPlus") + } + + ajarMinus() { + this.transition("ajarMinus") + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.ClazzGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.ClazzGenerate.verified.txt new file mode 100644 index 0000000..dbe27b9 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.ClazzGenerate.verified.txt @@ -0,0 +1,43 @@ +import {StaterStateMachine} from "./index.js"; + + +export class DoorStateMachine extends StaterStateMachine { + constructor() { + super( + [ + { + name: "preOpen", + start: "CLOSE", + end: "AJAR" + }, + { + name: "preClose", + start: "OPEN", + end: "AJAR" + }, + { + name: "open", + start: "AJAR", + end: "OPEN" + }, + { + name: "close", + start: "AJAR", + end: "CLOSE" + }, + { + name: "ajarPlus", + start: "AJAR", + end: "AJAR" + }, + { + name: "ajarMinus", + start: "AJAR", + end: "AJAR" + } + ], + {}, + "OPEN", + ) + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.ClazzGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.ClazzGenerateWithInterface.verified.txt new file mode 100644 index 0000000..430ddf6 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.ClazzGenerateWithInterface.verified.txt @@ -0,0 +1,67 @@ +import {StaterStateMachine} from "./index.js"; + + +export class DoorStateMachine extends StaterStateMachine { + constructor() { + super( + [ + { + name: "preOpen", + start: "CLOSE", + end: "AJAR" + }, + { + name: "preClose", + start: "OPEN", + end: "AJAR" + }, + { + name: "open", + start: "AJAR", + end: "OPEN" + }, + { + name: "close", + start: "AJAR", + end: "CLOSE" + }, + { + name: "ajarPlus", + start: "AJAR", + end: "AJAR" + }, + { + name: "ajarMinus", + start: "AJAR", + end: "AJAR" + } + ], + {}, + "OPEN", + ) + } + + preOpen() { + this.transition("preOpen") + } + + preClose() { + this.transition("preClose") + } + + open() { + this.transition("open") + } + + close() { + this.transition("close") + } + + ajarPlus() { + this.transition("ajarPlus") + } + + ajarMinus() { + this.transition("ajarMinus") + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.ClazzStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.ClazzStateContextGenerate.verified.txt new file mode 100644 index 0000000..e5795c9 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.ClazzStateContextGenerate.verified.txt @@ -0,0 +1,67 @@ +import {StaterStateMachine} from "./index.js"; + + +export const States = Object.freeze({ + OPEN: "OPEN", + AJAR: "AJAR", + CLOSE: "CLOSE" +}); + +const buildDoorFSMContext = () => { + return { + degreeOfOpening: 0, + closeVariable: true, + doorName: "asd", + floatVariable: 0 + } +} + + +export class DoorStateMachine extends StaterStateMachine { + constructor() { + super( + [ + { + name: "preOpen", + start: States.CLOSE, + end: States.AJAR, + event: (ctx) => { ctx.degreeOfOpening = 1 } + }, + { + name: "preClose", + start: States.OPEN, + end: States.AJAR, + event: (ctx) => { ctx.degreeOfOpening = 99 } + }, + { + name: "open", + start: States.AJAR, + end: States.OPEN, + condition: (ctx) => ctx.degreeOfOpening >= 0, + event: (ctx) => { ctx.degreeOfOpening = 100 } + }, + { + name: "close", + start: States.AJAR, + end: States.CLOSE, + condition: (ctx) => ctx.degreeOfOpening <= 0, + event: (ctx) => { ctx.degreeOfOpening = 0 } + }, + { + name: "ajarPlus", + start: States.AJAR, + end: States.AJAR, + event: (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening + 1 } + }, + { + name: "ajarMinus", + start: States.AJAR, + end: States.AJAR, + event: (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening - 1 } + } + ], + buildDoorFSMContext(), + States.OPEN, + ) + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.ClazzStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.ClazzStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..3d1307e --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.ClazzStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,91 @@ +import {StaterStateMachine} from "./index.js"; + + +export const States = Object.freeze({ + OPEN: "OPEN", + AJAR: "AJAR", + CLOSE: "CLOSE" +}); + +const buildDoorFSMContext = () => { + return { + degreeOfOpening: 0, + closeVariable: true, + doorName: "asd", + floatVariable: 0 + } +} + + +export class DoorStateMachine extends StaterStateMachine { + constructor() { + super( + [ + { + name: "preOpen", + start: States.CLOSE, + end: States.AJAR, + event: (ctx) => { ctx.degreeOfOpening = 1 } + }, + { + name: "preClose", + start: States.OPEN, + end: States.AJAR, + event: (ctx) => { ctx.degreeOfOpening = 99 } + }, + { + name: "open", + start: States.AJAR, + end: States.OPEN, + condition: (ctx) => ctx.degreeOfOpening >= 0, + event: (ctx) => { ctx.degreeOfOpening = 100 } + }, + { + name: "close", + start: States.AJAR, + end: States.CLOSE, + condition: (ctx) => ctx.degreeOfOpening <= 0, + event: (ctx) => { ctx.degreeOfOpening = 0 } + }, + { + name: "ajarPlus", + start: States.AJAR, + end: States.AJAR, + event: (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening + 1 } + }, + { + name: "ajarMinus", + start: States.AJAR, + end: States.AJAR, + event: (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening - 1 } + } + ], + buildDoorFSMContext(), + States.OPEN, + ) + } + + preOpen() { + this.transition("preOpen") + } + + preClose() { + this.transition("preClose") + } + + open() { + this.transition("open") + } + + close() { + this.transition("close") + } + + ajarPlus() { + this.transition("ajarPlus") + } + + ajarMinus() { + this.transition("ajarMinus") + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.ClazzStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.ClazzStateGenerate.verified.txt new file mode 100644 index 0000000..b8bd825 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.ClazzStateGenerate.verified.txt @@ -0,0 +1,49 @@ +import {StaterStateMachine} from "./index.js"; + + +export const States = Object.freeze({ + OPEN: "OPEN", + AJAR: "AJAR", + CLOSE: "CLOSE" +}); + +export class DoorStateMachine extends StaterStateMachine { + constructor() { + super( + [ + { + name: "preOpen", + start: States.CLOSE, + end: States.AJAR + }, + { + name: "preClose", + start: States.OPEN, + end: States.AJAR + }, + { + name: "open", + start: States.AJAR, + end: States.OPEN + }, + { + name: "close", + start: States.AJAR, + end: States.CLOSE + }, + { + name: "ajarPlus", + start: States.AJAR, + end: States.AJAR + }, + { + name: "ajarMinus", + start: States.AJAR, + end: States.AJAR + } + ], + {}, + States.OPEN, + ) + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.ClazzStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.ClazzStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..a5d16b9 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateDoorTests.ClazzStateGenerateWithInterface.verified.txt @@ -0,0 +1,73 @@ +import {StaterStateMachine} from "./index.js"; + + +export const States = Object.freeze({ + OPEN: "OPEN", + AJAR: "AJAR", + CLOSE: "CLOSE" +}); + +export class DoorStateMachine extends StaterStateMachine { + constructor() { + super( + [ + { + name: "preOpen", + start: States.CLOSE, + end: States.AJAR + }, + { + name: "preClose", + start: States.OPEN, + end: States.AJAR + }, + { + name: "open", + start: States.AJAR, + end: States.OPEN + }, + { + name: "close", + start: States.AJAR, + end: States.CLOSE + }, + { + name: "ajarPlus", + start: States.AJAR, + end: States.AJAR + }, + { + name: "ajarMinus", + start: States.AJAR, + end: States.AJAR + } + ], + {}, + States.OPEN, + ) + } + + preOpen() { + this.transition("preOpen") + } + + preClose() { + this.transition("preClose") + } + + open() { + this.transition("open") + } + + close() { + this.transition("close") + } + + ajarPlus() { + this.transition("ajarPlus") + } + + ajarMinus() { + this.transition("ajarMinus") + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.BuilderTestsContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.BuilderTestsContextGenerate.verified.txt new file mode 100644 index 0000000..2712c5c --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.BuilderTestsContextGenerate.verified.txt @@ -0,0 +1,257 @@ +import {builderDoorStateMachine} from "./Door.js"; + + +test('testInit', () => { + builderDoorStateMachine.build() +}) + + + +test('testScenario0', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe("AJAR") + + sm.transition('close') + expect(sm.getState()).toBe("CLOSE") + + sm.transition('preOpen') + expect(sm.getState()).toBe("AJAR") + + sm.transition('ajarPlus') + expect(sm.getState()).toBe("AJAR") + + sm.transition('open') + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario1', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe("AJAR") + + sm.transition('ajarPlus') + expect(sm.getState()).toBe("AJAR") + + sm.transition('close') + expect(sm.getState()).toBe("CLOSE") + + sm.transition('preOpen') + expect(sm.getState()).toBe("AJAR") + + sm.transition('open') + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario2', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe("AJAR") + + sm.transition('close') + expect(sm.getState()).toBe("CLOSE") + + sm.transition('preOpen') + expect(sm.getState()).toBe("AJAR") + + sm.transition('open') + expect(sm.getState()).toBe("OPEN") + +}) + + +test('testJsonSchema', () => { + const sm = builderDoorStateMachine.build() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + + +test('testSystemAppendStateTransition', () => { + let smBuilder = builderDoorStateMachine + + smBuilder = smBuilder.addState('__test_state_1__') + expect(JSON.parse(`{ + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addState('__test_state_2__') + expect(JSON.parse(`{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addTransition('__test_transition__', '__test_state_1__', '__test_state_2__') + expect(JSON.parse(`{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] +}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) +}) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.BuilderTestsContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.BuilderTestsContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..547ac99 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.BuilderTestsContextGenerateWithInterface.verified.txt @@ -0,0 +1,257 @@ +import {builderDoorStateMachine} from "./Door.js"; + + +test('testInit', () => { + builderDoorStateMachine.build() +}) + + + +test('testScenario0', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe("AJAR") + + sm.close() + expect(sm.getState()).toBe("CLOSE") + + sm.preOpen() + expect(sm.getState()).toBe("AJAR") + + sm.ajarPlus() + expect(sm.getState()).toBe("AJAR") + + sm.open() + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario1', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe("AJAR") + + sm.ajarPlus() + expect(sm.getState()).toBe("AJAR") + + sm.close() + expect(sm.getState()).toBe("CLOSE") + + sm.preOpen() + expect(sm.getState()).toBe("AJAR") + + sm.open() + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario2', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe("AJAR") + + sm.close() + expect(sm.getState()).toBe("CLOSE") + + sm.preOpen() + expect(sm.getState()).toBe("AJAR") + + sm.open() + expect(sm.getState()).toBe("OPEN") + +}) + + +test('testJsonSchema', () => { + const sm = builderDoorStateMachine.build() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + + +test('testSystemAppendStateTransition', () => { + let smBuilder = builderDoorStateMachine + + smBuilder = smBuilder.addState('__test_state_1__') + expect(JSON.parse(`{ + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addState('__test_state_2__') + expect(JSON.parse(`{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addTransition('__test_transition__', '__test_state_1__', '__test_state_2__') + expect(JSON.parse(`{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] +}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) +}) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.BuilderTestsGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.BuilderTestsGenerate.verified.txt new file mode 100644 index 0000000..2712c5c --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.BuilderTestsGenerate.verified.txt @@ -0,0 +1,257 @@ +import {builderDoorStateMachine} from "./Door.js"; + + +test('testInit', () => { + builderDoorStateMachine.build() +}) + + + +test('testScenario0', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe("AJAR") + + sm.transition('close') + expect(sm.getState()).toBe("CLOSE") + + sm.transition('preOpen') + expect(sm.getState()).toBe("AJAR") + + sm.transition('ajarPlus') + expect(sm.getState()).toBe("AJAR") + + sm.transition('open') + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario1', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe("AJAR") + + sm.transition('ajarPlus') + expect(sm.getState()).toBe("AJAR") + + sm.transition('close') + expect(sm.getState()).toBe("CLOSE") + + sm.transition('preOpen') + expect(sm.getState()).toBe("AJAR") + + sm.transition('open') + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario2', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe("AJAR") + + sm.transition('close') + expect(sm.getState()).toBe("CLOSE") + + sm.transition('preOpen') + expect(sm.getState()).toBe("AJAR") + + sm.transition('open') + expect(sm.getState()).toBe("OPEN") + +}) + + +test('testJsonSchema', () => { + const sm = builderDoorStateMachine.build() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + + +test('testSystemAppendStateTransition', () => { + let smBuilder = builderDoorStateMachine + + smBuilder = smBuilder.addState('__test_state_1__') + expect(JSON.parse(`{ + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addState('__test_state_2__') + expect(JSON.parse(`{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addTransition('__test_transition__', '__test_state_1__', '__test_state_2__') + expect(JSON.parse(`{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] +}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) +}) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.BuilderTestsGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.BuilderTestsGenerateWithInterface.verified.txt new file mode 100644 index 0000000..547ac99 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.BuilderTestsGenerateWithInterface.verified.txt @@ -0,0 +1,257 @@ +import {builderDoorStateMachine} from "./Door.js"; + + +test('testInit', () => { + builderDoorStateMachine.build() +}) + + + +test('testScenario0', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe("AJAR") + + sm.close() + expect(sm.getState()).toBe("CLOSE") + + sm.preOpen() + expect(sm.getState()).toBe("AJAR") + + sm.ajarPlus() + expect(sm.getState()).toBe("AJAR") + + sm.open() + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario1', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe("AJAR") + + sm.ajarPlus() + expect(sm.getState()).toBe("AJAR") + + sm.close() + expect(sm.getState()).toBe("CLOSE") + + sm.preOpen() + expect(sm.getState()).toBe("AJAR") + + sm.open() + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario2', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe("AJAR") + + sm.close() + expect(sm.getState()).toBe("CLOSE") + + sm.preOpen() + expect(sm.getState()).toBe("AJAR") + + sm.open() + expect(sm.getState()).toBe("OPEN") + +}) + + +test('testJsonSchema', () => { + const sm = builderDoorStateMachine.build() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + + +test('testSystemAppendStateTransition', () => { + let smBuilder = builderDoorStateMachine + + smBuilder = smBuilder.addState('__test_state_1__') + expect(JSON.parse(`{ + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addState('__test_state_2__') + expect(JSON.parse(`{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addTransition('__test_transition__', '__test_state_1__', '__test_state_2__') + expect(JSON.parse(`{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] +}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) +}) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerate.verified.txt new file mode 100644 index 0000000..b82440c --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerate.verified.txt @@ -0,0 +1,118 @@ +import {builderDoorStateMachine} from "./Door.js"; +import {States} from "./Door.js"; + + +test('testInit', () => { + builderDoorStateMachine.build() +}) + + + +test('testScenario0', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('close') + expect(sm.getState()).toBe(States.CLOSE) + + sm.transition('preOpen') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('ajarPlus') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('open') + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario1', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('ajarPlus') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('close') + expect(sm.getState()).toBe(States.CLOSE) + + sm.transition('preOpen') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('open') + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario2', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('close') + expect(sm.getState()).toBe(States.CLOSE) + + sm.transition('preOpen') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('open') + expect(sm.getState()).toBe(States.OPEN) + +}) + + +test('testJsonSchema', () => { + const sm = builderDoorStateMachine.build() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..8079817 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,118 @@ +import {builderDoorStateMachine} from "./Door.js"; +import {States} from "./Door.js"; + + +test('testInit', () => { + builderDoorStateMachine.build() +}) + + + +test('testScenario0', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe(States.AJAR) + + sm.close() + expect(sm.getState()).toBe(States.CLOSE) + + sm.preOpen() + expect(sm.getState()).toBe(States.AJAR) + + sm.ajarPlus() + expect(sm.getState()).toBe(States.AJAR) + + sm.open() + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario1', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe(States.AJAR) + + sm.ajarPlus() + expect(sm.getState()).toBe(States.AJAR) + + sm.close() + expect(sm.getState()).toBe(States.CLOSE) + + sm.preOpen() + expect(sm.getState()).toBe(States.AJAR) + + sm.open() + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario2', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe(States.AJAR) + + sm.close() + expect(sm.getState()).toBe(States.CLOSE) + + sm.preOpen() + expect(sm.getState()).toBe(States.AJAR) + + sm.open() + expect(sm.getState()).toBe(States.OPEN) + +}) + + +test('testJsonSchema', () => { + const sm = builderDoorStateMachine.build() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.BuilderTestsStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.BuilderTestsStateGenerate.verified.txt new file mode 100644 index 0000000..b82440c --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.BuilderTestsStateGenerate.verified.txt @@ -0,0 +1,118 @@ +import {builderDoorStateMachine} from "./Door.js"; +import {States} from "./Door.js"; + + +test('testInit', () => { + builderDoorStateMachine.build() +}) + + + +test('testScenario0', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('close') + expect(sm.getState()).toBe(States.CLOSE) + + sm.transition('preOpen') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('ajarPlus') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('open') + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario1', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('ajarPlus') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('close') + expect(sm.getState()).toBe(States.CLOSE) + + sm.transition('preOpen') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('open') + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario2', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('close') + expect(sm.getState()).toBe(States.CLOSE) + + sm.transition('preOpen') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('open') + expect(sm.getState()).toBe(States.OPEN) + +}) + + +test('testJsonSchema', () => { + const sm = builderDoorStateMachine.build() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.BuilderTestsStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.BuilderTestsStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..8079817 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.BuilderTestsStateGenerateWithInterface.verified.txt @@ -0,0 +1,118 @@ +import {builderDoorStateMachine} from "./Door.js"; +import {States} from "./Door.js"; + + +test('testInit', () => { + builderDoorStateMachine.build() +}) + + + +test('testScenario0', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe(States.AJAR) + + sm.close() + expect(sm.getState()).toBe(States.CLOSE) + + sm.preOpen() + expect(sm.getState()).toBe(States.AJAR) + + sm.ajarPlus() + expect(sm.getState()).toBe(States.AJAR) + + sm.open() + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario1', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe(States.AJAR) + + sm.ajarPlus() + expect(sm.getState()).toBe(States.AJAR) + + sm.close() + expect(sm.getState()).toBe(States.CLOSE) + + sm.preOpen() + expect(sm.getState()).toBe(States.AJAR) + + sm.open() + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario2', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe(States.AJAR) + + sm.close() + expect(sm.getState()).toBe(States.CLOSE) + + sm.preOpen() + expect(sm.getState()).toBe(States.AJAR) + + sm.open() + expect(sm.getState()).toBe(States.OPEN) + +}) + + +test('testJsonSchema', () => { + const sm = builderDoorStateMachine.build() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.ClazzTestsContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.ClazzTestsContextGenerate.verified.txt new file mode 100644 index 0000000..c9364b1 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.ClazzTestsContextGenerate.verified.txt @@ -0,0 +1,117 @@ +import {DoorStateMachine} from "./Door.js"; + + +test('testInit', () => { + new DoorStateMachine() +}) + + + +test('testScenario0', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe("AJAR") + + sm.transition('close') + expect(sm.getState()).toBe("CLOSE") + + sm.transition('preOpen') + expect(sm.getState()).toBe("AJAR") + + sm.transition('ajarPlus') + expect(sm.getState()).toBe("AJAR") + + sm.transition('open') + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario1', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe("AJAR") + + sm.transition('ajarPlus') + expect(sm.getState()).toBe("AJAR") + + sm.transition('close') + expect(sm.getState()).toBe("CLOSE") + + sm.transition('preOpen') + expect(sm.getState()).toBe("AJAR") + + sm.transition('open') + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario2', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe("AJAR") + + sm.transition('close') + expect(sm.getState()).toBe("CLOSE") + + sm.transition('preOpen') + expect(sm.getState()).toBe("AJAR") + + sm.transition('open') + expect(sm.getState()).toBe("OPEN") + +}) + + +test('testJsonSchema', () => { + const sm = new DoorStateMachine() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.ClazzTestsContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.ClazzTestsContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..7c9897e --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.ClazzTestsContextGenerateWithInterface.verified.txt @@ -0,0 +1,117 @@ +import {DoorStateMachine} from "./Door.js"; + + +test('testInit', () => { + new DoorStateMachine() +}) + + + +test('testScenario0', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe("AJAR") + + sm.close() + expect(sm.getState()).toBe("CLOSE") + + sm.preOpen() + expect(sm.getState()).toBe("AJAR") + + sm.ajarPlus() + expect(sm.getState()).toBe("AJAR") + + sm.open() + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario1', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe("AJAR") + + sm.ajarPlus() + expect(sm.getState()).toBe("AJAR") + + sm.close() + expect(sm.getState()).toBe("CLOSE") + + sm.preOpen() + expect(sm.getState()).toBe("AJAR") + + sm.open() + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario2', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe("AJAR") + + sm.close() + expect(sm.getState()).toBe("CLOSE") + + sm.preOpen() + expect(sm.getState()).toBe("AJAR") + + sm.open() + expect(sm.getState()).toBe("OPEN") + +}) + + +test('testJsonSchema', () => { + const sm = new DoorStateMachine() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.ClazzTestsGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.ClazzTestsGenerate.verified.txt new file mode 100644 index 0000000..c9364b1 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.ClazzTestsGenerate.verified.txt @@ -0,0 +1,117 @@ +import {DoorStateMachine} from "./Door.js"; + + +test('testInit', () => { + new DoorStateMachine() +}) + + + +test('testScenario0', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe("AJAR") + + sm.transition('close') + expect(sm.getState()).toBe("CLOSE") + + sm.transition('preOpen') + expect(sm.getState()).toBe("AJAR") + + sm.transition('ajarPlus') + expect(sm.getState()).toBe("AJAR") + + sm.transition('open') + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario1', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe("AJAR") + + sm.transition('ajarPlus') + expect(sm.getState()).toBe("AJAR") + + sm.transition('close') + expect(sm.getState()).toBe("CLOSE") + + sm.transition('preOpen') + expect(sm.getState()).toBe("AJAR") + + sm.transition('open') + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario2', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe("AJAR") + + sm.transition('close') + expect(sm.getState()).toBe("CLOSE") + + sm.transition('preOpen') + expect(sm.getState()).toBe("AJAR") + + sm.transition('open') + expect(sm.getState()).toBe("OPEN") + +}) + + +test('testJsonSchema', () => { + const sm = new DoorStateMachine() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.ClazzTestsGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.ClazzTestsGenerateWithInterface.verified.txt new file mode 100644 index 0000000..7c9897e --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.ClazzTestsGenerateWithInterface.verified.txt @@ -0,0 +1,117 @@ +import {DoorStateMachine} from "./Door.js"; + + +test('testInit', () => { + new DoorStateMachine() +}) + + + +test('testScenario0', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe("AJAR") + + sm.close() + expect(sm.getState()).toBe("CLOSE") + + sm.preOpen() + expect(sm.getState()).toBe("AJAR") + + sm.ajarPlus() + expect(sm.getState()).toBe("AJAR") + + sm.open() + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario1', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe("AJAR") + + sm.ajarPlus() + expect(sm.getState()).toBe("AJAR") + + sm.close() + expect(sm.getState()).toBe("CLOSE") + + sm.preOpen() + expect(sm.getState()).toBe("AJAR") + + sm.open() + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario2', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe("AJAR") + + sm.close() + expect(sm.getState()).toBe("CLOSE") + + sm.preOpen() + expect(sm.getState()).toBe("AJAR") + + sm.open() + expect(sm.getState()).toBe("OPEN") + +}) + + +test('testJsonSchema', () => { + const sm = new DoorStateMachine() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerate.verified.txt new file mode 100644 index 0000000..d1e1405 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerate.verified.txt @@ -0,0 +1,118 @@ +import {DoorStateMachine} from "./Door.js"; +import {States} from "./Door.js"; + + +test('testInit', () => { + new DoorStateMachine() +}) + + + +test('testScenario0', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('close') + expect(sm.getState()).toBe(States.CLOSE) + + sm.transition('preOpen') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('ajarPlus') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('open') + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario1', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('ajarPlus') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('close') + expect(sm.getState()).toBe(States.CLOSE) + + sm.transition('preOpen') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('open') + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario2', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('close') + expect(sm.getState()).toBe(States.CLOSE) + + sm.transition('preOpen') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('open') + expect(sm.getState()).toBe(States.OPEN) + +}) + + +test('testJsonSchema', () => { + const sm = new DoorStateMachine() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..94ac6dd --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,118 @@ +import {DoorStateMachine} from "./Door.js"; +import {States} from "./Door.js"; + + +test('testInit', () => { + new DoorStateMachine() +}) + + + +test('testScenario0', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe(States.AJAR) + + sm.close() + expect(sm.getState()).toBe(States.CLOSE) + + sm.preOpen() + expect(sm.getState()).toBe(States.AJAR) + + sm.ajarPlus() + expect(sm.getState()).toBe(States.AJAR) + + sm.open() + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario1', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe(States.AJAR) + + sm.ajarPlus() + expect(sm.getState()).toBe(States.AJAR) + + sm.close() + expect(sm.getState()).toBe(States.CLOSE) + + sm.preOpen() + expect(sm.getState()).toBe(States.AJAR) + + sm.open() + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario2', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe(States.AJAR) + + sm.close() + expect(sm.getState()).toBe(States.CLOSE) + + sm.preOpen() + expect(sm.getState()).toBe(States.AJAR) + + sm.open() + expect(sm.getState()).toBe(States.OPEN) + +}) + + +test('testJsonSchema', () => { + const sm = new DoorStateMachine() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.ClazzTestsStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.ClazzTestsStateGenerate.verified.txt new file mode 100644 index 0000000..d1e1405 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.ClazzTestsStateGenerate.verified.txt @@ -0,0 +1,118 @@ +import {DoorStateMachine} from "./Door.js"; +import {States} from "./Door.js"; + + +test('testInit', () => { + new DoorStateMachine() +}) + + + +test('testScenario0', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('close') + expect(sm.getState()).toBe(States.CLOSE) + + sm.transition('preOpen') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('ajarPlus') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('open') + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario1', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('ajarPlus') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('close') + expect(sm.getState()).toBe(States.CLOSE) + + sm.transition('preOpen') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('open') + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario2', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('close') + expect(sm.getState()).toBe(States.CLOSE) + + sm.transition('preOpen') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('open') + expect(sm.getState()).toBe(States.OPEN) + +}) + + +test('testJsonSchema', () => { + const sm = new DoorStateMachine() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.ClazzTestsStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.ClazzTestsStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..94ac6dd --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScript/JavaScriptAdapterGenerateTestsDoorTests.ClazzTestsStateGenerateWithInterface.verified.txt @@ -0,0 +1,118 @@ +import {DoorStateMachine} from "./Door.js"; +import {States} from "./Door.js"; + + +test('testInit', () => { + new DoorStateMachine() +}) + + + +test('testScenario0', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe(States.AJAR) + + sm.close() + expect(sm.getState()).toBe(States.CLOSE) + + sm.preOpen() + expect(sm.getState()).toBe(States.AJAR) + + sm.ajarPlus() + expect(sm.getState()).toBe(States.AJAR) + + sm.open() + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario1', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe(States.AJAR) + + sm.ajarPlus() + expect(sm.getState()).toBe(States.AJAR) + + sm.close() + expect(sm.getState()).toBe(States.CLOSE) + + sm.preOpen() + expect(sm.getState()).toBe(States.AJAR) + + sm.open() + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario2', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe(States.AJAR) + + sm.close() + expect(sm.getState()).toBe(States.CLOSE) + + sm.preOpen() + expect(sm.getState()).toBe(States.AJAR) + + sm.open() + expect(sm.getState()).toBe(States.OPEN) + +}) + + +test('testJsonSchema', () => { + const sm = new DoorStateMachine() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScriptAdapterGenerateDoorTests.cs b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScriptAdapterGenerateDoorTests.cs new file mode 100644 index 0000000..f56b5be --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/JavaScriptAdapterGenerateDoorTests.cs @@ -0,0 +1,19 @@ +using Stater.CodeGeneration.Entity; +using Stater.CodeGeneration.LanguageAdapter.Base; +using Stater.CodeGeneration.LanguageAdapter.Java; +using Stater.CodeGeneration.LanguageAdapter.JavaScript; +using Stater.CodeGeneration.LanguageAdapter.Kotlin; + +namespace Stater.CodeGeneration.Tests.LanguageAdapter; + +public class JavaScriptAdapterGenerateDoorTests : BaseTestAdapterGenerateDoorTests +{ + protected override BaseLanguageAdapter Adapter => new JavaScriptAdapter(); + protected override Language Language => Language.JavaScript; +} + +public class JavaScriptAdapterGenerateTestsDoorTests : BaseTestAdapterGenerateTestsDoorTests +{ + protected override BaseLanguageAdapter Adapter => new JavaScriptAdapter(); + protected override Language Language => Language.JavaScript; +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.BuilderContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.BuilderContextGenerate.verified.txt new file mode 100644 index 0000000..5e1aa9b --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.BuilderContextGenerate.verified.txt @@ -0,0 +1,28 @@ +package fsm.door + +import com.stater.statemachine.kotlin.* + +data class DoorFSMContext( + var degreeOfOpening: Int = 0, + var closeVariable: Boolean = true, + var doorName: String = "asd", + var floatVariable: Float = 0f +) : Context + +val builderDoorStateMachine = StaterStateMachineBuilder() + .setStartState("OPEN") + .setContext(DoorFSMContext()) + .addTransition("preOpen", "CLOSE", "AJAR") + .setTransitionEvent("preOpen") { it.degreeOfOpening = 1 } + .addTransition("preClose", "OPEN", "AJAR") + .setTransitionEvent("preClose") { it.degreeOfOpening = 99 } + .addTransition("open", "AJAR", "OPEN") + .setTransitionCondition("open") { it.degreeOfOpening >= 0 } + .setTransitionEvent("open") { it.degreeOfOpening = 100 } + .addTransition("close", "AJAR", "CLOSE") + .setTransitionCondition("close") { it.degreeOfOpening <= 0 } + .setTransitionEvent("close") { it.degreeOfOpening = 0 } + .addTransition("ajarPlus", "AJAR", "AJAR") + .setTransitionEvent("ajarPlus") { it.degreeOfOpening = it.degreeOfOpening + 1 } + .addTransition("ajarMinus", "AJAR", "AJAR") + .setTransitionEvent("ajarMinus") { it.degreeOfOpening = it.degreeOfOpening - 1 } \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.BuilderContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.BuilderContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..af22212 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.BuilderContextGenerateWithInterface.verified.txt @@ -0,0 +1,90 @@ +package fsm.door + +import com.stater.statemachine.kotlin.* + +data class DoorFSMContext( + var degreeOfOpening: Int = 0, + var closeVariable: Boolean = true, + var doorName: String = "asd", + var floatVariable: Float = 0f +) : Context + +class TypesDoorStateMachine( + transitions: List>, + startState: String, + states: Set, + context: DoorFSMContext, + transitionMiddlewares: Map>> = mapOf(), + transitionAllMiddlewares: List> = listOf(), + transitionCallbacks: Map>> = mapOf(), + transitionAllCallbacks: List> = listOf(), + stateCallbacks: Map>> = mapOf(), + stateAllCallbacks: List> = listOf(), + contextJsonAdapter: ContextJsonAdapter? = null, +) : StaterStateMachine( + transitions = transitions, + startState = startState, + states = states, + context = context, + transitionMiddlewares = transitionMiddlewares, + transitionAllMiddlewares = transitionAllMiddlewares, + transitionCallbacks = transitionCallbacks, + transitionAllCallbacks = transitionAllCallbacks, + stateCallbacks = stateCallbacks, + stateAllCallbacks = stateAllCallbacks, + contextJsonAdapter = contextJsonAdapter +) { + fun preOpen() = transition("preOpen") + fun preClose() = transition("preClose") + fun open() = transition("open") + fun close() = transition("close") + fun ajarPlus() = transition("ajarPlus") + fun ajarMinus() = transition("ajarMinus") +} + +private val typedDoorFactory: StateMachineFactory = { + transitionsA, + contextA, + startStateA, + statesA, + transitionMiddlewaresA, + transitionAllMiddlewaresA, + transitionCallbacksA, + transitionAllCallbacksA, + stateCallbacksA, + stateAllCallbacksA, + contextJsonAdapterA, + -> + TypesDoorStateMachine( + transitions = transitionsA, + context = contextA, + startState = startStateA, + states = statesA, + transitionMiddlewares = transitionMiddlewaresA, + transitionAllMiddlewares = transitionAllMiddlewaresA, + transitionCallbacks = transitionCallbacksA, + transitionAllCallbacks = transitionAllCallbacksA, + stateCallbacks = stateCallbacksA, + stateAllCallbacks = stateAllCallbacksA, + contextJsonAdapter = contextJsonAdapterA + ) +} + +val builderDoorStateMachine = StaterStateMachineBuilder() + .setStartState("OPEN") + .setContext(DoorFSMContext()) + .setFactory(typedDoorFactory) + .addTransition("preOpen", "CLOSE", "AJAR") + .setTransitionEvent("preOpen") { it.degreeOfOpening = 1 } + .addTransition("preClose", "OPEN", "AJAR") + .setTransitionEvent("preClose") { it.degreeOfOpening = 99 } + .addTransition("open", "AJAR", "OPEN") + .setTransitionCondition("open") { it.degreeOfOpening >= 0 } + .setTransitionEvent("open") { it.degreeOfOpening = 100 } + .addTransition("close", "AJAR", "CLOSE") + .setTransitionCondition("close") { it.degreeOfOpening <= 0 } + .setTransitionEvent("close") { it.degreeOfOpening = 0 } + .addTransition("ajarPlus", "AJAR", "AJAR") + .setTransitionEvent("ajarPlus") { it.degreeOfOpening = it.degreeOfOpening + 1 } + .addTransition("ajarMinus", "AJAR", "AJAR") + .setTransitionEvent("ajarMinus") { it.degreeOfOpening = it.degreeOfOpening - 1 } \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.BuilderGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.BuilderGenerate.verified.txt new file mode 100644 index 0000000..68b580e --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.BuilderGenerate.verified.txt @@ -0,0 +1,13 @@ +package fsm.door + +import com.stater.statemachine.kotlin.* + +val builderDoorStateMachine = StaterStateMachineBuilder() + .setStartState("OPEN") + .setContext(EmptyContext()) + .addTransition("preOpen", "CLOSE", "AJAR") + .addTransition("preClose", "OPEN", "AJAR") + .addTransition("open", "AJAR", "OPEN") + .addTransition("close", "AJAR", "CLOSE") + .addTransition("ajarPlus", "AJAR", "AJAR") + .addTransition("ajarMinus", "AJAR", "AJAR") \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.BuilderGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.BuilderGenerateWithInterface.verified.txt new file mode 100644 index 0000000..af4a437 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.BuilderGenerateWithInterface.verified.txt @@ -0,0 +1,75 @@ +package fsm.door + +import com.stater.statemachine.kotlin.* + +class TypesDoorStateMachine( + transitions: List>, + startState: String, + states: Set, + context: EmptyContext, + transitionMiddlewares: Map>> = mapOf(), + transitionAllMiddlewares: List> = listOf(), + transitionCallbacks: Map>> = mapOf(), + transitionAllCallbacks: List> = listOf(), + stateCallbacks: Map>> = mapOf(), + stateAllCallbacks: List> = listOf(), + contextJsonAdapter: ContextJsonAdapter? = null, +) : StaterStateMachine( + transitions = transitions, + startState = startState, + states = states, + context = context, + transitionMiddlewares = transitionMiddlewares, + transitionAllMiddlewares = transitionAllMiddlewares, + transitionCallbacks = transitionCallbacks, + transitionAllCallbacks = transitionAllCallbacks, + stateCallbacks = stateCallbacks, + stateAllCallbacks = stateAllCallbacks, + contextJsonAdapter = contextJsonAdapter +) { + fun preOpen() = transition("preOpen") + fun preClose() = transition("preClose") + fun open() = transition("open") + fun close() = transition("close") + fun ajarPlus() = transition("ajarPlus") + fun ajarMinus() = transition("ajarMinus") +} + +private val typedDoorFactory: StateMachineFactory = { + transitionsA, + contextA, + startStateA, + statesA, + transitionMiddlewaresA, + transitionAllMiddlewaresA, + transitionCallbacksA, + transitionAllCallbacksA, + stateCallbacksA, + stateAllCallbacksA, + contextJsonAdapterA, + -> + TypesDoorStateMachine( + transitions = transitionsA, + context = contextA, + startState = startStateA, + states = statesA, + transitionMiddlewares = transitionMiddlewaresA, + transitionAllMiddlewares = transitionAllMiddlewaresA, + transitionCallbacks = transitionCallbacksA, + transitionAllCallbacks = transitionAllCallbacksA, + stateCallbacks = stateCallbacksA, + stateAllCallbacks = stateAllCallbacksA, + contextJsonAdapter = contextJsonAdapterA + ) +} + +val builderDoorStateMachine = StaterStateMachineBuilder() + .setStartState("OPEN") + .setContext(EmptyContext()) + .setFactory(typedDoorFactory) + .addTransition("preOpen", "CLOSE", "AJAR") + .addTransition("preClose", "OPEN", "AJAR") + .addTransition("open", "AJAR", "OPEN") + .addTransition("close", "AJAR", "CLOSE") + .addTransition("ajarPlus", "AJAR", "AJAR") + .addTransition("ajarMinus", "AJAR", "AJAR") \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.BuilderStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.BuilderStateContextGenerate.verified.txt new file mode 100644 index 0000000..503c334 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.BuilderStateContextGenerate.verified.txt @@ -0,0 +1,34 @@ +package fsm.door + +import com.stater.statemachine.kotlin.* + +enum class States { + OPEN, + AJAR, + CLOSE +} + +data class DoorFSMContext( + var degreeOfOpening: Int = 0, + var closeVariable: Boolean = true, + var doorName: String = "asd", + var floatVariable: Float = 0f +) : Context + +val builderDoorStateMachine = StaterStateMachineBuilder() + .setStartState(States.OPEN) + .setContext(DoorFSMContext()) + .addTransition("preOpen", States.CLOSE, States.AJAR) + .setTransitionEvent("preOpen") { it.degreeOfOpening = 1 } + .addTransition("preClose", States.OPEN, States.AJAR) + .setTransitionEvent("preClose") { it.degreeOfOpening = 99 } + .addTransition("open", States.AJAR, States.OPEN) + .setTransitionCondition("open") { it.degreeOfOpening >= 0 } + .setTransitionEvent("open") { it.degreeOfOpening = 100 } + .addTransition("close", States.AJAR, States.CLOSE) + .setTransitionCondition("close") { it.degreeOfOpening <= 0 } + .setTransitionEvent("close") { it.degreeOfOpening = 0 } + .addTransition("ajarPlus", States.AJAR, States.AJAR) + .setTransitionEvent("ajarPlus") { it.degreeOfOpening = it.degreeOfOpening + 1 } + .addTransition("ajarMinus", States.AJAR, States.AJAR) + .setTransitionEvent("ajarMinus") { it.degreeOfOpening = it.degreeOfOpening - 1 } \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.BuilderStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.BuilderStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..ba58150 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.BuilderStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,96 @@ +package fsm.door + +import com.stater.statemachine.kotlin.* + +enum class States { + OPEN, + AJAR, + CLOSE +} + +data class DoorFSMContext( + var degreeOfOpening: Int = 0, + var closeVariable: Boolean = true, + var doorName: String = "asd", + var floatVariable: Float = 0f +) : Context + +class TypesDoorStateMachine( + transitions: List>, + startState: States, + states: Set, + context: DoorFSMContext, + transitionMiddlewares: Map>> = mapOf(), + transitionAllMiddlewares: List> = listOf(), + transitionCallbacks: Map>> = mapOf(), + transitionAllCallbacks: List> = listOf(), + stateCallbacks: Map>> = mapOf(), + stateAllCallbacks: List> = listOf(), + contextJsonAdapter: ContextJsonAdapter? = null, +) : StaterStateMachine( + transitions = transitions, + startState = startState, + states = states, + context = context, + transitionMiddlewares = transitionMiddlewares, + transitionAllMiddlewares = transitionAllMiddlewares, + transitionCallbacks = transitionCallbacks, + transitionAllCallbacks = transitionAllCallbacks, + stateCallbacks = stateCallbacks, + stateAllCallbacks = stateAllCallbacks, + contextJsonAdapter = contextJsonAdapter +) { + fun preOpen() = transition("preOpen") + fun preClose() = transition("preClose") + fun open() = transition("open") + fun close() = transition("close") + fun ajarPlus() = transition("ajarPlus") + fun ajarMinus() = transition("ajarMinus") +} + +private val typedDoorFactory: StateMachineFactory = { + transitionsA, + contextA, + startStateA, + statesA, + transitionMiddlewaresA, + transitionAllMiddlewaresA, + transitionCallbacksA, + transitionAllCallbacksA, + stateCallbacksA, + stateAllCallbacksA, + contextJsonAdapterA, + -> + TypesDoorStateMachine( + transitions = transitionsA, + context = contextA, + startState = startStateA, + states = statesA, + transitionMiddlewares = transitionMiddlewaresA, + transitionAllMiddlewares = transitionAllMiddlewaresA, + transitionCallbacks = transitionCallbacksA, + transitionAllCallbacks = transitionAllCallbacksA, + stateCallbacks = stateCallbacksA, + stateAllCallbacks = stateAllCallbacksA, + contextJsonAdapter = contextJsonAdapterA + ) +} + +val builderDoorStateMachine = StaterStateMachineBuilder() + .setStartState(States.OPEN) + .setContext(DoorFSMContext()) + .setFactory(typedDoorFactory) + .addTransition("preOpen", States.CLOSE, States.AJAR) + .setTransitionEvent("preOpen") { it.degreeOfOpening = 1 } + .addTransition("preClose", States.OPEN, States.AJAR) + .setTransitionEvent("preClose") { it.degreeOfOpening = 99 } + .addTransition("open", States.AJAR, States.OPEN) + .setTransitionCondition("open") { it.degreeOfOpening >= 0 } + .setTransitionEvent("open") { it.degreeOfOpening = 100 } + .addTransition("close", States.AJAR, States.CLOSE) + .setTransitionCondition("close") { it.degreeOfOpening <= 0 } + .setTransitionEvent("close") { it.degreeOfOpening = 0 } + .addTransition("ajarPlus", States.AJAR, States.AJAR) + .setTransitionEvent("ajarPlus") { it.degreeOfOpening = it.degreeOfOpening + 1 } + .addTransition("ajarMinus", States.AJAR, States.AJAR) + .setTransitionEvent("ajarMinus") { it.degreeOfOpening = it.degreeOfOpening - 1 } \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.BuilderStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.BuilderStateGenerate.verified.txt new file mode 100644 index 0000000..e7e94ae --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.BuilderStateGenerate.verified.txt @@ -0,0 +1,19 @@ +package fsm.door + +import com.stater.statemachine.kotlin.* + +enum class States { + OPEN, + AJAR, + CLOSE +} + +val builderDoorStateMachine = StaterStateMachineBuilder() + .setStartState(States.OPEN) + .setContext(EmptyContext()) + .addTransition("preOpen", States.CLOSE, States.AJAR) + .addTransition("preClose", States.OPEN, States.AJAR) + .addTransition("open", States.AJAR, States.OPEN) + .addTransition("close", States.AJAR, States.CLOSE) + .addTransition("ajarPlus", States.AJAR, States.AJAR) + .addTransition("ajarMinus", States.AJAR, States.AJAR) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.BuilderStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.BuilderStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..85b593e --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.BuilderStateGenerateWithInterface.verified.txt @@ -0,0 +1,81 @@ +package fsm.door + +import com.stater.statemachine.kotlin.* + +enum class States { + OPEN, + AJAR, + CLOSE +} + +class TypesDoorStateMachine( + transitions: List>, + startState: States, + states: Set, + context: EmptyContext, + transitionMiddlewares: Map>> = mapOf(), + transitionAllMiddlewares: List> = listOf(), + transitionCallbacks: Map>> = mapOf(), + transitionAllCallbacks: List> = listOf(), + stateCallbacks: Map>> = mapOf(), + stateAllCallbacks: List> = listOf(), + contextJsonAdapter: ContextJsonAdapter? = null, +) : StaterStateMachine( + transitions = transitions, + startState = startState, + states = states, + context = context, + transitionMiddlewares = transitionMiddlewares, + transitionAllMiddlewares = transitionAllMiddlewares, + transitionCallbacks = transitionCallbacks, + transitionAllCallbacks = transitionAllCallbacks, + stateCallbacks = stateCallbacks, + stateAllCallbacks = stateAllCallbacks, + contextJsonAdapter = contextJsonAdapter +) { + fun preOpen() = transition("preOpen") + fun preClose() = transition("preClose") + fun open() = transition("open") + fun close() = transition("close") + fun ajarPlus() = transition("ajarPlus") + fun ajarMinus() = transition("ajarMinus") +} + +private val typedDoorFactory: StateMachineFactory = { + transitionsA, + contextA, + startStateA, + statesA, + transitionMiddlewaresA, + transitionAllMiddlewaresA, + transitionCallbacksA, + transitionAllCallbacksA, + stateCallbacksA, + stateAllCallbacksA, + contextJsonAdapterA, + -> + TypesDoorStateMachine( + transitions = transitionsA, + context = contextA, + startState = startStateA, + states = statesA, + transitionMiddlewares = transitionMiddlewaresA, + transitionAllMiddlewares = transitionAllMiddlewaresA, + transitionCallbacks = transitionCallbacksA, + transitionAllCallbacks = transitionAllCallbacksA, + stateCallbacks = stateCallbacksA, + stateAllCallbacks = stateAllCallbacksA, + contextJsonAdapter = contextJsonAdapterA + ) +} + +val builderDoorStateMachine = StaterStateMachineBuilder() + .setStartState(States.OPEN) + .setContext(EmptyContext()) + .setFactory(typedDoorFactory) + .addTransition("preOpen", States.CLOSE, States.AJAR) + .addTransition("preClose", States.OPEN, States.AJAR) + .addTransition("open", States.AJAR, States.OPEN) + .addTransition("close", States.AJAR, States.CLOSE) + .addTransition("ajarPlus", States.AJAR, States.AJAR) + .addTransition("ajarMinus", States.AJAR, States.AJAR) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.ClazzContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.ClazzContextGenerate.verified.txt new file mode 100644 index 0000000..9ffd260 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.ClazzContextGenerate.verified.txt @@ -0,0 +1,55 @@ +package fsm.door + +import com.stater.statemachine.kotlin.* + +data class DoorFSMContext( + var degreeOfOpening: Int = 0, + var closeVariable: Boolean = true, + var doorName: String = "asd", + var floatVariable: Float = 0f +) : Context + +class DoorStateMachine : StaterStateMachine( + transitions = listOf( + Transition( + name = "preOpen", + start = "CLOSE", + end = "AJAR", + event = { it.degreeOfOpening = 1 } + ), + Transition( + name = "preClose", + start = "OPEN", + end = "AJAR", + event = { it.degreeOfOpening = 99 } + ), + Transition( + name = "open", + start = "AJAR", + end = "OPEN", + condition = { it.degreeOfOpening >= 0 }, + event = { it.degreeOfOpening = 100 } + ), + Transition( + name = "close", + start = "AJAR", + end = "CLOSE", + condition = { it.degreeOfOpening <= 0 }, + event = { it.degreeOfOpening = 0 } + ), + Transition( + name = "ajarPlus", + start = "AJAR", + end = "AJAR", + event = { it.degreeOfOpening = it.degreeOfOpening + 1 } + ), + Transition( + name = "ajarMinus", + start = "AJAR", + end = "AJAR", + event = { it.degreeOfOpening = it.degreeOfOpening - 1 } + ) + ), + startState = "OPEN", + context = DoorFSMContext() +) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.ClazzContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.ClazzContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..3577c6e --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.ClazzContextGenerateWithInterface.verified.txt @@ -0,0 +1,62 @@ +package fsm.door + +import com.stater.statemachine.kotlin.* + +data class DoorFSMContext( + var degreeOfOpening: Int = 0, + var closeVariable: Boolean = true, + var doorName: String = "asd", + var floatVariable: Float = 0f +) : Context + +class DoorStateMachine : StaterStateMachine( + transitions = listOf( + Transition( + name = "preOpen", + start = "CLOSE", + end = "AJAR", + event = { it.degreeOfOpening = 1 } + ), + Transition( + name = "preClose", + start = "OPEN", + end = "AJAR", + event = { it.degreeOfOpening = 99 } + ), + Transition( + name = "open", + start = "AJAR", + end = "OPEN", + condition = { it.degreeOfOpening >= 0 }, + event = { it.degreeOfOpening = 100 } + ), + Transition( + name = "close", + start = "AJAR", + end = "CLOSE", + condition = { it.degreeOfOpening <= 0 }, + event = { it.degreeOfOpening = 0 } + ), + Transition( + name = "ajarPlus", + start = "AJAR", + end = "AJAR", + event = { it.degreeOfOpening = it.degreeOfOpening + 1 } + ), + Transition( + name = "ajarMinus", + start = "AJAR", + end = "AJAR", + event = { it.degreeOfOpening = it.degreeOfOpening - 1 } + ) + ), + startState = "OPEN", + context = DoorFSMContext() +) { + fun preOpen() = transition("preOpen") + fun preClose() = transition("preClose") + fun open() = transition("open") + fun close() = transition("close") + fun ajarPlus() = transition("ajarPlus") + fun ajarMinus() = transition("ajarMinus") +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.ClazzGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.ClazzGenerate.verified.txt new file mode 100644 index 0000000..82db949 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.ClazzGenerate.verified.txt @@ -0,0 +1,40 @@ +package fsm.door + +import com.stater.statemachine.kotlin.* + +class DoorStateMachine : StaterStateMachine( + transitions = listOf( + Transition( + name = "preOpen", + start = "CLOSE", + end = "AJAR" + ), + Transition( + name = "preClose", + start = "OPEN", + end = "AJAR" + ), + Transition( + name = "open", + start = "AJAR", + end = "OPEN" + ), + Transition( + name = "close", + start = "AJAR", + end = "CLOSE" + ), + Transition( + name = "ajarPlus", + start = "AJAR", + end = "AJAR" + ), + Transition( + name = "ajarMinus", + start = "AJAR", + end = "AJAR" + ) + ), + startState = "OPEN", + context = EmptyContext() +) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.ClazzGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.ClazzGenerateWithInterface.verified.txt new file mode 100644 index 0000000..0bbc2b5 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.ClazzGenerateWithInterface.verified.txt @@ -0,0 +1,47 @@ +package fsm.door + +import com.stater.statemachine.kotlin.* + +class DoorStateMachine : StaterStateMachine( + transitions = listOf( + Transition( + name = "preOpen", + start = "CLOSE", + end = "AJAR" + ), + Transition( + name = "preClose", + start = "OPEN", + end = "AJAR" + ), + Transition( + name = "open", + start = "AJAR", + end = "OPEN" + ), + Transition( + name = "close", + start = "AJAR", + end = "CLOSE" + ), + Transition( + name = "ajarPlus", + start = "AJAR", + end = "AJAR" + ), + Transition( + name = "ajarMinus", + start = "AJAR", + end = "AJAR" + ) + ), + startState = "OPEN", + context = EmptyContext() +) { + fun preOpen() = transition("preOpen") + fun preClose() = transition("preClose") + fun open() = transition("open") + fun close() = transition("close") + fun ajarPlus() = transition("ajarPlus") + fun ajarMinus() = transition("ajarMinus") +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.ClazzStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.ClazzStateContextGenerate.verified.txt new file mode 100644 index 0000000..cab20c3 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.ClazzStateContextGenerate.verified.txt @@ -0,0 +1,61 @@ +package fsm.door + +import com.stater.statemachine.kotlin.* + +enum class States { + OPEN, + AJAR, + CLOSE +} + +data class DoorFSMContext( + var degreeOfOpening: Int = 0, + var closeVariable: Boolean = true, + var doorName: String = "asd", + var floatVariable: Float = 0f +) : Context + +class DoorStateMachine : StaterStateMachine( + transitions = listOf( + Transition( + name = "preOpen", + start = States.CLOSE, + end = States.AJAR, + event = { it.degreeOfOpening = 1 } + ), + Transition( + name = "preClose", + start = States.OPEN, + end = States.AJAR, + event = { it.degreeOfOpening = 99 } + ), + Transition( + name = "open", + start = States.AJAR, + end = States.OPEN, + condition = { it.degreeOfOpening >= 0 }, + event = { it.degreeOfOpening = 100 } + ), + Transition( + name = "close", + start = States.AJAR, + end = States.CLOSE, + condition = { it.degreeOfOpening <= 0 }, + event = { it.degreeOfOpening = 0 } + ), + Transition( + name = "ajarPlus", + start = States.AJAR, + end = States.AJAR, + event = { it.degreeOfOpening = it.degreeOfOpening + 1 } + ), + Transition( + name = "ajarMinus", + start = States.AJAR, + end = States.AJAR, + event = { it.degreeOfOpening = it.degreeOfOpening - 1 } + ) + ), + startState = States.OPEN, + context = DoorFSMContext() +) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.ClazzStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.ClazzStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..bf90ee9 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.ClazzStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,68 @@ +package fsm.door + +import com.stater.statemachine.kotlin.* + +enum class States { + OPEN, + AJAR, + CLOSE +} + +data class DoorFSMContext( + var degreeOfOpening: Int = 0, + var closeVariable: Boolean = true, + var doorName: String = "asd", + var floatVariable: Float = 0f +) : Context + +class DoorStateMachine : StaterStateMachine( + transitions = listOf( + Transition( + name = "preOpen", + start = States.CLOSE, + end = States.AJAR, + event = { it.degreeOfOpening = 1 } + ), + Transition( + name = "preClose", + start = States.OPEN, + end = States.AJAR, + event = { it.degreeOfOpening = 99 } + ), + Transition( + name = "open", + start = States.AJAR, + end = States.OPEN, + condition = { it.degreeOfOpening >= 0 }, + event = { it.degreeOfOpening = 100 } + ), + Transition( + name = "close", + start = States.AJAR, + end = States.CLOSE, + condition = { it.degreeOfOpening <= 0 }, + event = { it.degreeOfOpening = 0 } + ), + Transition( + name = "ajarPlus", + start = States.AJAR, + end = States.AJAR, + event = { it.degreeOfOpening = it.degreeOfOpening + 1 } + ), + Transition( + name = "ajarMinus", + start = States.AJAR, + end = States.AJAR, + event = { it.degreeOfOpening = it.degreeOfOpening - 1 } + ) + ), + startState = States.OPEN, + context = DoorFSMContext() +) { + fun preOpen() = transition("preOpen") + fun preClose() = transition("preClose") + fun open() = transition("open") + fun close() = transition("close") + fun ajarPlus() = transition("ajarPlus") + fun ajarMinus() = transition("ajarMinus") +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.ClazzStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.ClazzStateGenerate.verified.txt new file mode 100644 index 0000000..031c53f --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.ClazzStateGenerate.verified.txt @@ -0,0 +1,46 @@ +package fsm.door + +import com.stater.statemachine.kotlin.* + +enum class States { + OPEN, + AJAR, + CLOSE +} + +class DoorStateMachine : StaterStateMachine( + transitions = listOf( + Transition( + name = "preOpen", + start = States.CLOSE, + end = States.AJAR + ), + Transition( + name = "preClose", + start = States.OPEN, + end = States.AJAR + ), + Transition( + name = "open", + start = States.AJAR, + end = States.OPEN + ), + Transition( + name = "close", + start = States.AJAR, + end = States.CLOSE + ), + Transition( + name = "ajarPlus", + start = States.AJAR, + end = States.AJAR + ), + Transition( + name = "ajarMinus", + start = States.AJAR, + end = States.AJAR + ) + ), + startState = States.OPEN, + context = EmptyContext() +) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.ClazzStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.ClazzStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..7840728 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateDoorTests.ClazzStateGenerateWithInterface.verified.txt @@ -0,0 +1,53 @@ +package fsm.door + +import com.stater.statemachine.kotlin.* + +enum class States { + OPEN, + AJAR, + CLOSE +} + +class DoorStateMachine : StaterStateMachine( + transitions = listOf( + Transition( + name = "preOpen", + start = States.CLOSE, + end = States.AJAR + ), + Transition( + name = "preClose", + start = States.OPEN, + end = States.AJAR + ), + Transition( + name = "open", + start = States.AJAR, + end = States.OPEN + ), + Transition( + name = "close", + start = States.AJAR, + end = States.CLOSE + ), + Transition( + name = "ajarPlus", + start = States.AJAR, + end = States.AJAR + ), + Transition( + name = "ajarMinus", + start = States.AJAR, + end = States.AJAR + ) + ), + startState = States.OPEN, + context = EmptyContext() +) { + fun preOpen() = transition("preOpen") + fun preClose() = transition("preClose") + fun open() = transition("open") + fun close() = transition("close") + fun ajarPlus() = transition("ajarPlus") + fun ajarMinus() = transition("ajarMinus") +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.BuilderTestsContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.BuilderTestsContextGenerate.verified.txt new file mode 100644 index 0000000..357f64e --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.BuilderTestsContextGenerate.verified.txt @@ -0,0 +1,265 @@ +package fsm.door; + +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import com.fasterxml.jackson.databind.ObjectMapper + +class TestDoor { + @Test + fun testInit() { + builderDoorStateMachine.build() + } + + + @Test + fun testScenario0() { + val sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition("preClose") + assertEquals(sm.getState(), "AJAR") + + sm.transition("close") + assertEquals(sm.getState(), "CLOSE") + + sm.transition("preOpen") + assertEquals(sm.getState(), "AJAR") + + sm.transition("ajarPlus") + assertEquals(sm.getState(), "AJAR") + + sm.transition("open") + assertEquals(sm.getState(), "OPEN") + + } + @Test + fun testScenario1() { + val sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition("preClose") + assertEquals(sm.getState(), "AJAR") + + sm.transition("ajarPlus") + assertEquals(sm.getState(), "AJAR") + + sm.transition("close") + assertEquals(sm.getState(), "CLOSE") + + sm.transition("preOpen") + assertEquals(sm.getState(), "AJAR") + + sm.transition("open") + assertEquals(sm.getState(), "OPEN") + + } + @Test + fun testScenario2() { + val sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition("preClose") + assertEquals(sm.getState(), "AJAR") + + sm.transition("close") + assertEquals(sm.getState(), "CLOSE") + + sm.transition("preOpen") + assertEquals(sm.getState(), "AJAR") + + sm.transition("open") + assertEquals(sm.getState(), "OPEN") + + } + + @Test + fun testJsonSchema() { + val sm = builderDoorStateMachine.build() + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}"""), ObjectMapper().readTree(sm.toJsonSchema())) + } + + + @Test + fun testSystemAppendStateTransition(){ + var smBuilder = builderDoorStateMachine + + smBuilder = smBuilder.addState("__test_state_1__") + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}"""), ObjectMapper().readTree(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addState("__test_state_2__") + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}"""), ObjectMapper().readTree(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addTransition("__test_transition__", "__test_state_1__", "__test_state_2__") + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] +}"""), ObjectMapper().readTree(smBuilder.build().toJsonSchema())) + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.BuilderTestsContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.BuilderTestsContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..5285b4f --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.BuilderTestsContextGenerateWithInterface.verified.txt @@ -0,0 +1,265 @@ +package fsm.door; + +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import com.fasterxml.jackson.databind.ObjectMapper + +class TestDoor { + @Test + fun testInit() { + builderDoorStateMachine.build() as TypesDoorStateMachine + } + + + @Test + fun testScenario0() { + val sm = builderDoorStateMachine.build() as TypesDoorStateMachine + sm.disableEvents() + + + sm.preClose() + assertEquals(sm.getState(), "AJAR") + + sm.close() + assertEquals(sm.getState(), "CLOSE") + + sm.preOpen() + assertEquals(sm.getState(), "AJAR") + + sm.ajarPlus() + assertEquals(sm.getState(), "AJAR") + + sm.open() + assertEquals(sm.getState(), "OPEN") + + } + @Test + fun testScenario1() { + val sm = builderDoorStateMachine.build() as TypesDoorStateMachine + sm.disableEvents() + + + sm.preClose() + assertEquals(sm.getState(), "AJAR") + + sm.ajarPlus() + assertEquals(sm.getState(), "AJAR") + + sm.close() + assertEquals(sm.getState(), "CLOSE") + + sm.preOpen() + assertEquals(sm.getState(), "AJAR") + + sm.open() + assertEquals(sm.getState(), "OPEN") + + } + @Test + fun testScenario2() { + val sm = builderDoorStateMachine.build() as TypesDoorStateMachine + sm.disableEvents() + + + sm.preClose() + assertEquals(sm.getState(), "AJAR") + + sm.close() + assertEquals(sm.getState(), "CLOSE") + + sm.preOpen() + assertEquals(sm.getState(), "AJAR") + + sm.open() + assertEquals(sm.getState(), "OPEN") + + } + + @Test + fun testJsonSchema() { + val sm = builderDoorStateMachine.build() as TypesDoorStateMachine + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}"""), ObjectMapper().readTree(sm.toJsonSchema())) + } + + + @Test + fun testSystemAppendStateTransition(){ + var smBuilder = builderDoorStateMachine + + smBuilder = smBuilder.addState("__test_state_1__") + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}"""), ObjectMapper().readTree(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addState("__test_state_2__") + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}"""), ObjectMapper().readTree(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addTransition("__test_transition__", "__test_state_1__", "__test_state_2__") + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] +}"""), ObjectMapper().readTree(smBuilder.build().toJsonSchema())) + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.BuilderTestsGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.BuilderTestsGenerate.verified.txt new file mode 100644 index 0000000..357f64e --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.BuilderTestsGenerate.verified.txt @@ -0,0 +1,265 @@ +package fsm.door; + +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import com.fasterxml.jackson.databind.ObjectMapper + +class TestDoor { + @Test + fun testInit() { + builderDoorStateMachine.build() + } + + + @Test + fun testScenario0() { + val sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition("preClose") + assertEquals(sm.getState(), "AJAR") + + sm.transition("close") + assertEquals(sm.getState(), "CLOSE") + + sm.transition("preOpen") + assertEquals(sm.getState(), "AJAR") + + sm.transition("ajarPlus") + assertEquals(sm.getState(), "AJAR") + + sm.transition("open") + assertEquals(sm.getState(), "OPEN") + + } + @Test + fun testScenario1() { + val sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition("preClose") + assertEquals(sm.getState(), "AJAR") + + sm.transition("ajarPlus") + assertEquals(sm.getState(), "AJAR") + + sm.transition("close") + assertEquals(sm.getState(), "CLOSE") + + sm.transition("preOpen") + assertEquals(sm.getState(), "AJAR") + + sm.transition("open") + assertEquals(sm.getState(), "OPEN") + + } + @Test + fun testScenario2() { + val sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition("preClose") + assertEquals(sm.getState(), "AJAR") + + sm.transition("close") + assertEquals(sm.getState(), "CLOSE") + + sm.transition("preOpen") + assertEquals(sm.getState(), "AJAR") + + sm.transition("open") + assertEquals(sm.getState(), "OPEN") + + } + + @Test + fun testJsonSchema() { + val sm = builderDoorStateMachine.build() + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}"""), ObjectMapper().readTree(sm.toJsonSchema())) + } + + + @Test + fun testSystemAppendStateTransition(){ + var smBuilder = builderDoorStateMachine + + smBuilder = smBuilder.addState("__test_state_1__") + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}"""), ObjectMapper().readTree(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addState("__test_state_2__") + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}"""), ObjectMapper().readTree(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addTransition("__test_transition__", "__test_state_1__", "__test_state_2__") + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] +}"""), ObjectMapper().readTree(smBuilder.build().toJsonSchema())) + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.BuilderTestsGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.BuilderTestsGenerateWithInterface.verified.txt new file mode 100644 index 0000000..5285b4f --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.BuilderTestsGenerateWithInterface.verified.txt @@ -0,0 +1,265 @@ +package fsm.door; + +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import com.fasterxml.jackson.databind.ObjectMapper + +class TestDoor { + @Test + fun testInit() { + builderDoorStateMachine.build() as TypesDoorStateMachine + } + + + @Test + fun testScenario0() { + val sm = builderDoorStateMachine.build() as TypesDoorStateMachine + sm.disableEvents() + + + sm.preClose() + assertEquals(sm.getState(), "AJAR") + + sm.close() + assertEquals(sm.getState(), "CLOSE") + + sm.preOpen() + assertEquals(sm.getState(), "AJAR") + + sm.ajarPlus() + assertEquals(sm.getState(), "AJAR") + + sm.open() + assertEquals(sm.getState(), "OPEN") + + } + @Test + fun testScenario1() { + val sm = builderDoorStateMachine.build() as TypesDoorStateMachine + sm.disableEvents() + + + sm.preClose() + assertEquals(sm.getState(), "AJAR") + + sm.ajarPlus() + assertEquals(sm.getState(), "AJAR") + + sm.close() + assertEquals(sm.getState(), "CLOSE") + + sm.preOpen() + assertEquals(sm.getState(), "AJAR") + + sm.open() + assertEquals(sm.getState(), "OPEN") + + } + @Test + fun testScenario2() { + val sm = builderDoorStateMachine.build() as TypesDoorStateMachine + sm.disableEvents() + + + sm.preClose() + assertEquals(sm.getState(), "AJAR") + + sm.close() + assertEquals(sm.getState(), "CLOSE") + + sm.preOpen() + assertEquals(sm.getState(), "AJAR") + + sm.open() + assertEquals(sm.getState(), "OPEN") + + } + + @Test + fun testJsonSchema() { + val sm = builderDoorStateMachine.build() as TypesDoorStateMachine + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}"""), ObjectMapper().readTree(sm.toJsonSchema())) + } + + + @Test + fun testSystemAppendStateTransition(){ + var smBuilder = builderDoorStateMachine + + smBuilder = smBuilder.addState("__test_state_1__") + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}"""), ObjectMapper().readTree(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addState("__test_state_2__") + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}"""), ObjectMapper().readTree(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addTransition("__test_transition__", "__test_state_1__", "__test_state_2__") + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] +}"""), ObjectMapper().readTree(smBuilder.build().toJsonSchema())) + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerate.verified.txt new file mode 100644 index 0000000..a15095f --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerate.verified.txt @@ -0,0 +1,125 @@ +package fsm.door; + +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import com.fasterxml.jackson.databind.ObjectMapper + +class TestDoor { + @Test + fun testInit() { + builderDoorStateMachine.build() + } + + + @Test + fun testScenario0() { + val sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition("preClose") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("close") + assertEquals(sm.getState(), States.CLOSE) + + sm.transition("preOpen") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("ajarPlus") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("open") + assertEquals(sm.getState(), States.OPEN) + + } + @Test + fun testScenario1() { + val sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition("preClose") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("ajarPlus") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("close") + assertEquals(sm.getState(), States.CLOSE) + + sm.transition("preOpen") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("open") + assertEquals(sm.getState(), States.OPEN) + + } + @Test + fun testScenario2() { + val sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition("preClose") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("close") + assertEquals(sm.getState(), States.CLOSE) + + sm.transition("preOpen") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("open") + assertEquals(sm.getState(), States.OPEN) + + } + + @Test + fun testJsonSchema() { + val sm = builderDoorStateMachine.build() + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}"""), ObjectMapper().readTree(sm.toJsonSchema())) + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..3a5c5b2 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,125 @@ +package fsm.door; + +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import com.fasterxml.jackson.databind.ObjectMapper + +class TestDoor { + @Test + fun testInit() { + builderDoorStateMachine.build() as TypesDoorStateMachine + } + + + @Test + fun testScenario0() { + val sm = builderDoorStateMachine.build() as TypesDoorStateMachine + sm.disableEvents() + + + sm.preClose() + assertEquals(sm.getState(), States.AJAR) + + sm.close() + assertEquals(sm.getState(), States.CLOSE) + + sm.preOpen() + assertEquals(sm.getState(), States.AJAR) + + sm.ajarPlus() + assertEquals(sm.getState(), States.AJAR) + + sm.open() + assertEquals(sm.getState(), States.OPEN) + + } + @Test + fun testScenario1() { + val sm = builderDoorStateMachine.build() as TypesDoorStateMachine + sm.disableEvents() + + + sm.preClose() + assertEquals(sm.getState(), States.AJAR) + + sm.ajarPlus() + assertEquals(sm.getState(), States.AJAR) + + sm.close() + assertEquals(sm.getState(), States.CLOSE) + + sm.preOpen() + assertEquals(sm.getState(), States.AJAR) + + sm.open() + assertEquals(sm.getState(), States.OPEN) + + } + @Test + fun testScenario2() { + val sm = builderDoorStateMachine.build() as TypesDoorStateMachine + sm.disableEvents() + + + sm.preClose() + assertEquals(sm.getState(), States.AJAR) + + sm.close() + assertEquals(sm.getState(), States.CLOSE) + + sm.preOpen() + assertEquals(sm.getState(), States.AJAR) + + sm.open() + assertEquals(sm.getState(), States.OPEN) + + } + + @Test + fun testJsonSchema() { + val sm = builderDoorStateMachine.build() as TypesDoorStateMachine + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}"""), ObjectMapper().readTree(sm.toJsonSchema())) + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.BuilderTestsStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.BuilderTestsStateGenerate.verified.txt new file mode 100644 index 0000000..a15095f --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.BuilderTestsStateGenerate.verified.txt @@ -0,0 +1,125 @@ +package fsm.door; + +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import com.fasterxml.jackson.databind.ObjectMapper + +class TestDoor { + @Test + fun testInit() { + builderDoorStateMachine.build() + } + + + @Test + fun testScenario0() { + val sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition("preClose") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("close") + assertEquals(sm.getState(), States.CLOSE) + + sm.transition("preOpen") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("ajarPlus") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("open") + assertEquals(sm.getState(), States.OPEN) + + } + @Test + fun testScenario1() { + val sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition("preClose") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("ajarPlus") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("close") + assertEquals(sm.getState(), States.CLOSE) + + sm.transition("preOpen") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("open") + assertEquals(sm.getState(), States.OPEN) + + } + @Test + fun testScenario2() { + val sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition("preClose") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("close") + assertEquals(sm.getState(), States.CLOSE) + + sm.transition("preOpen") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("open") + assertEquals(sm.getState(), States.OPEN) + + } + + @Test + fun testJsonSchema() { + val sm = builderDoorStateMachine.build() + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}"""), ObjectMapper().readTree(sm.toJsonSchema())) + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.BuilderTestsStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.BuilderTestsStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..3a5c5b2 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.BuilderTestsStateGenerateWithInterface.verified.txt @@ -0,0 +1,125 @@ +package fsm.door; + +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import com.fasterxml.jackson.databind.ObjectMapper + +class TestDoor { + @Test + fun testInit() { + builderDoorStateMachine.build() as TypesDoorStateMachine + } + + + @Test + fun testScenario0() { + val sm = builderDoorStateMachine.build() as TypesDoorStateMachine + sm.disableEvents() + + + sm.preClose() + assertEquals(sm.getState(), States.AJAR) + + sm.close() + assertEquals(sm.getState(), States.CLOSE) + + sm.preOpen() + assertEquals(sm.getState(), States.AJAR) + + sm.ajarPlus() + assertEquals(sm.getState(), States.AJAR) + + sm.open() + assertEquals(sm.getState(), States.OPEN) + + } + @Test + fun testScenario1() { + val sm = builderDoorStateMachine.build() as TypesDoorStateMachine + sm.disableEvents() + + + sm.preClose() + assertEquals(sm.getState(), States.AJAR) + + sm.ajarPlus() + assertEquals(sm.getState(), States.AJAR) + + sm.close() + assertEquals(sm.getState(), States.CLOSE) + + sm.preOpen() + assertEquals(sm.getState(), States.AJAR) + + sm.open() + assertEquals(sm.getState(), States.OPEN) + + } + @Test + fun testScenario2() { + val sm = builderDoorStateMachine.build() as TypesDoorStateMachine + sm.disableEvents() + + + sm.preClose() + assertEquals(sm.getState(), States.AJAR) + + sm.close() + assertEquals(sm.getState(), States.CLOSE) + + sm.preOpen() + assertEquals(sm.getState(), States.AJAR) + + sm.open() + assertEquals(sm.getState(), States.OPEN) + + } + + @Test + fun testJsonSchema() { + val sm = builderDoorStateMachine.build() as TypesDoorStateMachine + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}"""), ObjectMapper().readTree(sm.toJsonSchema())) + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.ClazzTestsContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.ClazzTestsContextGenerate.verified.txt new file mode 100644 index 0000000..b779122 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.ClazzTestsContextGenerate.verified.txt @@ -0,0 +1,125 @@ +package fsm.door; + +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import com.fasterxml.jackson.databind.ObjectMapper + +class TestDoor { + @Test + fun testInit() { + DoorStateMachine() + } + + + @Test + fun testScenario0() { + val sm = DoorStateMachine() + sm.disableEvents() + + + sm.transition("preClose") + assertEquals(sm.getState(), "AJAR") + + sm.transition("close") + assertEquals(sm.getState(), "CLOSE") + + sm.transition("preOpen") + assertEquals(sm.getState(), "AJAR") + + sm.transition("ajarPlus") + assertEquals(sm.getState(), "AJAR") + + sm.transition("open") + assertEquals(sm.getState(), "OPEN") + + } + @Test + fun testScenario1() { + val sm = DoorStateMachine() + sm.disableEvents() + + + sm.transition("preClose") + assertEquals(sm.getState(), "AJAR") + + sm.transition("ajarPlus") + assertEquals(sm.getState(), "AJAR") + + sm.transition("close") + assertEquals(sm.getState(), "CLOSE") + + sm.transition("preOpen") + assertEquals(sm.getState(), "AJAR") + + sm.transition("open") + assertEquals(sm.getState(), "OPEN") + + } + @Test + fun testScenario2() { + val sm = DoorStateMachine() + sm.disableEvents() + + + sm.transition("preClose") + assertEquals(sm.getState(), "AJAR") + + sm.transition("close") + assertEquals(sm.getState(), "CLOSE") + + sm.transition("preOpen") + assertEquals(sm.getState(), "AJAR") + + sm.transition("open") + assertEquals(sm.getState(), "OPEN") + + } + + @Test + fun testJsonSchema() { + val sm = DoorStateMachine() + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}"""), ObjectMapper().readTree(sm.toJsonSchema())) + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.ClazzTestsContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.ClazzTestsContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..2c2922a --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.ClazzTestsContextGenerateWithInterface.verified.txt @@ -0,0 +1,125 @@ +package fsm.door; + +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import com.fasterxml.jackson.databind.ObjectMapper + +class TestDoor { + @Test + fun testInit() { + DoorStateMachine() + } + + + @Test + fun testScenario0() { + val sm = DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + assertEquals(sm.getState(), "AJAR") + + sm.close() + assertEquals(sm.getState(), "CLOSE") + + sm.preOpen() + assertEquals(sm.getState(), "AJAR") + + sm.ajarPlus() + assertEquals(sm.getState(), "AJAR") + + sm.open() + assertEquals(sm.getState(), "OPEN") + + } + @Test + fun testScenario1() { + val sm = DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + assertEquals(sm.getState(), "AJAR") + + sm.ajarPlus() + assertEquals(sm.getState(), "AJAR") + + sm.close() + assertEquals(sm.getState(), "CLOSE") + + sm.preOpen() + assertEquals(sm.getState(), "AJAR") + + sm.open() + assertEquals(sm.getState(), "OPEN") + + } + @Test + fun testScenario2() { + val sm = DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + assertEquals(sm.getState(), "AJAR") + + sm.close() + assertEquals(sm.getState(), "CLOSE") + + sm.preOpen() + assertEquals(sm.getState(), "AJAR") + + sm.open() + assertEquals(sm.getState(), "OPEN") + + } + + @Test + fun testJsonSchema() { + val sm = DoorStateMachine() + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}"""), ObjectMapper().readTree(sm.toJsonSchema())) + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.ClazzTestsGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.ClazzTestsGenerate.verified.txt new file mode 100644 index 0000000..b779122 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.ClazzTestsGenerate.verified.txt @@ -0,0 +1,125 @@ +package fsm.door; + +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import com.fasterxml.jackson.databind.ObjectMapper + +class TestDoor { + @Test + fun testInit() { + DoorStateMachine() + } + + + @Test + fun testScenario0() { + val sm = DoorStateMachine() + sm.disableEvents() + + + sm.transition("preClose") + assertEquals(sm.getState(), "AJAR") + + sm.transition("close") + assertEquals(sm.getState(), "CLOSE") + + sm.transition("preOpen") + assertEquals(sm.getState(), "AJAR") + + sm.transition("ajarPlus") + assertEquals(sm.getState(), "AJAR") + + sm.transition("open") + assertEquals(sm.getState(), "OPEN") + + } + @Test + fun testScenario1() { + val sm = DoorStateMachine() + sm.disableEvents() + + + sm.transition("preClose") + assertEquals(sm.getState(), "AJAR") + + sm.transition("ajarPlus") + assertEquals(sm.getState(), "AJAR") + + sm.transition("close") + assertEquals(sm.getState(), "CLOSE") + + sm.transition("preOpen") + assertEquals(sm.getState(), "AJAR") + + sm.transition("open") + assertEquals(sm.getState(), "OPEN") + + } + @Test + fun testScenario2() { + val sm = DoorStateMachine() + sm.disableEvents() + + + sm.transition("preClose") + assertEquals(sm.getState(), "AJAR") + + sm.transition("close") + assertEquals(sm.getState(), "CLOSE") + + sm.transition("preOpen") + assertEquals(sm.getState(), "AJAR") + + sm.transition("open") + assertEquals(sm.getState(), "OPEN") + + } + + @Test + fun testJsonSchema() { + val sm = DoorStateMachine() + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}"""), ObjectMapper().readTree(sm.toJsonSchema())) + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.ClazzTestsGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.ClazzTestsGenerateWithInterface.verified.txt new file mode 100644 index 0000000..2c2922a --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.ClazzTestsGenerateWithInterface.verified.txt @@ -0,0 +1,125 @@ +package fsm.door; + +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import com.fasterxml.jackson.databind.ObjectMapper + +class TestDoor { + @Test + fun testInit() { + DoorStateMachine() + } + + + @Test + fun testScenario0() { + val sm = DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + assertEquals(sm.getState(), "AJAR") + + sm.close() + assertEquals(sm.getState(), "CLOSE") + + sm.preOpen() + assertEquals(sm.getState(), "AJAR") + + sm.ajarPlus() + assertEquals(sm.getState(), "AJAR") + + sm.open() + assertEquals(sm.getState(), "OPEN") + + } + @Test + fun testScenario1() { + val sm = DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + assertEquals(sm.getState(), "AJAR") + + sm.ajarPlus() + assertEquals(sm.getState(), "AJAR") + + sm.close() + assertEquals(sm.getState(), "CLOSE") + + sm.preOpen() + assertEquals(sm.getState(), "AJAR") + + sm.open() + assertEquals(sm.getState(), "OPEN") + + } + @Test + fun testScenario2() { + val sm = DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + assertEquals(sm.getState(), "AJAR") + + sm.close() + assertEquals(sm.getState(), "CLOSE") + + sm.preOpen() + assertEquals(sm.getState(), "AJAR") + + sm.open() + assertEquals(sm.getState(), "OPEN") + + } + + @Test + fun testJsonSchema() { + val sm = DoorStateMachine() + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}"""), ObjectMapper().readTree(sm.toJsonSchema())) + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerate.verified.txt new file mode 100644 index 0000000..e7234ed --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerate.verified.txt @@ -0,0 +1,125 @@ +package fsm.door; + +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import com.fasterxml.jackson.databind.ObjectMapper + +class TestDoor { + @Test + fun testInit() { + DoorStateMachine() + } + + + @Test + fun testScenario0() { + val sm = DoorStateMachine() + sm.disableEvents() + + + sm.transition("preClose") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("close") + assertEquals(sm.getState(), States.CLOSE) + + sm.transition("preOpen") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("ajarPlus") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("open") + assertEquals(sm.getState(), States.OPEN) + + } + @Test + fun testScenario1() { + val sm = DoorStateMachine() + sm.disableEvents() + + + sm.transition("preClose") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("ajarPlus") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("close") + assertEquals(sm.getState(), States.CLOSE) + + sm.transition("preOpen") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("open") + assertEquals(sm.getState(), States.OPEN) + + } + @Test + fun testScenario2() { + val sm = DoorStateMachine() + sm.disableEvents() + + + sm.transition("preClose") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("close") + assertEquals(sm.getState(), States.CLOSE) + + sm.transition("preOpen") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("open") + assertEquals(sm.getState(), States.OPEN) + + } + + @Test + fun testJsonSchema() { + val sm = DoorStateMachine() + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}"""), ObjectMapper().readTree(sm.toJsonSchema())) + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..2c6252e --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,125 @@ +package fsm.door; + +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import com.fasterxml.jackson.databind.ObjectMapper + +class TestDoor { + @Test + fun testInit() { + DoorStateMachine() + } + + + @Test + fun testScenario0() { + val sm = DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + assertEquals(sm.getState(), States.AJAR) + + sm.close() + assertEquals(sm.getState(), States.CLOSE) + + sm.preOpen() + assertEquals(sm.getState(), States.AJAR) + + sm.ajarPlus() + assertEquals(sm.getState(), States.AJAR) + + sm.open() + assertEquals(sm.getState(), States.OPEN) + + } + @Test + fun testScenario1() { + val sm = DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + assertEquals(sm.getState(), States.AJAR) + + sm.ajarPlus() + assertEquals(sm.getState(), States.AJAR) + + sm.close() + assertEquals(sm.getState(), States.CLOSE) + + sm.preOpen() + assertEquals(sm.getState(), States.AJAR) + + sm.open() + assertEquals(sm.getState(), States.OPEN) + + } + @Test + fun testScenario2() { + val sm = DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + assertEquals(sm.getState(), States.AJAR) + + sm.close() + assertEquals(sm.getState(), States.CLOSE) + + sm.preOpen() + assertEquals(sm.getState(), States.AJAR) + + sm.open() + assertEquals(sm.getState(), States.OPEN) + + } + + @Test + fun testJsonSchema() { + val sm = DoorStateMachine() + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}"""), ObjectMapper().readTree(sm.toJsonSchema())) + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.ClazzTestsStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.ClazzTestsStateGenerate.verified.txt new file mode 100644 index 0000000..e7234ed --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.ClazzTestsStateGenerate.verified.txt @@ -0,0 +1,125 @@ +package fsm.door; + +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import com.fasterxml.jackson.databind.ObjectMapper + +class TestDoor { + @Test + fun testInit() { + DoorStateMachine() + } + + + @Test + fun testScenario0() { + val sm = DoorStateMachine() + sm.disableEvents() + + + sm.transition("preClose") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("close") + assertEquals(sm.getState(), States.CLOSE) + + sm.transition("preOpen") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("ajarPlus") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("open") + assertEquals(sm.getState(), States.OPEN) + + } + @Test + fun testScenario1() { + val sm = DoorStateMachine() + sm.disableEvents() + + + sm.transition("preClose") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("ajarPlus") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("close") + assertEquals(sm.getState(), States.CLOSE) + + sm.transition("preOpen") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("open") + assertEquals(sm.getState(), States.OPEN) + + } + @Test + fun testScenario2() { + val sm = DoorStateMachine() + sm.disableEvents() + + + sm.transition("preClose") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("close") + assertEquals(sm.getState(), States.CLOSE) + + sm.transition("preOpen") + assertEquals(sm.getState(), States.AJAR) + + sm.transition("open") + assertEquals(sm.getState(), States.OPEN) + + } + + @Test + fun testJsonSchema() { + val sm = DoorStateMachine() + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}"""), ObjectMapper().readTree(sm.toJsonSchema())) + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.ClazzTestsStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.ClazzTestsStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..2c6252e --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Kotlin/KotlinAdapterGenerateTestsDoorTests.ClazzTestsStateGenerateWithInterface.verified.txt @@ -0,0 +1,125 @@ +package fsm.door; + +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import com.fasterxml.jackson.databind.ObjectMapper + +class TestDoor { + @Test + fun testInit() { + DoorStateMachine() + } + + + @Test + fun testScenario0() { + val sm = DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + assertEquals(sm.getState(), States.AJAR) + + sm.close() + assertEquals(sm.getState(), States.CLOSE) + + sm.preOpen() + assertEquals(sm.getState(), States.AJAR) + + sm.ajarPlus() + assertEquals(sm.getState(), States.AJAR) + + sm.open() + assertEquals(sm.getState(), States.OPEN) + + } + @Test + fun testScenario1() { + val sm = DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + assertEquals(sm.getState(), States.AJAR) + + sm.ajarPlus() + assertEquals(sm.getState(), States.AJAR) + + sm.close() + assertEquals(sm.getState(), States.CLOSE) + + sm.preOpen() + assertEquals(sm.getState(), States.AJAR) + + sm.open() + assertEquals(sm.getState(), States.OPEN) + + } + @Test + fun testScenario2() { + val sm = DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + assertEquals(sm.getState(), States.AJAR) + + sm.close() + assertEquals(sm.getState(), States.CLOSE) + + sm.preOpen() + assertEquals(sm.getState(), States.AJAR) + + sm.open() + assertEquals(sm.getState(), States.OPEN) + + } + + @Test + fun testJsonSchema() { + val sm = DoorStateMachine() + assertEquals(ObjectMapper().readTree("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}"""), ObjectMapper().readTree(sm.toJsonSchema())) + } + + +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/KotlinAdapterGenerateDoorTests.cs b/src/Stater.CodeGeneration.Tests/LanguageAdapter/KotlinAdapterGenerateDoorTests.cs new file mode 100644 index 0000000..9abda35 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/KotlinAdapterGenerateDoorTests.cs @@ -0,0 +1,17 @@ +using Stater.CodeGeneration.Entity; +using Stater.CodeGeneration.LanguageAdapter.Base; +using Stater.CodeGeneration.LanguageAdapter.Kotlin; + +namespace Stater.CodeGeneration.Tests.LanguageAdapter; + +public class KotlinAdapterGenerateDoorTests : BaseTestAdapterGenerateDoorTests +{ + protected override BaseLanguageAdapter Adapter => new KotlinAdapter(); + protected override Language Language => Language.Kotlin; +} + +public class KotlinAdapterGenerateTestsDoorTests : BaseTestAdapterGenerateTestsDoorTests +{ + protected override BaseLanguageAdapter Adapter => new KotlinAdapter(); + protected override Language Language => Language.Kotlin; +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/ModuleInitializer.cs b/src/Stater.CodeGeneration.Tests/LanguageAdapter/ModuleInitializer.cs new file mode 100644 index 0000000..2b46b10 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/ModuleInitializer.cs @@ -0,0 +1,12 @@ +using System.Runtime.CompilerServices; + +namespace Stater.CodeGeneration.Tests.LanguageAdapter; + +public class ModuleInitializer +{ + [ModuleInitializer] + public static void Init() + { + // VerifierSettings.AutoVerify(); + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.BuilderContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.BuilderContextGenerate.verified.txt new file mode 100644 index 0000000..029c210 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.BuilderContextGenerate.verified.txt @@ -0,0 +1,30 @@ +from pydantic import BaseModel +from stater_state_machine import Context +from stater_state_machine import StaterStateMachineBuilder + + +class DoorFSMContext(BaseModel, Context): + degreeOfOpening: int = 0 + closeVariable: bool = True + doorName: str = "asd" + floatVariable: float = 0 + +builder_Door_state_machine = ( + StaterStateMachineBuilder[str, DoorFSMContext]() + .set_start_state("OPEN") + .set_context(DoorFSMContext()) + .add_transition("preOpen", "CLOSE", "AJAR") + .set_transition_event("preOpen", lambda ctx: setattr(ctx, 'degreeOfOpening', 1)) + .add_transition("preClose", "OPEN", "AJAR") + .set_transition_event("preClose", lambda ctx: setattr(ctx, 'degreeOfOpening', 99)) + .add_transition("open", "AJAR", "OPEN") + .set_transition_condition("open", lambda ctx: ctx.degreeOfOpening >= 0) + .set_transition_event("open", lambda ctx: setattr(ctx, 'degreeOfOpening', 100)) + .add_transition("close", "AJAR", "CLOSE") + .set_transition_condition("close", lambda ctx: ctx.degreeOfOpening <= 0) + .set_transition_event("close", lambda ctx: setattr(ctx, 'degreeOfOpening', 0)) + .add_transition("ajarPlus", "AJAR", "AJAR") + .set_transition_event("ajarPlus", lambda ctx: setattr(ctx, 'degreeOfOpening', ctx.degreeOfOpening + 1)) + .add_transition("ajarMinus", "AJAR", "AJAR") + .set_transition_event("ajarMinus", lambda ctx: setattr(ctx, 'degreeOfOpening', ctx.degreeOfOpening - 1)) +) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.BuilderContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.BuilderContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..6e2adb8 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.BuilderContextGenerateWithInterface.verified.txt @@ -0,0 +1,57 @@ +from pydantic import BaseModel +from stater_state_machine import Context +from stater_state_machine import StaterStateMachine +from stater_state_machine import StaterStateMachineBuilder + + +class DoorFSMContext(BaseModel, Context): + degreeOfOpening: int = 0 + closeVariable: bool = True + doorName: str = "asd" + floatVariable: float = 0 + + +class TypesDoorStateMachine(StaterStateMachine[str, DoorFSMContext]): + def preOpen(self): + self.transition("preOpen") + + def preClose(self): + self.transition("preClose") + + def open(self): + self.transition("open") + + def close(self): + self.transition("close") + + def ajarPlus(self): + self.transition("ajarPlus") + + def ajarMinus(self): + self.transition("ajarMinus") + + +def typed_Door_factory(*args, **kwargs): + return TypesDoorStateMachine(*args, **kwargs) + + +builder_Door_state_machine = ( + StaterStateMachineBuilder[str, DoorFSMContext]() + .set_start_state("OPEN") + .set_context(DoorFSMContext()) + .set_factory(typed_Door_factory) + .add_transition("preOpen", "CLOSE", "AJAR") + .set_transition_event("preOpen", lambda ctx: setattr(ctx, 'degreeOfOpening', 1)) + .add_transition("preClose", "OPEN", "AJAR") + .set_transition_event("preClose", lambda ctx: setattr(ctx, 'degreeOfOpening', 99)) + .add_transition("open", "AJAR", "OPEN") + .set_transition_condition("open", lambda ctx: ctx.degreeOfOpening >= 0) + .set_transition_event("open", lambda ctx: setattr(ctx, 'degreeOfOpening', 100)) + .add_transition("close", "AJAR", "CLOSE") + .set_transition_condition("close", lambda ctx: ctx.degreeOfOpening <= 0) + .set_transition_event("close", lambda ctx: setattr(ctx, 'degreeOfOpening', 0)) + .add_transition("ajarPlus", "AJAR", "AJAR") + .set_transition_event("ajarPlus", lambda ctx: setattr(ctx, 'degreeOfOpening', ctx.degreeOfOpening + 1)) + .add_transition("ajarMinus", "AJAR", "AJAR") + .set_transition_event("ajarMinus", lambda ctx: setattr(ctx, 'degreeOfOpening', ctx.degreeOfOpening - 1)) +) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.BuilderGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.BuilderGenerate.verified.txt new file mode 100644 index 0000000..2e2642d --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.BuilderGenerate.verified.txt @@ -0,0 +1,15 @@ +from stater_state_machine import EmptyContext +from stater_state_machine import StaterStateMachineBuilder + + +builder_Door_state_machine = ( + StaterStateMachineBuilder[str, EmptyContext]() + .set_start_state("OPEN") + .set_context(EmptyContext()) + .add_transition("preOpen", "CLOSE", "AJAR") + .add_transition("preClose", "OPEN", "AJAR") + .add_transition("open", "AJAR", "OPEN") + .add_transition("close", "AJAR", "CLOSE") + .add_transition("ajarPlus", "AJAR", "AJAR") + .add_transition("ajarMinus", "AJAR", "AJAR") +) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.BuilderGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.BuilderGenerateWithInterface.verified.txt new file mode 100644 index 0000000..7f9a38c --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.BuilderGenerateWithInterface.verified.txt @@ -0,0 +1,42 @@ +from stater_state_machine import EmptyContext +from stater_state_machine import StaterStateMachine +from stater_state_machine import StaterStateMachineBuilder + + + +class TypesDoorStateMachine(StaterStateMachine[str, EmptyContext]): + def preOpen(self): + self.transition("preOpen") + + def preClose(self): + self.transition("preClose") + + def open(self): + self.transition("open") + + def close(self): + self.transition("close") + + def ajarPlus(self): + self.transition("ajarPlus") + + def ajarMinus(self): + self.transition("ajarMinus") + + +def typed_Door_factory(*args, **kwargs): + return TypesDoorStateMachine(*args, **kwargs) + + +builder_Door_state_machine = ( + StaterStateMachineBuilder[str, EmptyContext]() + .set_start_state("OPEN") + .set_context(EmptyContext()) + .set_factory(typed_Door_factory) + .add_transition("preOpen", "CLOSE", "AJAR") + .add_transition("preClose", "OPEN", "AJAR") + .add_transition("open", "AJAR", "OPEN") + .add_transition("close", "AJAR", "CLOSE") + .add_transition("ajarPlus", "AJAR", "AJAR") + .add_transition("ajarMinus", "AJAR", "AJAR") +) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.BuilderStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.BuilderStateContextGenerate.verified.txt new file mode 100644 index 0000000..863ea0a --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.BuilderStateContextGenerate.verified.txt @@ -0,0 +1,37 @@ +from enum import Enum +from pydantic import BaseModel +from stater_state_machine import Context +from stater_state_machine import StaterStateMachineBuilder + + +class States(Enum): + OPEN = "OPEN" + AJAR = "AJAR" + CLOSE = "CLOSE" + + +class DoorFSMContext(BaseModel, Context): + degreeOfOpening: int = 0 + closeVariable: bool = True + doorName: str = "asd" + floatVariable: float = 0 + +builder_Door_state_machine = ( + StaterStateMachineBuilder[States, DoorFSMContext]() + .set_start_state(States.OPEN) + .set_context(DoorFSMContext()) + .add_transition("preOpen", States.CLOSE, States.AJAR) + .set_transition_event("preOpen", lambda ctx: setattr(ctx, 'degreeOfOpening', 1)) + .add_transition("preClose", States.OPEN, States.AJAR) + .set_transition_event("preClose", lambda ctx: setattr(ctx, 'degreeOfOpening', 99)) + .add_transition("open", States.AJAR, States.OPEN) + .set_transition_condition("open", lambda ctx: ctx.degreeOfOpening >= 0) + .set_transition_event("open", lambda ctx: setattr(ctx, 'degreeOfOpening', 100)) + .add_transition("close", States.AJAR, States.CLOSE) + .set_transition_condition("close", lambda ctx: ctx.degreeOfOpening <= 0) + .set_transition_event("close", lambda ctx: setattr(ctx, 'degreeOfOpening', 0)) + .add_transition("ajarPlus", States.AJAR, States.AJAR) + .set_transition_event("ajarPlus", lambda ctx: setattr(ctx, 'degreeOfOpening', ctx.degreeOfOpening + 1)) + .add_transition("ajarMinus", States.AJAR, States.AJAR) + .set_transition_event("ajarMinus", lambda ctx: setattr(ctx, 'degreeOfOpening', ctx.degreeOfOpening - 1)) +) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.BuilderStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.BuilderStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..76db2a5 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.BuilderStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,64 @@ +from enum import Enum +from pydantic import BaseModel +from stater_state_machine import Context +from stater_state_machine import StaterStateMachine +from stater_state_machine import StaterStateMachineBuilder + + +class States(Enum): + OPEN = "OPEN" + AJAR = "AJAR" + CLOSE = "CLOSE" + + +class DoorFSMContext(BaseModel, Context): + degreeOfOpening: int = 0 + closeVariable: bool = True + doorName: str = "asd" + floatVariable: float = 0 + + +class TypesDoorStateMachine(StaterStateMachine[States, DoorFSMContext]): + def preOpen(self): + self.transition("preOpen") + + def preClose(self): + self.transition("preClose") + + def open(self): + self.transition("open") + + def close(self): + self.transition("close") + + def ajarPlus(self): + self.transition("ajarPlus") + + def ajarMinus(self): + self.transition("ajarMinus") + + +def typed_Door_factory(*args, **kwargs): + return TypesDoorStateMachine(*args, **kwargs) + + +builder_Door_state_machine = ( + StaterStateMachineBuilder[States, DoorFSMContext]() + .set_start_state(States.OPEN) + .set_context(DoorFSMContext()) + .set_factory(typed_Door_factory) + .add_transition("preOpen", States.CLOSE, States.AJAR) + .set_transition_event("preOpen", lambda ctx: setattr(ctx, 'degreeOfOpening', 1)) + .add_transition("preClose", States.OPEN, States.AJAR) + .set_transition_event("preClose", lambda ctx: setattr(ctx, 'degreeOfOpening', 99)) + .add_transition("open", States.AJAR, States.OPEN) + .set_transition_condition("open", lambda ctx: ctx.degreeOfOpening >= 0) + .set_transition_event("open", lambda ctx: setattr(ctx, 'degreeOfOpening', 100)) + .add_transition("close", States.AJAR, States.CLOSE) + .set_transition_condition("close", lambda ctx: ctx.degreeOfOpening <= 0) + .set_transition_event("close", lambda ctx: setattr(ctx, 'degreeOfOpening', 0)) + .add_transition("ajarPlus", States.AJAR, States.AJAR) + .set_transition_event("ajarPlus", lambda ctx: setattr(ctx, 'degreeOfOpening', ctx.degreeOfOpening + 1)) + .add_transition("ajarMinus", States.AJAR, States.AJAR) + .set_transition_event("ajarMinus", lambda ctx: setattr(ctx, 'degreeOfOpening', ctx.degreeOfOpening - 1)) +) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.BuilderStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.BuilderStateGenerate.verified.txt new file mode 100644 index 0000000..59b2f10 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.BuilderStateGenerate.verified.txt @@ -0,0 +1,22 @@ +from enum import Enum +from stater_state_machine import EmptyContext +from stater_state_machine import StaterStateMachineBuilder + + +class States(Enum): + OPEN = "OPEN" + AJAR = "AJAR" + CLOSE = "CLOSE" + + +builder_Door_state_machine = ( + StaterStateMachineBuilder[States, EmptyContext]() + .set_start_state(States.OPEN) + .set_context(EmptyContext()) + .add_transition("preOpen", States.CLOSE, States.AJAR) + .add_transition("preClose", States.OPEN, States.AJAR) + .add_transition("open", States.AJAR, States.OPEN) + .add_transition("close", States.AJAR, States.CLOSE) + .add_transition("ajarPlus", States.AJAR, States.AJAR) + .add_transition("ajarMinus", States.AJAR, States.AJAR) +) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.BuilderStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.BuilderStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..943c7a9 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.BuilderStateGenerateWithInterface.verified.txt @@ -0,0 +1,49 @@ +from enum import Enum +from stater_state_machine import EmptyContext +from stater_state_machine import StaterStateMachine +from stater_state_machine import StaterStateMachineBuilder + + +class States(Enum): + OPEN = "OPEN" + AJAR = "AJAR" + CLOSE = "CLOSE" + + + +class TypesDoorStateMachine(StaterStateMachine[States, EmptyContext]): + def preOpen(self): + self.transition("preOpen") + + def preClose(self): + self.transition("preClose") + + def open(self): + self.transition("open") + + def close(self): + self.transition("close") + + def ajarPlus(self): + self.transition("ajarPlus") + + def ajarMinus(self): + self.transition("ajarMinus") + + +def typed_Door_factory(*args, **kwargs): + return TypesDoorStateMachine(*args, **kwargs) + + +builder_Door_state_machine = ( + StaterStateMachineBuilder[States, EmptyContext]() + .set_start_state(States.OPEN) + .set_context(EmptyContext()) + .set_factory(typed_Door_factory) + .add_transition("preOpen", States.CLOSE, States.AJAR) + .add_transition("preClose", States.OPEN, States.AJAR) + .add_transition("open", States.AJAR, States.OPEN) + .add_transition("close", States.AJAR, States.CLOSE) + .add_transition("ajarPlus", States.AJAR, States.AJAR) + .add_transition("ajarMinus", States.AJAR, States.AJAR) +) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.ClazzContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.ClazzContextGenerate.verified.txt new file mode 100644 index 0000000..db7dec8 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.ClazzContextGenerate.verified.txt @@ -0,0 +1,58 @@ +from pydantic import BaseModel +from stater_state_machine import Context +from stater_state_machine import StaterStateMachine +from stater_state_machine import Transition + + +class DoorFSMContext(BaseModel, Context): + degreeOfOpening: int = 0 + closeVariable: bool = True + doorName: str = "asd" + floatVariable: float = 0 + +class DoorStateMachine(StaterStateMachine[str, DoorFSMContext]): + def __init__(self): + super().__init__( + transitions=[ + Transition( + name="preOpen", + start="CLOSE", + end="AJAR", + event=lambda ctx: setattr(ctx, 'degreeOfOpening', 1) + ), + Transition( + name="preClose", + start="OPEN", + end="AJAR", + event=lambda ctx: setattr(ctx, 'degreeOfOpening', 99) + ), + Transition( + name="open", + start="AJAR", + end="OPEN", + condition=lambda ctx: ctx.degreeOfOpening >= 0, + event=lambda ctx: setattr(ctx, 'degreeOfOpening', 100) + ), + Transition( + name="close", + start="AJAR", + end="CLOSE", + condition=lambda ctx: ctx.degreeOfOpening <= 0, + event=lambda ctx: setattr(ctx, 'degreeOfOpening', 0) + ), + Transition( + name="ajarPlus", + start="AJAR", + end="AJAR", + event=lambda ctx: setattr(ctx, 'degreeOfOpening', ctx.degreeOfOpening + 1) + ), + Transition( + name="ajarMinus", + start="AJAR", + end="AJAR", + event=lambda ctx: setattr(ctx, 'degreeOfOpening', ctx.degreeOfOpening - 1) + ) + ], + context=DoorFSMContext(), + start_state="OPEN", + ) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.ClazzContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.ClazzContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..f95e90e --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.ClazzContextGenerateWithInterface.verified.txt @@ -0,0 +1,76 @@ +from pydantic import BaseModel +from stater_state_machine import Context +from stater_state_machine import StaterStateMachine +from stater_state_machine import Transition + + +class DoorFSMContext(BaseModel, Context): + degreeOfOpening: int = 0 + closeVariable: bool = True + doorName: str = "asd" + floatVariable: float = 0 + +class DoorStateMachine(StaterStateMachine[str, DoorFSMContext]): + def __init__(self): + super().__init__( + transitions=[ + Transition( + name="preOpen", + start="CLOSE", + end="AJAR", + event=lambda ctx: setattr(ctx, 'degreeOfOpening', 1) + ), + Transition( + name="preClose", + start="OPEN", + end="AJAR", + event=lambda ctx: setattr(ctx, 'degreeOfOpening', 99) + ), + Transition( + name="open", + start="AJAR", + end="OPEN", + condition=lambda ctx: ctx.degreeOfOpening >= 0, + event=lambda ctx: setattr(ctx, 'degreeOfOpening', 100) + ), + Transition( + name="close", + start="AJAR", + end="CLOSE", + condition=lambda ctx: ctx.degreeOfOpening <= 0, + event=lambda ctx: setattr(ctx, 'degreeOfOpening', 0) + ), + Transition( + name="ajarPlus", + start="AJAR", + end="AJAR", + event=lambda ctx: setattr(ctx, 'degreeOfOpening', ctx.degreeOfOpening + 1) + ), + Transition( + name="ajarMinus", + start="AJAR", + end="AJAR", + event=lambda ctx: setattr(ctx, 'degreeOfOpening', ctx.degreeOfOpening - 1) + ) + ], + context=DoorFSMContext(), + start_state="OPEN", + ) + + def preOpen(self): + self.transition("preOpen") + + def preClose(self): + self.transition("preClose") + + def open(self): + self.transition("open") + + def close(self): + self.transition("close") + + def ajarPlus(self): + self.transition("ajarPlus") + + def ajarMinus(self): + self.transition("ajarMinus") \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.ClazzGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.ClazzGenerate.verified.txt new file mode 100644 index 0000000..de546f0 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.ClazzGenerate.verified.txt @@ -0,0 +1,43 @@ +from stater_state_machine import EmptyContext +from stater_state_machine import StaterStateMachine +from stater_state_machine import Transition + + +class DoorStateMachine(StaterStateMachine[str, EmptyContext]): + def __init__(self): + super().__init__( + transitions=[ + Transition( + name="preOpen", + start="CLOSE", + end="AJAR" + ), + Transition( + name="preClose", + start="OPEN", + end="AJAR" + ), + Transition( + name="open", + start="AJAR", + end="OPEN" + ), + Transition( + name="close", + start="AJAR", + end="CLOSE" + ), + Transition( + name="ajarPlus", + start="AJAR", + end="AJAR" + ), + Transition( + name="ajarMinus", + start="AJAR", + end="AJAR" + ) + ], + context=EmptyContext(), + start_state="OPEN", + ) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.ClazzGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.ClazzGenerateWithInterface.verified.txt new file mode 100644 index 0000000..62b6f0f --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.ClazzGenerateWithInterface.verified.txt @@ -0,0 +1,61 @@ +from stater_state_machine import EmptyContext +from stater_state_machine import StaterStateMachine +from stater_state_machine import Transition + + +class DoorStateMachine(StaterStateMachine[str, EmptyContext]): + def __init__(self): + super().__init__( + transitions=[ + Transition( + name="preOpen", + start="CLOSE", + end="AJAR" + ), + Transition( + name="preClose", + start="OPEN", + end="AJAR" + ), + Transition( + name="open", + start="AJAR", + end="OPEN" + ), + Transition( + name="close", + start="AJAR", + end="CLOSE" + ), + Transition( + name="ajarPlus", + start="AJAR", + end="AJAR" + ), + Transition( + name="ajarMinus", + start="AJAR", + end="AJAR" + ) + ], + context=EmptyContext(), + start_state="OPEN", + ) + + def preOpen(self): + self.transition("preOpen") + + def preClose(self): + self.transition("preClose") + + def open(self): + self.transition("open") + + def close(self): + self.transition("close") + + def ajarPlus(self): + self.transition("ajarPlus") + + def ajarMinus(self): + self.transition("ajarMinus") \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.ClazzStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.ClazzStateContextGenerate.verified.txt new file mode 100644 index 0000000..8c0dba5 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.ClazzStateContextGenerate.verified.txt @@ -0,0 +1,65 @@ +from enum import Enum +from pydantic import BaseModel +from stater_state_machine import Context +from stater_state_machine import StaterStateMachine +from stater_state_machine import Transition + + +class States(Enum): + OPEN = "OPEN" + AJAR = "AJAR" + CLOSE = "CLOSE" + + +class DoorFSMContext(BaseModel, Context): + degreeOfOpening: int = 0 + closeVariable: bool = True + doorName: str = "asd" + floatVariable: float = 0 + +class DoorStateMachine(StaterStateMachine[States, DoorFSMContext]): + def __init__(self): + super().__init__( + transitions=[ + Transition( + name="preOpen", + start=States.CLOSE, + end=States.AJAR, + event=lambda ctx: setattr(ctx, 'degreeOfOpening', 1) + ), + Transition( + name="preClose", + start=States.OPEN, + end=States.AJAR, + event=lambda ctx: setattr(ctx, 'degreeOfOpening', 99) + ), + Transition( + name="open", + start=States.AJAR, + end=States.OPEN, + condition=lambda ctx: ctx.degreeOfOpening >= 0, + event=lambda ctx: setattr(ctx, 'degreeOfOpening', 100) + ), + Transition( + name="close", + start=States.AJAR, + end=States.CLOSE, + condition=lambda ctx: ctx.degreeOfOpening <= 0, + event=lambda ctx: setattr(ctx, 'degreeOfOpening', 0) + ), + Transition( + name="ajarPlus", + start=States.AJAR, + end=States.AJAR, + event=lambda ctx: setattr(ctx, 'degreeOfOpening', ctx.degreeOfOpening + 1) + ), + Transition( + name="ajarMinus", + start=States.AJAR, + end=States.AJAR, + event=lambda ctx: setattr(ctx, 'degreeOfOpening', ctx.degreeOfOpening - 1) + ) + ], + context=DoorFSMContext(), + start_state=States.OPEN, + ) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.ClazzStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.ClazzStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..5edb446 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.ClazzStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,83 @@ +from enum import Enum +from pydantic import BaseModel +from stater_state_machine import Context +from stater_state_machine import StaterStateMachine +from stater_state_machine import Transition + + +class States(Enum): + OPEN = "OPEN" + AJAR = "AJAR" + CLOSE = "CLOSE" + + +class DoorFSMContext(BaseModel, Context): + degreeOfOpening: int = 0 + closeVariable: bool = True + doorName: str = "asd" + floatVariable: float = 0 + +class DoorStateMachine(StaterStateMachine[States, DoorFSMContext]): + def __init__(self): + super().__init__( + transitions=[ + Transition( + name="preOpen", + start=States.CLOSE, + end=States.AJAR, + event=lambda ctx: setattr(ctx, 'degreeOfOpening', 1) + ), + Transition( + name="preClose", + start=States.OPEN, + end=States.AJAR, + event=lambda ctx: setattr(ctx, 'degreeOfOpening', 99) + ), + Transition( + name="open", + start=States.AJAR, + end=States.OPEN, + condition=lambda ctx: ctx.degreeOfOpening >= 0, + event=lambda ctx: setattr(ctx, 'degreeOfOpening', 100) + ), + Transition( + name="close", + start=States.AJAR, + end=States.CLOSE, + condition=lambda ctx: ctx.degreeOfOpening <= 0, + event=lambda ctx: setattr(ctx, 'degreeOfOpening', 0) + ), + Transition( + name="ajarPlus", + start=States.AJAR, + end=States.AJAR, + event=lambda ctx: setattr(ctx, 'degreeOfOpening', ctx.degreeOfOpening + 1) + ), + Transition( + name="ajarMinus", + start=States.AJAR, + end=States.AJAR, + event=lambda ctx: setattr(ctx, 'degreeOfOpening', ctx.degreeOfOpening - 1) + ) + ], + context=DoorFSMContext(), + start_state=States.OPEN, + ) + + def preOpen(self): + self.transition("preOpen") + + def preClose(self): + self.transition("preClose") + + def open(self): + self.transition("open") + + def close(self): + self.transition("close") + + def ajarPlus(self): + self.transition("ajarPlus") + + def ajarMinus(self): + self.transition("ajarMinus") \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.ClazzStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.ClazzStateGenerate.verified.txt new file mode 100644 index 0000000..ab4e1e8 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.ClazzStateGenerate.verified.txt @@ -0,0 +1,50 @@ +from enum import Enum +from stater_state_machine import EmptyContext +from stater_state_machine import StaterStateMachine +from stater_state_machine import Transition + + +class States(Enum): + OPEN = "OPEN" + AJAR = "AJAR" + CLOSE = "CLOSE" + + +class DoorStateMachine(StaterStateMachine[States, EmptyContext]): + def __init__(self): + super().__init__( + transitions=[ + Transition( + name="preOpen", + start=States.CLOSE, + end=States.AJAR + ), + Transition( + name="preClose", + start=States.OPEN, + end=States.AJAR + ), + Transition( + name="open", + start=States.AJAR, + end=States.OPEN + ), + Transition( + name="close", + start=States.AJAR, + end=States.CLOSE + ), + Transition( + name="ajarPlus", + start=States.AJAR, + end=States.AJAR + ), + Transition( + name="ajarMinus", + start=States.AJAR, + end=States.AJAR + ) + ], + context=EmptyContext(), + start_state=States.OPEN, + ) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.ClazzStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.ClazzStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..7cccd13 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateDoorTests.ClazzStateGenerateWithInterface.verified.txt @@ -0,0 +1,68 @@ +from enum import Enum +from stater_state_machine import EmptyContext +from stater_state_machine import StaterStateMachine +from stater_state_machine import Transition + + +class States(Enum): + OPEN = "OPEN" + AJAR = "AJAR" + CLOSE = "CLOSE" + + +class DoorStateMachine(StaterStateMachine[States, EmptyContext]): + def __init__(self): + super().__init__( + transitions=[ + Transition( + name="preOpen", + start=States.CLOSE, + end=States.AJAR + ), + Transition( + name="preClose", + start=States.OPEN, + end=States.AJAR + ), + Transition( + name="open", + start=States.AJAR, + end=States.OPEN + ), + Transition( + name="close", + start=States.AJAR, + end=States.CLOSE + ), + Transition( + name="ajarPlus", + start=States.AJAR, + end=States.AJAR + ), + Transition( + name="ajarMinus", + start=States.AJAR, + end=States.AJAR + ) + ], + context=EmptyContext(), + start_state=States.OPEN, + ) + + def preOpen(self): + self.transition("preOpen") + + def preClose(self): + self.transition("preClose") + + def open(self): + self.transition("open") + + def close(self): + self.transition("close") + + def ajarPlus(self): + self.transition("ajarPlus") + + def ajarMinus(self): + self.transition("ajarMinus") \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.BuilderTestsContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.BuilderTestsContextGenerate.verified.txt new file mode 100644 index 0000000..df80b47 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.BuilderTestsContextGenerate.verified.txt @@ -0,0 +1,251 @@ +import json + +from .Door import builder_Door_state_machine + + +def test_init(): + builder_Door_state_machine.build() + + +def test_scenario_0(): + sm = builder_Door_state_machine.build() + sm.disable_events() + + + sm.transition('preClose') + assert sm.get_state() == "AJAR" + + sm.transition('close') + assert sm.get_state() == "CLOSE" + + sm.transition('preOpen') + assert sm.get_state() == "AJAR" + + sm.transition('ajarPlus') + assert sm.get_state() == "AJAR" + + sm.transition('open') + assert sm.get_state() == "OPEN" + + +def test_scenario_1(): + sm = builder_Door_state_machine.build() + sm.disable_events() + + + sm.transition('preClose') + assert sm.get_state() == "AJAR" + + sm.transition('ajarPlus') + assert sm.get_state() == "AJAR" + + sm.transition('close') + assert sm.get_state() == "CLOSE" + + sm.transition('preOpen') + assert sm.get_state() == "AJAR" + + sm.transition('open') + assert sm.get_state() == "OPEN" + + +def test_scenario_2(): + sm = builder_Door_state_machine.build() + sm.disable_events() + + + sm.transition('preClose') + assert sm.get_state() == "AJAR" + + sm.transition('close') + assert sm.get_state() == "CLOSE" + + sm.transition('preOpen') + assert sm.get_state() == "AJAR" + + sm.transition('open') + assert sm.get_state() == "OPEN" + + +def test_json_schema(): + sm = builder_Door_state_machine.build() + assert json.loads("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}""") == json.loads(sm.to_json_schema()) + + +def test_system_append_state_transition(): + sm_builder = builder_Door_state_machine + + sm_builder = sm_builder.add_state('__test_state_1__') + assert json.loads("""{ + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}""") == json.loads(sm_builder.build().to_json_schema()) + + sm_builder = sm_builder.add_state('__test_state_2__') + assert json.loads("""{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}""") == json.loads(sm_builder.build().to_json_schema()) + + sm_builder = sm_builder.add_transition('__test_transition__', '__test_state_1__', '__test_state_2__') + assert json.loads("""{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] +}""") == json.loads(sm_builder.build().to_json_schema()) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.BuilderTestsContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.BuilderTestsContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..8c02cb3 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.BuilderTestsContextGenerateWithInterface.verified.txt @@ -0,0 +1,251 @@ +import json + +from .Door import builder_Door_state_machine + + +def test_init(): + builder_Door_state_machine.build() + + +def test_scenario_0(): + sm = builder_Door_state_machine.build() + sm.disable_events() + + + sm.preClose() + assert sm.get_state() == "AJAR" + + sm.close() + assert sm.get_state() == "CLOSE" + + sm.preOpen() + assert sm.get_state() == "AJAR" + + sm.ajarPlus() + assert sm.get_state() == "AJAR" + + sm.open() + assert sm.get_state() == "OPEN" + + +def test_scenario_1(): + sm = builder_Door_state_machine.build() + sm.disable_events() + + + sm.preClose() + assert sm.get_state() == "AJAR" + + sm.ajarPlus() + assert sm.get_state() == "AJAR" + + sm.close() + assert sm.get_state() == "CLOSE" + + sm.preOpen() + assert sm.get_state() == "AJAR" + + sm.open() + assert sm.get_state() == "OPEN" + + +def test_scenario_2(): + sm = builder_Door_state_machine.build() + sm.disable_events() + + + sm.preClose() + assert sm.get_state() == "AJAR" + + sm.close() + assert sm.get_state() == "CLOSE" + + sm.preOpen() + assert sm.get_state() == "AJAR" + + sm.open() + assert sm.get_state() == "OPEN" + + +def test_json_schema(): + sm = builder_Door_state_machine.build() + assert json.loads("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}""") == json.loads(sm.to_json_schema()) + + +def test_system_append_state_transition(): + sm_builder = builder_Door_state_machine + + sm_builder = sm_builder.add_state('__test_state_1__') + assert json.loads("""{ + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}""") == json.loads(sm_builder.build().to_json_schema()) + + sm_builder = sm_builder.add_state('__test_state_2__') + assert json.loads("""{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}""") == json.loads(sm_builder.build().to_json_schema()) + + sm_builder = sm_builder.add_transition('__test_transition__', '__test_state_1__', '__test_state_2__') + assert json.loads("""{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] +}""") == json.loads(sm_builder.build().to_json_schema()) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.BuilderTestsGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.BuilderTestsGenerate.verified.txt new file mode 100644 index 0000000..df80b47 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.BuilderTestsGenerate.verified.txt @@ -0,0 +1,251 @@ +import json + +from .Door import builder_Door_state_machine + + +def test_init(): + builder_Door_state_machine.build() + + +def test_scenario_0(): + sm = builder_Door_state_machine.build() + sm.disable_events() + + + sm.transition('preClose') + assert sm.get_state() == "AJAR" + + sm.transition('close') + assert sm.get_state() == "CLOSE" + + sm.transition('preOpen') + assert sm.get_state() == "AJAR" + + sm.transition('ajarPlus') + assert sm.get_state() == "AJAR" + + sm.transition('open') + assert sm.get_state() == "OPEN" + + +def test_scenario_1(): + sm = builder_Door_state_machine.build() + sm.disable_events() + + + sm.transition('preClose') + assert sm.get_state() == "AJAR" + + sm.transition('ajarPlus') + assert sm.get_state() == "AJAR" + + sm.transition('close') + assert sm.get_state() == "CLOSE" + + sm.transition('preOpen') + assert sm.get_state() == "AJAR" + + sm.transition('open') + assert sm.get_state() == "OPEN" + + +def test_scenario_2(): + sm = builder_Door_state_machine.build() + sm.disable_events() + + + sm.transition('preClose') + assert sm.get_state() == "AJAR" + + sm.transition('close') + assert sm.get_state() == "CLOSE" + + sm.transition('preOpen') + assert sm.get_state() == "AJAR" + + sm.transition('open') + assert sm.get_state() == "OPEN" + + +def test_json_schema(): + sm = builder_Door_state_machine.build() + assert json.loads("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}""") == json.loads(sm.to_json_schema()) + + +def test_system_append_state_transition(): + sm_builder = builder_Door_state_machine + + sm_builder = sm_builder.add_state('__test_state_1__') + assert json.loads("""{ + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}""") == json.loads(sm_builder.build().to_json_schema()) + + sm_builder = sm_builder.add_state('__test_state_2__') + assert json.loads("""{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}""") == json.loads(sm_builder.build().to_json_schema()) + + sm_builder = sm_builder.add_transition('__test_transition__', '__test_state_1__', '__test_state_2__') + assert json.loads("""{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] +}""") == json.loads(sm_builder.build().to_json_schema()) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.BuilderTestsGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.BuilderTestsGenerateWithInterface.verified.txt new file mode 100644 index 0000000..8c02cb3 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.BuilderTestsGenerateWithInterface.verified.txt @@ -0,0 +1,251 @@ +import json + +from .Door import builder_Door_state_machine + + +def test_init(): + builder_Door_state_machine.build() + + +def test_scenario_0(): + sm = builder_Door_state_machine.build() + sm.disable_events() + + + sm.preClose() + assert sm.get_state() == "AJAR" + + sm.close() + assert sm.get_state() == "CLOSE" + + sm.preOpen() + assert sm.get_state() == "AJAR" + + sm.ajarPlus() + assert sm.get_state() == "AJAR" + + sm.open() + assert sm.get_state() == "OPEN" + + +def test_scenario_1(): + sm = builder_Door_state_machine.build() + sm.disable_events() + + + sm.preClose() + assert sm.get_state() == "AJAR" + + sm.ajarPlus() + assert sm.get_state() == "AJAR" + + sm.close() + assert sm.get_state() == "CLOSE" + + sm.preOpen() + assert sm.get_state() == "AJAR" + + sm.open() + assert sm.get_state() == "OPEN" + + +def test_scenario_2(): + sm = builder_Door_state_machine.build() + sm.disable_events() + + + sm.preClose() + assert sm.get_state() == "AJAR" + + sm.close() + assert sm.get_state() == "CLOSE" + + sm.preOpen() + assert sm.get_state() == "AJAR" + + sm.open() + assert sm.get_state() == "OPEN" + + +def test_json_schema(): + sm = builder_Door_state_machine.build() + assert json.loads("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}""") == json.loads(sm.to_json_schema()) + + +def test_system_append_state_transition(): + sm_builder = builder_Door_state_machine + + sm_builder = sm_builder.add_state('__test_state_1__') + assert json.loads("""{ + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}""") == json.loads(sm_builder.build().to_json_schema()) + + sm_builder = sm_builder.add_state('__test_state_2__') + assert json.loads("""{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}""") == json.loads(sm_builder.build().to_json_schema()) + + sm_builder = sm_builder.add_transition('__test_transition__', '__test_state_1__', '__test_state_2__') + assert json.loads("""{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] +}""") == json.loads(sm_builder.build().to_json_schema()) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerate.verified.txt new file mode 100644 index 0000000..1ea3f75 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerate.verified.txt @@ -0,0 +1,113 @@ +import json + +from .Door import builder_Door_state_machine +from .Door import States + + +def test_init(): + builder_Door_state_machine.build() + + +def test_scenario_0(): + sm = builder_Door_state_machine.build() + sm.disable_events() + + + sm.transition('preClose') + assert sm.get_state() == States.AJAR + + sm.transition('close') + assert sm.get_state() == States.CLOSE + + sm.transition('preOpen') + assert sm.get_state() == States.AJAR + + sm.transition('ajarPlus') + assert sm.get_state() == States.AJAR + + sm.transition('open') + assert sm.get_state() == States.OPEN + + +def test_scenario_1(): + sm = builder_Door_state_machine.build() + sm.disable_events() + + + sm.transition('preClose') + assert sm.get_state() == States.AJAR + + sm.transition('ajarPlus') + assert sm.get_state() == States.AJAR + + sm.transition('close') + assert sm.get_state() == States.CLOSE + + sm.transition('preOpen') + assert sm.get_state() == States.AJAR + + sm.transition('open') + assert sm.get_state() == States.OPEN + + +def test_scenario_2(): + sm = builder_Door_state_machine.build() + sm.disable_events() + + + sm.transition('preClose') + assert sm.get_state() == States.AJAR + + sm.transition('close') + assert sm.get_state() == States.CLOSE + + sm.transition('preOpen') + assert sm.get_state() == States.AJAR + + sm.transition('open') + assert sm.get_state() == States.OPEN + + +def test_json_schema(): + sm = builder_Door_state_machine.build() + assert json.loads("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}""") == json.loads(sm.to_json_schema()) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..5f4e37b --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,113 @@ +import json + +from .Door import builder_Door_state_machine +from .Door import States + + +def test_init(): + builder_Door_state_machine.build() + + +def test_scenario_0(): + sm = builder_Door_state_machine.build() + sm.disable_events() + + + sm.preClose() + assert sm.get_state() == States.AJAR + + sm.close() + assert sm.get_state() == States.CLOSE + + sm.preOpen() + assert sm.get_state() == States.AJAR + + sm.ajarPlus() + assert sm.get_state() == States.AJAR + + sm.open() + assert sm.get_state() == States.OPEN + + +def test_scenario_1(): + sm = builder_Door_state_machine.build() + sm.disable_events() + + + sm.preClose() + assert sm.get_state() == States.AJAR + + sm.ajarPlus() + assert sm.get_state() == States.AJAR + + sm.close() + assert sm.get_state() == States.CLOSE + + sm.preOpen() + assert sm.get_state() == States.AJAR + + sm.open() + assert sm.get_state() == States.OPEN + + +def test_scenario_2(): + sm = builder_Door_state_machine.build() + sm.disable_events() + + + sm.preClose() + assert sm.get_state() == States.AJAR + + sm.close() + assert sm.get_state() == States.CLOSE + + sm.preOpen() + assert sm.get_state() == States.AJAR + + sm.open() + assert sm.get_state() == States.OPEN + + +def test_json_schema(): + sm = builder_Door_state_machine.build() + assert json.loads("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}""") == json.loads(sm.to_json_schema()) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.BuilderTestsStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.BuilderTestsStateGenerate.verified.txt new file mode 100644 index 0000000..1ea3f75 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.BuilderTestsStateGenerate.verified.txt @@ -0,0 +1,113 @@ +import json + +from .Door import builder_Door_state_machine +from .Door import States + + +def test_init(): + builder_Door_state_machine.build() + + +def test_scenario_0(): + sm = builder_Door_state_machine.build() + sm.disable_events() + + + sm.transition('preClose') + assert sm.get_state() == States.AJAR + + sm.transition('close') + assert sm.get_state() == States.CLOSE + + sm.transition('preOpen') + assert sm.get_state() == States.AJAR + + sm.transition('ajarPlus') + assert sm.get_state() == States.AJAR + + sm.transition('open') + assert sm.get_state() == States.OPEN + + +def test_scenario_1(): + sm = builder_Door_state_machine.build() + sm.disable_events() + + + sm.transition('preClose') + assert sm.get_state() == States.AJAR + + sm.transition('ajarPlus') + assert sm.get_state() == States.AJAR + + sm.transition('close') + assert sm.get_state() == States.CLOSE + + sm.transition('preOpen') + assert sm.get_state() == States.AJAR + + sm.transition('open') + assert sm.get_state() == States.OPEN + + +def test_scenario_2(): + sm = builder_Door_state_machine.build() + sm.disable_events() + + + sm.transition('preClose') + assert sm.get_state() == States.AJAR + + sm.transition('close') + assert sm.get_state() == States.CLOSE + + sm.transition('preOpen') + assert sm.get_state() == States.AJAR + + sm.transition('open') + assert sm.get_state() == States.OPEN + + +def test_json_schema(): + sm = builder_Door_state_machine.build() + assert json.loads("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}""") == json.loads(sm.to_json_schema()) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.BuilderTestsStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.BuilderTestsStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..5f4e37b --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.BuilderTestsStateGenerateWithInterface.verified.txt @@ -0,0 +1,113 @@ +import json + +from .Door import builder_Door_state_machine +from .Door import States + + +def test_init(): + builder_Door_state_machine.build() + + +def test_scenario_0(): + sm = builder_Door_state_machine.build() + sm.disable_events() + + + sm.preClose() + assert sm.get_state() == States.AJAR + + sm.close() + assert sm.get_state() == States.CLOSE + + sm.preOpen() + assert sm.get_state() == States.AJAR + + sm.ajarPlus() + assert sm.get_state() == States.AJAR + + sm.open() + assert sm.get_state() == States.OPEN + + +def test_scenario_1(): + sm = builder_Door_state_machine.build() + sm.disable_events() + + + sm.preClose() + assert sm.get_state() == States.AJAR + + sm.ajarPlus() + assert sm.get_state() == States.AJAR + + sm.close() + assert sm.get_state() == States.CLOSE + + sm.preOpen() + assert sm.get_state() == States.AJAR + + sm.open() + assert sm.get_state() == States.OPEN + + +def test_scenario_2(): + sm = builder_Door_state_machine.build() + sm.disable_events() + + + sm.preClose() + assert sm.get_state() == States.AJAR + + sm.close() + assert sm.get_state() == States.CLOSE + + sm.preOpen() + assert sm.get_state() == States.AJAR + + sm.open() + assert sm.get_state() == States.OPEN + + +def test_json_schema(): + sm = builder_Door_state_machine.build() + assert json.loads("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}""") == json.loads(sm.to_json_schema()) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.ClazzTestsContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.ClazzTestsContextGenerate.verified.txt new file mode 100644 index 0000000..9f04d6d --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.ClazzTestsContextGenerate.verified.txt @@ -0,0 +1,112 @@ +import json + +from .Door import DoorStateMachine + + +def test_init(): + DoorStateMachine() + + +def test_scenario_0(): + sm = DoorStateMachine() + sm.disable_events() + + + sm.transition('preClose') + assert sm.get_state() == "AJAR" + + sm.transition('close') + assert sm.get_state() == "CLOSE" + + sm.transition('preOpen') + assert sm.get_state() == "AJAR" + + sm.transition('ajarPlus') + assert sm.get_state() == "AJAR" + + sm.transition('open') + assert sm.get_state() == "OPEN" + + +def test_scenario_1(): + sm = DoorStateMachine() + sm.disable_events() + + + sm.transition('preClose') + assert sm.get_state() == "AJAR" + + sm.transition('ajarPlus') + assert sm.get_state() == "AJAR" + + sm.transition('close') + assert sm.get_state() == "CLOSE" + + sm.transition('preOpen') + assert sm.get_state() == "AJAR" + + sm.transition('open') + assert sm.get_state() == "OPEN" + + +def test_scenario_2(): + sm = DoorStateMachine() + sm.disable_events() + + + sm.transition('preClose') + assert sm.get_state() == "AJAR" + + sm.transition('close') + assert sm.get_state() == "CLOSE" + + sm.transition('preOpen') + assert sm.get_state() == "AJAR" + + sm.transition('open') + assert sm.get_state() == "OPEN" + + +def test_json_schema(): + sm = DoorStateMachine() + assert json.loads("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}""") == json.loads(sm.to_json_schema()) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.ClazzTestsContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.ClazzTestsContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..9b8217f --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.ClazzTestsContextGenerateWithInterface.verified.txt @@ -0,0 +1,112 @@ +import json + +from .Door import DoorStateMachine + + +def test_init(): + DoorStateMachine() + + +def test_scenario_0(): + sm = DoorStateMachine() + sm.disable_events() + + + sm.preClose() + assert sm.get_state() == "AJAR" + + sm.close() + assert sm.get_state() == "CLOSE" + + sm.preOpen() + assert sm.get_state() == "AJAR" + + sm.ajarPlus() + assert sm.get_state() == "AJAR" + + sm.open() + assert sm.get_state() == "OPEN" + + +def test_scenario_1(): + sm = DoorStateMachine() + sm.disable_events() + + + sm.preClose() + assert sm.get_state() == "AJAR" + + sm.ajarPlus() + assert sm.get_state() == "AJAR" + + sm.close() + assert sm.get_state() == "CLOSE" + + sm.preOpen() + assert sm.get_state() == "AJAR" + + sm.open() + assert sm.get_state() == "OPEN" + + +def test_scenario_2(): + sm = DoorStateMachine() + sm.disable_events() + + + sm.preClose() + assert sm.get_state() == "AJAR" + + sm.close() + assert sm.get_state() == "CLOSE" + + sm.preOpen() + assert sm.get_state() == "AJAR" + + sm.open() + assert sm.get_state() == "OPEN" + + +def test_json_schema(): + sm = DoorStateMachine() + assert json.loads("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}""") == json.loads(sm.to_json_schema()) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.ClazzTestsGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.ClazzTestsGenerate.verified.txt new file mode 100644 index 0000000..9f04d6d --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.ClazzTestsGenerate.verified.txt @@ -0,0 +1,112 @@ +import json + +from .Door import DoorStateMachine + + +def test_init(): + DoorStateMachine() + + +def test_scenario_0(): + sm = DoorStateMachine() + sm.disable_events() + + + sm.transition('preClose') + assert sm.get_state() == "AJAR" + + sm.transition('close') + assert sm.get_state() == "CLOSE" + + sm.transition('preOpen') + assert sm.get_state() == "AJAR" + + sm.transition('ajarPlus') + assert sm.get_state() == "AJAR" + + sm.transition('open') + assert sm.get_state() == "OPEN" + + +def test_scenario_1(): + sm = DoorStateMachine() + sm.disable_events() + + + sm.transition('preClose') + assert sm.get_state() == "AJAR" + + sm.transition('ajarPlus') + assert sm.get_state() == "AJAR" + + sm.transition('close') + assert sm.get_state() == "CLOSE" + + sm.transition('preOpen') + assert sm.get_state() == "AJAR" + + sm.transition('open') + assert sm.get_state() == "OPEN" + + +def test_scenario_2(): + sm = DoorStateMachine() + sm.disable_events() + + + sm.transition('preClose') + assert sm.get_state() == "AJAR" + + sm.transition('close') + assert sm.get_state() == "CLOSE" + + sm.transition('preOpen') + assert sm.get_state() == "AJAR" + + sm.transition('open') + assert sm.get_state() == "OPEN" + + +def test_json_schema(): + sm = DoorStateMachine() + assert json.loads("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}""") == json.loads(sm.to_json_schema()) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.ClazzTestsGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.ClazzTestsGenerateWithInterface.verified.txt new file mode 100644 index 0000000..9b8217f --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.ClazzTestsGenerateWithInterface.verified.txt @@ -0,0 +1,112 @@ +import json + +from .Door import DoorStateMachine + + +def test_init(): + DoorStateMachine() + + +def test_scenario_0(): + sm = DoorStateMachine() + sm.disable_events() + + + sm.preClose() + assert sm.get_state() == "AJAR" + + sm.close() + assert sm.get_state() == "CLOSE" + + sm.preOpen() + assert sm.get_state() == "AJAR" + + sm.ajarPlus() + assert sm.get_state() == "AJAR" + + sm.open() + assert sm.get_state() == "OPEN" + + +def test_scenario_1(): + sm = DoorStateMachine() + sm.disable_events() + + + sm.preClose() + assert sm.get_state() == "AJAR" + + sm.ajarPlus() + assert sm.get_state() == "AJAR" + + sm.close() + assert sm.get_state() == "CLOSE" + + sm.preOpen() + assert sm.get_state() == "AJAR" + + sm.open() + assert sm.get_state() == "OPEN" + + +def test_scenario_2(): + sm = DoorStateMachine() + sm.disable_events() + + + sm.preClose() + assert sm.get_state() == "AJAR" + + sm.close() + assert sm.get_state() == "CLOSE" + + sm.preOpen() + assert sm.get_state() == "AJAR" + + sm.open() + assert sm.get_state() == "OPEN" + + +def test_json_schema(): + sm = DoorStateMachine() + assert json.loads("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}""") == json.loads(sm.to_json_schema()) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerate.verified.txt new file mode 100644 index 0000000..d8ae62f --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerate.verified.txt @@ -0,0 +1,113 @@ +import json + +from .Door import DoorStateMachine +from .Door import States + + +def test_init(): + DoorStateMachine() + + +def test_scenario_0(): + sm = DoorStateMachine() + sm.disable_events() + + + sm.transition('preClose') + assert sm.get_state() == States.AJAR + + sm.transition('close') + assert sm.get_state() == States.CLOSE + + sm.transition('preOpen') + assert sm.get_state() == States.AJAR + + sm.transition('ajarPlus') + assert sm.get_state() == States.AJAR + + sm.transition('open') + assert sm.get_state() == States.OPEN + + +def test_scenario_1(): + sm = DoorStateMachine() + sm.disable_events() + + + sm.transition('preClose') + assert sm.get_state() == States.AJAR + + sm.transition('ajarPlus') + assert sm.get_state() == States.AJAR + + sm.transition('close') + assert sm.get_state() == States.CLOSE + + sm.transition('preOpen') + assert sm.get_state() == States.AJAR + + sm.transition('open') + assert sm.get_state() == States.OPEN + + +def test_scenario_2(): + sm = DoorStateMachine() + sm.disable_events() + + + sm.transition('preClose') + assert sm.get_state() == States.AJAR + + sm.transition('close') + assert sm.get_state() == States.CLOSE + + sm.transition('preOpen') + assert sm.get_state() == States.AJAR + + sm.transition('open') + assert sm.get_state() == States.OPEN + + +def test_json_schema(): + sm = DoorStateMachine() + assert json.loads("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}""") == json.loads(sm.to_json_schema()) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..bec93d3 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,113 @@ +import json + +from .Door import DoorStateMachine +from .Door import States + + +def test_init(): + DoorStateMachine() + + +def test_scenario_0(): + sm = DoorStateMachine() + sm.disable_events() + + + sm.preClose() + assert sm.get_state() == States.AJAR + + sm.close() + assert sm.get_state() == States.CLOSE + + sm.preOpen() + assert sm.get_state() == States.AJAR + + sm.ajarPlus() + assert sm.get_state() == States.AJAR + + sm.open() + assert sm.get_state() == States.OPEN + + +def test_scenario_1(): + sm = DoorStateMachine() + sm.disable_events() + + + sm.preClose() + assert sm.get_state() == States.AJAR + + sm.ajarPlus() + assert sm.get_state() == States.AJAR + + sm.close() + assert sm.get_state() == States.CLOSE + + sm.preOpen() + assert sm.get_state() == States.AJAR + + sm.open() + assert sm.get_state() == States.OPEN + + +def test_scenario_2(): + sm = DoorStateMachine() + sm.disable_events() + + + sm.preClose() + assert sm.get_state() == States.AJAR + + sm.close() + assert sm.get_state() == States.CLOSE + + sm.preOpen() + assert sm.get_state() == States.AJAR + + sm.open() + assert sm.get_state() == States.OPEN + + +def test_json_schema(): + sm = DoorStateMachine() + assert json.loads("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}""") == json.loads(sm.to_json_schema()) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.ClazzTestsStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.ClazzTestsStateGenerate.verified.txt new file mode 100644 index 0000000..d8ae62f --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.ClazzTestsStateGenerate.verified.txt @@ -0,0 +1,113 @@ +import json + +from .Door import DoorStateMachine +from .Door import States + + +def test_init(): + DoorStateMachine() + + +def test_scenario_0(): + sm = DoorStateMachine() + sm.disable_events() + + + sm.transition('preClose') + assert sm.get_state() == States.AJAR + + sm.transition('close') + assert sm.get_state() == States.CLOSE + + sm.transition('preOpen') + assert sm.get_state() == States.AJAR + + sm.transition('ajarPlus') + assert sm.get_state() == States.AJAR + + sm.transition('open') + assert sm.get_state() == States.OPEN + + +def test_scenario_1(): + sm = DoorStateMachine() + sm.disable_events() + + + sm.transition('preClose') + assert sm.get_state() == States.AJAR + + sm.transition('ajarPlus') + assert sm.get_state() == States.AJAR + + sm.transition('close') + assert sm.get_state() == States.CLOSE + + sm.transition('preOpen') + assert sm.get_state() == States.AJAR + + sm.transition('open') + assert sm.get_state() == States.OPEN + + +def test_scenario_2(): + sm = DoorStateMachine() + sm.disable_events() + + + sm.transition('preClose') + assert sm.get_state() == States.AJAR + + sm.transition('close') + assert sm.get_state() == States.CLOSE + + sm.transition('preOpen') + assert sm.get_state() == States.AJAR + + sm.transition('open') + assert sm.get_state() == States.OPEN + + +def test_json_schema(): + sm = DoorStateMachine() + assert json.loads("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}""") == json.loads(sm.to_json_schema()) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.ClazzTestsStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.ClazzTestsStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..bec93d3 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/Python3/PythonAdapterGenerateTestsDoorTests.ClazzTestsStateGenerateWithInterface.verified.txt @@ -0,0 +1,113 @@ +import json + +from .Door import DoorStateMachine +from .Door import States + + +def test_init(): + DoorStateMachine() + + +def test_scenario_0(): + sm = DoorStateMachine() + sm.disable_events() + + + sm.preClose() + assert sm.get_state() == States.AJAR + + sm.close() + assert sm.get_state() == States.CLOSE + + sm.preOpen() + assert sm.get_state() == States.AJAR + + sm.ajarPlus() + assert sm.get_state() == States.AJAR + + sm.open() + assert sm.get_state() == States.OPEN + + +def test_scenario_1(): + sm = DoorStateMachine() + sm.disable_events() + + + sm.preClose() + assert sm.get_state() == States.AJAR + + sm.ajarPlus() + assert sm.get_state() == States.AJAR + + sm.close() + assert sm.get_state() == States.CLOSE + + sm.preOpen() + assert sm.get_state() == States.AJAR + + sm.open() + assert sm.get_state() == States.OPEN + + +def test_scenario_2(): + sm = DoorStateMachine() + sm.disable_events() + + + sm.preClose() + assert sm.get_state() == States.AJAR + + sm.close() + assert sm.get_state() == States.CLOSE + + sm.preOpen() + assert sm.get_state() == States.AJAR + + sm.open() + assert sm.get_state() == States.OPEN + + +def test_json_schema(): + sm = DoorStateMachine() + assert json.loads("""{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}""") == json.loads(sm.to_json_schema()) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/PythonAdapterGenerateDoorTests.cs b/src/Stater.CodeGeneration.Tests/LanguageAdapter/PythonAdapterGenerateDoorTests.cs new file mode 100644 index 0000000..5e26ba9 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/PythonAdapterGenerateDoorTests.cs @@ -0,0 +1,17 @@ +using Stater.CodeGeneration.Entity; +using Stater.CodeGeneration.LanguageAdapter.Base; +using Stater.CodeGeneration.LanguageAdapter.Python; + +namespace Stater.CodeGeneration.Tests.LanguageAdapter; + +public class PythonAdapterGenerateDoorTests : BaseTestAdapterGenerateDoorTests +{ + protected override BaseLanguageAdapter Adapter => new PythonAdapter(); + protected override Language Language => Language.Python3; +} + +public class PythonAdapterGenerateTestsDoorTests : BaseTestAdapterGenerateTestsDoorTests +{ + protected override BaseLanguageAdapter Adapter => new PythonAdapter(); + protected override Language Language => Language.Python3; +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.BuilderContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.BuilderContextGenerate.verified.txt new file mode 100644 index 0000000..c3a3fd3 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.BuilderContextGenerate.verified.txt @@ -0,0 +1,37 @@ +import {Context} from "./StaterStateMachine"; +import {StaterStateMachineBuilder} from "./StaterStateMachine"; + +interface DoorFSMContext extends Context { + degreeOfOpening: number + closeVariable: boolean + doorName: string + floatVariable: number +} + +const buildDoorFSMContext: () => DoorFSMContext = () => { + return { + degreeOfOpening: 0, + closeVariable: true, + doorName: "asd", + floatVariable: 0 + } +} + + +export const builderDoorStateMachine = new StaterStateMachineBuilder() + .setStartState("OPEN") + .setContext(buildDoorFSMContext()) + .addTransition("preOpen", "CLOSE", "AJAR") + .setTransitionEvent("preOpen", (ctx) => { ctx.degreeOfOpening = 1 }) + .addTransition("preClose", "OPEN", "AJAR") + .setTransitionEvent("preClose", (ctx) => { ctx.degreeOfOpening = 99 }) + .addTransition("open", "AJAR", "OPEN") + .setTransitionCondition("open", (ctx) => ctx.degreeOfOpening >= 0) + .setTransitionEvent("open", (ctx) => { ctx.degreeOfOpening = 100 }) + .addTransition("close", "AJAR", "CLOSE") + .setTransitionCondition("close", (ctx) => ctx.degreeOfOpening <= 0) + .setTransitionEvent("close", (ctx) => { ctx.degreeOfOpening = 0 }) + .addTransition("ajarPlus", "AJAR", "AJAR") + .setTransitionEvent("ajarPlus", (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening + 1 }) + .addTransition("ajarMinus", "AJAR", "AJAR") + .setTransitionEvent("ajarMinus", (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening - 1 }) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.BuilderContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.BuilderContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..1cee7c3 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.BuilderContextGenerateWithInterface.verified.txt @@ -0,0 +1,70 @@ +import {Context} from "./StaterStateMachine"; +import {StateMachineFactory} from "./StaterStateMachine"; +import {StaterStateMachine} from "./StaterStateMachine"; +import {StaterStateMachineBuilder} from "./StaterStateMachine"; + +interface DoorFSMContext extends Context { + degreeOfOpening: number + closeVariable: boolean + doorName: string + floatVariable: number +} + +const buildDoorFSMContext: () => DoorFSMContext = () => { + return { + degreeOfOpening: 0, + closeVariable: true, + doorName: "asd", + floatVariable: 0 + } +} + + +export class TypesDoorStateMachine extends StaterStateMachine { + preOpen() { + this.transition("preOpen") + } + + preClose() { + this.transition("preClose") + } + + open() { + this.transition("open") + } + + close() { + this.transition("close") + } + + ajarPlus() { + this.transition("ajarPlus") + } + + ajarMinus() { + this.transition("ajarMinus") + } +} + +const typedDoorFactory: StateMachineFactory = (...args): StaterStateMachine => { + return new TypesDoorStateMachine(...args); +}; + +export const builderDoorStateMachine = new StaterStateMachineBuilder() + .setStartState("OPEN") + .setContext(buildDoorFSMContext()) + .setFactory(typedDoorFactory) + .addTransition("preOpen", "CLOSE", "AJAR") + .setTransitionEvent("preOpen", (ctx) => { ctx.degreeOfOpening = 1 }) + .addTransition("preClose", "OPEN", "AJAR") + .setTransitionEvent("preClose", (ctx) => { ctx.degreeOfOpening = 99 }) + .addTransition("open", "AJAR", "OPEN") + .setTransitionCondition("open", (ctx) => ctx.degreeOfOpening >= 0) + .setTransitionEvent("open", (ctx) => { ctx.degreeOfOpening = 100 }) + .addTransition("close", "AJAR", "CLOSE") + .setTransitionCondition("close", (ctx) => ctx.degreeOfOpening <= 0) + .setTransitionEvent("close", (ctx) => { ctx.degreeOfOpening = 0 }) + .addTransition("ajarPlus", "AJAR", "AJAR") + .setTransitionEvent("ajarPlus", (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening + 1 }) + .addTransition("ajarMinus", "AJAR", "AJAR") + .setTransitionEvent("ajarMinus", (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening - 1 }) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.BuilderGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.BuilderGenerate.verified.txt new file mode 100644 index 0000000..28b7a2d --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.BuilderGenerate.verified.txt @@ -0,0 +1,12 @@ +import {EmptyContext} from "./StaterStateMachine"; +import {StaterStateMachineBuilder} from "./StaterStateMachine"; + +export const builderDoorStateMachine = new StaterStateMachineBuilder() + .setStartState("OPEN") + .setContext(new EmptyContext()) + .addTransition("preOpen", "CLOSE", "AJAR") + .addTransition("preClose", "OPEN", "AJAR") + .addTransition("open", "AJAR", "OPEN") + .addTransition("close", "AJAR", "CLOSE") + .addTransition("ajarPlus", "AJAR", "AJAR") + .addTransition("ajarMinus", "AJAR", "AJAR") \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.BuilderGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.BuilderGenerateWithInterface.verified.txt new file mode 100644 index 0000000..efd53ad --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.BuilderGenerateWithInterface.verified.txt @@ -0,0 +1,45 @@ +import {EmptyContext} from "./StaterStateMachine"; +import {StateMachineFactory} from "./StaterStateMachine"; +import {StaterStateMachine} from "./StaterStateMachine"; +import {StaterStateMachineBuilder} from "./StaterStateMachine"; + +export class TypesDoorStateMachine extends StaterStateMachine { + preOpen() { + this.transition("preOpen") + } + + preClose() { + this.transition("preClose") + } + + open() { + this.transition("open") + } + + close() { + this.transition("close") + } + + ajarPlus() { + this.transition("ajarPlus") + } + + ajarMinus() { + this.transition("ajarMinus") + } +} + +const typedDoorFactory: StateMachineFactory = (...args): StaterStateMachine => { + return new TypesDoorStateMachine(...args); +}; + +export const builderDoorStateMachine = new StaterStateMachineBuilder() + .setStartState("OPEN") + .setContext(new EmptyContext()) + .setFactory(typedDoorFactory) + .addTransition("preOpen", "CLOSE", "AJAR") + .addTransition("preClose", "OPEN", "AJAR") + .addTransition("open", "AJAR", "OPEN") + .addTransition("close", "AJAR", "CLOSE") + .addTransition("ajarPlus", "AJAR", "AJAR") + .addTransition("ajarMinus", "AJAR", "AJAR") \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.BuilderStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.BuilderStateContextGenerate.verified.txt new file mode 100644 index 0000000..759409e --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.BuilderStateContextGenerate.verified.txt @@ -0,0 +1,43 @@ +import {Context} from "./StaterStateMachine"; +import {StaterStateMachineBuilder} from "./StaterStateMachine"; + +export enum States { + OPEN = "OPEN", + AJAR = "AJAR", + CLOSE = "CLOSE" +} + +interface DoorFSMContext extends Context { + degreeOfOpening: number + closeVariable: boolean + doorName: string + floatVariable: number +} + +const buildDoorFSMContext: () => DoorFSMContext = () => { + return { + degreeOfOpening: 0, + closeVariable: true, + doorName: "asd", + floatVariable: 0 + } +} + + +export const builderDoorStateMachine = new StaterStateMachineBuilder() + .setStartState(States.OPEN) + .setContext(buildDoorFSMContext()) + .addTransition("preOpen", States.CLOSE, States.AJAR) + .setTransitionEvent("preOpen", (ctx) => { ctx.degreeOfOpening = 1 }) + .addTransition("preClose", States.OPEN, States.AJAR) + .setTransitionEvent("preClose", (ctx) => { ctx.degreeOfOpening = 99 }) + .addTransition("open", States.AJAR, States.OPEN) + .setTransitionCondition("open", (ctx) => ctx.degreeOfOpening >= 0) + .setTransitionEvent("open", (ctx) => { ctx.degreeOfOpening = 100 }) + .addTransition("close", States.AJAR, States.CLOSE) + .setTransitionCondition("close", (ctx) => ctx.degreeOfOpening <= 0) + .setTransitionEvent("close", (ctx) => { ctx.degreeOfOpening = 0 }) + .addTransition("ajarPlus", States.AJAR, States.AJAR) + .setTransitionEvent("ajarPlus", (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening + 1 }) + .addTransition("ajarMinus", States.AJAR, States.AJAR) + .setTransitionEvent("ajarMinus", (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening - 1 }) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.BuilderStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.BuilderStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..adfa16c --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.BuilderStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,76 @@ +import {Context} from "./StaterStateMachine"; +import {StateMachineFactory} from "./StaterStateMachine"; +import {StaterStateMachine} from "./StaterStateMachine"; +import {StaterStateMachineBuilder} from "./StaterStateMachine"; + +export enum States { + OPEN = "OPEN", + AJAR = "AJAR", + CLOSE = "CLOSE" +} + +interface DoorFSMContext extends Context { + degreeOfOpening: number + closeVariable: boolean + doorName: string + floatVariable: number +} + +const buildDoorFSMContext: () => DoorFSMContext = () => { + return { + degreeOfOpening: 0, + closeVariable: true, + doorName: "asd", + floatVariable: 0 + } +} + + +export class TypesDoorStateMachine extends StaterStateMachine { + preOpen() { + this.transition("preOpen") + } + + preClose() { + this.transition("preClose") + } + + open() { + this.transition("open") + } + + close() { + this.transition("close") + } + + ajarPlus() { + this.transition("ajarPlus") + } + + ajarMinus() { + this.transition("ajarMinus") + } +} + +const typedDoorFactory: StateMachineFactory = (...args): StaterStateMachine => { + return new TypesDoorStateMachine(...args); +}; + +export const builderDoorStateMachine = new StaterStateMachineBuilder() + .setStartState(States.OPEN) + .setContext(buildDoorFSMContext()) + .setFactory(typedDoorFactory) + .addTransition("preOpen", States.CLOSE, States.AJAR) + .setTransitionEvent("preOpen", (ctx) => { ctx.degreeOfOpening = 1 }) + .addTransition("preClose", States.OPEN, States.AJAR) + .setTransitionEvent("preClose", (ctx) => { ctx.degreeOfOpening = 99 }) + .addTransition("open", States.AJAR, States.OPEN) + .setTransitionCondition("open", (ctx) => ctx.degreeOfOpening >= 0) + .setTransitionEvent("open", (ctx) => { ctx.degreeOfOpening = 100 }) + .addTransition("close", States.AJAR, States.CLOSE) + .setTransitionCondition("close", (ctx) => ctx.degreeOfOpening <= 0) + .setTransitionEvent("close", (ctx) => { ctx.degreeOfOpening = 0 }) + .addTransition("ajarPlus", States.AJAR, States.AJAR) + .setTransitionEvent("ajarPlus", (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening + 1 }) + .addTransition("ajarMinus", States.AJAR, States.AJAR) + .setTransitionEvent("ajarMinus", (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening - 1 }) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.BuilderStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.BuilderStateGenerate.verified.txt new file mode 100644 index 0000000..5683fd3 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.BuilderStateGenerate.verified.txt @@ -0,0 +1,18 @@ +import {EmptyContext} from "./StaterStateMachine"; +import {StaterStateMachineBuilder} from "./StaterStateMachine"; + +export enum States { + OPEN = "OPEN", + AJAR = "AJAR", + CLOSE = "CLOSE" +} + +export const builderDoorStateMachine = new StaterStateMachineBuilder() + .setStartState(States.OPEN) + .setContext(new EmptyContext()) + .addTransition("preOpen", States.CLOSE, States.AJAR) + .addTransition("preClose", States.OPEN, States.AJAR) + .addTransition("open", States.AJAR, States.OPEN) + .addTransition("close", States.AJAR, States.CLOSE) + .addTransition("ajarPlus", States.AJAR, States.AJAR) + .addTransition("ajarMinus", States.AJAR, States.AJAR) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.BuilderStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.BuilderStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..133b5fa --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.BuilderStateGenerateWithInterface.verified.txt @@ -0,0 +1,51 @@ +import {EmptyContext} from "./StaterStateMachine"; +import {StateMachineFactory} from "./StaterStateMachine"; +import {StaterStateMachine} from "./StaterStateMachine"; +import {StaterStateMachineBuilder} from "./StaterStateMachine"; + +export enum States { + OPEN = "OPEN", + AJAR = "AJAR", + CLOSE = "CLOSE" +} + +export class TypesDoorStateMachine extends StaterStateMachine { + preOpen() { + this.transition("preOpen") + } + + preClose() { + this.transition("preClose") + } + + open() { + this.transition("open") + } + + close() { + this.transition("close") + } + + ajarPlus() { + this.transition("ajarPlus") + } + + ajarMinus() { + this.transition("ajarMinus") + } +} + +const typedDoorFactory: StateMachineFactory = (...args): StaterStateMachine => { + return new TypesDoorStateMachine(...args); +}; + +export const builderDoorStateMachine = new StaterStateMachineBuilder() + .setStartState(States.OPEN) + .setContext(new EmptyContext()) + .setFactory(typedDoorFactory) + .addTransition("preOpen", States.CLOSE, States.AJAR) + .addTransition("preClose", States.OPEN, States.AJAR) + .addTransition("open", States.AJAR, States.OPEN) + .addTransition("close", States.AJAR, States.CLOSE) + .addTransition("ajarPlus", States.AJAR, States.AJAR) + .addTransition("ajarMinus", States.AJAR, States.AJAR) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.ClazzContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.ClazzContextGenerate.verified.txt new file mode 100644 index 0000000..bc5a550 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.ClazzContextGenerate.verified.txt @@ -0,0 +1,69 @@ +import {Context} from "./StaterStateMachine"; +import {StaterStateMachine} from "./StaterStateMachine"; + + +interface DoorFSMContext extends Context { + degreeOfOpening: number + closeVariable: boolean + doorName: string + floatVariable: number +} + +const buildDoorFSMContext: () => DoorFSMContext = () => { + return { + degreeOfOpening: 0, + closeVariable: true, + doorName: "asd", + floatVariable: 0 + } +} + + +export class DoorStateMachine extends StaterStateMachine { + constructor() { + super( + [ + { + name: "preOpen", + start: "CLOSE", + end: "AJAR", + event: (ctx) => { ctx.degreeOfOpening = 1 } + }, + { + name: "preClose", + start: "OPEN", + end: "AJAR", + event: (ctx) => { ctx.degreeOfOpening = 99 } + }, + { + name: "open", + start: "AJAR", + end: "OPEN", + condition: (ctx) => ctx.degreeOfOpening >= 0, + event: (ctx) => { ctx.degreeOfOpening = 100 } + }, + { + name: "close", + start: "AJAR", + end: "CLOSE", + condition: (ctx) => ctx.degreeOfOpening <= 0, + event: (ctx) => { ctx.degreeOfOpening = 0 } + }, + { + name: "ajarPlus", + start: "AJAR", + end: "AJAR", + event: (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening + 1 } + }, + { + name: "ajarMinus", + start: "AJAR", + end: "AJAR", + event: (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening - 1 } + } + ], + buildDoorFSMContext(), + "OPEN", + ) + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.ClazzContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.ClazzContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..2f9d2c1 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.ClazzContextGenerateWithInterface.verified.txt @@ -0,0 +1,94 @@ +import {Context} from "./StaterStateMachine"; +import {StateMachineFactory} from "./StaterStateMachine"; +import {StaterStateMachine} from "./StaterStateMachine"; + + +interface DoorFSMContext extends Context { + degreeOfOpening: number + closeVariable: boolean + doorName: string + floatVariable: number +} + +const buildDoorFSMContext: () => DoorFSMContext = () => { + return { + degreeOfOpening: 0, + closeVariable: true, + doorName: "asd", + floatVariable: 0 + } +} + + +export class DoorStateMachine extends StaterStateMachine { + constructor() { + super( + [ + { + name: "preOpen", + start: "CLOSE", + end: "AJAR", + event: (ctx) => { ctx.degreeOfOpening = 1 } + }, + { + name: "preClose", + start: "OPEN", + end: "AJAR", + event: (ctx) => { ctx.degreeOfOpening = 99 } + }, + { + name: "open", + start: "AJAR", + end: "OPEN", + condition: (ctx) => ctx.degreeOfOpening >= 0, + event: (ctx) => { ctx.degreeOfOpening = 100 } + }, + { + name: "close", + start: "AJAR", + end: "CLOSE", + condition: (ctx) => ctx.degreeOfOpening <= 0, + event: (ctx) => { ctx.degreeOfOpening = 0 } + }, + { + name: "ajarPlus", + start: "AJAR", + end: "AJAR", + event: (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening + 1 } + }, + { + name: "ajarMinus", + start: "AJAR", + end: "AJAR", + event: (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening - 1 } + } + ], + buildDoorFSMContext(), + "OPEN", + ) + } + + preOpen() { + this.transition("preOpen") + } + + preClose() { + this.transition("preClose") + } + + open() { + this.transition("open") + } + + close() { + this.transition("close") + } + + ajarPlus() { + this.transition("ajarPlus") + } + + ajarMinus() { + this.transition("ajarMinus") + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.ClazzGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.ClazzGenerate.verified.txt new file mode 100644 index 0000000..9624b89 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.ClazzGenerate.verified.txt @@ -0,0 +1,44 @@ +import {EmptyContext} from "./StaterStateMachine"; +import {StaterStateMachine} from "./StaterStateMachine"; + + +export class DoorStateMachine extends StaterStateMachine { + constructor() { + super( + [ + { + name: "preOpen", + start: "CLOSE", + end: "AJAR" + }, + { + name: "preClose", + start: "OPEN", + end: "AJAR" + }, + { + name: "open", + start: "AJAR", + end: "OPEN" + }, + { + name: "close", + start: "AJAR", + end: "CLOSE" + }, + { + name: "ajarPlus", + start: "AJAR", + end: "AJAR" + }, + { + name: "ajarMinus", + start: "AJAR", + end: "AJAR" + } + ], + new EmptyContext(), + "OPEN", + ) + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.ClazzGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.ClazzGenerateWithInterface.verified.txt new file mode 100644 index 0000000..348d999 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.ClazzGenerateWithInterface.verified.txt @@ -0,0 +1,69 @@ +import {EmptyContext} from "./StaterStateMachine"; +import {StateMachineFactory} from "./StaterStateMachine"; +import {StaterStateMachine} from "./StaterStateMachine"; + + +export class DoorStateMachine extends StaterStateMachine { + constructor() { + super( + [ + { + name: "preOpen", + start: "CLOSE", + end: "AJAR" + }, + { + name: "preClose", + start: "OPEN", + end: "AJAR" + }, + { + name: "open", + start: "AJAR", + end: "OPEN" + }, + { + name: "close", + start: "AJAR", + end: "CLOSE" + }, + { + name: "ajarPlus", + start: "AJAR", + end: "AJAR" + }, + { + name: "ajarMinus", + start: "AJAR", + end: "AJAR" + } + ], + new EmptyContext(), + "OPEN", + ) + } + + preOpen() { + this.transition("preOpen") + } + + preClose() { + this.transition("preClose") + } + + open() { + this.transition("open") + } + + close() { + this.transition("close") + } + + ajarPlus() { + this.transition("ajarPlus") + } + + ajarMinus() { + this.transition("ajarMinus") + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.ClazzStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.ClazzStateContextGenerate.verified.txt new file mode 100644 index 0000000..a530460 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.ClazzStateContextGenerate.verified.txt @@ -0,0 +1,75 @@ +import {Context} from "./StaterStateMachine"; +import {StaterStateMachine} from "./StaterStateMachine"; + + +export enum States { + OPEN = "OPEN", + AJAR = "AJAR", + CLOSE = "CLOSE" +} + +interface DoorFSMContext extends Context { + degreeOfOpening: number + closeVariable: boolean + doorName: string + floatVariable: number +} + +const buildDoorFSMContext: () => DoorFSMContext = () => { + return { + degreeOfOpening: 0, + closeVariable: true, + doorName: "asd", + floatVariable: 0 + } +} + + +export class DoorStateMachine extends StaterStateMachine { + constructor() { + super( + [ + { + name: "preOpen", + start: States.CLOSE, + end: States.AJAR, + event: (ctx) => { ctx.degreeOfOpening = 1 } + }, + { + name: "preClose", + start: States.OPEN, + end: States.AJAR, + event: (ctx) => { ctx.degreeOfOpening = 99 } + }, + { + name: "open", + start: States.AJAR, + end: States.OPEN, + condition: (ctx) => ctx.degreeOfOpening >= 0, + event: (ctx) => { ctx.degreeOfOpening = 100 } + }, + { + name: "close", + start: States.AJAR, + end: States.CLOSE, + condition: (ctx) => ctx.degreeOfOpening <= 0, + event: (ctx) => { ctx.degreeOfOpening = 0 } + }, + { + name: "ajarPlus", + start: States.AJAR, + end: States.AJAR, + event: (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening + 1 } + }, + { + name: "ajarMinus", + start: States.AJAR, + end: States.AJAR, + event: (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening - 1 } + } + ], + buildDoorFSMContext(), + States.OPEN, + ) + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.ClazzStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.ClazzStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..e0f9cc8 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.ClazzStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,100 @@ +import {Context} from "./StaterStateMachine"; +import {StateMachineFactory} from "./StaterStateMachine"; +import {StaterStateMachine} from "./StaterStateMachine"; + + +export enum States { + OPEN = "OPEN", + AJAR = "AJAR", + CLOSE = "CLOSE" +} + +interface DoorFSMContext extends Context { + degreeOfOpening: number + closeVariable: boolean + doorName: string + floatVariable: number +} + +const buildDoorFSMContext: () => DoorFSMContext = () => { + return { + degreeOfOpening: 0, + closeVariable: true, + doorName: "asd", + floatVariable: 0 + } +} + + +export class DoorStateMachine extends StaterStateMachine { + constructor() { + super( + [ + { + name: "preOpen", + start: States.CLOSE, + end: States.AJAR, + event: (ctx) => { ctx.degreeOfOpening = 1 } + }, + { + name: "preClose", + start: States.OPEN, + end: States.AJAR, + event: (ctx) => { ctx.degreeOfOpening = 99 } + }, + { + name: "open", + start: States.AJAR, + end: States.OPEN, + condition: (ctx) => ctx.degreeOfOpening >= 0, + event: (ctx) => { ctx.degreeOfOpening = 100 } + }, + { + name: "close", + start: States.AJAR, + end: States.CLOSE, + condition: (ctx) => ctx.degreeOfOpening <= 0, + event: (ctx) => { ctx.degreeOfOpening = 0 } + }, + { + name: "ajarPlus", + start: States.AJAR, + end: States.AJAR, + event: (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening + 1 } + }, + { + name: "ajarMinus", + start: States.AJAR, + end: States.AJAR, + event: (ctx) => { ctx.degreeOfOpening = ctx.degreeOfOpening - 1 } + } + ], + buildDoorFSMContext(), + States.OPEN, + ) + } + + preOpen() { + this.transition("preOpen") + } + + preClose() { + this.transition("preClose") + } + + open() { + this.transition("open") + } + + close() { + this.transition("close") + } + + ajarPlus() { + this.transition("ajarPlus") + } + + ajarMinus() { + this.transition("ajarMinus") + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.ClazzStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.ClazzStateGenerate.verified.txt new file mode 100644 index 0000000..4cdf26b --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.ClazzStateGenerate.verified.txt @@ -0,0 +1,50 @@ +import {EmptyContext} from "./StaterStateMachine"; +import {StaterStateMachine} from "./StaterStateMachine"; + + +export enum States { + OPEN = "OPEN", + AJAR = "AJAR", + CLOSE = "CLOSE" +} + +export class DoorStateMachine extends StaterStateMachine { + constructor() { + super( + [ + { + name: "preOpen", + start: States.CLOSE, + end: States.AJAR + }, + { + name: "preClose", + start: States.OPEN, + end: States.AJAR + }, + { + name: "open", + start: States.AJAR, + end: States.OPEN + }, + { + name: "close", + start: States.AJAR, + end: States.CLOSE + }, + { + name: "ajarPlus", + start: States.AJAR, + end: States.AJAR + }, + { + name: "ajarMinus", + start: States.AJAR, + end: States.AJAR + } + ], + new EmptyContext(), + States.OPEN, + ) + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.ClazzStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.ClazzStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..2d48518 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateDoorTests.ClazzStateGenerateWithInterface.verified.txt @@ -0,0 +1,75 @@ +import {EmptyContext} from "./StaterStateMachine"; +import {StateMachineFactory} from "./StaterStateMachine"; +import {StaterStateMachine} from "./StaterStateMachine"; + + +export enum States { + OPEN = "OPEN", + AJAR = "AJAR", + CLOSE = "CLOSE" +} + +export class DoorStateMachine extends StaterStateMachine { + constructor() { + super( + [ + { + name: "preOpen", + start: States.CLOSE, + end: States.AJAR + }, + { + name: "preClose", + start: States.OPEN, + end: States.AJAR + }, + { + name: "open", + start: States.AJAR, + end: States.OPEN + }, + { + name: "close", + start: States.AJAR, + end: States.CLOSE + }, + { + name: "ajarPlus", + start: States.AJAR, + end: States.AJAR + }, + { + name: "ajarMinus", + start: States.AJAR, + end: States.AJAR + } + ], + new EmptyContext(), + States.OPEN, + ) + } + + preOpen() { + this.transition("preOpen") + } + + preClose() { + this.transition("preClose") + } + + open() { + this.transition("open") + } + + close() { + this.transition("close") + } + + ajarPlus() { + this.transition("ajarPlus") + } + + ajarMinus() { + this.transition("ajarMinus") + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.BuilderTestsContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.BuilderTestsContextGenerate.verified.txt new file mode 100644 index 0000000..b695a79 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.BuilderTestsContextGenerate.verified.txt @@ -0,0 +1,257 @@ +import {builderDoorStateMachine} from "./Door"; + + +test('testInit', () => { + builderDoorStateMachine.build() +}) + + + +test('testScenario0', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe("AJAR") + + sm.transition('close') + expect(sm.getState()).toBe("CLOSE") + + sm.transition('preOpen') + expect(sm.getState()).toBe("AJAR") + + sm.transition('ajarPlus') + expect(sm.getState()).toBe("AJAR") + + sm.transition('open') + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario1', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe("AJAR") + + sm.transition('ajarPlus') + expect(sm.getState()).toBe("AJAR") + + sm.transition('close') + expect(sm.getState()).toBe("CLOSE") + + sm.transition('preOpen') + expect(sm.getState()).toBe("AJAR") + + sm.transition('open') + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario2', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe("AJAR") + + sm.transition('close') + expect(sm.getState()).toBe("CLOSE") + + sm.transition('preOpen') + expect(sm.getState()).toBe("AJAR") + + sm.transition('open') + expect(sm.getState()).toBe("OPEN") + +}) + + +test('testJsonSchema', () => { + const sm = builderDoorStateMachine.build() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + + +test('testSystemAppendStateTransition', () => { + let smBuilder = builderDoorStateMachine + + smBuilder = smBuilder.addState('__test_state_1__') + expect(JSON.parse(`{ + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addState('__test_state_2__') + expect(JSON.parse(`{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addTransition('__test_transition__', '__test_state_1__', '__test_state_2__') + expect(JSON.parse(`{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] +}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) +}) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.BuilderTestsContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.BuilderTestsContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..ff0da21 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.BuilderTestsContextGenerateWithInterface.verified.txt @@ -0,0 +1,257 @@ +import {builderDoorStateMachine, TypesDoorStateMachine} from "./Door"; + + +test('testInit', () => { + builderDoorStateMachine.build() as TypesDoorStateMachine +}) + + + +test('testScenario0', () => { + const sm = builderDoorStateMachine.build() as TypesDoorStateMachine + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe("AJAR") + + sm.close() + expect(sm.getState()).toBe("CLOSE") + + sm.preOpen() + expect(sm.getState()).toBe("AJAR") + + sm.ajarPlus() + expect(sm.getState()).toBe("AJAR") + + sm.open() + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario1', () => { + const sm = builderDoorStateMachine.build() as TypesDoorStateMachine + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe("AJAR") + + sm.ajarPlus() + expect(sm.getState()).toBe("AJAR") + + sm.close() + expect(sm.getState()).toBe("CLOSE") + + sm.preOpen() + expect(sm.getState()).toBe("AJAR") + + sm.open() + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario2', () => { + const sm = builderDoorStateMachine.build() as TypesDoorStateMachine + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe("AJAR") + + sm.close() + expect(sm.getState()).toBe("CLOSE") + + sm.preOpen() + expect(sm.getState()).toBe("AJAR") + + sm.open() + expect(sm.getState()).toBe("OPEN") + +}) + + +test('testJsonSchema', () => { + const sm = builderDoorStateMachine.build() as TypesDoorStateMachine + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + + +test('testSystemAppendStateTransition', () => { + let smBuilder = builderDoorStateMachine + + smBuilder = smBuilder.addState('__test_state_1__') + expect(JSON.parse(`{ + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addState('__test_state_2__') + expect(JSON.parse(`{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addTransition('__test_transition__', '__test_state_1__', '__test_state_2__') + expect(JSON.parse(`{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] +}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) +}) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.BuilderTestsGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.BuilderTestsGenerate.verified.txt new file mode 100644 index 0000000..b695a79 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.BuilderTestsGenerate.verified.txt @@ -0,0 +1,257 @@ +import {builderDoorStateMachine} from "./Door"; + + +test('testInit', () => { + builderDoorStateMachine.build() +}) + + + +test('testScenario0', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe("AJAR") + + sm.transition('close') + expect(sm.getState()).toBe("CLOSE") + + sm.transition('preOpen') + expect(sm.getState()).toBe("AJAR") + + sm.transition('ajarPlus') + expect(sm.getState()).toBe("AJAR") + + sm.transition('open') + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario1', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe("AJAR") + + sm.transition('ajarPlus') + expect(sm.getState()).toBe("AJAR") + + sm.transition('close') + expect(sm.getState()).toBe("CLOSE") + + sm.transition('preOpen') + expect(sm.getState()).toBe("AJAR") + + sm.transition('open') + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario2', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe("AJAR") + + sm.transition('close') + expect(sm.getState()).toBe("CLOSE") + + sm.transition('preOpen') + expect(sm.getState()).toBe("AJAR") + + sm.transition('open') + expect(sm.getState()).toBe("OPEN") + +}) + + +test('testJsonSchema', () => { + const sm = builderDoorStateMachine.build() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + + +test('testSystemAppendStateTransition', () => { + let smBuilder = builderDoorStateMachine + + smBuilder = smBuilder.addState('__test_state_1__') + expect(JSON.parse(`{ + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addState('__test_state_2__') + expect(JSON.parse(`{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addTransition('__test_transition__', '__test_state_1__', '__test_state_2__') + expect(JSON.parse(`{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] +}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) +}) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.BuilderTestsGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.BuilderTestsGenerateWithInterface.verified.txt new file mode 100644 index 0000000..ff0da21 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.BuilderTestsGenerateWithInterface.verified.txt @@ -0,0 +1,257 @@ +import {builderDoorStateMachine, TypesDoorStateMachine} from "./Door"; + + +test('testInit', () => { + builderDoorStateMachine.build() as TypesDoorStateMachine +}) + + + +test('testScenario0', () => { + const sm = builderDoorStateMachine.build() as TypesDoorStateMachine + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe("AJAR") + + sm.close() + expect(sm.getState()).toBe("CLOSE") + + sm.preOpen() + expect(sm.getState()).toBe("AJAR") + + sm.ajarPlus() + expect(sm.getState()).toBe("AJAR") + + sm.open() + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario1', () => { + const sm = builderDoorStateMachine.build() as TypesDoorStateMachine + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe("AJAR") + + sm.ajarPlus() + expect(sm.getState()).toBe("AJAR") + + sm.close() + expect(sm.getState()).toBe("CLOSE") + + sm.preOpen() + expect(sm.getState()).toBe("AJAR") + + sm.open() + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario2', () => { + const sm = builderDoorStateMachine.build() as TypesDoorStateMachine + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe("AJAR") + + sm.close() + expect(sm.getState()).toBe("CLOSE") + + sm.preOpen() + expect(sm.getState()).toBe("AJAR") + + sm.open() + expect(sm.getState()).toBe("OPEN") + +}) + + +test('testJsonSchema', () => { + const sm = builderDoorStateMachine.build() as TypesDoorStateMachine + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + + +test('testSystemAppendStateTransition', () => { + let smBuilder = builderDoorStateMachine + + smBuilder = smBuilder.addState('__test_state_1__') + expect(JSON.parse(`{ + "states": [ + "__test_state_1__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addState('__test_state_2__') + expect(JSON.parse(`{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addTransition('__test_transition__', '__test_state_1__', '__test_state_2__') + expect(JSON.parse(`{ + "states": [ + "__test_state_1__", + "__test_state_2__", + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "__test_transition__", + "start": "__test_state_1__", + "end": "__test_state_2__" + } + ] +}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) +}) \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerate.verified.txt new file mode 100644 index 0000000..03e7f2e --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerate.verified.txt @@ -0,0 +1,118 @@ +import {builderDoorStateMachine} from "./Door"; +import {States} from "./Door"; + + +test('testInit', () => { + builderDoorStateMachine.build() +}) + + + +test('testScenario0', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('close') + expect(sm.getState()).toBe(States.CLOSE) + + sm.transition('preOpen') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('ajarPlus') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('open') + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario1', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('ajarPlus') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('close') + expect(sm.getState()).toBe(States.CLOSE) + + sm.transition('preOpen') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('open') + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario2', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('close') + expect(sm.getState()).toBe(States.CLOSE) + + sm.transition('preOpen') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('open') + expect(sm.getState()).toBe(States.OPEN) + +}) + + +test('testJsonSchema', () => { + const sm = builderDoorStateMachine.build() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..7d789b9 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.BuilderTestsStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,118 @@ +import {builderDoorStateMachine, TypesDoorStateMachine} from "./Door"; +import {States} from "./Door"; + + +test('testInit', () => { + builderDoorStateMachine.build() as TypesDoorStateMachine +}) + + + +test('testScenario0', () => { + const sm = builderDoorStateMachine.build() as TypesDoorStateMachine + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe(States.AJAR) + + sm.close() + expect(sm.getState()).toBe(States.CLOSE) + + sm.preOpen() + expect(sm.getState()).toBe(States.AJAR) + + sm.ajarPlus() + expect(sm.getState()).toBe(States.AJAR) + + sm.open() + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario1', () => { + const sm = builderDoorStateMachine.build() as TypesDoorStateMachine + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe(States.AJAR) + + sm.ajarPlus() + expect(sm.getState()).toBe(States.AJAR) + + sm.close() + expect(sm.getState()).toBe(States.CLOSE) + + sm.preOpen() + expect(sm.getState()).toBe(States.AJAR) + + sm.open() + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario2', () => { + const sm = builderDoorStateMachine.build() as TypesDoorStateMachine + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe(States.AJAR) + + sm.close() + expect(sm.getState()).toBe(States.CLOSE) + + sm.preOpen() + expect(sm.getState()).toBe(States.AJAR) + + sm.open() + expect(sm.getState()).toBe(States.OPEN) + +}) + + +test('testJsonSchema', () => { + const sm = builderDoorStateMachine.build() as TypesDoorStateMachine + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.BuilderTestsStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.BuilderTestsStateGenerate.verified.txt new file mode 100644 index 0000000..03e7f2e --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.BuilderTestsStateGenerate.verified.txt @@ -0,0 +1,118 @@ +import {builderDoorStateMachine} from "./Door"; +import {States} from "./Door"; + + +test('testInit', () => { + builderDoorStateMachine.build() +}) + + + +test('testScenario0', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('close') + expect(sm.getState()).toBe(States.CLOSE) + + sm.transition('preOpen') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('ajarPlus') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('open') + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario1', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('ajarPlus') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('close') + expect(sm.getState()).toBe(States.CLOSE) + + sm.transition('preOpen') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('open') + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario2', () => { + const sm = builderDoorStateMachine.build() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('close') + expect(sm.getState()).toBe(States.CLOSE) + + sm.transition('preOpen') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('open') + expect(sm.getState()).toBe(States.OPEN) + +}) + + +test('testJsonSchema', () => { + const sm = builderDoorStateMachine.build() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.BuilderTestsStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.BuilderTestsStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..7d789b9 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.BuilderTestsStateGenerateWithInterface.verified.txt @@ -0,0 +1,118 @@ +import {builderDoorStateMachine, TypesDoorStateMachine} from "./Door"; +import {States} from "./Door"; + + +test('testInit', () => { + builderDoorStateMachine.build() as TypesDoorStateMachine +}) + + + +test('testScenario0', () => { + const sm = builderDoorStateMachine.build() as TypesDoorStateMachine + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe(States.AJAR) + + sm.close() + expect(sm.getState()).toBe(States.CLOSE) + + sm.preOpen() + expect(sm.getState()).toBe(States.AJAR) + + sm.ajarPlus() + expect(sm.getState()).toBe(States.AJAR) + + sm.open() + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario1', () => { + const sm = builderDoorStateMachine.build() as TypesDoorStateMachine + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe(States.AJAR) + + sm.ajarPlus() + expect(sm.getState()).toBe(States.AJAR) + + sm.close() + expect(sm.getState()).toBe(States.CLOSE) + + sm.preOpen() + expect(sm.getState()).toBe(States.AJAR) + + sm.open() + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario2', () => { + const sm = builderDoorStateMachine.build() as TypesDoorStateMachine + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe(States.AJAR) + + sm.close() + expect(sm.getState()).toBe(States.CLOSE) + + sm.preOpen() + expect(sm.getState()).toBe(States.AJAR) + + sm.open() + expect(sm.getState()).toBe(States.OPEN) + +}) + + +test('testJsonSchema', () => { + const sm = builderDoorStateMachine.build() as TypesDoorStateMachine + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.ClazzTestsContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.ClazzTestsContextGenerate.verified.txt new file mode 100644 index 0000000..349c13f --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.ClazzTestsContextGenerate.verified.txt @@ -0,0 +1,117 @@ +import {DoorStateMachine} from "./Door"; + + +test('testInit', () => { + new DoorStateMachine() +}) + + + +test('testScenario0', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe("AJAR") + + sm.transition('close') + expect(sm.getState()).toBe("CLOSE") + + sm.transition('preOpen') + expect(sm.getState()).toBe("AJAR") + + sm.transition('ajarPlus') + expect(sm.getState()).toBe("AJAR") + + sm.transition('open') + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario1', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe("AJAR") + + sm.transition('ajarPlus') + expect(sm.getState()).toBe("AJAR") + + sm.transition('close') + expect(sm.getState()).toBe("CLOSE") + + sm.transition('preOpen') + expect(sm.getState()).toBe("AJAR") + + sm.transition('open') + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario2', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe("AJAR") + + sm.transition('close') + expect(sm.getState()).toBe("CLOSE") + + sm.transition('preOpen') + expect(sm.getState()).toBe("AJAR") + + sm.transition('open') + expect(sm.getState()).toBe("OPEN") + +}) + + +test('testJsonSchema', () => { + const sm = new DoorStateMachine() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.ClazzTestsContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.ClazzTestsContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..46957b2 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.ClazzTestsContextGenerateWithInterface.verified.txt @@ -0,0 +1,117 @@ +import {DoorStateMachine} from "./Door"; + + +test('testInit', () => { + new DoorStateMachine() +}) + + + +test('testScenario0', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe("AJAR") + + sm.close() + expect(sm.getState()).toBe("CLOSE") + + sm.preOpen() + expect(sm.getState()).toBe("AJAR") + + sm.ajarPlus() + expect(sm.getState()).toBe("AJAR") + + sm.open() + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario1', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe("AJAR") + + sm.ajarPlus() + expect(sm.getState()).toBe("AJAR") + + sm.close() + expect(sm.getState()).toBe("CLOSE") + + sm.preOpen() + expect(sm.getState()).toBe("AJAR") + + sm.open() + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario2', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe("AJAR") + + sm.close() + expect(sm.getState()).toBe("CLOSE") + + sm.preOpen() + expect(sm.getState()).toBe("AJAR") + + sm.open() + expect(sm.getState()).toBe("OPEN") + +}) + + +test('testJsonSchema', () => { + const sm = new DoorStateMachine() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.ClazzTestsGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.ClazzTestsGenerate.verified.txt new file mode 100644 index 0000000..349c13f --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.ClazzTestsGenerate.verified.txt @@ -0,0 +1,117 @@ +import {DoorStateMachine} from "./Door"; + + +test('testInit', () => { + new DoorStateMachine() +}) + + + +test('testScenario0', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe("AJAR") + + sm.transition('close') + expect(sm.getState()).toBe("CLOSE") + + sm.transition('preOpen') + expect(sm.getState()).toBe("AJAR") + + sm.transition('ajarPlus') + expect(sm.getState()).toBe("AJAR") + + sm.transition('open') + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario1', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe("AJAR") + + sm.transition('ajarPlus') + expect(sm.getState()).toBe("AJAR") + + sm.transition('close') + expect(sm.getState()).toBe("CLOSE") + + sm.transition('preOpen') + expect(sm.getState()).toBe("AJAR") + + sm.transition('open') + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario2', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe("AJAR") + + sm.transition('close') + expect(sm.getState()).toBe("CLOSE") + + sm.transition('preOpen') + expect(sm.getState()).toBe("AJAR") + + sm.transition('open') + expect(sm.getState()).toBe("OPEN") + +}) + + +test('testJsonSchema', () => { + const sm = new DoorStateMachine() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.ClazzTestsGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.ClazzTestsGenerateWithInterface.verified.txt new file mode 100644 index 0000000..46957b2 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.ClazzTestsGenerateWithInterface.verified.txt @@ -0,0 +1,117 @@ +import {DoorStateMachine} from "./Door"; + + +test('testInit', () => { + new DoorStateMachine() +}) + + + +test('testScenario0', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe("AJAR") + + sm.close() + expect(sm.getState()).toBe("CLOSE") + + sm.preOpen() + expect(sm.getState()).toBe("AJAR") + + sm.ajarPlus() + expect(sm.getState()).toBe("AJAR") + + sm.open() + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario1', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe("AJAR") + + sm.ajarPlus() + expect(sm.getState()).toBe("AJAR") + + sm.close() + expect(sm.getState()).toBe("CLOSE") + + sm.preOpen() + expect(sm.getState()).toBe("AJAR") + + sm.open() + expect(sm.getState()).toBe("OPEN") + +}) + +test('testScenario2', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe("AJAR") + + sm.close() + expect(sm.getState()).toBe("CLOSE") + + sm.preOpen() + expect(sm.getState()).toBe("AJAR") + + sm.open() + expect(sm.getState()).toBe("OPEN") + +}) + + +test('testJsonSchema', () => { + const sm = new DoorStateMachine() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerate.verified.txt new file mode 100644 index 0000000..9c4d633 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerate.verified.txt @@ -0,0 +1,118 @@ +import {DoorStateMachine} from "./Door"; +import {States} from "./Door"; + + +test('testInit', () => { + new DoorStateMachine() +}) + + + +test('testScenario0', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('close') + expect(sm.getState()).toBe(States.CLOSE) + + sm.transition('preOpen') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('ajarPlus') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('open') + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario1', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('ajarPlus') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('close') + expect(sm.getState()).toBe(States.CLOSE) + + sm.transition('preOpen') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('open') + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario2', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('close') + expect(sm.getState()).toBe(States.CLOSE) + + sm.transition('preOpen') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('open') + expect(sm.getState()).toBe(States.OPEN) + +}) + + +test('testJsonSchema', () => { + const sm = new DoorStateMachine() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerateWithInterface.verified.txt new file mode 100644 index 0000000..7806a77 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.ClazzTestsStateContextGenerateWithInterface.verified.txt @@ -0,0 +1,118 @@ +import {DoorStateMachine} from "./Door"; +import {States} from "./Door"; + + +test('testInit', () => { + new DoorStateMachine() +}) + + + +test('testScenario0', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe(States.AJAR) + + sm.close() + expect(sm.getState()).toBe(States.CLOSE) + + sm.preOpen() + expect(sm.getState()).toBe(States.AJAR) + + sm.ajarPlus() + expect(sm.getState()).toBe(States.AJAR) + + sm.open() + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario1', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe(States.AJAR) + + sm.ajarPlus() + expect(sm.getState()).toBe(States.AJAR) + + sm.close() + expect(sm.getState()).toBe(States.CLOSE) + + sm.preOpen() + expect(sm.getState()).toBe(States.AJAR) + + sm.open() + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario2', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe(States.AJAR) + + sm.close() + expect(sm.getState()).toBe(States.CLOSE) + + sm.preOpen() + expect(sm.getState()).toBe(States.AJAR) + + sm.open() + expect(sm.getState()).toBe(States.OPEN) + +}) + + +test('testJsonSchema', () => { + const sm = new DoorStateMachine() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.ClazzTestsStateGenerate.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.ClazzTestsStateGenerate.verified.txt new file mode 100644 index 0000000..9c4d633 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.ClazzTestsStateGenerate.verified.txt @@ -0,0 +1,118 @@ +import {DoorStateMachine} from "./Door"; +import {States} from "./Door"; + + +test('testInit', () => { + new DoorStateMachine() +}) + + + +test('testScenario0', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('close') + expect(sm.getState()).toBe(States.CLOSE) + + sm.transition('preOpen') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('ajarPlus') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('open') + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario1', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('ajarPlus') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('close') + expect(sm.getState()).toBe(States.CLOSE) + + sm.transition('preOpen') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('open') + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario2', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.transition('preClose') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('close') + expect(sm.getState()).toBe(States.CLOSE) + + sm.transition('preOpen') + expect(sm.getState()).toBe(States.AJAR) + + sm.transition('open') + expect(sm.getState()).toBe(States.OPEN) + +}) + + +test('testJsonSchema', () => { + const sm = new DoorStateMachine() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.ClazzTestsStateGenerateWithInterface.verified.txt b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.ClazzTestsStateGenerateWithInterface.verified.txt new file mode 100644 index 0000000..7806a77 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScript/TypeScriptAdapterGenerateTestsDoorTests.ClazzTestsStateGenerateWithInterface.verified.txt @@ -0,0 +1,118 @@ +import {DoorStateMachine} from "./Door"; +import {States} from "./Door"; + + +test('testInit', () => { + new DoorStateMachine() +}) + + + +test('testScenario0', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe(States.AJAR) + + sm.close() + expect(sm.getState()).toBe(States.CLOSE) + + sm.preOpen() + expect(sm.getState()).toBe(States.AJAR) + + sm.ajarPlus() + expect(sm.getState()).toBe(States.AJAR) + + sm.open() + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario1', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe(States.AJAR) + + sm.ajarPlus() + expect(sm.getState()).toBe(States.AJAR) + + sm.close() + expect(sm.getState()).toBe(States.CLOSE) + + sm.preOpen() + expect(sm.getState()).toBe(States.AJAR) + + sm.open() + expect(sm.getState()).toBe(States.OPEN) + +}) + +test('testScenario2', () => { + const sm = new DoorStateMachine() + sm.disableEvents() + + + sm.preClose() + expect(sm.getState()).toBe(States.AJAR) + + sm.close() + expect(sm.getState()).toBe(States.CLOSE) + + sm.preOpen() + expect(sm.getState()).toBe(States.AJAR) + + sm.open() + expect(sm.getState()).toBe(States.OPEN) + +}) + + +test('testJsonSchema', () => { + const sm = new DoorStateMachine() + expect(JSON.parse(`{ + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] +}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + diff --git a/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScriptAdapterGenerateDoorTests.cs b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScriptAdapterGenerateDoorTests.cs new file mode 100644 index 0000000..cbdd011 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/LanguageAdapter/TypeScriptAdapterGenerateDoorTests.cs @@ -0,0 +1,17 @@ +using Stater.CodeGeneration.Entity; +using Stater.CodeGeneration.LanguageAdapter.Base; +using Stater.CodeGeneration.LanguageAdapter.TypeScript; + +namespace Stater.CodeGeneration.Tests.LanguageAdapter; + +public class TypeScriptAdapterGenerateDoorTests : BaseTestAdapterGenerateDoorTests +{ + protected override BaseLanguageAdapter Adapter => new TypeScriptAdapter(); + protected override Language Language => Language.TypeScript; +} + +public class TypeScriptAdapterGenerateTestsDoorTests : BaseTestAdapterGenerateTestsDoorTests +{ + protected override BaseLanguageAdapter Adapter => new TypeScriptAdapter(); + protected override Language Language => Language.TypeScript; +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/ScenarioFinderTests.cs b/src/Stater.CodeGeneration.Tests/ScenarioFinderTests.cs new file mode 100644 index 0000000..109e2b6 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/ScenarioFinderTests.cs @@ -0,0 +1,33 @@ +using Stater.CodeGeneration.Tests.LanguageAdapter; + +namespace Stater.CodeGeneration.Tests; + +public class ScenarioFinderTests +{ + [Fact] + public void TestScenarioFinder() + { + var stateMachine = DoorStateMachineTestData.CreateDoorStateMachine(); + var results = ScenarioFinder.FindScenarios(stateMachine); + Assert.Equal(3, results.Count); + Assert.Equal(5, results[0].Count); + Assert.Equal("preClose", results[0][0].Name); + Assert.Equal("close", results[0][1].Name); + Assert.Equal("preOpen", results[0][2].Name); + Assert.Equal("ajarPlus", results[0][3].Name); + Assert.Equal("open", results[0][4].Name); + + Assert.Equal(5, results[1].Count); + Assert.Equal("preClose", results[1][0].Name); + Assert.Equal("ajarPlus", results[1][1].Name); + Assert.Equal("close", results[1][2].Name); + Assert.Equal("preOpen", results[1][3].Name); + Assert.Equal("open", results[1][4].Name); + + Assert.Equal(4, results[2].Count); + Assert.Equal("preClose", results[2][0].Name); + Assert.Equal("close", results[2][1].Name); + Assert.Equal("preOpen", results[2][2].Name); + Assert.Equal("open", results[2][3].Name); + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration.Tests/Stater.CodeGeneration.Tests.csproj b/src/Stater.CodeGeneration.Tests/Stater.CodeGeneration.Tests.csproj new file mode 100644 index 0000000..183e9c5 --- /dev/null +++ b/src/Stater.CodeGeneration.Tests/Stater.CodeGeneration.Tests.csproj @@ -0,0 +1,20 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + diff --git a/src/Stater.CodeGeneration/CodeGenerator.cs b/src/Stater.CodeGeneration/CodeGenerator.cs new file mode 100644 index 0000000..b64bd01 --- /dev/null +++ b/src/Stater.CodeGeneration/CodeGenerator.cs @@ -0,0 +1,62 @@ +using Stater.CodeGeneration.Entity; +using Stater.CodeGeneration.LanguageAdapter.CPlusPlus; +using Stater.CodeGeneration.LanguageAdapter.CSharp; +using Stater.CodeGeneration.LanguageAdapter.Java; +using Stater.CodeGeneration.LanguageAdapter.JavaScript; +using Stater.CodeGeneration.LanguageAdapter.Kotlin; +using Stater.CodeGeneration.LanguageAdapter.Python; +using Stater.CodeGeneration.LanguageAdapter.TypeScript; +using Stater.Domain.Models; + +namespace Stater.CodeGeneration; + +public class CodeGenerator +{ + private readonly KotlinAdapter kotlinAdapter = new(); + private readonly PythonAdapter pythonAdapter = new(); + private readonly JavaScriptAdapter javaScriptAdapter = new(); + private readonly TypeScriptAdapter typeScriptAdapter = new(); + private readonly JavaAdapter javaAdapter = new(); + private readonly CSharpAdapter cSharpAdapter = new(); + private readonly CPlusPlusAdapter cPlusPlusAdapter = new(); + + public string Generate(StateMachine stateMachine, GenerationSettings generationSettings) + { + if (generationSettings is { GenerateEventAndCondition: true, GenerateContext: false }) + { + throw new InvalidDataException(); + } + + return generationSettings.Language switch + { + Language.Kotlin => kotlinAdapter.Generate(stateMachine, generationSettings), + Language.Java => javaAdapter.Generate(stateMachine, generationSettings), + Language.CSharp => cSharpAdapter.Generate(stateMachine, generationSettings), + Language.Python3 => pythonAdapter.Generate(stateMachine, generationSettings), + Language.JavaScript => javaScriptAdapter.Generate(stateMachine, generationSettings), + Language.TypeScript => typeScriptAdapter.Generate(stateMachine, generationSettings), + Language.CPlusPlus => cPlusPlusAdapter.Generate(stateMachine, generationSettings), + _ => throw new ArgumentOutOfRangeException(nameof(generationSettings)) + }; + } + + public string GenerateTests(StateMachine stateMachine, GenerationSettings generationSettings, List> scenarios) + { + if (generationSettings is { GenerateEventAndCondition: true, GenerateContext: false }) + { + throw new InvalidDataException(); + } + + return generationSettings.Language switch + { + Language.Kotlin => kotlinAdapter.GenerateTests(stateMachine, generationSettings, scenarios), + Language.Java => javaAdapter.GenerateTests(stateMachine, generationSettings, scenarios), + Language.CSharp => cSharpAdapter.GenerateTests(stateMachine, generationSettings, scenarios), + Language.Python3 => pythonAdapter.GenerateTests(stateMachine, generationSettings, scenarios), + Language.JavaScript => javaScriptAdapter.GenerateTests(stateMachine, generationSettings, scenarios), + Language.TypeScript => typeScriptAdapter.GenerateTests(stateMachine, generationSettings, scenarios), + Language.CPlusPlus => cPlusPlusAdapter.GenerateTests(stateMachine, generationSettings, scenarios), + _ => throw new ArgumentOutOfRangeException(nameof(generationSettings)) + }; + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/Entity/GenerationSettings.cs b/src/Stater.CodeGeneration/Entity/GenerationSettings.cs new file mode 100644 index 0000000..d30b505 --- /dev/null +++ b/src/Stater.CodeGeneration/Entity/GenerationSettings.cs @@ -0,0 +1,10 @@ +namespace Stater.CodeGeneration.Entity; + +public record GenerationSettings( + Language Language, + Mode Mode = Mode.Clazz, + bool GenerateStates = false, + bool GenerateContext = false, + bool GenerateInterface = false, + bool GenerateEventAndCondition = false +); \ No newline at end of file diff --git a/src/Stater.CodeGeneration/Entity/Language.cs b/src/Stater.CodeGeneration/Entity/Language.cs new file mode 100644 index 0000000..48cbbb3 --- /dev/null +++ b/src/Stater.CodeGeneration/Entity/Language.cs @@ -0,0 +1,13 @@ +namespace Stater.CodeGeneration.Entity; + +public enum Language +{ + Kotlin, + Java, + CSharp, + Python3, + JavaScript, + TypeScript, + // C, + CPlusPlus +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/Entity/Mode.cs b/src/Stater.CodeGeneration/Entity/Mode.cs new file mode 100644 index 0000000..8f2cfa4 --- /dev/null +++ b/src/Stater.CodeGeneration/Entity/Mode.cs @@ -0,0 +1,6 @@ +namespace Stater.CodeGeneration.Entity; + +public enum Mode +{ + Clazz, Builder +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/FileGenerator.cs b/src/Stater.CodeGeneration/FileGenerator.cs new file mode 100644 index 0000000..5644ce6 --- /dev/null +++ b/src/Stater.CodeGeneration/FileGenerator.cs @@ -0,0 +1,140 @@ +using Stater.CodeGeneration.Entity; +using Stater.Domain.Models; + +namespace Stater.CodeGeneration; + +public class FileGenerator +{ + private CodeGenerator codeGenerator = new(); + + + public void GenerateCode( + Language language, + StateMachine stateMachine, + string outputPath, + Mode generateMode, + bool generateStates, + bool generateContext, + bool generateInterface) + { + var path = outputPath; + var testPath = outputPath; + if (!outputPath.EndsWith('/')) + { + path += "/"; + testPath += "/"; + } + + switch (language) + { + case Language.Python3: + path += stateMachine.Name + ".py"; + testPath += "test_" + stateMachine.Name + ".py"; + break; + case Language.JavaScript: + path += stateMachine.Name + ".js"; + testPath += stateMachine.Name + ".test.js"; + break; + case Language.TypeScript: + path += stateMachine.Name + ".ts"; + testPath += stateMachine.Name + ".test.ts"; + break; + case Language.Kotlin: + path += "main/kotlin/fsm/" + stateMachine.Name.ToLower() + "/"; + testPath += "test/kotlin/fsm/" + stateMachine.Name.ToLower() + "/"; + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + Console.WriteLine($"Folder created: {path}"); + } + + if (!Directory.Exists(testPath)) + { + Directory.CreateDirectory(testPath); + Console.WriteLine($"Folder created: {testPath}"); + } + + path += stateMachine.Name + ".kt"; + testPath += "Test" + stateMachine.Name + ".kt"; + + break; + case Language.Java: + path += "main/java/fsm/" + stateMachine.Name.ToLower() + "/"; + testPath += "test/java/fsm/" + stateMachine.Name.ToLower() + "/"; + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + Console.WriteLine($"Folder created: {path}"); + } + + if (!Directory.Exists(testPath)) + { + Directory.CreateDirectory(testPath); + Console.WriteLine($"Folder created: {testPath}"); + } + + path += stateMachine.Name + ".java"; + testPath += "Test" + stateMachine.Name + ".java"; + + break; + case Language.CSharp: + path += "/Stater.StateMachine.Lib/fsm/" + stateMachine.Name.ToLower() + "/"; + testPath += "/Stater.StateMachine.Lib.Tests/fsm/" + stateMachine.Name.ToLower() + "/"; + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + Console.WriteLine($"Folder created: {path}"); + } + + if (!Directory.Exists(testPath)) + { + Directory.CreateDirectory(testPath); + Console.WriteLine($"Folder created: {testPath}"); + } + + path += stateMachine.Name + ".cs"; + testPath += "Test" + stateMachine.Name + ".cs"; + + break; + case Language.CPlusPlus: + path += "fsm/" + stateMachine.Name + "/"; + testPath += "tests/"; + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + Console.WriteLine($"Folder created: {path}"); + } + + if (!Directory.Exists(testPath)) + { + Directory.CreateDirectory(testPath); + Console.WriteLine($"Folder created: {testPath}"); + } + + path += stateMachine.Name + ".h"; + testPath += "test_" + stateMachine.Name + ".cpp"; + + break; + } + + var settings = new GenerationSettings( + language + , generateMode + , GenerateStates: generateStates + , GenerateContext: generateContext + , GenerateInterface: generateInterface + ); + + var newStateMachine = stateMachine with { Name = stateMachine.Name.Replace(" ", "_") }; + + using var sw = new StreamWriter(path); + var result = codeGenerator.Generate(newStateMachine, settings); + sw.WriteLine(result); + + + using var swTest = new StreamWriter(testPath); + var results = ScenarioFinder.FindScenarios(newStateMachine); + var resultTest = codeGenerator.GenerateTests(newStateMachine, settings, results); + swTest.WriteLine(resultTest); + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/LanguageAdapter/Base/BaseLanguageAdapter.cs b/src/Stater.CodeGeneration/LanguageAdapter/Base/BaseLanguageAdapter.cs new file mode 100644 index 0000000..8d54ee0 --- /dev/null +++ b/src/Stater.CodeGeneration/LanguageAdapter/Base/BaseLanguageAdapter.cs @@ -0,0 +1,91 @@ +using Stater.CodeGeneration.Entity; +using Stater.Domain.Models; + +namespace Stater.CodeGeneration.LanguageAdapter.Base; + +public abstract class BaseLanguageAdapter +{ + protected abstract string TemplateName { get; } + protected abstract string TestTemplateName { get; } + + protected abstract string GetVariableValueTypeName(VariableValue value); + protected abstract string GetVariableValue(VariableValue value); + + protected abstract string GetCondition(Transition transition, Condition condition, StateMachine stateMachine); + protected abstract string GetEvent(Transition transition, Event eEvent, StateMachine stateMachine); + + public string Generate(StateMachine stateMachine, GenerationSettings settings) + { + return TemplateLoader.RenderTemplate( + TemplateName, + stateMachine, + settings, + GetVariableValueTypeName, + GetVariableValue, + GetCondition, + GetEvent, + new List>() + ); + } + + public string GenerateTests(StateMachine stateMachine, GenerationSettings settings, + List> scenarios) + { + return TemplateLoader.RenderTemplate( + TestTemplateName, + stateMachine, + settings, + GetVariableValueTypeName, + GetVariableValue, + GetCondition, + GetEvent, + scenarios + ); + } + + protected bool CheckDefaultMathCondition( + VariableValue variableValue1, + VariableValue variableValue2, + Condition.VariableCondition.ConditionTypeEnum conditionType + ) + { + return (variableValue1, variableValue2, conditionType) switch + { + (VariableValue.IntVariable, VariableValue.IntVariable, _) => true, + (VariableValue.IntVariable, VariableValue.FloatVariable, _) => true, + (VariableValue.FloatVariable, VariableValue.IntVariable, _) => true, + (VariableValue.FloatVariable, VariableValue.FloatVariable, _) => true, + + (VariableValue.StringVariable, VariableValue.StringVariable, Condition.VariableCondition.ConditionTypeEnum + .Eq) => true, + (VariableValue.StringVariable, VariableValue.StringVariable, Condition.VariableCondition.ConditionTypeEnum + .Ne) => true, + + (VariableValue.BoolVariable, VariableValue.BoolVariable, Condition.VariableCondition.ConditionTypeEnum.Eq) + => true, + (VariableValue.BoolVariable, VariableValue.BoolVariable, Condition.VariableCondition.ConditionTypeEnum.Ne) + => true, + + _ => false + }; + } + + protected bool CheckDefaultMathEvent( + VariableValue variableValue1, + VariableValue variableValue2, + Event.VariableMath.MathTypeEnum mathTypeEnum + ) + { + return (variableValue1, variableValue2, mathTypeEnum) switch + { + (VariableValue.IntVariable, VariableValue.IntVariable, _) => true, + (VariableValue.IntVariable, VariableValue.FloatVariable, _) => true, + (VariableValue.FloatVariable, VariableValue.IntVariable, _) => true, + (VariableValue.FloatVariable, VariableValue.FloatVariable, _) => true, + + (VariableValue.StringVariable, VariableValue.StringVariable, Event.VariableMath.MathTypeEnum.Sum) => true, + + _ => false + }; + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/LanguageAdapter/Base/TemplateLoader.cs b/src/Stater.CodeGeneration/LanguageAdapter/Base/TemplateLoader.cs new file mode 100644 index 0000000..0d8d472 --- /dev/null +++ b/src/Stater.CodeGeneration/LanguageAdapter/Base/TemplateLoader.cs @@ -0,0 +1,82 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using Scriban; +using Scriban.Runtime; +using Stater.CodeGeneration.Entity; +using Stater.Domain.Json; +using Stater.Domain.Models; + +namespace Stater.CodeGeneration.LanguageAdapter.Base; + +public static class TemplateLoader +{ + public static string LoadTemplate(string templateName) + { + var resourceName = $"Stater.CodeGeneration.Templates.{templateName}.scriban"; + + using var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName); + if (stream == null) + throw new FileNotFoundException($"Template {templateName} not found"); + + using var reader = new StreamReader(stream); + return reader.ReadToEnd(); + } + + public static string RenderTemplate( + string templateName, + StateMachine stateMachine, + GenerationSettings settings, + Func convertVariableType, + Func convertVariableValue, + Func convertCondition, + Func convertEvent, + List> scenarios + ) + { + var scriptObject = new ScriptObject(); + scriptObject.Import("convert_variable_type", new Func(convertVariableType)); + scriptObject.Import("convert_variable_value", new Func(convertVariableValue)); + + scriptObject.Import("convert_condition", + new Func((transition, condition) => + convertCondition(transition, condition, stateMachine))); + scriptObject.Import("convert_event", new Func((transition, eEvent) => + convertEvent(transition, eEvent, stateMachine))); + scriptObject["fsm"] = stateMachine; + scriptObject["settings"] = settings; + scriptObject["scenarios"] = scenarios; + scriptObject.Import("get_variable_by_uuid", stateMachine.GetVariableByGuid); + scriptObject.Import("get_state_by_uuid", stateMachine.GetStateByGuid); + scriptObject.Import("state_machine_json_schema", StateMachineJsonAdapter.ToJsonSchema); + + InitTestStateMachines(scriptObject, stateMachine); + + var context = new TemplateContext(); + context.PushGlobal(scriptObject); + + var templateContent = LoadTemplate(templateName); + var template = Template.Parse(templateContent); + return template.Render(context); + } + + private static void InitTestStateMachines(ScriptObject scriptObject, StateMachine sm) + { + var sm1 = sm with { States = sm.States.Concat(new[] { new State { Name = "__test_state_1__" } }).ToList() }; + var sm2 = sm1 with { States = sm1.States.Concat(new[] { new State { Name = "__test_state_2__" } }).ToList() }; + var sm3 = sm2 with + { + Transitions = sm2.Transitions.Concat(new[] + { + new Transition + { + Name = "__test_transition__", + Start = sm2.GetStateByName("__test_state_1__")!.Guid, + End = sm2.GetStateByName("__test_state_2__")!.Guid, + } + }).ToList() + }; + scriptObject["fsm_test_state_1"] = sm1; + scriptObject["fsm_test_state_2"] = sm2; + scriptObject["fsm_test_state_3"] = sm3; + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/LanguageAdapter/CPlusPlus/CPlusPlusAdapter.cs b/src/Stater.CodeGeneration/LanguageAdapter/CPlusPlus/CPlusPlusAdapter.cs new file mode 100644 index 0000000..1c83b75 --- /dev/null +++ b/src/Stater.CodeGeneration/LanguageAdapter/CPlusPlus/CPlusPlusAdapter.cs @@ -0,0 +1,66 @@ +using Stater.CodeGeneration.LanguageAdapter.Base; +using Stater.Domain.Models; + +namespace Stater.CodeGeneration.LanguageAdapter.CPlusPlus; + +public class CPlusPlusAdapter: BaseLanguageAdapter +{ + protected override string TemplateName => "cplusplus"; + protected override string TestTemplateName => "cplusplus-test"; + + protected override string GetVariableValueTypeName(VariableValue value) + { + return value switch + { + VariableValue.IntVariable => "int", + VariableValue.BoolVariable => "bool", + VariableValue.StringVariable => "std::string", + VariableValue.FloatVariable => "float", + _ => "unknown" + }; + } + + protected override string GetVariableValue(VariableValue value) + { + return value switch + { + VariableValue.IntVariable variable => variable.ToString(), + VariableValue.BoolVariable variable => variable.Value ? "false" : "true", + VariableValue.StringVariable variable => '"' + variable.Value + '"', + VariableValue.FloatVariable variable => variable.ToString() + 'f', + _ => "unknown" + }; + } + + protected override string GetCondition(Transition transition, Condition condition, StateMachine stateMachine) + { + switch (condition) + { + case Condition.VariableCondition e: + var variable = stateMachine.GetVariableByGuid(e.VariableGuid); + return !CheckDefaultMathCondition(variable!.StartValue, e.Value, e.ConditionType) + ? "return true;" + : $"return ctx->{variable.Name} {e.GetDefaultConditionSign()} {GetVariableValue(variable.StartValue)};"; + } + + return "true"; + } + + protected override string GetEvent(Transition transition, Event eEvent, StateMachine stateMachine) + { + switch (eEvent) + { + case Event.VariableMath e: + var variable1 = stateMachine.GetVariableByGuid(e.VariableGuid); + return !CheckDefaultMathEvent(variable1!.StartValue, e.Value, e.MathType) + ? "{};" + : $"ctx->{variable1.Name} = ctx->{variable1.Name} {e.GetDefaultMathTypeSign()} {GetVariableValue(e.Value)};"; + + case Event.VariableSet e: + var variable2 = stateMachine.GetVariableByGuid(e.VariableGuid); + return $"ctx->{variable2!.Name} = {GetVariableValue(e.Value)};"; + } + + return "{}"; + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/LanguageAdapter/CSharp/CSharpAdapter.cs b/src/Stater.CodeGeneration/LanguageAdapter/CSharp/CSharpAdapter.cs new file mode 100644 index 0000000..39f3667 --- /dev/null +++ b/src/Stater.CodeGeneration/LanguageAdapter/CSharp/CSharpAdapter.cs @@ -0,0 +1,66 @@ +using Stater.CodeGeneration.LanguageAdapter.Base; +using Stater.Domain.Models; + +namespace Stater.CodeGeneration.LanguageAdapter.CSharp; + +public class CSharpAdapter: BaseLanguageAdapter +{ + protected override string TemplateName => "csharp"; + protected override string TestTemplateName => "csharp-test"; + + protected override string GetVariableValueTypeName(VariableValue value) + { + return value switch + { + VariableValue.IntVariable => "int", + VariableValue.BoolVariable => "bool", + VariableValue.StringVariable => "string", + VariableValue.FloatVariable => "float", + _ => "unknown" + }; + } + + protected override string GetVariableValue(VariableValue value) + { + return value switch + { + VariableValue.IntVariable variable => variable.ToString(), + VariableValue.BoolVariable variable => variable.Value ? "false" : "true", + VariableValue.StringVariable variable => '"' + variable.Value + '"', + VariableValue.FloatVariable variable => variable.ToString() + 'f', + _ => "unknown" + }; + } + + protected override string GetCondition(Transition transition, Condition condition, StateMachine stateMachine) + { + switch (condition) + { + case Condition.VariableCondition e: + var variable = stateMachine.GetVariableByGuid(e.VariableGuid); + return !CheckDefaultMathCondition(variable!.StartValue, e.Value, e.ConditionType) + ? "true" + : $"ctx.{variable.Name} {e.GetDefaultConditionSign()} {GetVariableValue(variable.StartValue)}"; + } + + return "true"; + } + + protected override string GetEvent(Transition transition, Event eEvent, StateMachine stateMachine) + { + switch (eEvent) + { + case Event.VariableMath e: + var variable1 = stateMachine.GetVariableByGuid(e.VariableGuid); + return !CheckDefaultMathEvent(variable1!.StartValue, e.Value, e.MathType) + ? "{}" + : $"ctx.{variable1.Name} = ctx.{variable1.Name} {e.GetDefaultMathTypeSign()} {GetVariableValue(e.Value)}"; + + case Event.VariableSet e: + var variable2 = stateMachine.GetVariableByGuid(e.VariableGuid); + return $"ctx.{variable2!.Name} = {GetVariableValue(e.Value)}"; + } + + return "{}"; + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/LanguageAdapter/Java/JavaAdapter.cs b/src/Stater.CodeGeneration/LanguageAdapter/Java/JavaAdapter.cs new file mode 100644 index 0000000..5278e62 --- /dev/null +++ b/src/Stater.CodeGeneration/LanguageAdapter/Java/JavaAdapter.cs @@ -0,0 +1,66 @@ +using Stater.CodeGeneration.LanguageAdapter.Base; +using Stater.Domain.Models; + +namespace Stater.CodeGeneration.LanguageAdapter.Java; + +public class JavaAdapter : BaseLanguageAdapter +{ + protected override string TemplateName => "java"; + protected override string TestTemplateName => "java-test"; + + protected override string GetVariableValueTypeName(VariableValue value) + { + return value switch + { + VariableValue.IntVariable => "int", + VariableValue.BoolVariable => "boolean", + VariableValue.StringVariable => "String", + VariableValue.FloatVariable => "float", + _ => "unknown" + }; + } + + protected override string GetVariableValue(VariableValue value) + { + return value switch + { + VariableValue.IntVariable variable => variable.ToString(), + VariableValue.BoolVariable variable => variable.Value ? "false" : "true", + VariableValue.StringVariable variable => '"' + variable.Value + '"', + VariableValue.FloatVariable variable => variable.ToString() + 'f', + _ => "unknown" + }; + } + + protected override string GetCondition(Transition transition, Condition condition, StateMachine stateMachine) + { + switch (condition) + { + case Condition.VariableCondition e: + var variable = stateMachine.GetVariableByGuid(e.VariableGuid); + return !CheckDefaultMathCondition(variable!.StartValue, e.Value, e.ConditionType) + ? "true" + : $"ctx.{variable.Name} {e.GetDefaultConditionSign()} {GetVariableValue(variable.StartValue)}"; + } + + return "true"; + } + + protected override string GetEvent(Transition transition, Event eEvent, StateMachine stateMachine) + { + switch (eEvent) + { + case Event.VariableMath e: + var variable1 = stateMachine.GetVariableByGuid(e.VariableGuid); + return !CheckDefaultMathEvent(variable1!.StartValue, e.Value, e.MathType) + ? "{}" + : $"ctx.{variable1.Name} = ctx.{variable1.Name} {e.GetDefaultMathTypeSign()} {GetVariableValue(e.Value)}"; + + case Event.VariableSet e: + var variable2 = stateMachine.GetVariableByGuid(e.VariableGuid); + return $"ctx.{variable2!.Name} = {GetVariableValue(e.Value)}"; + } + + return "{}"; + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/LanguageAdapter/JavaScript/JavaScriptAdapter.cs b/src/Stater.CodeGeneration/LanguageAdapter/JavaScript/JavaScriptAdapter.cs new file mode 100644 index 0000000..a87f539 --- /dev/null +++ b/src/Stater.CodeGeneration/LanguageAdapter/JavaScript/JavaScriptAdapter.cs @@ -0,0 +1,56 @@ +using Stater.CodeGeneration.LanguageAdapter.Base; +using Stater.Domain.Models; + +namespace Stater.CodeGeneration.LanguageAdapter.JavaScript; + +public class JavaScriptAdapter : BaseLanguageAdapter +{ + protected override string TemplateName => "javascript"; + protected override string TestTemplateName => "javascript-test"; + + protected override string GetVariableValueTypeName(VariableValue value) + { + throw new NotImplementedException(); + } + + protected override string GetVariableValue(VariableValue value) + { + return value switch + { + VariableValue.IntVariable variable => variable.ToString(), + VariableValue.BoolVariable variable => variable.Value ? "false" : "true", + VariableValue.StringVariable variable => '"' + variable.Value + '"', + VariableValue.FloatVariable variable => variable.ToString(), + _ => "unknown" + }; + } + + protected override string GetCondition(Transition transition, Condition condition, StateMachine stateMachine) + { + switch (condition) + { + case Condition.VariableCondition e: + var variable = stateMachine.GetVariableByGuid(e.VariableGuid); + return + $"ctx.{variable!.Name} {e.GetDefaultConditionSign().Replace("==", "===")} {GetVariableValue(variable.StartValue)}"; + } + + return ""; + } + + protected override string GetEvent(Transition transition, Event eEvent, StateMachine stateMachine) + { + switch (eEvent) + { + case Event.VariableMath e: + var variable1 = stateMachine.GetVariableByGuid(e.VariableGuid); + return $"ctx.{variable1!.Name} = ctx.{variable1.Name} {e.GetDefaultMathTypeSign()} {GetVariableValue(e.Value)}"; + + case Event.VariableSet e: + var variable2 = stateMachine.GetVariableByGuid(e.VariableGuid); + return $"ctx.{variable2!.Name} = {GetVariableValue(e.Value)}"; + } + + return ""; + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/LanguageAdapter/Kotlin/KotlinAdapter.cs b/src/Stater.CodeGeneration/LanguageAdapter/Kotlin/KotlinAdapter.cs new file mode 100644 index 0000000..9baf708 --- /dev/null +++ b/src/Stater.CodeGeneration/LanguageAdapter/Kotlin/KotlinAdapter.cs @@ -0,0 +1,64 @@ +using Stater.CodeGeneration.LanguageAdapter.Base; +using Stater.Domain.Models; + +namespace Stater.CodeGeneration.LanguageAdapter.Kotlin; + +public class KotlinAdapter : BaseLanguageAdapter +{ + protected override string TemplateName => "kotlin"; + protected override string TestTemplateName => "kotlin-test"; + + protected override string GetVariableValueTypeName(VariableValue value) + { + return value switch + { + VariableValue.IntVariable => "Int", + VariableValue.BoolVariable => "Boolean", + VariableValue.StringVariable => "String", + VariableValue.FloatVariable => "Float", + _ => "unknown" + }; + } + + protected override string GetVariableValue(VariableValue value) + { + return value switch + { + VariableValue.IntVariable variable => variable.ToString(), + VariableValue.BoolVariable variable => variable.Value ? "false" : "true", + VariableValue.StringVariable variable => '"' + variable.Value + '"', + VariableValue.FloatVariable variable => variable.ToString() + 'f', + _ => "unknown" + }; + } + + protected override string GetCondition(Transition transition, Condition condition, StateMachine stateMachine) + { + switch (condition) + { + case Condition.VariableCondition e: + var variable = stateMachine.GetVariableByGuid(e.VariableGuid); + return $"it.{variable!.Name} {e.GetDefaultConditionSign()} {GetVariableValue(variable.StartValue)}"; + } + + return ""; + } + + protected override string GetEvent(Transition transition, Event eEvent, StateMachine stateMachine) + { + switch (eEvent) + { + case Event.VariableMath e: + var variable1 = stateMachine.GetVariableByGuid(e.VariableGuid); + return !CheckDefaultMathEvent(variable1!.StartValue, e.Value, e.MathType) + ? "" + : $"it.{variable1.Name} = it.{variable1.Name} {e.GetDefaultMathTypeSign()} {GetVariableValue(e.Value)}"; + + case Event.VariableSet e: + var variable2 = stateMachine.GetVariableByGuid(e.VariableGuid); + return $"it.{variable2!.Name} = {GetVariableValue(e.Value)}"; + } + + return ""; + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/LanguageAdapter/Python/PythonAdapter.cs b/src/Stater.CodeGeneration/LanguageAdapter/Python/PythonAdapter.cs new file mode 100644 index 0000000..2ada3a2 --- /dev/null +++ b/src/Stater.CodeGeneration/LanguageAdapter/Python/PythonAdapter.cs @@ -0,0 +1,62 @@ +using Stater.CodeGeneration.LanguageAdapter.Base; +using Stater.Domain.Models; + +namespace Stater.CodeGeneration.LanguageAdapter.Python; + +public class PythonAdapter : BaseLanguageAdapter +{ + protected override string TemplateName => "python"; + protected override string TestTemplateName => "python-test"; + + protected override string GetVariableValueTypeName(VariableValue value) + { + return value switch + { + VariableValue.IntVariable => "int", + VariableValue.BoolVariable => "bool", + VariableValue.StringVariable => "str", + VariableValue.FloatVariable => "float", + _ => "" + }; + } + + protected override string GetVariableValue(VariableValue value) + { + return value switch + { + VariableValue.IntVariable variable => variable.ToString(), + VariableValue.BoolVariable variable => variable.Value ? "False" : "True", + VariableValue.StringVariable variable => '"' + variable.Value + '"', + VariableValue.FloatVariable variable => variable.ToString(), + _ => "" + }; + } + + protected override string GetCondition(Transition transition, Condition condition, StateMachine stateMachine) + { + switch (condition) + { + case Condition.VariableCondition e: + var variable = stateMachine.GetVariableByGuid(e.VariableGuid); + return $"ctx.{variable!.Name} {e.GetDefaultConditionSign()} {GetVariableValue(variable.StartValue)}"; + } + + return ""; + } + + protected override string GetEvent(Transition transition, Event eEvent, StateMachine stateMachine) + { + switch (eEvent) + { + case Event.VariableMath e: + var variable1 = stateMachine.GetVariableByGuid(e.VariableGuid); + return + $"setattr(ctx, '{variable1!.Name}', ctx.{variable1.Name} {e.GetDefaultMathTypeSign()} {GetVariableValue(e.Value)})"; + case Event.VariableSet e: + var variable2 = stateMachine.GetVariableByGuid(e.VariableGuid); + return $"setattr(ctx, '{variable2!.Name}', {GetVariableValue(e.Value)})"; + } + + return ""; + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/LanguageAdapter/TypeScript/TypeScriptAdapter.cs b/src/Stater.CodeGeneration/LanguageAdapter/TypeScript/TypeScriptAdapter.cs new file mode 100644 index 0000000..7f1f26c --- /dev/null +++ b/src/Stater.CodeGeneration/LanguageAdapter/TypeScript/TypeScriptAdapter.cs @@ -0,0 +1,64 @@ +using Stater.CodeGeneration.LanguageAdapter.Base; +using Stater.Domain.Models; + +namespace Stater.CodeGeneration.LanguageAdapter.TypeScript; + +public class TypeScriptAdapter : BaseLanguageAdapter +{ + protected override string TemplateName => "typescript"; + protected override string TestTemplateName => "typescript-test"; + + protected override string GetVariableValueTypeName(VariableValue value) + { + return value switch + { + VariableValue.IntVariable => "number", + VariableValue.BoolVariable => "boolean", + VariableValue.StringVariable => "string", + VariableValue.FloatVariable => "number", + _ => "unknown" + }; + } + + protected override string GetVariableValue(VariableValue value) + { + return value switch + { + VariableValue.IntVariable variable => variable.ToString(), + VariableValue.BoolVariable variable => variable.Value ? "false" : "true", + VariableValue.StringVariable variable => '"' + variable.Value + '"', + VariableValue.FloatVariable variable => variable.ToString(), + _ => "unknown" + }; + } + + protected override string GetCondition(Transition transition, Condition condition, StateMachine stateMachine) + { + switch (condition) + { + case Condition.VariableCondition e: + var variable = stateMachine.GetVariableByGuid(e.VariableGuid); + return $"ctx.{variable!.Name} {e.GetDefaultConditionSign()} {GetVariableValue(variable.StartValue)}"; + } + + return ""; + } + + protected override string GetEvent(Transition transition, Event eEvent, StateMachine stateMachine) + { + switch (eEvent) + { + case Event.VariableMath e: + var variable1 = stateMachine.GetVariableByGuid(e.VariableGuid); + return !CheckDefaultMathEvent(variable1!.StartValue, e.Value, e.MathType) + ? "" + : $"ctx.{variable1.Name} = ctx.{variable1.Name} {e.GetDefaultMathTypeSign()} {GetVariableValue(e.Value)}"; + + case Event.VariableSet e: + var variable2 = stateMachine.GetVariableByGuid(e.VariableGuid); + return $"ctx.{variable2!.Name} = {GetVariableValue(e.Value)}"; + } + + return ""; + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/ScenarioFinder.cs b/src/Stater.CodeGeneration/ScenarioFinder.cs new file mode 100644 index 0000000..074a430 --- /dev/null +++ b/src/Stater.CodeGeneration/ScenarioFinder.cs @@ -0,0 +1,84 @@ +using Stater.Domain.Models; + +namespace Stater.CodeGeneration; + +internal record MultipleGuid( + Guid Guid1, + Guid Guid2 +); + +public static class ScenarioFinder +{ + public static List> FindScenarios(StateMachine stateMachine) + { + if (stateMachine.StartState == null) return new List>(); + var result = FindAllPaths(stateMachine.Transitions, stateMachine.StartState.Guid); + return result + .Where(el => el.Count > 0) + .DistinctBy(el => el + .Select(t => t.Guid.GetHashCode()) + .Aggregate(0, HashCode.Combine) + ) + .OrderByDescending(el => el.Count) + .Take(3) + .ToList(); + } + + private static IEnumerable> FindAllPaths(List transitions, Guid start) + { + var graph = BuildGraph(transitions); + var paths = new List>(); + var visited = new HashSet(); + Dfs(graph, transitions, null, start, new List(), visited, paths); + return paths; + } + + private static Dictionary> BuildGraph(List transitions) + { + var graph = new Dictionary>(); + + foreach (var transition in + transitions.Where(transition => transition is { Start: not null, End: not null })) + { + if (!graph.ContainsKey(transition.Start!.Value)) + graph[transition.Start.Value] = new List(); + + graph[transition.Start.Value].Add(transition.End!.Value); + } + + return graph; + } + + private static void Dfs( + IReadOnlyDictionary> graph, + IReadOnlyCollection transitions, + Guid? prev, + Guid current, + IList path, + ISet visited, + ICollection> paths) + { + if (prev != null) + visited.Add(new MultipleGuid((Guid)prev, current)); + + var isEnd = true; + if (graph.TryGetValue(current, out var value)) + { + foreach (var neighbor in value) + { + if (visited.Contains(new MultipleGuid(current, neighbor))) continue; + var transition = transitions.First(t => t.Start == current && t.End == neighbor); + path.Add(transition); + Dfs(graph, transitions, current, neighbor, path, visited, paths); + path.RemoveAt(path.Count - 1); + isEnd = false; + } + } + + if (isEnd) + paths.Add(new List(path)); + + if (prev != null) + visited.Remove(new MultipleGuid((Guid)prev, current)); + } +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/Stater.CodeGeneration.csproj b/src/Stater.CodeGeneration/Stater.CodeGeneration.csproj new file mode 100644 index 0000000..a8126c3 --- /dev/null +++ b/src/Stater.CodeGeneration/Stater.CodeGeneration.csproj @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + net8.0 + enable + enable + + + diff --git a/src/Stater.CodeGeneration/Templates/cplusplus-test.scriban b/src/Stater.CodeGeneration/Templates/cplusplus-test.scriban new file mode 100644 index 0000000..9704c5d --- /dev/null +++ b/src/Stater.CodeGeneration/Templates/cplusplus-test.scriban @@ -0,0 +1,60 @@ +#include <{{fsm.name}}.h> + +#include + +{{ func state(name) }} +{{- if settings.generate_states -}} +e_{{ fsm.name }}_states::{{ name }} +{{- else -}} +"{{ name }}" +{{- end -}} +{{ end }} + +{{if settings.mode == "Clazz"; build_generic = "new " + fsm.name + "_state_machine()"; else if settings.generate_interface; build_generic = "dynamic_cast(" + "st.get())"; else; build_generic = "builder_" + fsm.name + "_state_machine.build()"; end -}} +TEST({{ fsm.name }}_state_machine_test, test_init) { + {{- if settings.mode != "Clazz" && settings.generate_interface }} + const auto st = builder_{{ fsm.name }}_state_machine.build(); + {{- end }} + {{ build_generic }}; +} +{{ for index in 0..(scenarios.size - 1) }} + +TEST({{ fsm.name }}_state_machine_test, test_scenario_{{index}}) { + {{- if settings.mode != "Clazz" && settings.generate_interface }} + const auto st = builder_{{ fsm.name }}_state_machine.build(); + {{- end }} + const auto sm = {{ build_generic }}; + sm->disable_events(); + +{{ for transition in scenarios[index] }} + {{- if settings.generate_interface }} + sm->{{ transition.name }}(); + {{- else }} + sm->transition("{{ transition.name }}"); + {{- end }} + ASSERT_EQ(sm->get_state(), {{ state get_state_by_uuid(transition.end).name }}); +{{ end -}} +} +{{- end }} + +TEST({{ fsm.name }}_state_machine_test, test_json_schema) { + {{- if settings.mode != "Clazz" && settings.generate_interface }} + const auto st = builder_{{ fsm.name }}_state_machine.build(); + {{- end }} + auto sm = {{ build_generic }}; + ASSERT_EQ(nlohmann::json::parse(R"({{ state_machine_json_schema fsm }})"), nlohmann::json::parse(sm->to_json_schema())); +} +{{ if settings.mode == "Builder" && !settings.generate_states }} +TEST({{ fsm.name }}_state_machine_test, test_system_append_state_transition) { + auto sm_builder = builder_{{ fsm.name }}_state_machine; + + sm_builder = sm_builder.add_state("__test_state_1__"); + ASSERT_EQ(nlohmann::json::parse(R"({{ state_machine_json_schema fsm_test_state_1 }})"), nlohmann::json::parse(sm_builder.build()->to_json_schema())); + + sm_builder = sm_builder.add_state("__test_state_2__"); + ASSERT_EQ(nlohmann::json::parse(R"({{ state_machine_json_schema fsm_test_state_2 }})"), nlohmann::json::parse(sm_builder.build()->to_json_schema())); + + sm_builder = sm_builder.add_transition("__test_transition__", "__test_state_1__", "__test_state_2__"); + ASSERT_EQ(nlohmann::json::parse(R"({{ state_machine_json_schema fsm_test_state_3 }})"), nlohmann::json::parse(sm_builder.build()->to_json_schema())); +} +{{- end }} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/Templates/cplusplus.scriban b/src/Stater.CodeGeneration/Templates/cplusplus.scriban new file mode 100644 index 0000000..02d890e --- /dev/null +++ b/src/Stater.CodeGeneration/Templates/cplusplus.scriban @@ -0,0 +1,161 @@ +#pragma once + +#include + +{{ if settings.generate_states ~}} +enum class e_{{ fsm.name }}_states { + {{- for item in fsm.states }} + {{ item.name }}{{- if !for.last }}{{ "," }}{{- end }} + {{- end }} +}; + +inline void to_json(nlohmann::json &j, const e_{{ fsm.name }}_states &e) { + switch (e) { + {{- for item in fsm.states }} + case e_{{ fsm.name }}_states::{{ item.name }}: j = "{{ item.name }}"; + break; + {{- end }} + } +} + +inline void from_json(const nlohmann::json &j, e_{{ fsm.name }}_states &e) { + std::string state_str = j.get(); +{{~ for item in fsm.states }} + {{ if for.first }}if{{ else }}else if{{- end }} (state_str == "{{ item.name }}") e = e_{{ fsm.name }}_states::{{ item.name }}; + {{- end }} +} + +{{ end }} +{{- func state(name) -}} +{{- if settings.generate_states -}} +e_{{ fsm.name }}_states::{{ name }} +{{- else -}} +"{{ name }}" +{{- end -}} +{{- end -}} +{{- if settings.generate_context ~}} +class {{ fsm.name }}_context final : context { +public: +{{- for item in fsm.variables }} + {{ convert_variable_type item.start_value }} {{ item.name }} = {{ convert_variable_value item.start_value }}; +{{- end }} +}; + +{{ end -}} +{{- if !settings.generate_states; state_generic = "std::string"; else; state_generic = "e_" + fsm.name + "_states"; end }} +{{- if !settings.generate_context; context_generic = "empty_context"; else; context_generic = fsm.name + "_context"; end -}} +{{- if settings.mode == "Clazz" ~}} +class {{ fsm.name }}_state_machine : public stater_state_machine<{{ state_generic }}, {{ context_generic }}> { +public: + {{ fsm.name }}_state_machine() : stater_state_machine ( + { + {{- for item in fsm.state_transitions }} + transition_t<::{{ state_generic }}, {{ context_generic }}>( + "{{ item.transition.name }}", + {{ state item.start_state.name }}, + {{ state item.end_state.name }} {{- if item.transition.condition && settings.generate_context }}, + []({{ context_generic }} *ctx) { {{ convert_condition item.transition item.transition.condition }} }{{- else }}, + []({{ context_generic }} *ctx) { return true; } + {{- end }}{{- if item.transition.event && settings.generate_context }}, + []({{ context_generic }} *ctx) { {{ convert_event item.transition item.transition.event }} }{{- else }}, + []({{ context_generic }} *ctx) { } + {{- end }} + ){{- if !for.last }}{{ "," }}{{- end }} + {{- end }} + }, + new {{ context_generic }}(), + {{- if fsm.start_state != null }} + {{ state fsm.start_state.name }} + {{- else }}nullptr{{ end }} + ) { + } +{{ if settings.generate_interface }} + {{- for item in fsm.transitions }} + void {{ item.name }}() { + transition("{{ item.name }}"); + }{{- if !for.last }}{{ "\n" }}{{- end }} + {{- end }} +{{- end }} +}; +{{- else if settings.mode == "Builder" -}} +{{~ if settings.generate_interface ~}} +class types_{{ fsm.name }}_state_machine : public stater_state_machine<{{ state_generic }}, {{ context_generic }}> { +public: + types_{{ fsm.name }}_state_machine( + const std::vector> &transitions, + {{ context_generic }} *context, + const {{ state_generic }} &start_state, + const std::unordered_set<{{ state_generic }}> &states, + const std::unordered_map>> &transition_middlewares, + const std::vector> &transition_all_middlewares, + const std::unordered_map>> &transition_callbacks, + const std::vector> &transition_all_callbacks, + const std::unordered_map<{{ state_generic }}, std::vector>> &state_callbacks, + const std::vector> &state_all_callbacks, + const std::shared_ptr<::context_json_adapter<{{ context_generic }}> > &context_json_adapter + ) : stater_state_machine( + transitions, + context, + start_state, + states, + transition_middlewares, + transition_all_middlewares, + transition_callbacks, + transition_all_callbacks, + state_callbacks, + state_all_callbacks, + context_json_adapter + ) { + } +{{ if settings.generate_interface }} + {{- for item in fsm.transitions }} + void {{ item.name }}() { + transition("{{ item.name }}"); + }{{- if !for.last }}{{ "\n" }}{{- end }} + {{- end }} +{{- end }} +}; + +inline state_machine_factory<{{ state_generic }}, {{ context_generic }}> typed_{{ fsm.name }}_factory = []( + const std::vector > &transitions, + {{ context_generic }} *context, + {{ state_generic }} start_state, + const std::unordered_set<{{ state_generic }}> &states, + const std::unordered_map > > & + transition_middleware, + const std::vector > & + transition_all_middlewares, + const std::unordered_map > > & + transition_callbacks, + const std::vector > &transition_all_callbacks, + const std::unordered_map<::{{ state_generic }}, std::vector > > &state_callbacks, + const std::vector > &state_all_callbacks, + const std::shared_ptr >& context_json_adapter_) -> + std::unique_ptr { + return std::make_unique( + transitions, context, start_state, states, + transition_middleware, transition_all_middlewares, + transition_callbacks, transition_all_callbacks, + state_callbacks, state_all_callbacks, context_json_adapter_); +}; + + +{{ end ~}} +inline stater_state_machine_builder<{{ state_generic }}, {{ context_generic }}> builder_{{ fsm.name }}_state_machine = stater_state_machine_builder<{{ state_generic }}, {{ context_generic }}>() +{{- if fsm.start_state != null }} + .set_start_state({{ state fsm.start_state.name }}) +{{- end }} + .set_context(new {{ context_generic }}()) +{{- if settings.generate_interface }} + .set_factory(typed_{{ fsm.name }}_factory) +{{- end }} +{{- for item in fsm.state_transitions }} + .add_transition("{{ item.transition.name }}", {{ state item.start_state.name }}, {{ state item.end_state.name }}) +{{- if item.transition.condition && settings.generate_context }} + .set_transition_condition("{{ item.transition.name }}", []({{ context_generic }} *ctx) { {{ convert_condition item.transition item.transition.condition }} }) +{{- end }} +{{- if item.transition.event && settings.generate_context }} + .set_transition_event("{{ item.transition.name }}", []({{ context_generic }} *ctx) { {{ convert_event item.transition item.transition.event }} }) +{{- end }} +{{- end }}; +{{- end }} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/Templates/csharp-test.scriban b/src/Stater.CodeGeneration/Templates/csharp-test.scriban new file mode 100644 index 0000000..4e36c31 --- /dev/null +++ b/src/Stater.CodeGeneration/Templates/csharp-test.scriban @@ -0,0 +1,73 @@ +namespace fsm.{{ fsm.name | string.downcase }}; + +using Newtonsoft.Json.Linq; + + +{{- func state(name) -}} +{{- if settings.generate_states -}} +States.{{ name }} +{{- else -}} +"{{ name }}" +{{- end -}} +{{- end }} + +{{if settings.mode == "Clazz"; build_generic = "new " + fsm.name + "StateMachine()"; else if settings.generate_interface; build_generic = fsm.name + ".Builder" + fsm.name + "StateMachine.Build() as " + fsm.name + ".Types" + fsm.name + "StateMachine"; else; build_generic = fsm.name + ".Builder" + fsm.name + "StateMachine.Build()"; end -}} +[Collection("{{ fsm.name }} Auto Generated Tests")] +public class Test{{ fsm.name }} { + [Fact] + private void TestInit() + { + _ = {{ build_generic }}; + } + +{{ for index in 0..(scenarios.size - 1) }} + [Fact] + private void TestScenario{{index}}() + { + var sm = {{ build_generic }}; + sm.DisableEvents(); + +{{ for transition in scenarios[index] }} + {{- if settings.generate_interface }} + sm.{{ transition.name }}(); + {{- else }} + sm.Transition("{{ transition.name }}"); + {{- end }} + Assert.Equal({{ state get_state_by_uuid(transition.end).name }}, sm.GetState()); +{{ end }} + } + {{- end }} + + [Fact] + private void TestJsonSchema() + { + var sm = {{ build_generic }}; + Assert.Equal(JObject.Parse(""" + {{ state_machine_json_schema fsm }} + """ + ), JObject.Parse(sm.ToJsonSchema())); + } + +{{ if settings.mode == "Builder" && !settings.generate_states }} + [Fact] + private void TestSystemAppendStateTransition() + { + var smBuilder = {{ fsm.name }}.Builder{{ fsm.name }}StateMachine.Copy(); + + smBuilder = smBuilder.AddState("__test_state_1__"); + Assert.Equal(JObject.Parse(""" + {{ state_machine_json_schema fsm_test_state_1 }} + """), JObject.Parse(smBuilder.Build().ToJsonSchema())); + + smBuilder = smBuilder.AddState("__test_state_2__"); + Assert.Equal(JObject.Parse(""" + {{ state_machine_json_schema fsm_test_state_2 }} + """), JObject.Parse(smBuilder.Build().ToJsonSchema())); + + smBuilder = smBuilder.AddTransition("__test_transition__", "__test_state_1__", "__test_state_2__"); + Assert.Equal(JObject.Parse(""" + {{ state_machine_json_schema fsm_test_state_3 }} + """), JObject.Parse(smBuilder.Build().ToJsonSchema())); + } + {{- end }} +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/Templates/csharp.scriban b/src/Stater.CodeGeneration/Templates/csharp.scriban new file mode 100644 index 0000000..7335df7 --- /dev/null +++ b/src/Stater.CodeGeneration/Templates/csharp.scriban @@ -0,0 +1,147 @@ +namespace fsm.{{ fsm.name | string.downcase }}; + +using Stater.StateMachine.Lib; + +{{ if settings.generate_states ~}} +public enum States { + {{- for item in fsm.states }} + {{ item.name }}{{- if !for.last }}{{ "," }}{{- end }} + {{- end }} +} + +{{ end }} +{{- func state(name) -}} +{{- if settings.generate_states -}} +States.{{ name }} +{{- else -}} +"{{ name }}" +{{- end -}} +{{- end -}} +{{- if settings.generate_context ~}} +public class {{ fsm.name }}FSMContext : IContext{ +{{- for item in fsm.variables }} + public {{ convert_variable_type item.start_value }} {{ item.name }} = {{ convert_variable_value item.start_value }}; +{{- end}} +} + +{{ end -}} +{{- if !settings.generate_states; state_generic = "String"; else; state_generic = "States"; end }} +{{- if !settings.generate_context; context_generic = "EmptyContext"; else; context_generic = fsm.name+"FSMContext"; end -}} +{{- if settings.mode == "Clazz" ~}} +public class {{ fsm.name }}StateMachine() : StaterStateMachine<{{ state_generic }}, {{ context_generic }}>( + new List> + { + {{- for item in fsm.state_transitions }} + new( + "{{ item.transition.name }}", + {{ state item.start_state.name }}, + {{ state item.end_state.name }} {{- if item.transition.condition && settings.generate_context }}, + ctx => {{ convert_condition item.transition item.transition.condition }} {{- else }}, + ctx => true + {{- end }}{{- if item.transition.event && settings.generate_context }}, + ctx => {{ convert_event item.transition item.transition.event }} {{- else }}, + ctx => { } + {{- end }} + ){{- if !for.last }}{{ "," }}{{- end }} + {{- end }} + }, + new {{ context_generic }}(), + {{- if fsm.start_state != null }} + {{ state fsm.start_state.name }} + {{- else }}null{{ end }} +) +{ +{{- if settings.generate_interface }} + {{- for item in fsm.transitions }} + public void {{ item.name }}() + { + Transition("{{ item.name }}"); + }{{- if !for.last }}{{ "\n" }}{{- end }} + {{- end }} +{{- end }} +} +{{- else if settings.mode == "Builder" -}} +public class {{fsm.name}} { +{{~ if settings.generate_interface ~}} + public class Types{{ fsm.name }}StateMachine( + List> transitions, + {{ context_generic }} context, + {{ state_generic }} startState, + HashSet<{{ state_generic }}> states, + Dictionary>> transitionMiddlewares, + List> transitionAllMiddlewares, + Dictionary>> transitionCallbacks, + List> transitionAllCallbacks, + Dictionary<{{ state_generic }}, List>> stateCallbacks, + List> stateAllCallbacks, + IContextJsonAdapter<{{ context_generic }}> contextJsonAdapter + ) : StaterStateMachine<{{ state_generic }}, {{ context_generic }}>( + transitions, + context, + startState, + states, + transitionMiddlewares, + transitionAllMiddlewares, + transitionCallbacks, + transitionAllCallbacks, + stateCallbacks, + stateAllCallbacks, + contextJsonAdapter + ) + { + {{- if settings.generate_interface }} + {{- for item in fsm.transitions }} + public void {{ item.name }}() + { + Transition("{{ item.name }}"); + }{{- if !for.last }}{{ "\n" }}{{- end }} + {{- end }} + } +{{- end }} + private static StateMachineFactory<{{ state_generic }}, {{ context_generic }}> Typed{{ fsm.name }}Factory = ( + transitionsA, + contextA, + startStateA, + statesA, + transitionMiddlewaresA, + transitionAllMiddlewaresA, + transitionCallbacksA, + transitionAllCallbacksA, + stateCallbacksA, + stateAllCallbacksA, + contextJsonAdapterA + ) => new Types{{ fsm.name }}StateMachine( + transitionsA, + contextA, + startStateA, + statesA, + transitionMiddlewaresA, + transitionAllMiddlewaresA, + transitionCallbacksA, + transitionAllCallbacksA, + stateCallbacksA, + stateAllCallbacksA, + contextJsonAdapterA + ); + + +{{ end ~}} + public static StaterStateMachineBuilder<{{ state_generic }}, {{ context_generic }}> Builder{{ fsm.name }}StateMachine = new StaterStateMachineBuilder<{{ state_generic }}, {{ context_generic }}>() + {{- if fsm.start_state != null }} + .SetStartState({{ state fsm.start_state.name }}) + {{- end }} + .SetContext(new {{ context_generic }}()) + {{- if settings.generate_interface }} + .SetFactory(Typed{{ fsm.name }}Factory) + {{- end }} + {{- for item in fsm.state_transitions }} + .AddTransition("{{ item.transition.name }}", {{ state item.start_state.name }}, {{ state item.end_state.name }}) + {{- if item.transition.condition && settings.generate_context }} + .SetTransitionCondition("{{ item.transition.name }}", ctx => {{ convert_condition item.transition item.transition.condition }}) + {{- end }} + {{- if item.transition.event && settings.generate_context }} + .SetTransitionEvent("{{ item.transition.name }}", ctx => {{ convert_event item.transition item.transition.event }}) + {{- end }} + {{- end }}; +} +{{- end }} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/Templates/java-test.scriban b/src/Stater.CodeGeneration/Templates/java-test.scriban new file mode 100644 index 0000000..d8cca27 --- /dev/null +++ b/src/Stater.CodeGeneration/Templates/java-test.scriban @@ -0,0 +1,67 @@ +package fsm.{{ fsm.name | string.downcase }}; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; +import com.fasterxml.jackson.databind.ObjectMapper; + + +{{- func state(name) -}} +{{- if settings.generate_states -}} +{{ fsm.name }}.States.{{ name }} +{{- else -}} +"{{ name }}" +{{- end -}} +{{- end }} + +{{if settings.mode == "Clazz"; build_generic = "new " + fsm.name + "." + fsm.name + "StateMachine()"; else if settings.generate_interface; build_generic = "(" + fsm.name + ".Types" + fsm.name + "StateMachine)" + fsm.name + ".builder" + fsm.name + "StateMachine.build()"; else; build_generic = fsm.name + ".builder" + fsm.name + "StateMachine.build()"; end -}} +class Test{{ fsm.name }} { + @Test + void testInit() { + var fsm = {{ build_generic }}; + } + +{{ for index in 0..(scenarios.size - 1) }} + @Test + void testScenario{{index}}() { + var sm = {{ build_generic }}; + sm.disableEvents(); + +{{ for transition in scenarios[index] }} + {{- if settings.generate_interface }} + sm.{{ transition.name }}(); + {{- else }} + sm.transition("{{ transition.name }}"); + {{- end }} + assertEquals(sm.getState(), {{ state get_state_by_uuid(transition.end).name }}); +{{ end }} + } + {{- end }} + + @Test + void testJsonSchema() throws Exception { + var sm = {{ build_generic }}; + assertEquals(new ObjectMapper().readTree(""" + {{ state_machine_json_schema fsm }} + """ + ), new ObjectMapper().readTree(sm.toJsonSchema())); + } + + {{ if settings.mode == "Builder" && !settings.generate_states }} + @Test + void testSystemAppendStateTransition() throws Exception { + var smBuilder = {{ fsm.name }}.builder{{ fsm.name }}StateMachine; + + smBuilder = smBuilder.addState("__test_state_1__"); + assertEquals(new ObjectMapper().readTree(""" + {{ state_machine_json_schema fsm_test_state_1 }}"""), new ObjectMapper().readTree(smBuilder.build().toJsonSchema())); + + smBuilder = smBuilder.addState("__test_state_2__"); + assertEquals(new ObjectMapper().readTree(""" + {{ state_machine_json_schema fsm_test_state_2 }}"""), new ObjectMapper().readTree(smBuilder.build().toJsonSchema())); + + smBuilder = smBuilder.addTransition("__test_transition__", "__test_state_1__", "__test_state_2__"); + assertEquals(new ObjectMapper().readTree(""" + {{ state_machine_json_schema fsm_test_state_3 }}"""), new ObjectMapper().readTree(smBuilder.build().toJsonSchema())); + } + {{- end }} +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/Templates/java.scriban b/src/Stater.CodeGeneration/Templates/java.scriban new file mode 100644 index 0000000..7018f1c --- /dev/null +++ b/src/Stater.CodeGeneration/Templates/java.scriban @@ -0,0 +1,128 @@ +package fsm.{{ fsm.name | string.downcase }}; + +import com.stater.statemachine.java.*; +import java.util.*; + +class {{ fsm.name }} { +{{ if settings.generate_states ~}} + static enum States { + {{- for item in fsm.states }} + {{ item.name }}{{- if !for.last }}{{ "," }}{{- end }} + {{- end }} + } + +{{ end }} +{{- func state(name) -}} +{{- if settings.generate_states -}} +States.{{ name }} +{{- else -}} +"{{ name }}" +{{- end -}} +{{- end -}} +{{- if settings.generate_context ~}} + static class {{ fsm.name }}FSMContext implements Context{ +{{- for item in fsm.variables }} + {{ convert_variable_type item.start_value }} {{ item.name }} = {{ convert_variable_value item.start_value }}; +{{- end}} + } + +{{ end -}} +{{- if !settings.generate_states; state_generic = "String"; else; state_generic = "States"; end }} +{{- if !settings.generate_context; context_generic = "EmptyContext"; else; context_generic = fsm.name+"FSMContext"; end -}} +{{- if settings.mode == "Clazz" ~}} + static class {{ fsm.name }}StateMachine extends StaterStateMachine<{{ state_generic }}, {{ context_generic }}>{ + public {{ fsm.name }}StateMachine() { + super( + List.of( + {{- for item in fsm.state_transitions }} + new Transition<>( + "{{ item.transition.name }}", + {{ state item.start_state.name }}, + {{ state item.end_state.name }} {{- if item.transition.condition && settings.generate_context }}, + ctx -> {{ convert_condition item.transition item.transition.condition }} {{- else }}, + ctx -> true + {{- end }}{{- if item.transition.event && settings.generate_context }}, + ctx -> {{ convert_event item.transition item.transition.event }} {{- else }}, + ctx -> {} + {{- end }} + ){{- if !for.last }}{{ "," }}{{- end }} + {{- end }} + ), + new {{ context_generic }}(), + {{- if fsm.start_state != null }} + {{ state fsm.start_state.name }} + {{- else }}null{{ end }} + ); + } +{{- if settings.generate_interface }} + {{- for item in fsm.transitions }} + + void {{ item.name }}() { + transition("{{ item.name }}"); + } + {{- end }} +{{- end }} + } +{{- else if settings.mode == "Builder" -}} +{{- if settings.generate_interface ~}} + static class Types{{ fsm.name }}StateMachine extends StaterStateMachine<{{ state_generic }}, {{ context_generic }}> { + public Types{{ fsm.name }}StateMachine( + List> transitions, + {{ context_generic }} context, + {{ state_generic }} startState, + Set<{{ state_generic }}> states, + Map>> transitionMiddlewares, + List> transitionAllMiddlewares, + Map>> transitionCallbacks, + List> transitionAllCallbacks, + Map<{{ state_generic }}, List>> stateCallbacks, + List> stateAllCallbacks, + ContextJsonAdapter<{{ context_generic }}> contextJsonAdapter + ) { + super( + transitions, + context, + startState, + states, + transitionMiddlewares, + transitionAllMiddlewares, + transitionCallbacks, + transitionAllCallbacks, + stateCallbacks, + stateAllCallbacks, + contextJsonAdapter + ); + } +{{- if settings.generate_interface }} + {{- for item in fsm.transitions }} + + void {{ item.name }}() { + transition("{{ item.name }}"); + } + {{- end }} + } +{{- end }} + + static private final StateMachineFactory<{{ state_generic }}, {{ context_generic }}> typed{{ fsm.name }}Factory = Types{{ fsm.name }}StateMachine::new; + + +{{ end ~}} + static public final StaterStateMachineBuilder<{{ state_generic }}, {{ context_generic }}> builder{{ fsm.name }}StateMachine = new StaterStateMachineBuilder<{{ state_generic }}, {{ context_generic }}>() + {{- if fsm.start_state != null }} + .setStartState({{ state fsm.start_state.name }}) + {{- end }} + .setContext(new {{ context_generic }}()) + {{- if settings.generate_interface }} + .setFactory(typed{{ fsm.name }}Factory) + {{- end }} + {{- for item in fsm.state_transitions }} + .addTransition("{{ item.transition.name }}", {{ state item.start_state.name }}, {{ state item.end_state.name }}) + {{- if item.transition.condition && settings.generate_context }} + .setTransitionCondition("{{ item.transition.name }}", ctx -> {{ convert_condition item.transition item.transition.condition }}) + {{- end }} + {{- if item.transition.event && settings.generate_context }} + .setTransitionEvent("{{ item.transition.name }}", ctx -> {{ convert_event item.transition item.transition.event }}) + {{- end }} + {{- end }}; +{{- end }} +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/Templates/javascript-test.scriban b/src/Stater.CodeGeneration/Templates/javascript-test.scriban new file mode 100644 index 0000000..041cfee --- /dev/null +++ b/src/Stater.CodeGeneration/Templates/javascript-test.scriban @@ -0,0 +1,54 @@ +{{- if settings.mode == "Builder" }}import {builder{{ fsm.name }}StateMachine} from "./{{ fsm.name }}.js";{{ "\n" }}{{- end }} +{{- if settings.mode == "Clazz" }}import { {{- fsm.name }}StateMachine} from "./{{ fsm.name }}.js";{{ "\n" }}{{- end }} +{{- if settings.generate_states }}import {States} from "./{{fsm.name}}.js";{{ "\n" }}{{- end }} + +{{ func state(name) }} +{{- if settings.generate_states -}} +States.{{ name }} +{{- else -}} +"{{ name }}" +{{- end -}} +{{ end }} + +{{- if settings.mode == "Clazz"; build_generic = "new " + fsm.name + "StateMachine"; else; build_generic = "builder" + fsm.name + "StateMachine.build"; end -}} + +test('testInit', () => { + {{ build_generic }}() +}) + +{{ for index in 0..(scenarios.size - 1) }} + +test('testScenario{{ index }}', () => { + const sm = {{ build_generic }}() + sm.disableEvents() + +{{ for transition in scenarios[index] }} + {{- if settings.generate_interface }} + sm.{{ transition.name }}() + {{- else }} + sm.transition('{{ transition.name }}') + {{- end }} + expect(sm.getState()).toBe({{ state get_state_by_uuid(transition.end).name }}) +{{ end }} +}){{- end }} + + +test('testJsonSchema', () => { + const sm = {{ build_generic }}() + expect(JSON.parse(`{{ state_machine_json_schema fsm }}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + +{{ if settings.mode == "Builder" && !settings.generate_states }} +test('testSystemAppendStateTransition', () => { + let smBuilder = builder{{ fsm.name }}StateMachine + + smBuilder = smBuilder.addState('__test_state_1__') + expect(JSON.parse(`{{ state_machine_json_schema fsm_test_state_1 }}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addState('__test_state_2__') + expect(JSON.parse(`{{ state_machine_json_schema fsm_test_state_2 }}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addTransition('__test_transition__', '__test_state_1__', '__test_state_2__') + expect(JSON.parse(`{{ state_machine_json_schema fsm_test_state_3 }}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) +}) +{{- end }} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/Templates/javascript.scriban b/src/Stater.CodeGeneration/Templates/javascript.scriban new file mode 100644 index 0000000..f34eec1 --- /dev/null +++ b/src/Stater.CodeGeneration/Templates/javascript.scriban @@ -0,0 +1,100 @@ +{{- if settings.generate_interface || settings.mode == "Clazz" }}import {StaterStateMachine} from "./index.js";{{ "\n" }}{{- end }} +{{- if settings.mode == "Builder" }}import {StaterStateMachineBuilder} from "./index.js";{{ "\n" }}{{- end }} +{{- if settings.mode == "Clazz" }}{{ "\n" }}{{- end }} +{{ if settings.generate_states -}} +export const States = Object.freeze({ + {{- for item in fsm.states }} + {{ item.name }}: "{{ item.name }}"{{- if !for.last }}{{ "," }}{{- end }} + {{- end }} +}); + +{{ end }} +{{- func state(name) -}} +{{- if settings.generate_states -}} +States.{{ name }} +{{- else -}} +"{{ name }}" +{{- end -}} +{{- end -}} +{{- if settings.generate_context -}} +const build{{ fsm.name }}FSMContext = () => { + return { +{{- for item in fsm.variables }} + {{ item.name }}: {{ convert_variable_value item.start_value }}{{- if !for.last }}{{ "," }}{{- end }} +{{- end}} + } +} + + +{{ end -}} +{{- if !settings.generate_states; state_generic = "string"; else; state_generic = "States"; end }} +{{- if !settings.generate_context; context_generic_builder = "{}"; else; context_generic_builder = "build"+fsm.name+"FSMContext()"; end -}} +{{- if settings.mode == "Clazz" -}} +export class {{ fsm.name }}StateMachine extends StaterStateMachine { + constructor() { + super( + [ + {{- for item in fsm.state_transitions }} + { + name: "{{ item.transition.name }}", + start: {{ state item.start_state.name }}, + end: {{ state item.end_state.name }} {{- if item.transition.condition && settings.generate_context }}, + condition: (ctx) => {{ convert_condition item.transition item.transition.condition }} + {{- end }}{{- if item.transition.event && settings.generate_context }}, + event: (ctx) => { {{ convert_event item.transition item.transition.event }} } + {{- end }} + }{{- if !for.last }}{{ "," }}{{- end }} + {{- end }} + ], + {{ context_generic_builder }}, + {{- if fsm.start_state != null }} + {{ state fsm.start_state.name }}, + {{- end }} + ) + } +{{- if settings.generate_interface }} +{{ end -}} +{{- if settings.generate_interface }} +{{- for item in fsm.transitions }} + {{ item.name }}() { + this.transition("{{ item.name }}") + } +{{- if !for.last }} +{{ end -}} +{{- end }} +{{- end }} +} + +{{- else if settings.mode == "Builder" -}} +{{- if settings.generate_interface -}} +class Types{{ fsm.name }}StateMachine extends StaterStateMachine { +{{- for item in fsm.transitions }} + {{ item.name }}() { + this.transition("{{ item.name }}") + } +{{- if !for.last }} +{{ end -}} +{{- end }} +} + +const typed{{ fsm.name }}Factory = (...args) => new Types{{ fsm.name }}StateMachine(...args); + +{{ end -}} +export const builder{{ fsm.name }}StateMachine = new StaterStateMachineBuilder() + {{- if fsm.start_state != null }} + .setStartState({{ state fsm.start_state.name }}) + {{- end }} + .setContext({{ context_generic_builder }}) + {{- if settings.generate_interface }} + .setFactory(typed{{ fsm.name }}Factory) + {{- end }} + {{- for item in fsm.state_transitions }} + .addTransition("{{ item.transition.name }}", {{ state item.start_state.name }}, {{ state item.end_state.name }}) + {{- if item.transition.condition && settings.generate_context }} + .setTransitionCondition("{{ item.transition.name }}", (ctx) => {{ convert_condition item.transition item.transition.condition }}) + {{- end }} + {{- if item.transition.event && settings.generate_context }} + .setTransitionEvent("{{ item.transition.name }}", (ctx) => { {{ convert_event item.transition item.transition.event }} }) + {{- end }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/Templates/kotlin-test.scriban b/src/Stater.CodeGeneration/Templates/kotlin-test.scriban new file mode 100644 index 0000000..e0bab08 --- /dev/null +++ b/src/Stater.CodeGeneration/Templates/kotlin-test.scriban @@ -0,0 +1,62 @@ +package fsm.{{ fsm.name | string.downcase }}; + +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import com.fasterxml.jackson.databind.ObjectMapper + + +{{- func state(name) -}} +{{- if settings.generate_states -}} +States.{{ name }} +{{- else -}} +"{{ name }}" +{{- end -}} +{{- end }} + +{{if settings.mode == "Clazz"; build_generic = fsm.name + "StateMachine()"; else if settings.generate_interface; build_generic = "builder" + fsm.name + "StateMachine.build() as Types" + fsm.name + "StateMachine"; else; build_generic = "builder" + fsm.name + "StateMachine.build()"; end -}} +class Test{{ fsm.name }} { + @Test + fun testInit() { + {{ build_generic }} + } + +{{ for index in 0..(scenarios.size - 1) }} + @Test + fun testScenario{{index}}() { + val sm = {{ build_generic }} + sm.disableEvents() + +{{ for transition in scenarios[index] }} + {{- if settings.generate_interface }} + sm.{{ transition.name }}() + {{- else }} + sm.transition("{{ transition.name }}") + {{- end }} + assertEquals(sm.getState(), {{ state get_state_by_uuid(transition.end).name }}) +{{ end }} + } + {{- end }} + + @Test + fun testJsonSchema() { + val sm = {{ build_generic }} + assertEquals(ObjectMapper().readTree("""{{ state_machine_json_schema fsm }}"""), ObjectMapper().readTree(sm.toJsonSchema())) + } + + {{ if settings.mode == "Builder" && !settings.generate_states }} + @Test + fun testSystemAppendStateTransition(){ + var smBuilder = builder{{ fsm.name }}StateMachine + + smBuilder = smBuilder.addState("__test_state_1__") + assertEquals(ObjectMapper().readTree("""{{ state_machine_json_schema fsm_test_state_1 }}"""), ObjectMapper().readTree(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addState("__test_state_2__") + assertEquals(ObjectMapper().readTree("""{{ state_machine_json_schema fsm_test_state_2 }}"""), ObjectMapper().readTree(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addTransition("__test_transition__", "__test_state_1__", "__test_state_2__") + assertEquals(ObjectMapper().readTree("""{{ state_machine_json_schema fsm_test_state_3 }}"""), ObjectMapper().readTree(smBuilder.build().toJsonSchema())) + } + {{- end }} +} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/Templates/kotlin.scriban b/src/Stater.CodeGeneration/Templates/kotlin.scriban new file mode 100644 index 0000000..5c2b70f --- /dev/null +++ b/src/Stater.CodeGeneration/Templates/kotlin.scriban @@ -0,0 +1,134 @@ +package fsm.{{ fsm.name | string.downcase }} + +import com.stater.statemachine.kotlin.* + +{{ if settings.generate_states -}} +enum class States { + {{- for item in fsm.states }} + {{ item.name }}{{- if !for.last }}{{ "," }}{{- end }} + {{- end }} +} + +{{ end }} +{{- func state(name) -}} +{{- if settings.generate_states -}} +States.{{ name }} +{{- else -}} +"{{ name }}" +{{- end -}} +{{- end -}} +{{- if settings.generate_context -}} +data class {{ fsm.name }}FSMContext( +{{- for item in fsm.variables }} + var {{ item.name }}: {{ convert_variable_type item.start_value }} = {{ convert_variable_value item.start_value }}{{- if !for.last }}{{ "," }}{{- end }} +{{- end}} +) : Context + +{{ end -}} +{{- if !settings.generate_states; state_generic = "String"; else; state_generic = "States"; end }} +{{- if !settings.generate_context; context_generic = "EmptyContext"; else; context_generic = fsm.name+"FSMContext"; end -}} +{{- if settings.mode == "Clazz" -}} +class {{ fsm.name }}StateMachine : StaterStateMachine<{{ state_generic }}, {{ context_generic }}>( + transitions = listOf( + {{- for item in fsm.state_transitions }} + Transition( + name = "{{ item.transition.name }}", + start = {{ state item.start_state.name }}, + end = {{ state item.end_state.name }} {{- if item.transition.condition && settings.generate_context }}, + condition = { {{ convert_condition item.transition item.transition.condition }} } + {{- end }}{{- if item.transition.event && settings.generate_context }}, + event = { {{ convert_event item.transition item.transition.event }} } + {{- end }} + ){{- if !for.last }}{{ "," }}{{- end }} + {{- end }} + ), + {{- if fsm.start_state != null }} + startState = {{ state fsm.start_state.name }}, + {{- end }} + context = {{ context_generic }}() +){{- if settings.generate_interface }} { + {{- for item in fsm.transitions }} + fun {{ item.name }}() = transition("{{ item.name }}") + {{- end }} +} +{{- end }} +{{- else if settings.mode == "Builder" -}} +{{- if settings.generate_interface -}} +class Types{{ fsm.name }}StateMachine( + transitions: List>, + startState: {{ state_generic }}, + states: Set<{{ state_generic }}>, + context: {{ context_generic }}, + transitionMiddlewares: Map>> = mapOf(), + transitionAllMiddlewares: List> = listOf(), + transitionCallbacks: Map>> = mapOf(), + transitionAllCallbacks: List> = listOf(), + stateCallbacks: Map<{{ state_generic }}, List>> = mapOf(), + stateAllCallbacks: List> = listOf(), + contextJsonAdapter: ContextJsonAdapter<{{ context_generic }}>? = null, +) : StaterStateMachine<{{ state_generic }}, {{ context_generic }}>( + transitions = transitions, + startState = startState, + states = states, + context = context, + transitionMiddlewares = transitionMiddlewares, + transitionAllMiddlewares = transitionAllMiddlewares, + transitionCallbacks = transitionCallbacks, + transitionAllCallbacks = transitionAllCallbacks, + stateCallbacks = stateCallbacks, + stateAllCallbacks = stateAllCallbacks, + contextJsonAdapter = contextJsonAdapter +){{- if settings.generate_interface }} { + {{- for item in fsm.transitions }} + fun {{ item.name }}() = transition("{{ item.name }}") + {{- end }} +} +{{- end }} + +private val typed{{ fsm.name }}Factory: StateMachineFactory<{{ state_generic }}, {{ context_generic }}> = { + transitionsA, + contextA, + startStateA, + statesA, + transitionMiddlewaresA, + transitionAllMiddlewaresA, + transitionCallbacksA, + transitionAllCallbacksA, + stateCallbacksA, + stateAllCallbacksA, + contextJsonAdapterA, + -> + Types{{ fsm.name }}StateMachine( + transitions = transitionsA, + context = contextA, + startState = startStateA, + states = statesA, + transitionMiddlewares = transitionMiddlewaresA, + transitionAllMiddlewares = transitionAllMiddlewaresA, + transitionCallbacks = transitionCallbacksA, + transitionAllCallbacks = transitionAllCallbacksA, + stateCallbacks = stateCallbacksA, + stateAllCallbacks = stateAllCallbacksA, + contextJsonAdapter = contextJsonAdapterA + ) +} + +{{ end -}} +val builder{{ fsm.name }}StateMachine = StaterStateMachineBuilder<{{ state_generic }}, {{ context_generic }}>() + {{- if fsm.start_state != null }} + .setStartState({{ state fsm.start_state.name }}) + {{- end }} + .setContext({{ context_generic }}()) + {{- if settings.generate_interface }} + .setFactory(typed{{ fsm.name }}Factory) + {{- end }} + {{- for item in fsm.state_transitions }} + .addTransition("{{ item.transition.name }}", {{ state item.start_state.name }}, {{ state item.end_state.name }}) + {{- if item.transition.condition && settings.generate_context }} + .setTransitionCondition("{{ item.transition.name }}") { {{ convert_condition item.transition item.transition.condition }} } + {{- end }} + {{- if item.transition.event && settings.generate_context }} + .setTransitionEvent("{{ item.transition.name }}") { {{ convert_event item.transition item.transition.event }} } + {{- end }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/Templates/python-test.scriban b/src/Stater.CodeGeneration/Templates/python-test.scriban new file mode 100644 index 0000000..47b8307 --- /dev/null +++ b/src/Stater.CodeGeneration/Templates/python-test.scriban @@ -0,0 +1,51 @@ +import json{{ "\n" }}{{ "\n" }} + +{{- if settings.mode == "Builder" }}from .{{ fsm.name }} import builder_{{ fsm.name }}_state_machine{{ "\n" }}{{- end }} +{{- if settings.mode == "Clazz" }}from .{{ fsm.name }} import {{ fsm.name }}StateMachine{{ "\n" }}{{- end }} +{{- if settings.generate_states }}from .{{ fsm.name }} import States{{ "\n" }}{{- end }} + +{{ func state(name) }} +{{- if settings.generate_states -}} +States.{{ name }} +{{- else -}} +"{{ name }}" +{{- end -}} +{{ end }} + +{{- if settings.mode == "Clazz"; build_generic = fsm.name + "StateMachine"; else; build_generic = "builder_" + fsm.name + "_state_machine.build"; end -}} + +def test_init(): + {{ build_generic }}() +{{ for index in 0..(scenarios.size - 1) }} + +def test_scenario_{{index}}(): + sm = {{ build_generic }}() + sm.disable_events() + +{{ for transition in scenarios[index] }} + {{- if settings.generate_interface }} + sm.{{ transition.name }}() + {{- else }} + sm.transition('{{ transition.name }}') + {{- end }} + assert sm.get_state() == {{ state get_state_by_uuid(transition.end).name }} +{{ end }} +{{- end }} + +def test_json_schema(): + sm = {{ build_generic }}() + assert json.loads("""{{ state_machine_json_schema fsm }}""") == json.loads(sm.to_json_schema()) + +{{ if settings.mode == "Builder" && !settings.generate_states }} +def test_system_append_state_transition(): + sm_builder = builder_{{ fsm.name }}_state_machine + + sm_builder = sm_builder.add_state('__test_state_1__') + assert json.loads("""{{ state_machine_json_schema fsm_test_state_1 }}""") == json.loads(sm_builder.build().to_json_schema()) + + sm_builder = sm_builder.add_state('__test_state_2__') + assert json.loads("""{{ state_machine_json_schema fsm_test_state_2 }}""") == json.loads(sm_builder.build().to_json_schema()) + + sm_builder = sm_builder.add_transition('__test_transition__', '__test_state_1__', '__test_state_2__') + assert json.loads("""{{ state_machine_json_schema fsm_test_state_3 }}""") == json.loads(sm_builder.build().to_json_schema()) +{{- end }} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/Templates/python.scriban b/src/Stater.CodeGeneration/Templates/python.scriban new file mode 100644 index 0000000..0c86eb9 --- /dev/null +++ b/src/Stater.CodeGeneration/Templates/python.scriban @@ -0,0 +1,101 @@ +{{- if settings.generate_states }}from enum import Enum{{ "\n" }}{{- end }} +{{- if settings.generate_context }}from pydantic import BaseModel{{ "\n" }}{{- end }} +{{- if settings.generate_context }}from stater_state_machine import Context{{ "\n" }}{{- else }}from stater_state_machine import EmptyContext{{ "\n" }}{{- end }} +{{- if settings.generate_interface || settings.mode == "Clazz" }}from stater_state_machine import StaterStateMachine{{ "\n" }}{{- end }} +{{- if settings.mode == "Builder" }}from stater_state_machine import StaterStateMachineBuilder{{ "\n" }}{{- end }} +{{- if settings.mode == "Clazz" }}from stater_state_machine import Transition{{ "\n" }}{{- end }} + +{{ if settings.generate_states -}} +class States(Enum): + {{- for item in fsm.states }} + {{ item.name }} = "{{ item.name }}" + {{- end }} + + +{{ end }} +{{- func state(name) -}} +{{- if settings.generate_states -}} +States.{{ name }} +{{- else -}} +"{{ name }}" +{{- end -}} +{{- end -}} +{{- if settings.generate_context -}} +class {{ fsm.name }}FSMContext(BaseModel, Context): +{{- for item in fsm.variables }} + {{ item.name }}: {{ convert_variable_type item.start_value }} = {{ convert_variable_value item.start_value }} +{{- end}} + +{{ end -}} +{{- if !settings.generate_states; state_generic = "str"; else; state_generic = "States"; end }} +{{- if !settings.generate_context; context_generic = "EmptyContext"; else; context_generic = fsm.name+"FSMContext"; end -}} +{{- if settings.mode == "Clazz" -}} +class {{ fsm.name }}StateMachine(StaterStateMachine[{{ state_generic }}, {{ context_generic }}]): + def __init__(self): + super().__init__( + transitions=[ + {{- for item in fsm.state_transitions }} + Transition( + name="{{ item.transition.name }}", + start={{ state item.start_state.name }}, + end={{ state item.end_state.name }} {{- if item.transition.condition && settings.generate_context }}, + condition=lambda ctx: {{ convert_condition item.transition item.transition.condition }} + {{- end }}{{- if item.transition.event && settings.generate_context }}, + event=lambda ctx: {{ convert_event item.transition item.transition.event }} + {{- end }} + ){{- if !for.last }}{{ "," }}{{- end }} + {{- end }} + ], + context={{ context_generic }}(), + {{- if fsm.start_state != null }} + start_state={{ state fsm.start_state.name }}, + {{- end }} + ) +{{- if settings.generate_interface }} +{{ end -}} +{{- if settings.generate_interface }} +{{- for item in fsm.transitions }} + def {{ item.name }}(self): + self.transition("{{ item.name }}") +{{- if !for.last }} +{{ end -}} +{{- end -}} +{{- end }} + +{{- else if settings.mode == "Builder" -}} +{{- if settings.generate_interface }} +class Types{{ fsm.name }}StateMachine(StaterStateMachine[{{ state_generic }}, {{ context_generic }}]): + {{- for item in fsm.transitions }} + def {{ item.name }}(self): + self.transition("{{ item.name }}") + {{- if !for.last }} + {{ end -}} + + {{- end }} + + +def typed_{{ fsm.name }}_factory(*args, **kwargs): + return Types{{ fsm.name }}StateMachine(*args, **kwargs) + + +{{ end -}} +builder_{{ fsm.name }}_state_machine = ( + StaterStateMachineBuilder[{{ state_generic }}, {{ context_generic }}]() + {{- if fsm.start_state != null }} + .set_start_state({{ state fsm.start_state.name }}) + {{- end }} + .set_context({{ context_generic }}()) + {{- if settings.generate_interface }} + .set_factory(typed_{{ fsm.name }}_factory) + {{- end }} + {{- for item in fsm.state_transitions }} + .add_transition("{{ item.transition.name }}", {{ state item.start_state.name }}, {{ state item.end_state.name }}) + {{- if item.transition.condition && settings.generate_context }} + .set_transition_condition("{{ item.transition.name }}", lambda ctx: {{ convert_condition item.transition item.transition.condition }}) + {{- end }} + {{- if item.transition.event && settings.generate_context }} + .set_transition_event("{{ item.transition.name }}", lambda ctx: {{ convert_event item.transition item.transition.event }}) + {{- end }} + {{- end }} +) +{{- end }} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/Templates/typescript-test.scriban b/src/Stater.CodeGeneration/Templates/typescript-test.scriban new file mode 100644 index 0000000..bd273ba --- /dev/null +++ b/src/Stater.CodeGeneration/Templates/typescript-test.scriban @@ -0,0 +1,55 @@ +{{- if settings.mode == "Builder" && settings.generate_interface }}import {builder{{ fsm.name }}StateMachine, Types{{ fsm.name }}StateMachine} from "./{{ fsm.name }}";{{ "\n" }}{{- end }} +{{- if settings.mode == "Builder" && !settings.generate_interface }}import {builder{{ fsm.name }}StateMachine} from "./{{ fsm.name }}";{{ "\n" }}{{- end }} +{{- if settings.mode == "Clazz" }}import { {{- fsm.name }}StateMachine} from "./{{ fsm.name }}";{{ "\n" }}{{- end }} +{{- if settings.generate_states }}import {States} from "./{{fsm.name}}";{{ "\n" }}{{- end }} + +{{ func state(name) }} +{{- if settings.generate_states -}} +States.{{ name }} +{{- else -}} +"{{ name }}" +{{- end -}} +{{ end }} + +{{- if settings.mode == "Clazz"; build_generic = "new " + fsm.name + "StateMachine()"; else if settings.generate_interface; build_generic = "builder" + fsm.name + "StateMachine.build() as Types" + fsm.name + "StateMachine"; else; build_generic = "builder" + fsm.name + "StateMachine.build()"; end -}} + +test('testInit', () => { + {{ build_generic }} +}) + +{{ for index in 0..(scenarios.size - 1) }} + +test('testScenario{{ index }}', () => { + const sm = {{ build_generic }} + sm.disableEvents() + +{{ for transition in scenarios[index] }} + {{- if settings.generate_interface }} + sm.{{ transition.name }}() + {{- else }} + sm.transition('{{ transition.name }}') + {{- end }} + expect(sm.getState()).toBe({{ state get_state_by_uuid(transition.end).name }}) +{{ end }} +}){{- end }} + + +test('testJsonSchema', () => { + const sm = {{ build_generic }} + expect(JSON.parse(`{{ state_machine_json_schema fsm }}`)).toStrictEqual(JSON.parse(sm.toJsonSchema())) +}) + +{{ if settings.mode == "Builder" && !settings.generate_states }} +test('testSystemAppendStateTransition', () => { + let smBuilder = builder{{ fsm.name }}StateMachine + + smBuilder = smBuilder.addState('__test_state_1__') + expect(JSON.parse(`{{ state_machine_json_schema fsm_test_state_1 }}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addState('__test_state_2__') + expect(JSON.parse(`{{ state_machine_json_schema fsm_test_state_2 }}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) + + smBuilder = smBuilder.addTransition('__test_transition__', '__test_state_1__', '__test_state_2__') + expect(JSON.parse(`{{ state_machine_json_schema fsm_test_state_3 }}`)).toStrictEqual(JSON.parse(smBuilder.build().toJsonSchema())) +}) +{{- end }} \ No newline at end of file diff --git a/src/Stater.CodeGeneration/Templates/typescript.scriban b/src/Stater.CodeGeneration/Templates/typescript.scriban new file mode 100644 index 0000000..1f37795 --- /dev/null +++ b/src/Stater.CodeGeneration/Templates/typescript.scriban @@ -0,0 +1,111 @@ +{{- if settings.generate_context }}import {Context} from "./StaterStateMachine";{{ "\n" }}{{- else }}import {EmptyContext} from "./StaterStateMachine";{{ "\n" }}{{- end }} +{{- if settings.generate_interface }}import {StateMachineFactory} from "./StaterStateMachine";{{ "\n" }}{{- end }} +{{- if settings.generate_interface || settings.mode == "Clazz" }}import {StaterStateMachine} from "./StaterStateMachine";{{ "\n" }}{{- end }} +{{- if settings.mode == "Builder" }}import {StaterStateMachineBuilder} from "./StaterStateMachine";{{ "\n" }}{{- end }} +{{- if settings.mode == "Clazz" }}{{ "\n" }}{{- end }} +{{ if settings.generate_states -}} +export enum States { + {{- for item in fsm.states }} + {{ item.name }} = "{{ item.name }}"{{- if !for.last }}{{ "," }}{{- end }} + {{- end }} +} + +{{ end }} +{{- func state(name) -}} +{{- if settings.generate_states -}} +States.{{ name }} +{{- else -}} +"{{ name }}" +{{- end -}} +{{- end -}} +{{- if settings.generate_context -}} +interface {{ fsm.name }}FSMContext extends Context { +{{- for item in fsm.variables }} + {{ item.name }}: {{ convert_variable_type item.start_value }} +{{- end}} +} + +const build{{ fsm.name }}FSMContext: () => {{ fsm.name }}FSMContext = () => { + return { +{{- for item in fsm.variables }} + {{ item.name }}: {{ convert_variable_value item.start_value }}{{- if !for.last }}{{ "," }}{{- end }} +{{- end}} + } +} + + +{{ end -}} +{{- if !settings.generate_states; state_generic = "string"; else; state_generic = "States"; end }} +{{- if !settings.generate_context; context_generic = "EmptyContext"; else; context_generic = fsm.name+"FSMContext"; end -}} +{{- if !settings.generate_context; context_generic_builder = "new EmptyContext()"; else; context_generic_builder = "build"+fsm.name+"FSMContext()"; end -}} +{{- if settings.mode == "Clazz" -}} +export class {{ fsm.name }}StateMachine extends StaterStateMachine<{{ state_generic }}, {{ context_generic }}> { + constructor() { + super( + [ + {{- for item in fsm.state_transitions }} + { + name: "{{ item.transition.name }}", + start: {{ state item.start_state.name }}, + end: {{ state item.end_state.name }} {{- if item.transition.condition && settings.generate_context }}, + condition: (ctx) => {{ convert_condition item.transition item.transition.condition }} + {{- end }}{{- if item.transition.event && settings.generate_context }}, + event: (ctx) => { {{ convert_event item.transition item.transition.event }} } + {{- end }} + }{{- if !for.last }}{{ "," }}{{- end }} + {{- end }} + ], + {{ context_generic_builder }}, + {{- if fsm.start_state != null }} + {{ state fsm.start_state.name }}, + {{- end }} + ) + } +{{- if settings.generate_interface }} +{{ end -}} +{{- if settings.generate_interface }} +{{- for item in fsm.transitions }} + {{ item.name }}() { + this.transition("{{ item.name }}") + } +{{- if !for.last }} +{{ end -}} +{{- end }} +{{- end }} +} + +{{- else if settings.mode == "Builder" -}} +{{- if settings.generate_interface -}} +export class Types{{ fsm.name }}StateMachine extends StaterStateMachine<{{ state_generic }}, {{ context_generic }}> { +{{- for item in fsm.transitions }} + {{ item.name }}() { + this.transition("{{ item.name }}") + } +{{- if !for.last }} +{{ end -}} +{{- end }} +} + +const typed{{ fsm.name }}Factory: StateMachineFactory<{{ state_generic }}, {{ context_generic }}> = (...args): StaterStateMachine<{{ state_generic }}, {{ context_generic }}> => { + return new Types{{ fsm.name }}StateMachine(...args); +}; + +{{ end -}} +export const builder{{ fsm.name }}StateMachine = new StaterStateMachineBuilder<{{ state_generic }}, {{ context_generic }}>() + {{- if fsm.start_state != null }} + .setStartState({{ state fsm.start_state.name }}) + {{- end }} + .setContext({{ context_generic_builder }}) + {{- if settings.generate_interface }} + .setFactory(typed{{ fsm.name }}Factory) + {{- end }} + {{- for item in fsm.state_transitions }} + .addTransition("{{ item.transition.name }}", {{ state item.start_state.name }}, {{ state item.end_state.name }}) + {{- if item.transition.condition && settings.generate_context }} + .setTransitionCondition("{{ item.transition.name }}", (ctx) => {{ convert_condition item.transition item.transition.condition }}) + {{- end }} + {{- if item.transition.event && settings.generate_context }} + .setTransitionEvent("{{ item.transition.name }}", (ctx) => { {{ convert_event item.transition item.transition.event }} }) + {{- end }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/src/Stater.Domain.Tests/Json/StateMachineJsonAdapterTests.cs b/src/Stater.Domain.Tests/Json/StateMachineJsonAdapterTests.cs new file mode 100644 index 0000000..514d61f --- /dev/null +++ b/src/Stater.Domain.Tests/Json/StateMachineJsonAdapterTests.cs @@ -0,0 +1,202 @@ +using Stater.Domain.Json; +using Stater.Domain.Models; +using Xunit; + +namespace Stater.Domain.Tests.Json; + +public class StateMachineJsonAdapterTests +{ + private static StateMachine DoorTestStateMachine() + { + var open = new State( + Guid.NewGuid(), + "OPEN", + "Open door", + StateType.Start, + 0, + 0, + new List(), + new List() + ); + + var close = new State( + Guid.NewGuid(), + "CLOSE", + "Close door", + StateType.Common, + 0, + 0, + new List(), + new List() + ); + + var ajar = new State( + Guid.NewGuid(), + "AJAR", + "Ajar door", + StateType.Common, + 0, + 0, + new List(), + new List() + ); + + var states = new List + { + ajar, close, open + }; + + + var preOpen = new Transition( + Guid.NewGuid(), + "preOpen", + close.Guid, + ajar.Guid, + null, + null + ); + + var preClose = new Transition( + Guid.NewGuid(), + "preClose", + open.Guid, + ajar.Guid, + null, + null + ); + + var openEvent = new Transition( + Guid.NewGuid(), + "open", + ajar.Guid, + open.Guid, + null, + null + ); + + var closeEvent = new Transition( + Guid.NewGuid(), + "close", + ajar.Guid, + close.Guid, + null, + null + ); + + var ajarPlus = new Transition( + Guid.NewGuid(), + "ajarPlus", + ajar.Guid, + ajar.Guid, + null, + null + ); + + var ajarMinus = new Transition( + Guid.NewGuid(), + "ajarMinus", + ajar.Guid, + ajar.Guid, + null, + null + ); + + + var transitions = new List + { + preOpen, + preClose, + openEvent, + closeEvent, + ajarPlus, + ajarMinus + }; + + return new StateMachine( + Guid.NewGuid(), + "Door", + states, + transitions, + new List() + ); + } + + private const string Json = + """ + { + "states": [ + "AJAR", + "CLOSE", + "OPEN" + ], + "startState": "OPEN", + "transitions": [ + { + "name": "preOpen", + "start": "CLOSE", + "end": "AJAR" + }, + { + "name": "preClose", + "start": "OPEN", + "end": "AJAR" + }, + { + "name": "open", + "start": "AJAR", + "end": "OPEN" + }, + { + "name": "close", + "start": "AJAR", + "end": "CLOSE" + }, + { + "name": "ajarPlus", + "start": "AJAR", + "end": "AJAR" + }, + { + "name": "ajarMinus", + "start": "AJAR", + "end": "AJAR" + } + ] + } + """; + + [Fact] + public void TestToJsonSchema() + { + var sm = DoorTestStateMachine(); + var result = StateMachineJsonAdapter.ToJsonSchema(sm); + + Assert.Equal(Json, result); + } + + [Fact] + public void TestFromJsonSchema() + { + var actualSm = DoorTestStateMachine(); + var sm = StateMachineJsonAdapter.FromJsonSchema(Json); + Assert.Equal(actualSm.States.Count, sm.States.Count); + + for (var i = 0; i < actualSm.States.Count; i++) + { + Assert.Equal(actualSm.States[i].Name, sm.States[i].Name); + Assert.Equal(actualSm.States[i].Type, sm.States[i].Type); + } + + + var actualStateTransition = actualSm.StateTransitions; + var stateTransition = sm.StateTransitions; + Assert.Equal(actualStateTransition.Count, stateTransition.Count); + + for (var i = 0; i < actualStateTransition.Count; i++) + { + Assert.Equal(actualStateTransition[i].Transition.Name, stateTransition[i].Transition.Name); + Assert.Equal(actualStateTransition[i].StartState.Name, stateTransition[i].StartState.Name); + Assert.Equal(actualStateTransition[i].EndState.Name, stateTransition[i].EndState.Name); + } + } +} \ No newline at end of file diff --git a/src/Stater.Domain.Tests/Stater.Domain.Tests.csproj b/src/Stater.Domain.Tests/Stater.Domain.Tests.csproj new file mode 100644 index 0000000..d19fb26 --- /dev/null +++ b/src/Stater.Domain.Tests/Stater.Domain.Tests.csproj @@ -0,0 +1,29 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/src/Stater.Domain/Json/JsonSchema.cs b/src/Stater.Domain/Json/JsonSchema.cs new file mode 100644 index 0000000..be763dd --- /dev/null +++ b/src/Stater.Domain/Json/JsonSchema.cs @@ -0,0 +1,14 @@ +namespace Stater.Domain.Json; + +public record JsonTransition( + string Name, + string Start, + string End +); + +public record JsonSchema +( + List States, + string StartState, + List Transitions +); \ No newline at end of file diff --git a/src/Stater.Domain/Json/StateMachineJsonAdapter.cs b/src/Stater.Domain/Json/StateMachineJsonAdapter.cs new file mode 100644 index 0000000..3088ee5 --- /dev/null +++ b/src/Stater.Domain/Json/StateMachineJsonAdapter.cs @@ -0,0 +1,61 @@ +using System.Text.Json; +using Stater.Domain.Models; + +namespace Stater.Domain.Json; + +public static class StateMachineJsonAdapter +{ + private static readonly JsonSerializerOptions Options = new() + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + WriteIndented = true + }; + + public static string ToJsonSchema(StateMachine stateMachine) + { + var startState = stateMachine.StartState; + if (startState == null) + { + startState = stateMachine.States[0]; + } + var jsonSchema = new JsonSchema( + States: stateMachine.States.Select(el => el.Name).Distinct().Order().ToList(), + StartState: startState.Name, + Transitions: stateMachine.StateTransitions.Select( + el => new JsonTransition(Name: el.Transition.Name, Start: el.StartState.Name, End: el.EndState.Name) + ).ToList() + ); + return JsonSerializer.Serialize(jsonSchema, Options); + } + + public static StateMachine FromJsonSchema(string json) + { + var jsonSchema = JsonSerializer.Deserialize(json, Options); + + if (jsonSchema == null) + { + throw new ArgumentException(null, nameof(json)); + } + + var sm = new StateMachine + { + States = jsonSchema.States.Select(el => new State + { + Name = el, + Type = el == jsonSchema.StartState ? StateType.Start : StateType.Common + }).ToList() + }; + sm = sm with + { + Transitions = jsonSchema.Transitions.Select(el => new Transition + { + Name = el.Name, + Start = sm.GetStateByName(el.Start)!.Guid, + End = sm.GetStateByName(el.End)!.Guid, + }) + .ToList() + }; + + return sm; + } +} \ No newline at end of file diff --git a/src/Stater.Domain/Logic/ConditionLogic.cs b/src/Stater.Domain/Logic/ConditionLogic.cs new file mode 100644 index 0000000..2f52b0f --- /dev/null +++ b/src/Stater.Domain/Logic/ConditionLogic.cs @@ -0,0 +1,39 @@ +using Stater.Domain.Models; + +namespace Stater.Domain.Logic; + +public static class ConditionLogic +{ + private static VariableValue GetValueByVariable(Guid guid, IDictionary variables) + { + var variable = variables.Keys.First(v => v == guid); + return variables[variable]; + } + + public static bool Evaluate(Condition condition, IDictionary variables) + { + return condition switch + { + Condition.VariableCondition cond => EvaluateVariableCondition(cond, variables), + _ => false + }; + } + + private static bool EvaluateVariableCondition( + Condition.VariableCondition condition, + IDictionary variables + ) + { + var variableValue = GetValueByVariable(condition.VariableGuid, variables); + return condition.ConditionType switch + { + Condition.VariableCondition.ConditionTypeEnum.Lt => variableValue < condition.Value, + Condition.VariableCondition.ConditionTypeEnum.Le => variableValue <= condition.Value, + Condition.VariableCondition.ConditionTypeEnum.Eq => variableValue == condition.Value, + Condition.VariableCondition.ConditionTypeEnum.Ne => variableValue != condition.Value, + Condition.VariableCondition.ConditionTypeEnum.Gt => variableValue > condition.Value, + Condition.VariableCondition.ConditionTypeEnum.Ge => variableValue >= condition.Value, + _ => false + }; + } +} \ No newline at end of file diff --git a/src/Stater.Domain/Logic/EventLogic.cs b/src/Stater.Domain/Logic/EventLogic.cs new file mode 100644 index 0000000..2334465 --- /dev/null +++ b/src/Stater.Domain/Logic/EventLogic.cs @@ -0,0 +1,35 @@ +using Stater.Domain.Models; + +namespace Stater.Domain.Logic; + +public class EventLogic +{ + private static VariableValue GetValueByVariable(Guid guid, IDictionary variables) => + variables[variables.Keys.First(v => v == guid)]; + + public static IDictionary Evaluate(Event eEvent, IDictionary variables) + { + return eEvent switch + { + Event.VariableMath e => EvaluateVariableMath(e, variables), + _ => variables + }; + } + + private static IDictionary EvaluateVariableMath( + Event.VariableMath eEvent, + IDictionary variables + ) + { + var variableValue = GetValueByVariable(eEvent.VariableGuid, variables); + _ = eEvent.MathType switch + { + Event.VariableMath.MathTypeEnum.Sum => variables[eEvent.VariableGuid] = variableValue + eEvent.Value, + Event.VariableMath.MathTypeEnum.Sub => variables[eEvent.VariableGuid] = variableValue - eEvent.Value, + Event.VariableMath.MathTypeEnum.Mul => variables[eEvent.VariableGuid] = variableValue * eEvent.Value, + Event.VariableMath.MathTypeEnum.Div => variables[eEvent.VariableGuid] = variableValue / eEvent.Value, + _ => null + }; + return variables; + } +} \ No newline at end of file diff --git a/src/Stater.Domain/Models/Condition.cs b/src/Stater.Domain/Models/Condition.cs new file mode 100644 index 0000000..9e4a9d8 --- /dev/null +++ b/src/Stater.Domain/Models/Condition.cs @@ -0,0 +1,40 @@ +using System.Xml.Serialization; + +namespace Stater.Domain.Models; + +[XmlInclude(typeof(VariableCondition))] +[Serializable] +public abstract record Condition +{ + public record VariableCondition( + Guid VariableGuid, + VariableCondition.ConditionTypeEnum ConditionType, + VariableValue Value + ) : Condition + { + public enum ConditionTypeEnum + { + Lt, // < + Le, // <= + Eq, // == + Ne, // != + Gt, // > + Ge, // >= + } + + public string GetDefaultConditionSign() => ConditionType switch + { + ConditionTypeEnum.Lt => "<", + ConditionTypeEnum.Le => "<=", + ConditionTypeEnum.Eq => "==", + ConditionTypeEnum.Ne => "!=", + ConditionTypeEnum.Gt => ">", + ConditionTypeEnum.Ge => ">=", + _ => throw new ArgumentOutOfRangeException() + }; + + public VariableCondition() : this(Guid.Empty, ConditionTypeEnum.Lt, null) + { + } + } +} \ No newline at end of file diff --git a/src/Stater.Domain/Models/Event.cs b/src/Stater.Domain/Models/Event.cs new file mode 100644 index 0000000..c4320e9 --- /dev/null +++ b/src/Stater.Domain/Models/Event.cs @@ -0,0 +1,41 @@ +using System.Xml.Serialization; + +namespace Stater.Domain.Models; + +[XmlInclude(typeof(VariableMath))] +[Serializable] +public abstract record Event +{ + public record VariableMath( + Guid VariableGuid, + VariableMath.MathTypeEnum MathType, + VariableValue Value + ) : Event + { + public enum MathTypeEnum + { + Sum, // + + Sub, // - + Mul, // * + Div, // / + } + + public string GetDefaultMathTypeSign() => MathType switch + { + MathTypeEnum.Sum => "+", + MathTypeEnum.Sub => "-", + MathTypeEnum.Mul => "*", + MathTypeEnum.Div => "/", + _ => throw new ArgumentOutOfRangeException() + }; + + public VariableMath() : this(Guid.Empty, MathTypeEnum.Sum, null) + { + } + } + + public record VariableSet( + Guid VariableGuid, + VariableValue Value + ) : Event; +} \ No newline at end of file diff --git a/src/Stater.Domain/Models/State.cs b/src/Stater.Domain/Models/State.cs new file mode 100644 index 0000000..8f94a5e --- /dev/null +++ b/src/Stater.Domain/Models/State.cs @@ -0,0 +1,33 @@ +namespace Stater.Domain.Models; + +public enum StateType +{ + Common, + Start, + End +} + +public record State( + Guid Guid, + string Name, + string Description, + StateType Type, + float X, + float Y, + List EntryEvents, + List ExitEvents +) +{ + public State() : this( + Guid.NewGuid(), + "State", + "", + StateType.Common, + 0, + 0, + new List(), + new List() + ) + { + } +} \ No newline at end of file diff --git a/src/Stater.Domain/Models/StateMachine.cs b/src/Stater.Domain/Models/StateMachine.cs new file mode 100644 index 0000000..1b74574 --- /dev/null +++ b/src/Stater.Domain/Models/StateMachine.cs @@ -0,0 +1,53 @@ +namespace Stater.Domain.Models; + +public record StateMachine( + Guid Guid, + string Name, + List States, + List Transitions, + List Variables +) +{ + public StateMachine() : this( + Guid.NewGuid(), + "", + new List(), + new List(), + new List() + ) + { + } + + public State? StartState + { + get { return States.Find(x => x.Type == StateType.Start); } + } + + public Variable? GetVariableByGuid(Guid guid) => Variables.Find(el => el.Guid == guid); + public State? GetStateByGuid(Guid guid) => States.Find(el => el.Guid == guid); + public State? GetStateByName(string name) => States.Find(el => el.Name == name); + + public List StateTransitions + { + get + { + return Transitions + .Select(y => + { + var startState = States.Find(s => s.Guid == y.Start); + var endState = States.Find(s => s.Guid == y.End); + if (startState != null && endState != null) + return new StateTransition( + Transition: y, + StartState: startState, + EndState: endState + ); + return null; + } + ) + .Where(item => item != null) + .Cast() + .ToList(); + } + } +} \ No newline at end of file diff --git a/src/Stater.Domain/Models/StateTransition.cs b/src/Stater.Domain/Models/StateTransition.cs new file mode 100644 index 0000000..cd41b99 --- /dev/null +++ b/src/Stater.Domain/Models/StateTransition.cs @@ -0,0 +1,14 @@ +namespace Stater.Domain.Models; + +public record StateTransition( + State StartState, + State EndState, + Transition Transition +) +{ + public StateTransition() : this( + null, null, null + ) + { + } +}; \ No newline at end of file diff --git a/src/Stater.Domain/Models/Transition.cs b/src/Stater.Domain/Models/Transition.cs new file mode 100644 index 0000000..19976c6 --- /dev/null +++ b/src/Stater.Domain/Models/Transition.cs @@ -0,0 +1,22 @@ +namespace Stater.Domain.Models; + +public record Transition( + Guid Guid, + string Name, + Guid? Start, + Guid? End, + Condition? Condition, + Event? Event +) +{ + public Transition() : this( + Guid.NewGuid(), + "Transition", + null, + null, + null, + null + ) + { + } +} \ No newline at end of file diff --git a/src/Stater.Domain/Models/Variable.cs b/src/Stater.Domain/Models/Variable.cs new file mode 100644 index 0000000..0c7289b --- /dev/null +++ b/src/Stater.Domain/Models/Variable.cs @@ -0,0 +1,255 @@ +using System.Globalization; +using System.Xml.Serialization; + +namespace Stater.Domain.Models; + +public record Variable( + Guid Guid, + string Name, + VariableValue StartValue +) +{ + public Variable() : this( + Guid.NewGuid(), + "Variable", + VariableValueBuilder.fromString("0") + ) + { + } +} + +public class VariableOperatorException(string message) : Exception(message); + +public class VariableMathException(string message) : Exception(message); + +public static class VariableValueBuilder +{ + public static VariableValue fromString(string input) + { + switch (input) + { + case "true": + return new VariableValue.BoolVariable(true); + case "false": + return new VariableValue.BoolVariable(false); + } + + try + { + return new VariableValue.FloatVariable(float.Parse(input)); + } + catch (Exception _) + { + // ignored + } + + try + { + return new VariableValue.IntVariable(int.Parse(input)); + } + catch (Exception _) + { + // ignored + } + + return new VariableValue.StringVariable(input); + } +} + +[XmlInclude(typeof(IntVariable))] +[XmlInclude(typeof(BoolVariable))] +[XmlInclude(typeof(FloatVariable))] +[XmlInclude(typeof(StringVariable))] +[Serializable] +public abstract record VariableValue +{ + public record IntVariable(int Value) : VariableValue + { + public IntVariable() : this(0) + { + } + + public override string ToString() => Value.ToString(); + + protected override VariableValue Default() => new IntVariable(0); + + protected override bool Greater(VariableValue otherVariableValue) => otherVariableValue switch + { + IntVariable v => Value > v.Value, + FloatVariable v => Value > v.Value, + _ => throw new VariableOperatorException("Integer must compare only with integer or float") + }; + + protected override VariableValue Sum(VariableValue otherVariableValue) => otherVariableValue switch + { + IntVariable v => new IntVariable(Value + v.Value), + FloatVariable v => new IntVariable(Value + (int)v.Value), + _ => throw new VariableMathException("Integer must sum only with integer or float") + }; + + protected override VariableValue Sub(VariableValue otherVariableValue) => otherVariableValue switch + { + IntVariable v => new IntVariable(Value - v.Value), + FloatVariable v => new IntVariable(Value - (int)v.Value), + _ => throw new VariableMathException("Integer must sub only with integer or float") + }; + + protected override VariableValue Mul(VariableValue otherVariableValue) => otherVariableValue switch + { + IntVariable v => new IntVariable(Value * v.Value), + FloatVariable v => new IntVariable(Value * (int)v.Value), + StringVariable v => new StringVariable(string.Concat(Enumerable.Repeat(v.Value, Value))), + _ => throw new VariableMathException("Integer must mul only with integer, float or string") + }; + + protected override VariableValue Div(VariableValue otherVariableValue) => otherVariableValue switch + { + IntVariable v => new IntVariable(Value / v.Value), + FloatVariable v => new IntVariable(Value / (int)v.Value), + _ => throw new VariableMathException("Integer must div only with integer or float") + }; + }; + + public record BoolVariable(bool Value) : VariableValue + { + public BoolVariable() : this(false) + { + } + + public override string ToString() => Value.ToString(); + protected override VariableValue Default() => new BoolVariable(false); + + protected override bool Greater(VariableValue otherVariableValue) + { + throw new VariableOperatorException("Bool variables not support operations: >, <, <=, >="); + } + + protected override VariableValue Sum(VariableValue otherVariableValue) + { + throw new VariableOperatorException("Bool variables not support operations: +, -, *, /"); + } + + protected override VariableValue Sub(VariableValue otherVariableValue) + { + throw new VariableOperatorException("Bool variables not support operations: +, -, *, /"); + } + + protected override VariableValue Mul(VariableValue otherVariableValue) + { + throw new VariableOperatorException("Bool variables not support operations: +, -, *, /"); + } + + protected override VariableValue Div(VariableValue otherVariableValue) + { + throw new VariableOperatorException("Bool variables not support operations: +, -, *, /"); + } + } + + public record FloatVariable(float Value) : VariableValue + { + public FloatVariable() : this(0f) + { + } + + public override string ToString() => Value.ToString(CultureInfo.InvariantCulture); + protected override VariableValue Default() => new FloatVariable(0); + + protected override bool Greater(VariableValue otherVariableValue) => otherVariableValue switch + { + FloatVariable v => Value > v.Value, + IntVariable v => Value > v.Value, + _ => throw new VariableOperatorException("Float must compare only with integer or float") + }; + + protected override VariableValue Sum(VariableValue otherVariableValue) => otherVariableValue switch + { + IntVariable v => new FloatVariable(Value + v.Value), + FloatVariable v => new FloatVariable(Value + v.Value), + _ => throw new VariableMathException("Float must sum only with integer or float") + }; + + protected override VariableValue Sub(VariableValue otherVariableValue) => otherVariableValue switch + { + IntVariable v => new FloatVariable(Value - v.Value), + FloatVariable v => new FloatVariable(Value - v.Value), + _ => throw new VariableMathException("Float must sub only with integer or float") + }; + + protected override VariableValue Mul(VariableValue otherVariableValue) => otherVariableValue switch + { + IntVariable v => new FloatVariable(Value * v.Value), + FloatVariable v => new FloatVariable(Value * v.Value), + _ => throw new VariableMathException("Float must mul only with integer or float") + }; + + protected override VariableValue Div(VariableValue otherVariableValue) => otherVariableValue switch + { + IntVariable v => new FloatVariable(Value / v.Value), + FloatVariable v => new FloatVariable(Value / v.Value), + _ => throw new VariableMathException("Float must div only with integer or float") + }; + }; + + public record StringVariable(string Value) : VariableValue + { + public StringVariable() : this("") + { + } + + public override string ToString() => Value; + protected override VariableValue Default() => new StringVariable(""); + + protected override bool Greater(VariableValue otherVariableValue) => otherVariableValue switch + { + StringVariable v => string.CompareOrdinal(Value, v.Value) > 0, + _ => throw new VariableOperatorException("String must compare only with string") + }; + + protected override VariableValue Sum(VariableValue otherVariableValue) => otherVariableValue switch + { + StringVariable v => new StringVariable(Value + v.Value), + _ => throw new VariableMathException("String must sum only with string") + }; + + protected override VariableValue Sub(VariableValue otherVariableValue) + { + throw new VariableOperatorException("String variables not support operations: +, -, *, /"); + } + + protected override VariableValue Mul(VariableValue otherVariableValue) => otherVariableValue switch + { + IntVariable v => new StringVariable(string.Concat(Enumerable.Repeat(Value, v.Value))), + _ => throw new VariableMathException("String must sum only with string") + }; + + protected override VariableValue Div(VariableValue otherVariableValue) + { + throw new VariableOperatorException("String variables not support operations /"); + } + }; + + protected abstract VariableValue Default(); + + protected abstract bool Greater(VariableValue otherVariableValue); // > + + public static bool operator >(VariableValue a, VariableValue b) => a.Greater(b); + public static bool operator >=(VariableValue a, VariableValue b) => a.Greater(b) || a == b; + public static bool operator <(VariableValue a, VariableValue b) => !(a.Greater(b) || a == b); + public static bool operator <=(VariableValue a, VariableValue b) => !a.Greater(b); + + + protected abstract VariableValue Sum(VariableValue otherVariableValue); + protected abstract VariableValue Sub(VariableValue otherVariableValue); + protected abstract VariableValue Mul(VariableValue otherVariableValue); + protected abstract VariableValue Div(VariableValue otherVariableValue); + + public static VariableValue operator +(VariableValue a, VariableValue b) => a.Sum(b); + public static VariableValue operator -(VariableValue a, VariableValue b) => a.Sub(b); + public static VariableValue operator *(VariableValue a, VariableValue b) => a.Mul(b); + public static VariableValue operator /(VariableValue a, VariableValue b) => a.Div(b); + + public override string ToString() + { + return base.ToString(); + } +} \ No newline at end of file diff --git a/src/Stater.Domain/Stater.Domain.csproj b/src/Stater.Domain/Stater.Domain.csproj new file mode 100644 index 0000000..825b107 --- /dev/null +++ b/src/Stater.Domain/Stater.Domain.csproj @@ -0,0 +1,10 @@ + + + + net8.0 + enable + enable + Stater.Domain + + + diff --git a/src/Stater.SLXParser/Models/BaseNode.cs b/src/Stater.SLXParser/Models/BaseNode.cs new file mode 100644 index 0000000..6abbe65 --- /dev/null +++ b/src/Stater.SLXParser/Models/BaseNode.cs @@ -0,0 +1,7 @@ +namespace Stater.SLXParser.Models; + +public class BaseNode +{ + // id или SSID + public Guid Id { get; set; } +} \ No newline at end of file diff --git a/src/Stater.SLXParser/Models/Chart.cs b/src/Stater.SLXParser/Models/Chart.cs new file mode 100644 index 0000000..ef1dd0d --- /dev/null +++ b/src/Stater.SLXParser/Models/Chart.cs @@ -0,0 +1,22 @@ +using Stater.SLXParser.Utils; + +namespace Stater.SLXParser.Models; + +public class Chart : BaseNode +{ + public string Name { get; set; } + public DoublePoint WindowPosition { get; set; } + public DoublePoint ViewLimits { get; set; } + public float ZoomFactor { get; set; } + public Color StateColor { get; set; } + public Color StateLabelColor { get; set; } + public Color TransitionColor { get; set; } + public Color TransitionLabelColor { get; set; } + public Color JunctionColor { get; set; } + public Color ChartColor { get; set; } + public int ViewObj { get; set; } + public bool Visible { get; set; } + + public List ChildrenState = new List(); + public List ChildrenData = new List(); +} \ No newline at end of file diff --git a/src/Stater.SLXParser/Models/Data.cs b/src/Stater.SLXParser/Models/Data.cs new file mode 100644 index 0000000..e3169fb --- /dev/null +++ b/src/Stater.SLXParser/Models/Data.cs @@ -0,0 +1,28 @@ +namespace Stater.SLXParser.Models; + +public class Data : BaseNode +{ + public string Name { get; set; } + public string Scope { get; set; } + public Props Props = new Props(); + public string DataType { get; set; } +} + +public class Props +{ + public string Frame { get; set; } + + // Type + public string TypeMethod { get; set; } + public string TypePrimitive { get; set; } + public int TypeWordLength { get; set; } + + // Type Fixpt + public string TypeFixptScalingMode { get; set; } + public int TypeFixptFractionLength { get; set; } + public string TypeFixptSlope { get; set; } + public int TypeFixptBias { get; set; } + + // Unit + public string UnitName { get; set; } +} \ No newline at end of file diff --git a/src/Stater.SLXParser/Models/Instance.cs b/src/Stater.SLXParser/Models/Instance.cs new file mode 100644 index 0000000..07192ce --- /dev/null +++ b/src/Stater.SLXParser/Models/Instance.cs @@ -0,0 +1,6 @@ +namespace Stater.SLXParser.Models; + +public class Instance : BaseNode +{ + public string Name { get; set; } +} \ No newline at end of file diff --git a/src/Stater.SLXParser/Models/Machine.cs b/src/Stater.SLXParser/Models/Machine.cs new file mode 100644 index 0000000..ba70a0a --- /dev/null +++ b/src/Stater.SLXParser/Models/Machine.cs @@ -0,0 +1,7 @@ +namespace Stater.SLXParser.Models; + +public class Machine : BaseNode +{ + public Chart Chart { get; set; } + public string Created { get; set; } +} \ No newline at end of file diff --git a/src/Stater.SLXParser/Models/SlxState.cs b/src/Stater.SLXParser/Models/SlxState.cs new file mode 100644 index 0000000..643282e --- /dev/null +++ b/src/Stater.SLXParser/Models/SlxState.cs @@ -0,0 +1,27 @@ +using Stater.SLXParser.Utils; + +namespace Stater.SLXParser.Models; + +public class SlxState : BaseNode +{ + public string LabelString { get; set; } + public DoublePoint Position { get; set; } + public int FontSize { get; set; } + public bool Visible { get; set; } + public int Subviewer { get; set; } + public string Type { get; set; } + public string Decomposition { get; set; } + public int ExecutionOrder { get; set; } + + public static ActiveStateOutput ActiveStateOutput = new ActiveStateOutput(); + public List ChildrenState = new List(); + public List ChildrenTransition = new List(); +} + +public class ActiveStateOutput +{ + public bool UseCustomName { get; set; } + public string CustomName { get; set; } + public bool UseCustomEnumTypeName { get; set; } + public string EnumTypeName { get; set; } +} \ No newline at end of file diff --git a/src/Stater.SLXParser/Models/SlxTransition.cs b/src/Stater.SLXParser/Models/SlxTransition.cs new file mode 100644 index 0000000..64dcc50 --- /dev/null +++ b/src/Stater.SLXParser/Models/SlxTransition.cs @@ -0,0 +1,25 @@ +using Stater.SLXParser.Utils; + +namespace Stater.SLXParser.Models; + +public class SlxTransition : BaseNode +{ + public string LabelString { get; set; } + + public DoublePoint LabelPosition { get; set; } + public int FontSize { get; set; } + + public Address Src { get; set; } + public Address Dst { get; set; } + public Point2D MidPoint { get; set; } + public DoublePoint DataLimits { get; set; } + public int Subviewer { get; set; } + public string DrawStyle { get; set; } + public int ExecutionOrder { get; set; } +} + +public class Address +{ + public Guid SSID { get; set; } + public DoubleDoublePoint Intersection { get; set; } +} \ No newline at end of file diff --git a/src/Stater.SLXParser/Models/Stateflow.cs b/src/Stater.SLXParser/Models/Stateflow.cs new file mode 100644 index 0000000..82f0c2b --- /dev/null +++ b/src/Stater.SLXParser/Models/Stateflow.cs @@ -0,0 +1,7 @@ +namespace Stater.SLXParser.Models; + +public class Stateflow +{ + public Machine Machine { get; set; } + public Instance Instance { get; set; } +} \ No newline at end of file diff --git a/src/Stater.SLXParser/Parser.cs b/src/Stater.SLXParser/Parser.cs new file mode 100644 index 0000000..835789d --- /dev/null +++ b/src/Stater.SLXParser/Parser.cs @@ -0,0 +1,660 @@ +using System.Globalization; +using System.Xml; +using Stater.SLXParser.Models; +using Stater.SLXParser.Utils; + +namespace Stater.SLXParser; + +public class Parser +{ + private readonly string inFile; + private readonly string zipPath; + + public Parser(string path) + { + if (!File.Exists(path)) + { + throw new InvalidOperationException("Файл не найден"); + } + + inFile = path; + var parentDir = Directory.GetParent(inFile); + + if (parentDir == null) + { + throw new InvalidOperationException("Не удалось выбрать папку для распаковки"); + } + + zipPath = Path.Combine(parentDir.ToString(), "slx_parser.temp"); + } + + public Stateflow Parse() + { + System.IO.Compression.ZipFile.ExtractToDirectory(inFile, zipPath); + + var simulinkPath = Path.Combine(zipPath, "simulink", "stateflow.xml"); + + if (!File.Exists(simulinkPath)) + { + Directory.Delete(zipPath, true); + throw new InvalidOperationException("Не удалось найти файл от stateflow"); + } + + try + { + return ParseFile(simulinkPath); + } + catch (Exception e) + { + Console.WriteLine(e); + throw; + } + finally + { + Directory.Delete(zipPath, true); + } + } + + private Stateflow ParseFile(string file) + { + var xDoc = new XmlDocument(); + xDoc.Load(file); + var xRoot = xDoc.DocumentElement; + if (xRoot == null) + { + throw new InvalidOperationException("Проблема парсинга stateflow xml"); + } + + if (xRoot.Name != "Stateflow") + { + throw new InvalidOperationException("Главный элемент не является Stateflow"); + } + + return ParseStateflow(xRoot); + } + + private Stateflow ParseStateflow(XmlNode xmlNode) + { + var stateflow = new Stateflow(); + + foreach (XmlNode node in xmlNode.ChildNodes) + { + if (node.Name == "machine") + { + stateflow.Machine = ParseMachine(node); + } + + if (node.Name == "instance") + { + stateflow.Instance = ParseInstance(node); + } + } + + return stateflow; + } + + private Instance ParseInstance(XmlNode xmlNode) + { + var instance = new Instance + { + Id = ParseId(xmlNode) + }; + + foreach (XmlNode node in xmlNode.ChildNodes) + { + if (node.Name == "P") + { + { + var name = node.Attributes?["Name"]?.Value; + switch (name) + { + case null: + continue; + case "name": + instance.Name = node.InnerText; + break; + } + + break; + } + } + } + + return instance; + } + + private Machine ParseMachine(XmlNode xmlNode) + { + var machine = new Machine + { + Id = ParseId(xmlNode) + }; + + foreach (XmlNode node in xmlNode.ChildNodes) + { + switch (node.Name) + { + case "P": + { + var name = node.Attributes?["Name"]?.Value; + switch (name) + { + case null: + continue; + case "created": + machine.Created = node.InnerText; + break; + } + + break; + } + case "Children": + foreach (XmlNode childrenNode in node.ChildNodes) + { + if (childrenNode.Name == "chart") + { + machine.Chart = ParseChart(childrenNode); + } + } + + break; + } + } + + return machine; + } + + private Chart ParseChart(XmlNode xmlNode) + { + var chart = new Chart + { + Id = ParseId(xmlNode) + }; + + foreach (XmlNode node in xmlNode.ChildNodes) + { + switch (node.Name) + { + case "P": + { + var name = node.Attributes?["Name"]?.Value; + switch (name) + { + case null: + continue; + case "name": + chart.Name = node.InnerText; + break; + case "windowPosition": + chart.WindowPosition = Parse4Point(node.InnerText); + break; + case "viewLimits": + chart.ViewLimits = Parse4Point(node.InnerText); + break; + case "zoomFactor": + chart.ZoomFactor = float.Parse(node.InnerText, CultureInfo.InvariantCulture); + break; + case "stateColor": + chart.StateColor = ParseColor(node.InnerText); + break; + case "stateLabelColor": + chart.StateLabelColor = ParseColor(node.InnerText); + break; + case "transitionColor": + chart.TransitionColor = ParseColor(node.InnerText); + break; + case "transitionLabelColor": + chart.TransitionLabelColor = ParseColor(node.InnerText); + break; + case "junctionColor": + chart.JunctionColor = ParseColor(node.InnerText); + break; + case "chartColor": + chart.ChartColor = ParseColor(node.InnerText); + break; + case "viewObj": + chart.ViewObj = int.Parse(node.InnerText); + break; + case "visible": + chart.Visible = ParseBool(node.InnerText); + break; + } + + break; + } + case "Children": + foreach (XmlNode childrenNode in node.ChildNodes) + { + switch (childrenNode.Name) + { + case "state": + chart.ChildrenState.Add(ParseState(childrenNode)); + break; + case "data": + chart.ChildrenData.Add(ParseData(childrenNode)); + break; + } + } + + break; + } + } + + return chart; + } + + private SlxState ParseState(XmlNode xmlNode) + { + var state = new SlxState + { + Id = ParseId(xmlNode) + }; + + foreach (XmlNode node in xmlNode.ChildNodes) + { + switch (node.Name) + { + case "P": + { + var name = node.Attributes?["Name"]?.Value; + switch (name) + { + case null: + continue; + case "labelString": + state.LabelString = node.InnerText; + break; + case "position": + state.Position = Parse4Point(node.InnerText); + break; + case "fontSize": + state.FontSize = int.Parse(node.InnerText); + break; + case "visible": + state.Visible = ParseBool(node.InnerText); + break; + case "subviewer": + state.Subviewer = int.Parse(node.InnerText); + break; + case "type": + state.Type = node.InnerText; + break; + case "decomposition": + state.Decomposition = node.InnerText; + break; + case "executionOrder": + state.ExecutionOrder = int.Parse(node.InnerText); + break; + } + + break; + } + case "activeStateOutput": + { + foreach (XmlNode childrenNode in node.ChildNodes) + { + if (childrenNode.Name == "P") + { + var name = childrenNode.Attributes?["Name"]?.Value; + switch (name) + { + case null: + continue; + case "useCustomName": + SlxState.ActiveStateOutput.UseCustomName = ParseBool(node.InnerText); + break; + case "customName": + SlxState.ActiveStateOutput.CustomName = node.InnerText; + break; + case "useCustomEnumTypeName": + SlxState.ActiveStateOutput.UseCustomEnumTypeName = ParseBool(node.InnerText); + break; + case "enumTypeName": + SlxState.ActiveStateOutput.EnumTypeName = node.InnerText; + break; + } + } + } + + break; + } + case "Children": + foreach (XmlNode childrenNode in node.ChildNodes) + { + switch (childrenNode.Name) + { + case "state": + state.ChildrenState.Add(ParseState(childrenNode)); + break; + case "transition": + state.ChildrenTransition.Add(ParseTransition(childrenNode)); + break; + } + } + + break; + } + } + + return state; + } + + + private SlxTransition ParseTransition(XmlNode xmlNode) + { + var transition = new SlxTransition + { + Id = ParseId(xmlNode) + }; + + foreach (XmlNode node in xmlNode.ChildNodes) + { + switch (node.Name) + { + case "P": + { + var name = node.Attributes?["Name"]?.Value; + switch (name) + { + case null: + continue; + case "labelString": + transition.LabelString = node.InnerText; + break; + case "labelPosition": + transition.LabelPosition = Parse4Point(node.InnerText); + break; + case "fontSize": + transition.FontSize = int.Parse(node.InnerText); + break; + case "midPoint": + transition.MidPoint = ParsePoint(node.InnerText); + break; + case "dataLimits": + transition.DataLimits = Parse4Point(node.InnerText); + break; + case "subviewer": + transition.Subviewer = int.Parse(node.InnerText); + break; + case "drawStyle": + transition.DrawStyle = node.InnerText; + break; + case "executionOrder": + transition.ExecutionOrder = int.Parse(node.InnerText); + break; + } + + break; + } + case "src": + transition.Src = ParseAddress(node); + break; + case "dst": + transition.Dst = ParseAddress(node); + break; + } + } + + return transition; + } + + private static Address ParseAddress(XmlNode xmlNode) + { + var address = new Address(); + foreach (XmlNode node in xmlNode.ChildNodes) + { + switch (node.Name) + { + case "P": + { + var name = node.Attributes?["Name"]?.Value; + switch (name) + { + case null: + continue; + case "SSID": + address.SSID = Int2Guid(int.Parse(node.InnerText)); + break; + case "intersection": + address.Intersection = Parse8Point(node.InnerText); + break; + } + + break; + } + } + } + + return address; + } + + + private static Models.Data ParseData(XmlNode xmlNode) + { + var data = new Models.Data + { + Id = ParseId(xmlNode), + Name = ParseName(xmlNode) + }; + + foreach (XmlNode node in xmlNode.ChildNodes) + { + switch (node.Name) + { + case "P": + { + var name = node.Attributes?["Name"]?.Value; + switch (name) + { + case null: + continue; + case "scope": + data.Scope = node.InnerText; + break; + case "dataType": + data.DataType = node.InnerText; + break; + } + + break; + } + case "props": + foreach (XmlNode childrenNode in node.ChildNodes) + { + switch (childrenNode.Name) + { + case "P": + { + var name = childrenNode.Attributes?["Name"]?.Value; + switch (name) + { + case null: + continue; + case "frame": + data.Props.Frame = childrenNode.InnerText; + break; + } + + break; + } + case "type": + { + foreach (XmlNode childrenNode2 in childrenNode.ChildNodes) + { + if (childrenNode2.Name == "P") + { + var name = childrenNode2.Attributes?["Name"]?.Value; + switch (name) + { + case null: + continue; + case "method": + data.Props.TypeMethod = childrenNode2.InnerText; + break; + case "primitive": + data.Props.TypePrimitive = childrenNode2.InnerText; + break; + case "wordLength": + data.Props.TypeWordLength = int.Parse(childrenNode2.InnerText); + break; + } + + break; + } + + switch (childrenNode2.Name) + { + case "fixpt": + { + foreach (XmlNode childrenNode3 in childrenNode2.ChildNodes) + { + if (childrenNode3.Name == "P") + { + var name = childrenNode3.Attributes?["Name"]?.Value; + switch (name) + { + case null: + continue; + case "scalingMode": + data.Props.TypeFixptScalingMode = + childrenNode3.InnerText; + break; + case "fractionLength": + data.Props.TypeFixptFractionLength = + int.Parse(childrenNode3.InnerText); + break; + case "slope": + data.Props.TypeFixptSlope = childrenNode3.InnerText; + break; + case "bias": + data.Props.TypeFixptBias = + int.Parse(childrenNode3.InnerText); + break; + } + } + } + + break; + } + } + } + + break; + } + case "unit": + { + foreach (XmlNode childrenNode2 in childrenNode.ChildNodes) + { + if (childrenNode2.Name == "P") + { + var name = childrenNode2.Attributes?["Name"]?.Value; + switch (name) + { + case null: + continue; + case "frame": + data.Props.UnitName = childrenNode2.InnerText; + break; + } + } + } + + break; + } + } + } + + break; + } + } + + return data; + } + + public static Guid Int2Guid(int value) + { + byte[] bytes = new byte[16]; + BitConverter.GetBytes(value).CopyTo(bytes, 0); + return new Guid(bytes); + } + + private static Guid ParseId(XmlNode xmlNode) + { + var id = xmlNode.Attributes?["id"]; + if (id != null) return Int2Guid(int.Parse(id.Value)); + var name = xmlNode.Attributes?["Name"]; + if (name != null && name.Value == "SSID") + { + return Int2Guid(int.Parse(xmlNode.InnerText)); + } + var ssid = xmlNode.Attributes?["SSID"]; + return ssid != null ? Int2Guid(int.Parse(ssid.Value)) : new Guid(); + } + + + private static string ParseName(XmlNode xmlNode) + { + var name = xmlNode.Attributes?["name"]?.Value; + return name ?? ""; + } + + private static Point2D ParsePoint(string line) + { + line = line.Substring(1, line.Length - 2); + var numbers = line.Split(' '); + + var x1 = float.Parse(numbers[0], CultureInfo.InvariantCulture); + var y1 = float.Parse(numbers[1], CultureInfo.InvariantCulture); + + return new Point2D(x1, y1); + } + + private static DoublePoint Parse4Point(string line) + { + line = line.Substring(1, line.Length - 2); + + var numbers = line.Split(' '); + + var x1 = float.Parse(numbers[0], CultureInfo.InvariantCulture); + var y1 = float.Parse(numbers[1], CultureInfo.InvariantCulture); + var x2 = float.Parse(numbers[2], CultureInfo.InvariantCulture); + var y2 = float.Parse(numbers[3], CultureInfo.InvariantCulture); + + return new DoublePoint(new Point2D(x1, y1), new Point2D(x2, y2)); + } + + private static DoubleDoublePoint Parse8Point(string line) + { + line = line.Substring(1, line.Length - 2); + var numbers = line.Split(' '); + + var x1 = float.Parse(numbers[0], CultureInfo.InvariantCulture); + var y1 = float.Parse(numbers[1], CultureInfo.InvariantCulture); + var x2 = float.Parse(numbers[2], CultureInfo.InvariantCulture); + var y2 = float.Parse(numbers[3], CultureInfo.InvariantCulture); + var x3 = float.Parse(numbers[4], CultureInfo.InvariantCulture); + var y3 = float.Parse(numbers[5], CultureInfo.InvariantCulture); + var x4 = float.Parse(numbers[6], CultureInfo.InvariantCulture); + var y4 = float.Parse(numbers[7], CultureInfo.InvariantCulture); + + return new DoubleDoublePoint(new DoublePoint(new Point2D(x1, y1), new Point2D(x2, y2)), + new DoublePoint(new Point2D(x3, y3), new Point2D(x4, y4))); + } + + private static Color ParseColor(string line) + { + line = line.Substring(1, line.Length - 2); + var numbers = line.Split(' '); + + var r = (int)(double.Parse(numbers[0], CultureInfo.InvariantCulture) * 256); + var g = (int)(double.Parse(numbers[1], CultureInfo.InvariantCulture) * 256); + var b = (int)(double.Parse(numbers[2], CultureInfo.InvariantCulture) * 256); + + return new Color(r, g, b); + } + + private static bool ParseBool(string line) + { + return line == "1"; + } +} \ No newline at end of file diff --git a/src/Stater.SLXParser/Stater.SLXParser.csproj b/src/Stater.SLXParser/Stater.SLXParser.csproj new file mode 100644 index 0000000..00f6239 --- /dev/null +++ b/src/Stater.SLXParser/Stater.SLXParser.csproj @@ -0,0 +1,13 @@ + + + + + + + + net8.0 + enable + enable + + + diff --git a/src/Stater.SLXParser/TestData/BR_GATES_HDL.slx b/src/Stater.SLXParser/TestData/BR_GATES_HDL.slx new file mode 100644 index 0000000..ec512fa Binary files /dev/null and b/src/Stater.SLXParser/TestData/BR_GATES_HDL.slx differ diff --git a/src/Stater.SLXParser/Translator.cs b/src/Stater.SLXParser/Translator.cs new file mode 100644 index 0000000..a986cc3 --- /dev/null +++ b/src/Stater.SLXParser/Translator.cs @@ -0,0 +1,143 @@ +using Stater.Domain.Models; +using Stater.SLXParser.Models; + +namespace Stater.SLXParser; + +public class Translator +{ + public StateMachine Convert(Stateflow stateflow) + { + var stateMachine = new StateMachine + { + // Type = "SLX", + Name = stateflow.Instance.Name, + States = ConvertChart(stateflow.Machine.Chart), + Variables = ConvertVariable(stateflow.Machine.Chart.ChildrenData), + }; + + stateMachine.Transitions.AddRange(ConvertChartTransitions(stateflow.Machine.Chart, stateMachine.States)); + + stateMachine.States[0] = stateMachine.States[0] with { Type = StateType.Start }; + stateMachine.States[^1] = stateMachine.States[^1] with { Type = StateType.End }; + + return stateMachine; + } + + private static List ConvertChart(Chart chart) + { + var states = new List(); + + foreach (var state in chart.ChildrenState) + { + states.AddRange(ConvertState(state)); + } + + return states; + } + + private static IEnumerable ConvertState(SlxState slxSlxState) + { + var state = new State + { + Guid = slxSlxState.Id, + Name = slxSlxState.LabelString, + Type = StateType.Common, + X = slxSlxState.Position.X.X, + Y = slxSlxState.Position.X.Y, + }; + + var states = new List { state }; + + foreach (var slxStateChildren in slxSlxState.ChildrenState) + { + states.AddRange(ConvertState(slxStateChildren)); + } + + return states; + } + + private List ConvertChartTransitions(Chart chart, List slxStateOriginList) + { + var transitions = new List(); + + foreach (var state in chart.ChildrenState) + { + transitions.AddRange(ConvertStateTransition(state, slxStateOriginList)); + } + + return transitions; + } + + private static IEnumerable ConvertStateTransition(SlxState slxSlxState, List slxStateOriginList) + { + var transitions = new List(); + + foreach (var transition in slxSlxState.ChildrenTransition) + { + var transition_ = ConvertTransition(transition, slxStateOriginList); + if (transition_ != null) + { + transitions.Add(transition_); + } + } + + foreach (var state in slxSlxState.ChildrenState) + { + transitions.AddRange(ConvertStateTransition(state, slxStateOriginList)); + } + + return transitions; + } + + private static Transition ConvertTransition(SlxTransition slxTransition, List slxStateOriginList) + { + var transition = new Transition + { + Guid = slxTransition.Id + }; + + var start = FindStateById(slxTransition.Src.SSID, slxStateOriginList); + var end = FindStateById(slxTransition.Dst.SSID, slxStateOriginList); + + if (start == null || end == null) + { + return null; + } + + transition = transition with + { + Start = start.Guid, + End = end.Guid, + Name = slxTransition.LabelString + }; + + // start.Outgoing.Add(transition); + // end.Incoming.Add(transition); + + return transition; + } + + private static State FindStateById(Guid id, List slxStateOriginList) + { + return slxStateOriginList.FirstOrDefault(state => state.Guid == id); + } + + private static List ConvertVariable(List datas) + { + var result = new List(); + foreach (var data in datas) + { + // var variableValue = VariableValueBuilder.fromString(""); + + var variable = new Variable + { + Name = data.Name + }; + + // variable.ID = new UID(data.Id); + result.Add(variable); + } + + return result; + } +} \ No newline at end of file diff --git a/src/Stater.SLXParser/Utils/Color.cs b/src/Stater.SLXParser/Utils/Color.cs new file mode 100644 index 0000000..62dbcb8 --- /dev/null +++ b/src/Stater.SLXParser/Utils/Color.cs @@ -0,0 +1,15 @@ +namespace Stater.SLXParser.Utils; + +public class Color +{ + public int R { get; set; } + public int G { get; set; } + public int B { get; set; } + + public Color(int r, int g, int b) + { + R = r; + G = g; + B = b; + } +} \ No newline at end of file diff --git a/src/Stater.SLXParser/Utils/Point2D.cs b/src/Stater.SLXParser/Utils/Point2D.cs new file mode 100644 index 0000000..628eafd --- /dev/null +++ b/src/Stater.SLXParser/Utils/Point2D.cs @@ -0,0 +1,38 @@ +namespace Stater.SLXParser.Utils; + +public class Point2D +{ + public float X { get; set; } + public float Y { get; set; } + + public Point2D(float x, float y) + { + X = x; + Y = y; + } +} + +public class DoublePoint +{ + public Point2D X { get; set; } + public Point2D Y { get; set; } + + public DoublePoint(Point2D x, Point2D y) + { + X = x; + Y = y; + } +} + + +public class DoubleDoublePoint +{ + public DoublePoint X { get; set; } + public DoublePoint Y { get; set; } + + public DoubleDoublePoint(DoublePoint x, DoublePoint y) + { + X = x; + Y = y; + } +} \ No newline at end of file diff --git a/src/Stater/App.axaml b/src/Stater/App.axaml new file mode 100644 index 0000000..8ffa9c1 --- /dev/null +++ b/src/Stater/App.axaml @@ -0,0 +1,15 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/Stater/App.axaml.cs b/src/Stater/App.axaml.cs new file mode 100644 index 0000000..0daae44 --- /dev/null +++ b/src/Stater/App.axaml.cs @@ -0,0 +1,68 @@ +using Avalonia; +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Data.Core.Plugins; +using Avalonia.Markup.Xaml; +using Splat; +using Stater.Models; +using Stater.Models.Editors; +using Stater.Models.Editors.impl; +using Stater.Models.Executor; +using Stater.Models.Executor.impl; +using Stater.Models.impl; +using Stater.ViewModels; +using Stater.Views; + +namespace Stater; + +public partial class App : Application +{ + public override void Initialize() + { + AvaloniaXamlLoader.Load(this); + } + + public override void OnFrameworkInitializationCompleted() + { + if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + { + // Line below is needed to remove Avalonia data validation. + // Without this line you will get duplicate validations from both Avalonia and CT + + InitDependency(); + + var projectManager = Locator.Current.GetService()!; + var editorManager = Locator.Current.GetService()!; + + + BindingPlugins.DataValidators.RemoveAt(0); + desktop.MainWindow = new MainWindow + { + DataContext = new MainWindowViewModel(projectManager, editorManager), + }; + } + + base.OnFrameworkInitializationCompleted(); + } + + private void InitDependency() + { + var projectManager = new ProjectManager(); + var stateMachineEditor = new StateMachineEditor(projectManager); + var stateEditor = new StateEditor(projectManager); + var transitionEditor = new TransitionEditor(projectManager); + var variableEditor = new VariableEditor(projectManager); + + var execitor = new Executor(projectManager); + + Locator.CurrentMutable.RegisterConstant(projectManager, typeof(IProjectManager)); + + Locator.CurrentMutable.RegisterConstant( + new EditorManager(stateMachineEditor, stateEditor, transitionEditor, variableEditor), + typeof(IEditorManager)); + Locator.CurrentMutable.RegisterConstant(stateMachineEditor, typeof(IStateMachineEditor)); + Locator.CurrentMutable.RegisterConstant(stateEditor, typeof(IStateEditor)); + Locator.CurrentMutable.RegisterConstant(transitionEditor, typeof(ITransitionEditor)); + Locator.CurrentMutable.RegisterConstant(variableEditor, typeof(IVariableEditor)); + Locator.CurrentMutable.RegisterConstant(execitor, typeof(IExecutor)); + } +} \ No newline at end of file diff --git a/src/Stater/Assets/avalonia-logo.ico b/src/Stater/Assets/avalonia-logo.ico new file mode 100644 index 0000000..da8d49f Binary files /dev/null and b/src/Stater/Assets/avalonia-logo.ico differ diff --git a/src/Stater/Converters/EditorTypeToBoolConverter.cs b/src/Stater/Converters/EditorTypeToBoolConverter.cs new file mode 100644 index 0000000..ca63246 --- /dev/null +++ b/src/Stater/Converters/EditorTypeToBoolConverter.cs @@ -0,0 +1,28 @@ +using System; +using System.Globalization; +using Avalonia.Data.Converters; +using Stater.Models.Editors; + +namespace Stater.Converters; + +public class EditorTypeToBoolConverter : IValueConverter +{ + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (parameter == null || value == null) + return false; + + var editorType = (EditorTypeEnum)value; + if (Enum.TryParse(parameter.ToString(), out EditorTypeEnum targetEditorType)) + { + return editorType == targetEditorType; + } + + return false; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/Stater/FodyWeavers.xml b/src/Stater/FodyWeavers.xml new file mode 100644 index 0000000..63fc148 --- /dev/null +++ b/src/Stater/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/Stater/FodyWeavers.xsd b/src/Stater/FodyWeavers.xsd new file mode 100644 index 0000000..f3ac476 --- /dev/null +++ b/src/Stater/FodyWeavers.xsd @@ -0,0 +1,26 @@ + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/src/Stater/Models/AssociateTransition.cs b/src/Stater/Models/AssociateTransition.cs new file mode 100644 index 0000000..7a12204 --- /dev/null +++ b/src/Stater/Models/AssociateTransition.cs @@ -0,0 +1,19 @@ +using Avalonia; +using Stater.Domain.Models; + +namespace Stater.Models; + +public record AssociateTransition( + State? Start, + Point StartPoint, + State? End, + Point EndPoint, + Transition Transition +); + + +public record StateTransition( + State StartState, + State EndState, + Transition Transition +); \ No newline at end of file diff --git a/src/Stater/Models/Editors/IEditorManager.cs b/src/Stater/Models/Editors/IEditorManager.cs new file mode 100644 index 0000000..f60e7f7 --- /dev/null +++ b/src/Stater/Models/Editors/IEditorManager.cs @@ -0,0 +1,27 @@ +using System; +using Stater.Domain.Models; + +namespace Stater.Models.Editors; + +public enum EditorTypeEnum +{ + Null, + StateMachine, + State, + Transition, + Variable, + CodeGeneration +} + +public interface IEditorManager +{ + IObservable EditorType { get; } + + void DoSelectNull(); + + void DoSelectStateMachine(StateMachine stateMachine); + void DoSelectState(State state); + void DoSelectTransition(Transition transition); + void DoSelectVariable(Variable variable); + void DoSelectCodeGeneration(); +} \ No newline at end of file diff --git a/src/Stater/Models/Editors/IStateEditor.cs b/src/Stater/Models/Editors/IStateEditor.cs new file mode 100644 index 0000000..4517af9 --- /dev/null +++ b/src/Stater/Models/Editors/IStateEditor.cs @@ -0,0 +1,12 @@ +using System; +using Stater.Domain.Models; + +namespace Stater.Models.Editors; + +public interface IStateEditor +{ + IObservable State { get; } + + void DoSelect(State state); + void Update(State state); +} \ No newline at end of file diff --git a/src/Stater/Models/Editors/IStateMachineEditor.cs b/src/Stater/Models/Editors/IStateMachineEditor.cs new file mode 100644 index 0000000..009905c --- /dev/null +++ b/src/Stater/Models/Editors/IStateMachineEditor.cs @@ -0,0 +1,12 @@ +using System; +using Stater.Domain.Models; + +namespace Stater.Models.Editors; + +public interface IStateMachineEditor +{ + IObservable StateMachine { get; } + + void DoSelect(StateMachine stateMachine); + void Update(StateMachine stateMachine); +} \ No newline at end of file diff --git a/src/Stater/Models/Editors/ITransitionEditor.cs b/src/Stater/Models/Editors/ITransitionEditor.cs new file mode 100644 index 0000000..55a1d45 --- /dev/null +++ b/src/Stater/Models/Editors/ITransitionEditor.cs @@ -0,0 +1,12 @@ +using System; +using Stater.Domain.Models; + +namespace Stater.Models.Editors; + +public interface ITransitionEditor +{ + IObservable Transition { get; } + + void DoSelect(Transition transition); + void Update(Transition transition); +} \ No newline at end of file diff --git a/src/Stater/Models/Editors/IVariableEditor.cs b/src/Stater/Models/Editors/IVariableEditor.cs new file mode 100644 index 0000000..f455400 --- /dev/null +++ b/src/Stater/Models/Editors/IVariableEditor.cs @@ -0,0 +1,12 @@ +using System; +using Stater.Domain.Models; + +namespace Stater.Models.Editors; + +public interface IVariableEditor +{ + IObservable Variable { get; } + + void DoSelect(Variable transition); + void Update(Variable transition); +} \ No newline at end of file diff --git a/src/Stater/Models/Editors/impl/EditorManager.cs b/src/Stater/Models/Editors/impl/EditorManager.cs new file mode 100644 index 0000000..21faa09 --- /dev/null +++ b/src/Stater/Models/Editors/impl/EditorManager.cs @@ -0,0 +1,64 @@ +using System; +using System.Reactive.Subjects; +using Stater.Domain.Models; + +namespace Stater.Models.Editors.impl; + +public class EditorManager : IEditorManager +{ + private readonly ReplaySubject _editorType = new(); + public IObservable EditorType => _editorType; + + private IStateMachineEditor _stateMachineEditor; + private IStateEditor _stateEditor; + private ITransitionEditor _transitionEditor; + private IVariableEditor _variableEditor; + + public void DoSelectNull() + { + _editorType.OnNext(EditorTypeEnum.Null); + } + + public EditorManager( + IStateMachineEditor stateMachineEditor, + IStateEditor stateEditor, + ITransitionEditor transitionEditor, + IVariableEditor variableEditor) + { + _editorType.OnNext(EditorTypeEnum.Null); + _stateMachineEditor = stateMachineEditor; + _stateEditor = stateEditor; + _transitionEditor = transitionEditor; + _variableEditor = variableEditor; + } + + + public void DoSelectStateMachine(StateMachine stateMachine) + { + _stateMachineEditor.DoSelect(stateMachine); + _editorType.OnNext(EditorTypeEnum.StateMachine); + } + + public void DoSelectState(State state) + { + _stateEditor.DoSelect(state); + _editorType.OnNext(EditorTypeEnum.State); + } + + public void DoSelectTransition(Transition transition) + { + _transitionEditor.DoSelect(transition); + _editorType.OnNext(EditorTypeEnum.Transition); + } + + public void DoSelectVariable(Variable variable) + { + _variableEditor.DoSelect(variable); + _editorType.OnNext(EditorTypeEnum.Variable); + } + + public void DoSelectCodeGeneration() + { + _editorType.OnNext(EditorTypeEnum.CodeGeneration); + } +} \ No newline at end of file diff --git a/src/Stater/Models/Editors/impl/StateEditor.cs b/src/Stater/Models/Editors/impl/StateEditor.cs new file mode 100644 index 0000000..50dff18 --- /dev/null +++ b/src/Stater/Models/Editors/impl/StateEditor.cs @@ -0,0 +1,21 @@ +using System; +using System.Reactive.Subjects; +using Stater.Domain.Models; + +namespace Stater.Models.Editors.impl; + +public class StateEditor(IProjectManager projectManager): IStateEditor +{ + private readonly ReplaySubject _state = new(); + public IObservable State => _state; + + public void DoSelect(State state) + { + _state.OnNext(state); + } + + public void Update(State state) + { + projectManager.UpdateState(state); + } +} \ No newline at end of file diff --git a/src/Stater/Models/Editors/impl/StateMachineEditor.cs b/src/Stater/Models/Editors/impl/StateMachineEditor.cs new file mode 100644 index 0000000..77d5ee4 --- /dev/null +++ b/src/Stater/Models/Editors/impl/StateMachineEditor.cs @@ -0,0 +1,23 @@ +using System; +using System.Reactive.Subjects; +using Stater.Domain.Models; + +namespace Stater.Models.Editors.impl; + +public class StateMachineEditor( + IProjectManager projectManager +) : IStateMachineEditor +{ + private readonly ReplaySubject _stateMachine = new(); + public IObservable StateMachine => _stateMachine; + + public void DoSelect(StateMachine stateMachine) + { + _stateMachine.OnNext(stateMachine); + } + + public void Update(StateMachine stateMachine) + { + projectManager.UpdateStateMachine(stateMachine); + } +} \ No newline at end of file diff --git a/src/Stater/Models/Editors/impl/TransitionEditor.cs b/src/Stater/Models/Editors/impl/TransitionEditor.cs new file mode 100644 index 0000000..7cc5765 --- /dev/null +++ b/src/Stater/Models/Editors/impl/TransitionEditor.cs @@ -0,0 +1,23 @@ +using System; +using System.Reactive.Subjects; +using Stater.Domain.Models; + +namespace Stater.Models.Editors.impl; + +public class TransitionEditor( + IProjectManager projectManager +) : ITransitionEditor +{ + private readonly ReplaySubject _transition = new(); + public IObservable Transition => _transition; + + public void DoSelect(Transition transition) + { + _transition.OnNext(transition); + } + + public void Update(Transition transition) + { + projectManager.UpdateTransition(transition); + } +} \ No newline at end of file diff --git a/src/Stater/Models/Editors/impl/VariableEditor.cs b/src/Stater/Models/Editors/impl/VariableEditor.cs new file mode 100644 index 0000000..b979d4e --- /dev/null +++ b/src/Stater/Models/Editors/impl/VariableEditor.cs @@ -0,0 +1,23 @@ +using System; +using System.Reactive.Subjects; +using Stater.Domain.Models; + +namespace Stater.Models.Editors.impl; + +public class VariableEditor( + IProjectManager projectManager +) : IVariableEditor +{ + private readonly ReplaySubject _variable = new(); + public IObservable Variable => _variable; + + public void DoSelect(Variable variable) + { + _variable.OnNext(variable); + } + + public void Update(Variable variable) + { + projectManager.UpdateVariable(variable); + } +} \ No newline at end of file diff --git a/src/Stater/Models/Executor/ExecuteLog.cs b/src/Stater/Models/Executor/ExecuteLog.cs new file mode 100644 index 0000000..2601b63 --- /dev/null +++ b/src/Stater/Models/Executor/ExecuteLog.cs @@ -0,0 +1,15 @@ +namespace Stater.Models.Executor; + + + +public record ExecuteLog( + string Text, + int Tab, + ExecuteLog.ExecuteLogStatusEnum ExecuteLogStatus +) +{ + public enum ExecuteLogStatusEnum + { + Info, Warning, Error + } +}; \ No newline at end of file diff --git a/src/Stater/Models/Executor/IExecutor.cs b/src/Stater/Models/Executor/IExecutor.cs new file mode 100644 index 0000000..637f19a --- /dev/null +++ b/src/Stater/Models/Executor/IExecutor.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using Stater.Domain.Models; + +namespace Stater.Models.Executor; + +public record LogContainer( + List Logs +); + +public interface IExecutor +{ + IObservable State { get; } + IObservable Logs { get; } + IObservable?> Variables { get; } + + void Start(int stepTime); + void Stop(); + void Reset(); + void Step(); + + void ClearLog(); +} \ No newline at end of file diff --git a/src/Stater/Models/Executor/impl/Executor.cs b/src/Stater/Models/Executor/impl/Executor.cs new file mode 100644 index 0000000..54f7bfe --- /dev/null +++ b/src/Stater/Models/Executor/impl/Executor.cs @@ -0,0 +1,228 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Subjects; +using System.Threading; +using Stater.Domain.Logic; +using Stater.Domain.Models; + +namespace Stater.Models.Executor.impl; + +public class Executor(IProjectManager projectManager) : IExecutor +{ + private readonly ReplaySubject _state = new(); + public IObservable State => _state; + + private StateMachine? _stateMachine; + + private readonly ReplaySubject _logs = new(); + public IObservable Logs => _logs; + + private readonly ReplaySubject?> _variables = new(); + public IObservable?> Variables => _variables; + + private Thread? ExecuteThread; + private bool StopExecution; + + private void WriteLog( + string message, + int tab = 0, + ExecuteLog.ExecuteLogStatusEnum executeLogStatus = ExecuteLog.ExecuteLogStatusEnum.Info) + { + LogContainer? logs = null; + var s = _logs.Subscribe(x => logs = x); + s.Dispose(); + logs ??= new LogContainer(new List()); + logs.Logs.Add(new ExecuteLog(Text: message, Tab: tab, ExecuteLogStatus: executeLogStatus)); + _logs.OnNext(logs); + } + + private State? GetCurrentState() + { + State? currentState = null; + var subscribe = _state.Subscribe(s => currentState = s); + subscribe.Dispose(); + Console.WriteLine(currentState); + return currentState; + } + + private IDictionary? GetCurrentVariables() + { + IDictionary? variables = null; + var subscribe = _variables.Subscribe(s => variables = s); + subscribe.Dispose(); + return variables; + } + + private StateMachine? GetCurrentStateMachine() + { + StateMachine? currentStateMachine = null; + var s = projectManager.StateMachine.Subscribe(stateMachine => currentStateMachine = stateMachine); + s.Dispose(); + return currentStateMachine; + } + + public void Start(int stepTime) + { + WriteLog("Starting executing."); + if (_stateMachine == null) + { + Console.WriteLine("YES"); + var currentStateMachine = GetCurrentStateMachine(); + if (currentStateMachine == null) + { + WriteLog("Execution not started, State Machine not set", 0, ExecuteLog.ExecuteLogStatusEnum.Error); + return; + } + + _stateMachine = currentStateMachine; + _state.OnNext(null); + _variables.OnNext(null); + } + + WriteLog("State Machine: " + _stateMachine.Name); + + var state = GetCurrentState(); + if (state == null) + { + state = _stateMachine.States.FirstOrDefault(s => s.Type == StateType.Start); + if (state == null) + { + WriteLog("Execution not started, Start State not set", 0, ExecuteLog.ExecuteLogStatusEnum.Error); + return; + } + + _state.OnNext(state); + } + + var variables = GetCurrentVariables(); + if (variables == null) + { + WriteLog("Initializing variables"); + + variables = _stateMachine.Variables.ToDictionary(x => x.Guid, x => + { + WriteLog($"{x.Name} init with {x.StartValue}"); + return x.StartValue; + }); + _variables.OnNext(variables); + } + + WriteLog("Start State: " + state.Name); + + ExecuteThread = new Thread(() => + { + WriteLog("Execution started."); + StopExecution = false; + while (!StopExecution) + { + Step(); + Thread.Sleep(stepTime); + } + + WriteLog("Execution stopped."); + }); + ExecuteThread.Start(); + } + + public void Stop() + { + if (StopExecution) return; + WriteLog("Stopping execution"); + StopExecution = true; + } + + public void Reset() + { + StopExecution = true; + WriteLog("Reset execution"); + _state.OnNext(null); + _stateMachine = null; + } + + public void Step() + { + var state = GetCurrentState(); + if (state == null) + { + WriteLog("Step is incorrect: State is not set", 0, ExecuteLog.ExecuteLogStatusEnum.Error); + Stop(); + return; + } + + if (state.Type == StateType.End) + { + WriteLog("State is end", 0, ExecuteLog.ExecuteLogStatusEnum.Info); + Stop(); + return; + } + + if (_stateMachine == null) + { + WriteLog("Step is incorrect: StateMachine is not set", 0, ExecuteLog.ExecuteLogStatusEnum.Error); + Stop(); + return; + } + + var variables = GetCurrentVariables(); + if (variables == null) + { + WriteLog("Step is incorrect: Variables is not set", 0, ExecuteLog.ExecuteLogStatusEnum.Error); + Stop(); + return; + } + + WriteLog("Processing state: " + state.Name + ". State Machine: " + _stateMachine.Name); + + var transitions = _stateMachine.Transitions.Where(t => t.Start == state.Guid).ToList(); + WriteLog($"Found {transitions.Count} transitions", 1); + + foreach (var transition in transitions) + { + if (transition.Condition == null) + { + WriteLog($"Transition {transition.Name} has not condition", 1); + continue; + } + + bool res; + try + { + res = ConditionLogic.Evaluate(transition.Condition, variables); + } + catch (VariableOperatorException e) + { + Console.WriteLine(e); + throw; + } + + if (res) + { + WriteLog($"Transition {transition.Name} condition is true", 1); + if (transition.Event != null) + { + var newVariables = EventLogic.Evaluate(transition.Event, GetCurrentVariables()); + foreach (var keyValuePair in newVariables) + { + Console.WriteLine(keyValuePair.Key + " " + keyValuePair.Value); + variables[keyValuePair.Key] = keyValuePair.Value; + } + } + + var newState = _stateMachine.States.First(s => s.Guid == transition.End); + _state.OnNext(newState); + return; + } + + WriteLog($"Transition {transition.Name} condition is false", 1); + } + + WriteLog("No transition was suitable", 0, ExecuteLog.ExecuteLogStatusEnum.Warning); + Stop(); + } + + public void ClearLog() + { + _logs.OnNext(new LogContainer(new List())); + } +} \ No newline at end of file diff --git a/src/Stater/Models/IProjectManager.cs b/src/Stater/Models/IProjectManager.cs new file mode 100644 index 0000000..1eb5668 --- /dev/null +++ b/src/Stater/Models/IProjectManager.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.IO; +using DynamicData; +using Stater.Domain.Models; + +namespace Stater.Models; + +public interface IProjectManager +{ + IObservable Project { get; } + IObservable> StateMachines { get; } + IObservable StateMachine { get; } + + void CreateProject(string name); + Project? LoadProject(StreamReader sr); + void SaveProject(StreamWriter sw); + + Project? GetProject(); + StateMachine? GetStateMachine(); + List GetStateMachines(); + + void Undo(); + void Redo(); + + StateMachine CreateStateMachine(); + void RemoveStateMachine(Guid guid); + void UpdateStateMachine(Domain.Models.StateMachine newStateMachine); + StateMachine? OpenStateMachine(Guid guid); + + State? CreateState(); + void RemoveState(Guid guid); + State? GetState(Guid guid); + void UpdateState(State state); + + Transition? CreateTransition(State start, State end); + void RemoveTransition(Guid guid); + Transition? GetTransition(Guid guid); + void UpdateTransition(Transition transition); + + Variable? CreateVariable(); + void RemoveVariable(Guid guid); + void UpdateVariable(Variable variable); + + void ChangeStateMachines(List stateMachines); +} \ No newline at end of file diff --git a/src/Stater/Models/Project.cs b/src/Stater/Models/Project.cs new file mode 100644 index 0000000..c5abc51 --- /dev/null +++ b/src/Stater/Models/Project.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; +using System.Xml.Serialization; +using Stater.Domain.Models; + +namespace Stater.Models; + +public record Project( + [property: XmlAttribute("name")] string Name, + [property: XmlAttribute("Location")] string? Location +) +{ + public Project() : this("Project", null) + { + } +}; + +public record ExportProject( + [property: XmlElement("Project")] Project? Project, + [property: XmlElement("StateMachines")] + List? StateMachines +) +{ + public ExportProject() : this(null, null) + { + } +} \ No newline at end of file diff --git a/src/Stater/Models/impl/ProjectManager.cs b/src/Stater/Models/impl/ProjectManager.cs new file mode 100644 index 0000000..cc37224 --- /dev/null +++ b/src/Stater/Models/impl/ProjectManager.cs @@ -0,0 +1,289 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.IO; +using System.Linq; +using System.Reactive.Subjects; +using System.Xml; +using DynamicData; +using Stater.Domain.Models; + +namespace Stater.Models.impl; + +internal class ProjectManager : IProjectManager +{ + private readonly ReplaySubject _project = new(); + public IObservable Project => _project; + + private readonly SourceCache _stateMachines = new(x => x.Guid.ToString()); + public IObservable> StateMachines => _stateMachines.Connect(); + + private readonly ReplaySubject _stateMachine = new(); + public IObservable StateMachine => _stateMachine; + + // private readonly ReplaySubject _state = new(); + // public IObservable State => _state; + + // private readonly ReplaySubject _transtion = new(); + // public IObservable Transition => _transtion; + + private readonly Stack undoStack = new(); + private readonly Stack redoStack = new(); + + public StateMachine? GetStateMachine() + { + StateMachine? currentStateMachine = null; + var s = _stateMachine.Subscribe(stateMachine => currentStateMachine = stateMachine); + s.Dispose(); + return currentStateMachine; + } + + public Project? GetProject() + { + Project? currentProject = null; + var s = _project.Subscribe(x => currentProject = x); + s.Dispose(); + return currentProject; + } + + public List GetStateMachines() + { + var s = _stateMachines.KeyValues.Select(x => x.Value).ToList(); + return s; + } + + + public void CreateProject(string name) + { + var project = new Project( + Name: name, + Location: null + ); + _project.OnNext(project); + GetStateMachines().ForEach(e => RemoveStateMachine(e.Guid)); + CreateStateMachine(); + } + + public Project? LoadProject(StreamReader sr) + { + XmlDocument doc = new XmlDocument(); + var writer = new System.Xml.Serialization.XmlSerializer(typeof(ExportProject)); + var project = writer.Deserialize(sr); + if (project is not ExportProject project1) throw new ValidationException(); + if (project1.Project != null) _project.OnNext(project1.Project); + project1.StateMachines?.ForEach(UpdateStateMachine); + return project1?.Project; + } + + public void SaveProject(StreamWriter sw) + { + var writer = new System.Xml.Serialization.XmlSerializer(typeof(ExportProject)); + var exportProject = new ExportProject( + GetProject(), + GetStateMachines() + ); + writer.Serialize(sw, exportProject); + sw.Close(); + } + + public void Undo() + { + Console.WriteLine("YES " + undoStack.Count); + if (undoStack.Count <= 1) return; + var stateMachine = undoStack.Pop(); + redoStack.Push(stateMachine); + _stateMachine.OnNext(undoStack.Peek()); + } + + public void Redo() + { + if (redoStack.Count <= 0) return; + var stateMachine = redoStack.Pop(); + undoStack.Push(stateMachine); + _stateMachine.OnNext(stateMachine); + } + + public void UpdateStateMachine(StateMachine newStateMachine) + { + undoStack.Push(newStateMachine); + redoStack.Clear(); + _stateMachines.AddOrUpdate(newStateMachine); + _stateMachine.OnNext(newStateMachine); + } + + public void RemoveStateMachine(Guid guid) + { + _stateMachines.Remove(guid.ToString()); + } + + public StateMachine CreateStateMachine() + { + var stateMachine = new StateMachine( + Guid: Guid.NewGuid(), + Name: "StateMachine " + _stateMachines.Count, + States: new List(), + Transitions: new List(), + Variables: new List() + ); + UpdateStateMachine(stateMachine); + return stateMachine; + } + + public StateMachine? OpenStateMachine(Guid guid) + { + var currentStateMachine = GetStateMachine(); + if (currentStateMachine?.Guid == guid) return null; + var stateMachine = _stateMachines.KeyValues[guid.ToString()]; + undoStack.Clear(); + redoStack.Clear(); + _stateMachine.OnNext(stateMachine); + undoStack.Push(stateMachine); + return stateMachine; + } + + public State? CreateState() + { + var currentStateMachine = GetStateMachine(); + if (currentStateMachine == null) return null; + var state = new State( + Guid: Guid.NewGuid(), + Name: "State", + Description: "", + Type: StateType.Common, + 10, + 10, + new List(), + new List() + ); + var newStateMachine = currentStateMachine with + { + States = new List(currentStateMachine.States) { state } + }; + UpdateStateMachine(newStateMachine); + return state; + } + + public void RemoveState(Guid guid) + { + var currentStateMachine = GetStateMachine(); + if (currentStateMachine == null) return; + var states = currentStateMachine.States.Where(el => el.Guid != guid); + var newStateMachine = currentStateMachine with + { + States = new List(states) + }; + UpdateStateMachine(newStateMachine); + } + + public State? GetState(Guid guid) + { + var currentStateMachine = GetStateMachine(); + return currentStateMachine?.States.FirstOrDefault(e => e.Guid == guid); + } + + public void UpdateState(State state) + { + var currentStateMachine = GetStateMachine(); + if (currentStateMachine == null) return; + var states = currentStateMachine.States.Where(el => el.Guid != state.Guid); + var newStateMachine = currentStateMachine with + { + States = new List(states) { state } + }; + UpdateStateMachine(newStateMachine); + } + + public Transition? CreateTransition(State start, State end) + { + var currentStateMachine = GetStateMachine(); + if (currentStateMachine == null) return null; + Transition transition = new( + Guid: Guid.NewGuid(), + Name: "State", + Start: start.Guid, + End: end.Guid, + Condition: null, + Event: null + ); + var newStateMachine = currentStateMachine with + { + Transitions = new List(currentStateMachine.Transitions) + { + transition + } + }; + UpdateStateMachine(newStateMachine); + return transition; + } + + public Transition? GetTransition(Guid guid) + { + var currentStateMachine = GetStateMachine(); + return currentStateMachine?.Transitions.FirstOrDefault(e => e.Guid == guid); + } + + public void RemoveTransition(Guid guid) + { + var currentStateMachine = GetStateMachine(); + if (currentStateMachine == null) return; + var transitions = currentStateMachine.Transitions.Where(el => el.Guid != guid); + var newStateMachine = currentStateMachine with + { + Transitions = new List(transitions) + }; + UpdateStateMachine(newStateMachine); + } + + public void UpdateTransition(Transition transition) + { + var currentStateMachine = GetStateMachine(); + if (currentStateMachine == null) return; + var transitions = currentStateMachine.Transitions.Where(el => el.Guid != transition.Guid); + var newStateMachine = currentStateMachine with + { + Transitions = new List(transitions) { transition } + }; + UpdateStateMachine(newStateMachine); + } + + public Variable? CreateVariable() + { + var currentStateMachine = GetStateMachine(); + if (currentStateMachine == null) return null; + + var variable = new Variable(); + currentStateMachine.Variables.Add(variable); + + UpdateStateMachine(currentStateMachine); + return variable; + } + + public void RemoveVariable(Guid guid) + { + var currentStateMachine = GetStateMachine(); + if (currentStateMachine == null) return; + var variables = currentStateMachine.Variables.Where(el => el.Guid != guid); + var newStateMachine = currentStateMachine with + { + Variables = variables.ToList() + }; + UpdateStateMachine(newStateMachine); + } + + public void UpdateVariable(Variable variable) + { + var currentStateMachine = GetStateMachine(); + if (currentStateMachine == null) return; + var variables = currentStateMachine.Variables.Where(el => el.Guid != variable.Guid); + var newStateMachine = currentStateMachine with + { + Variables = new List(variables) { variable } + }; + UpdateStateMachine(newStateMachine); + } + + public void ChangeStateMachines(List stateMachines) + { + stateMachines.ForEach(e => _stateMachines.AddOrUpdate(e)); + } +} \ No newline at end of file diff --git a/src/Stater/Plugin/ButtonFilePlugin.cs b/src/Stater/Plugin/ButtonFilePlugin.cs new file mode 100644 index 0000000..49c9793 --- /dev/null +++ b/src/Stater/Plugin/ButtonFilePlugin.cs @@ -0,0 +1,9 @@ +namespace Stater.Plugin; + +public abstract class ButtonFilePlugin : IPlugin +{ + public abstract PluginOutput Start(PluginInput pluginInput, string path); + public abstract bool Directory { get; } + + public virtual string Name => "ButtonFilePlugin"; +} \ No newline at end of file diff --git a/src/Stater/Plugin/ButtonPlugin.cs b/src/Stater/Plugin/ButtonPlugin.cs new file mode 100644 index 0000000..6c23b4a --- /dev/null +++ b/src/Stater/Plugin/ButtonPlugin.cs @@ -0,0 +1,8 @@ +namespace Stater.Plugin; + +public abstract class ButtonPlugin : IPlugin +{ + public abstract PluginOutput Start(PluginInput pluginInput); + + public virtual string Name => "ButtonPlugin"; +} \ No newline at end of file diff --git a/src/Stater/Plugin/IPlugin.cs b/src/Stater/Plugin/IPlugin.cs new file mode 100644 index 0000000..e890ec5 --- /dev/null +++ b/src/Stater/Plugin/IPlugin.cs @@ -0,0 +1,6 @@ +namespace Stater.Plugin; + +public interface IPlugin +{ + string Name { get; } +} \ No newline at end of file diff --git a/src/Stater/Plugin/JsonCodeExportPlugin.cs b/src/Stater/Plugin/JsonCodeExportPlugin.cs new file mode 100644 index 0000000..4edd78b --- /dev/null +++ b/src/Stater/Plugin/JsonCodeExportPlugin.cs @@ -0,0 +1,18 @@ +using System.IO; +using Stater.Domain.Json; + +namespace Stater.Plugin; + +public class JsonCodeExportPlugin : ButtonFilePlugin +{ + public override PluginOutput Start(PluginInput pluginInput, string path) + { + System.IO.Directory.CreateDirectory(path); + var jsonSchema = StateMachineJsonAdapter.ToJsonSchema(pluginInput.StateMachine); + File.WriteAllText(Path.Combine(path, pluginInput.StateMachine.Name + "_schema.json"), jsonSchema); + return PluginOutput.From("OK"); + } + + public override string Name => "Export json code"; + public override bool Directory => true; +} \ No newline at end of file diff --git a/src/Stater/Plugin/JsonCodeImportPlugin.cs b/src/Stater/Plugin/JsonCodeImportPlugin.cs new file mode 100644 index 0000000..ec5f720 --- /dev/null +++ b/src/Stater/Plugin/JsonCodeImportPlugin.cs @@ -0,0 +1,23 @@ +using System.IO; +using Stater.Domain.Json; + +namespace Stater.Plugin; + +public class JsonCodeImportPlugin : ButtonFilePlugin +{ + public override PluginOutput Start(PluginInput pluginInput, string path) + { + if (File.Exists(path)) + { + var content = File.ReadAllText(path); + var result = PluginOutput.From("OK"); + result.ChangedStateMachines.Add(StateMachineJsonAdapter.FromJsonSchema(content)); + return result; + } + + return PluginOutput.From("File not found"); + } + + public override string Name => "Import json code"; + public override bool Directory => false; +} \ No newline at end of file diff --git a/src/Stater/Plugin/PluginInput.cs b/src/Stater/Plugin/PluginInput.cs new file mode 100644 index 0000000..741b73d --- /dev/null +++ b/src/Stater/Plugin/PluginInput.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using Stater.Domain.Models; +using Stater.Models; + +namespace Stater.Plugin; + +public record PluginInput( + Project Project, + StateMachine StateMachine, + List StateMachines, + + IProjectManager ProjectManager +); \ No newline at end of file diff --git a/src/Stater/Plugin/PluginOutput.cs b/src/Stater/Plugin/PluginOutput.cs new file mode 100644 index 0000000..35f8cd5 --- /dev/null +++ b/src/Stater/Plugin/PluginOutput.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using Stater.Domain.Models; + +namespace Stater.Plugin; + +public record PluginOutput( + string? Message, + List ChangedStateMachines +) +{ + public static PluginOutput From( + string message + ) + { + return new PluginOutput(message, new List()); + } +} \ No newline at end of file diff --git a/src/Stater/Plugin/SLXPlugin.cs b/src/Stater/Plugin/SLXPlugin.cs new file mode 100644 index 0000000..7b73138 --- /dev/null +++ b/src/Stater/Plugin/SLXPlugin.cs @@ -0,0 +1,19 @@ +using Stater.SLXParser; + +namespace Stater.Plugin; + +public class SLXPlugin: ButtonFilePlugin +{ + public override PluginOutput Start(PluginInput pluginInput, string file) + { + var parser = new Parser(file); + var stateflow = parser.Parse(); + var pluginStateflow = new Translator().Convert(stateflow); + var result = PluginOutput.From("Ok"); + result.ChangedStateMachines.Add(pluginStateflow); + return result; + } + + public override string Name => "SLXParser"; + public override bool Directory => false; +} \ No newline at end of file diff --git a/src/Stater/Program.cs b/src/Stater/Program.cs new file mode 100644 index 0000000..aef94e0 --- /dev/null +++ b/src/Stater/Program.cs @@ -0,0 +1,23 @@ +using Avalonia; +using Avalonia.ReactiveUI; +using System; + +namespace Stater; + +sealed class Program +{ + // Initialization code. Don't use any Avalonia, third-party APIs or any + // SynchronizationContext-reliant code before AppMain is called: things aren't initialized + // yet and stuff might break. + [STAThread] + public static void Main(string[] args) => BuildAvaloniaApp() + .StartWithClassicDesktopLifetime(args); + + // Avalonia configuration, don't remove; also used by visual designer. + public static AppBuilder BuildAvaloniaApp() + => AppBuilder.Configure() + .UseReactiveUI() + .UsePlatformDetect() + .WithInterFont() + .LogToTrace(); +} \ No newline at end of file diff --git a/src/Stater/Stater.csproj b/src/Stater/Stater.csproj new file mode 100644 index 0000000..c5c7f3c --- /dev/null +++ b/src/Stater/Stater.csproj @@ -0,0 +1,46 @@ + + + WinExe + net8.0 + enable + true + app.manifest + true + + + + + + + + + + + + + + + + + + + + + + + + MainEditor.axaml + Code + + + BoardCanvas.axaml + Code + + + + + + + + + diff --git a/src/Stater/TestData/BR_GATES_CH_schema.json b/src/Stater/TestData/BR_GATES_CH_schema.json new file mode 100644 index 0000000..2a44432 --- /dev/null +++ b/src/Stater/TestData/BR_GATES_CH_schema.json @@ -0,0 +1,90 @@ +{ + "states": [ + "B1", + "dt\nBxG3 = 0;", + "dt\nen: BxG1 = 0;", + "dt1\nen: BxG0 = 0;", + "dt1\nen: BxG2 = 0;", + "G0_G1", + "G2_G3", + "OFF\nen: BxG0 = 0;...\nBxG1 = 1;", + "OFF\nen: BxG2 = 0;...\nBxG3 = 1;", + "ON\nen: BxG0 = 1;...\nBxG1 = 0;", + "ON\nen: BxG2 = 1;...\nBxG3 = 0;", + "tri_state\nen: BxG0 = 0;...\nBxG1 = 0;\n", + "tri_state\nen: BxG2 = 0;...\nBxG3 = 0;\n" + ], + "startState": "G0_G1", + "transitions": [ + { + "name": "[BRx == 2 || ... \nBRx == 3]", + "start": "tri_state\nen: BxG0 = 0;...\nBxG1 = 0;\n", + "end": "OFF\nen: BxG0 = 0;...\nBxG1 = 1;" + }, + { + "name": "[BRx == 0]", + "start": "B1", + "end": "tri_state\nen: BxG0 = 0;...\nBxG1 = 0;\n" + }, + { + "name": "[BRx == 1 || ... \nBRx == 4]", + "start": "tri_state\nen: BxG0 = 0;...\nBxG1 = 0;\n", + "end": "ON\nen: BxG0 = 1;...\nBxG1 = 0;" + }, + { + "name": "[BRx == 1 || ... \nBRx == 4]", + "start": "OFF\nen: BxG0 = 0;...\nBxG1 = 1;", + "end": "dt\nen: BxG1 = 0;" + }, + { + "name": "[after(dt,tick)]", + "start": "dt1\nen: BxG0 = 0;", + "end": "OFF\nen: BxG0 = 0;...\nBxG1 = 1;" + }, + { + "name": "[after(dt,tick)]", + "start": "dt\nen: BxG1 = 0;", + "end": "ON\nen: BxG0 = 1;...\nBxG1 = 0;" + }, + { + "name": "[BRx == 2 || ... \nBRx == 3]", + "start": "ON\nen: BxG0 = 1;...\nBxG1 = 0;", + "end": "dt1\nen: BxG0 = 0;" + }, + { + "name": "[BRx == 1 || ... \nBRx == 2]", + "start": "tri_state\nen: BxG2 = 0;...\nBxG3 = 0;\n", + "end": "OFF\nen: BxG2 = 0;...\nBxG3 = 1;" + }, + { + "name": "[BRx == 0]", + "start": "B1", + "end": "tri_state\nen: BxG2 = 0;...\nBxG3 = 0;\n" + }, + { + "name": "[BRx == 3 || ... \nBRx == 4]", + "start": "tri_state\nen: BxG2 = 0;...\nBxG3 = 0;\n", + "end": "ON\nen: BxG2 = 1;...\nBxG3 = 0;" + }, + { + "name": "[BRx == 3 || ... \nBRx == 4]", + "start": "OFF\nen: BxG2 = 0;...\nBxG3 = 1;", + "end": "dt\nBxG3 = 0;" + }, + { + "name": "[after(dt,tick)]", + "start": "dt1\nen: BxG2 = 0;", + "end": "OFF\nen: BxG2 = 0;...\nBxG3 = 1;" + }, + { + "name": "[after(dt,tick)]", + "start": "dt\nBxG3 = 0;", + "end": "ON\nen: BxG2 = 1;...\nBxG3 = 0;" + }, + { + "name": "[BRx == 1 || ... \nBRx == 2]", + "start": "ON\nen: BxG2 = 1;...\nBxG3 = 0;", + "end": "dt1\nen: BxG2 = 0;" + } + ] +} \ No newline at end of file diff --git a/src/Stater/TestData/min b/src/Stater/TestData/min new file mode 100644 index 0000000..00da7d8 --- /dev/null +++ b/src/Stater/TestData/min @@ -0,0 +1,517 @@ + + + + + 3a2653f0-c0cc-4a17-8b4a-c48ec1c90eb6 + StateMachine 0 + + + 3ae1f825-65a4-487c-bb13-0c929579166f + Start + + Start + 10.269531 + 10.5390625 + + + + + 0dc5b654-d428-4bf7-b353-222845123f5d + Min + + Common + 10 + 92.556076 + + + + + acdb44a9-c58d-4f5d-b2da-cb7ff26da63d + Check + + Common + 266.55078 + 94.616295 + + + + + 86aa9a4c-4dce-482e-a191-f268609e45d6 + End + + End + 272.0586 + 171.8017 + + + + + 2f112f90-424f-4cdc-a907-0a39a6d61f3b + Pass + + Common + 125.096 + 174.51524 + + + + + + + ec5ebf48-25fd-4212-a2f7-c193c086243f + toPass + acdb44a9-c58d-4f5d-b2da-cb7ff26da63d + 2f112f90-424f-4cdc-a907-0a39a6d61f3b + + e5680cf9-cc87-4ff7-bff9-a3ef53e63c6e + Ne + + 5 + + + + + 1127c9fe-6ab3-4646-b518-289f9fd5c47c + toEnd + acdb44a9-c58d-4f5d-b2da-cb7ff26da63d + 86aa9a4c-4dce-482e-a191-f268609e45d6 + + e5680cf9-cc87-4ff7-bff9-a3ef53e63c6e + Eq + + 5 + + + + + b3a75179-b49e-4a60-b436-3e8cce241080 + State + 2f112f90-424f-4cdc-a907-0a39a6d61f3b + 0dc5b654-d428-4bf7-b353-222845123f5d + + e5680cf9-cc87-4ff7-bff9-a3ef53e63c6e + Gt + + 0 + + + + + 80e06dae-26ba-4f61-8d50-431c9d857021 + State + 3ae1f825-65a4-487c-bb13-0c929579166f + 0dc5b654-d428-4bf7-b353-222845123f5d + + e5680cf9-cc87-4ff7-bff9-a3ef53e63c6e + Gt + + 0 + + + + + 64cf3119-8cb3-4517-a265-60ea893839bf + State + 0dc5b654-d428-4bf7-b353-222845123f5d + acdb44a9-c58d-4f5d-b2da-cb7ff26da63d + + e5680cf9-cc87-4ff7-bff9-a3ef53e63c6e + Gt + + 0 + + + + e5680cf9-cc87-4ff7-bff9-a3ef53e63c6e + Sub + + 1 + + + + + + + e5680cf9-cc87-4ff7-bff9-a3ef53e63c6e + A + + 10 + + + + + + a931e318-d982-4b1c-b4fc-dc728315b529 + StateMachine 1 + + + 1f31bc1e-5e80-45ed-bd89-c728dee52eef + A + + Start + 9.797979 + 67.99305 + + + + + 930650f2-3138-48dc-aa0f-9d9363685bca + B + + Common + 273.92557 + 72.72873 + + + + + a1b24ba1-7923-44c7-b55f-a297ebd43cd9 + C + + Common + 155.5467 + 148.72523 + + + + + + + e858522a-e32f-4fac-b76e-8475823d6225 + State + 930650f2-3138-48dc-aa0f-9d9363685bca + a1b24ba1-7923-44c7-b55f-a297ebd43cd9 + + + 5222825d-d8a1-4a8d-9e77-a4b28958c33a + State + a1b24ba1-7923-44c7-b55f-a297ebd43cd9 + 1f31bc1e-5e80-45ed-bd89-c728dee52eef + + + d3ba65a7-894f-4a32-8ea2-8018d24b0119 + toB + 1f31bc1e-5e80-45ed-bd89-c728dee52eef + 930650f2-3138-48dc-aa0f-9d9363685bca + + 5f805493-8c5e-41ae-b16a-5f29da473d2c + Eq + + 1 + + + + + + + 5f805493-8c5e-41ae-b16a-5f29da473d2c + A + + 0 + + + + + + 9938e855-fa6e-4222-9f15-da4b9d491b0c + BR_GATES_CH + + + 00000061-0000-0000-0000-000000000000 + G0_G1 + + Start + 20.0875 + 77.985 + + + + + 00000086-0000-0000-0000-000000000000 + G2_G3 + + Common + 20.0875 + 410.485 + + + + + 00000080-0000-0000-0000-000000000000 + B1 + + Common + 28.8575 + 430.72 + + + + + 0000007a-0000-0000-0000-000000000000 + OFF +en: BxG2 = 0;... +BxG3 = 1; + + Common + 108.8575 + 439.58 + + + + + 0000007f-0000-0000-0000-000000000000 + dt +BxG3 = 0; + + Common + 38.5475 + 539.785 + + + + + 00000084-0000-0000-0000-000000000000 + dt1 +en: BxG2 = 0; + + Common + 180.7175 + 539.785 + + + + + 00000083-0000-0000-0000-000000000000 + ON +en: BxG2 = 1;... +BxG3 = 0; + + Common + 108.8575 + 645.925 + + + + + 00000081-0000-0000-0000-000000000000 + tri_state +en: BxG2 = 0;... +BxG3 = 0; + + + End + 347.3725 + 537.44 + + + + + 00000068-0000-0000-0000-000000000000 + OFF +en: BxG0 = 0;... +BxG1 = 1; + + Common + 179.98236 + 50.160686 + + + + + 00000072-0000-0000-0000-000000000000 + dt1 +en: BxG0 = 0; + + Common + 228.45139 + 163.88199 + + + + + 00000069-0000-0000-0000-000000000000 + dt +en: BxG1 = 0; + + Common + 30.665432 + 197.26773 + + + + + 0000006a-0000-0000-0000-000000000000 + ON +en: BxG0 = 1;... +BxG1 = 0; + + Common + 110.0875 + 301.97647 + + + + + 00000076-0000-0000-0000-000000000000 + B1 + + Common + 30.0875 + 136.94293 + + + + + 0000006c-0000-0000-0000-000000000000 + tri_state +en: BxG0 = 0;... +BxG1 = 0; + + + Common + 264.84747 + 248.10228 + + + + + + + 0000006f-0000-0000-0000-000000000000 + [BRx == 2 || ... +BRx == 3] + 0000006c-0000-0000-0000-000000000000 + 00000068-0000-0000-0000-000000000000 + + + 00000077-0000-0000-0000-000000000000 + [BRx == 0] + 00000076-0000-0000-0000-000000000000 + 0000006c-0000-0000-0000-000000000000 + + + 0000006e-0000-0000-0000-000000000000 + [BRx == 1 || ... +BRx == 4] + 0000006c-0000-0000-0000-000000000000 + 0000006a-0000-0000-0000-000000000000 + + + 00000070-0000-0000-0000-000000000000 + [BRx == 1 || ... +BRx == 4] + 00000068-0000-0000-0000-000000000000 + 00000069-0000-0000-0000-000000000000 + + + 00000074-0000-0000-0000-000000000000 + [after(dt,tick)] + 00000072-0000-0000-0000-000000000000 + 00000068-0000-0000-0000-000000000000 + + + 00000071-0000-0000-0000-000000000000 + [after(dt,tick)] + 00000069-0000-0000-0000-000000000000 + 0000006a-0000-0000-0000-000000000000 + + + 00000073-0000-0000-0000-000000000000 + [BRx == 2 || ... +BRx == 3] + 0000006a-0000-0000-0000-000000000000 + 00000072-0000-0000-0000-000000000000 + + + 00000079-0000-0000-0000-000000000000 + [BRx == 1 || ... +BRx == 2] + 00000081-0000-0000-0000-000000000000 + 0000007a-0000-0000-0000-000000000000 + + + 00000082-0000-0000-0000-000000000000 + [BRx == 0] + 00000080-0000-0000-0000-000000000000 + 00000081-0000-0000-0000-000000000000 + + + 00000078-0000-0000-0000-000000000000 + [BRx == 3 || ... +BRx == 4] + 00000081-0000-0000-0000-000000000000 + 00000083-0000-0000-0000-000000000000 + + + 0000007c-0000-0000-0000-000000000000 + [BRx == 3 || ... +BRx == 4] + 0000007a-0000-0000-0000-000000000000 + 0000007f-0000-0000-0000-000000000000 + + + 0000007d-0000-0000-0000-000000000000 + [after(dt,tick)] + 00000084-0000-0000-0000-000000000000 + 0000007a-0000-0000-0000-000000000000 + + + 0000007b-0000-0000-0000-000000000000 + [after(dt,tick)] + 0000007f-0000-0000-0000-000000000000 + 00000083-0000-0000-0000-000000000000 + + + 00000085-0000-0000-0000-000000000000 + [BRx == 1 || ... +BRx == 2] + 00000083-0000-0000-0000-000000000000 + 00000084-0000-0000-0000-000000000000 + + + + + a8643d72-a8cf-4630-a859-739c975bc40c + BRx + + 0 + + + + c634e3f8-75b4-40f9-b8e1-1fbe167edda9 + BxG0 + + 0 + + + + e6a69bb2-2ad0-4b0c-85c0-1fa7d7ccccf5 + BxG1 + + 0 + + + + e04d08ad-341d-42f3-b9c8-f09ce325d8c1 + BxG2 + + 0 + + + + 01ff732c-4d5a-4db9-9852-cae6eb2f8a71 + BxG3 + + 0 + + + + 204d00a4-17b0-4799-88e1-e66470ea1f93 + dt + + 0 + + + + + \ No newline at end of file diff --git a/src/Stater/TestSave.cs b/src/Stater/TestSave.cs new file mode 100644 index 0000000..cbae5bc --- /dev/null +++ b/src/Stater/TestSave.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Stater.Domain.Models; +using Stater.Models; + +namespace Stater; + +public class TestSave +{ + public static void main2() + { + var writer = new System.Xml.Serialization.XmlSerializer(typeof(ExportProject)); + + Project project = new("Project", null); + + var stateMachine1 = new StateMachine(); + + var start = new State(); + start = start with + { + Name = "Start", + Type = StateType.Start + }; + stateMachine1.States.Add(start); + + var end = new State(); + end = end with + { + Name = "End", + Type = StateType.End + }; + + var transition = new Transition(); + transition = transition with + { + Start = start.Guid, + End = end.Guid, + Condition = new Condition.VariableCondition() + }; + + stateMachine1.States.Add(end); + stateMachine1.Transitions.Add(transition); + + var exportProject = new ExportProject( + project, + new List { stateMachine1 } + ); + + Console.WriteLine("YES1"); + var fileName = Path.GetFullPath("./statemachine.xml"); + Console.WriteLine(fileName); + var sw = new StreamWriter(fileName); + // Console.WriteLine(sw.); + writer.Serialize(sw, exportProject); + Console.WriteLine("YES3"); + sw.Close(); + } +} \ No newline at end of file diff --git a/src/Stater/ViewLocator.cs b/src/Stater/ViewLocator.cs new file mode 100644 index 0000000..a519100 --- /dev/null +++ b/src/Stater/ViewLocator.cs @@ -0,0 +1,32 @@ +using System; +using Avalonia.Controls; +using Avalonia.Controls.Templates; +using Stater.ViewModels; + +namespace Stater; + +public class ViewLocator : IDataTemplate +{ + public Control? Build(object? data) + { + if (data is null) + return null; + + var name = data.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal); + var type = Type.GetType(name); + + if (type != null) + { + var control = (Control)Activator.CreateInstance(type)!; + control.DataContext = data; + return control; + } + + return new TextBlock { Text = "Not Found: " + name }; + } + + public bool Match(object? data) + { + return data is ViewModelBase; + } +} \ No newline at end of file diff --git a/src/Stater/ViewModels/Board/BoardCanvasViewModel.cs b/src/Stater/ViewModels/Board/BoardCanvasViewModel.cs new file mode 100644 index 0000000..414855c --- /dev/null +++ b/src/Stater/ViewModels/Board/BoardCanvasViewModel.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Reactive; +using Avalonia; +using ReactiveUI; +using ReactiveUI.Fody.Helpers; +using Stater.Domain.Models; +using Stater.Models; +using Stater.Models.Editors; + +namespace Stater.ViewModels.Board; + +public class BoardCanvasViewModel : ReactiveObject +{ + public BoardCanvasViewModel(IProjectManager projectManager, IEditorManager editorManager) + { + _projectManager = projectManager; + _editorManager = editorManager; + + projectManager + .StateMachine + .Subscribe(x => + { + StateMachine = x; + Transitions = x.Transitions.Select(y => + { + var startState = x.States.Find(s => s.Guid == y.Start); + var endState = x.States.Find(s => s.Guid == y.End); + if (startState != null && endState != null) + return new AssociateTransition( + Transition: y, + StartPoint: new Point(startState.X, startState.Y), + EndPoint: new Point(endState.X, endState.Y), + Start: startState, + End: endState + ); + return null; + } + ) + .Where(y => y != null) + .OfType() + .ToList(); + }); + + StateClickCommand = ReactiveCommand.Create(OnStateClicked); + UpdateStateCoordsCommand = ReactiveCommand.Create(UpdateStateCoords); + TransitionClickCommand = ReactiveCommand.Create(OnTransitionClicked); + } + + private readonly IProjectManager _projectManager; + private readonly IEditorManager _editorManager; + + [Reactive] public List Transitions { get; set; } + [Reactive] public State? State { get; private set; } + [Reactive] public StateMachine StateMachine { get; private set; } + + public ReactiveCommand StateClickCommand { get; } + public ReactiveCommand UpdateStateCoordsCommand { get; } + + public ReactiveCommand TransitionClickCommand { get; } + + private void OnStateClicked(State state) + { + var selectedState = _projectManager.GetState(state.Guid); + State = selectedState ?? null; + if (State != null) _editorManager.DoSelectState(State); + } + + private void OnTransitionClicked(Transition transition) + { + var selectedTransition = _projectManager.GetTransition(transition.Guid); + if (selectedTransition != null) _editorManager.DoSelectTransition(selectedTransition); + } + + private void UpdateStateCoords(Vector2 coords) + { + if (State == null) return; + var newState = State with + { + X = State.X + coords.X, + Y = State.Y + coords.Y + }; + _projectManager.UpdateState(newState); + } +} \ No newline at end of file diff --git a/src/Stater/ViewModels/Editors/MainEditorViewModel.cs b/src/Stater/ViewModels/Editors/MainEditorViewModel.cs new file mode 100644 index 0000000..ba0ba2c --- /dev/null +++ b/src/Stater/ViewModels/Editors/MainEditorViewModel.cs @@ -0,0 +1,18 @@ +using System; +using ReactiveUI; +using ReactiveUI.Fody.Helpers; +using Stater.Models.Editors; + +namespace Stater.ViewModels.Editors; + +public class MainEditorViewModel : ReactiveObject +{ + public MainEditorViewModel(IEditorManager editorManager) + { + editorManager + .EditorType + .Subscribe(x => EditorType = x); + } + + [Reactive] public EditorTypeEnum EditorType { get; private set; } +} \ No newline at end of file diff --git a/src/Stater/ViewModels/Editors/StateEditorViewModel.cs b/src/Stater/ViewModels/Editors/StateEditorViewModel.cs new file mode 100644 index 0000000..234ca7a --- /dev/null +++ b/src/Stater/ViewModels/Editors/StateEditorViewModel.cs @@ -0,0 +1,133 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive; +using System.Windows.Input; +using Avalonia; +using ReactiveUI; +using ReactiveUI.Fody.Helpers; +using Stater.Domain.Models; +using Stater.Models; +using Stater.Models.Editors; + +namespace Stater.ViewModels.Editors; + +public class StateEditorViewModel : ReactiveObject +{ + public StateEditorViewModel(IStateEditor stateEditor, IProjectManager projectManager, IEditorManager editorManager) + { + _stateEditor = stateEditor; + _projectManager = projectManager; + _editorManager = editorManager; + + SaveCommand = ReactiveCommand.Create(Save); + + _stateEditor + .State + .Subscribe(x => + { + try + { + State = x; + Name = x.Name; + Description = x.Description; + TypeIndex = x.Type switch + { + StateType.Common => 0, + StateType.Start => 1, + StateType.End => 2, + _ => TypeIndex + }; + } + catch (Exception e) + { + Console.WriteLine(e); + } + }); + + projectManager + .StateMachine + .Subscribe(x => + { + AllStates = x.States; + Transitions = x.Transitions + .Where(t => t.Start == State?.Guid || t.End == State?.Guid) + .Select(y => + { + var startState = x.States.Find(s => s.Guid == y.Start); + var endState = x.States.Find(s => s.Guid == y.End); + if (startState != null && endState != null) + return new AssociateTransition( + Transition: y, + StartPoint: new Point(startState.X, startState.Y), + EndPoint: new Point(endState.X, endState.Y), + Start: startState, + End: endState + ); + return null; + } + ) + .Where(y => y != null) + .OfType() + .ToList(); + }); + + + AddTransitionCommand = ReactiveCommand.Create(AddTransition); + RemoveTransitionCommand = ReactiveCommand.Create(RemoveTransition); + RemoveCommand = ReactiveCommand.Create(Remove); + } + + private readonly IStateEditor _stateEditor; + private readonly IProjectManager _projectManager; + private readonly IEditorManager _editorManager; + + public ICommand SaveCommand { get; } + public ICommand RemoveCommand { get; } + + public ReactiveCommand AddTransitionCommand { get; } + public ReactiveCommand RemoveTransitionCommand { get; } + + [Reactive] private State? State { get; set; } + + [Reactive] public string Name { get; set; } + [Reactive] public string Description { get; set; } + [Reactive] public int TypeIndex { get; set; } + + [Reactive] public List AllStates { get; set; } + [Reactive] public List Transitions { get; set; } + + + private void AddTransition(State state) + { + if (State == null) return; + _projectManager.CreateTransition(State, state); + } + + private void RemoveTransition(Transition transition) + { + _projectManager.RemoveTransition(transition.Guid); + } + + private void Save() + { + if (State == null) return; + var type = TypeIndex switch + { + 2 => StateType.End, + 1 => StateType.Start, + _ => StateType.Common + }; + var state = _projectManager.GetState(State.Guid); + if (state == null) return; + var newState = state with { Name = Name, Description = Description, Type = type }; + _stateEditor.Update(newState); + } + + private void Remove() + { + if (State == null) return; + _editorManager.DoSelectNull(); + _projectManager.RemoveState(State.Guid); + } +} \ No newline at end of file diff --git a/src/Stater/ViewModels/Editors/StateMachineEditorViewModel.cs b/src/Stater/ViewModels/Editors/StateMachineEditorViewModel.cs new file mode 100644 index 0000000..87daf25 --- /dev/null +++ b/src/Stater/ViewModels/Editors/StateMachineEditorViewModel.cs @@ -0,0 +1,41 @@ +using System; +using System.Windows.Input; +using ReactiveUI; +using ReactiveUI.Fody.Helpers; +using Stater.Domain.Models; +using Stater.Models.Editors; + +namespace Stater.ViewModels.Editors; + +public class StateMachineEditorViewModel : ReactiveObject +{ + public StateMachineEditorViewModel(IStateMachineEditor stateMachineEditor) + { + _stateMachineEditor = stateMachineEditor; + + SaveCommand = ReactiveCommand.Create(Save); + + stateMachineEditor + .StateMachine + .Subscribe(x => + { + StateMachine = x; + Name = x.Name; + }); + } + + private readonly IStateMachineEditor _stateMachineEditor; + + public ICommand SaveCommand { get; } + + + [Reactive] private StateMachine? StateMachine { get; set; } + [Reactive] public string Name { get; set; } + + private void Save() + { + if (StateMachine == null) return; + var newStateMachine = StateMachine with { Name = Name }; + _stateMachineEditor.Update(newStateMachine); + } +} \ No newline at end of file diff --git a/src/Stater/ViewModels/Editors/TransitionEditorViewModel.cs b/src/Stater/ViewModels/Editors/TransitionEditorViewModel.cs new file mode 100644 index 0000000..e536b17 --- /dev/null +++ b/src/Stater/ViewModels/Editors/TransitionEditorViewModel.cs @@ -0,0 +1,147 @@ +using System; +using System.Collections.Generic; +using System.Windows.Input; +using ReactiveUI; +using ReactiveUI.Fody.Helpers; +using Stater.Domain.Models; +using Stater.Models; +using Stater.Models.Editors; + +namespace Stater.ViewModels.Editors; + +public class TransitionEditorViewModel : ReactiveObject +{ + public TransitionEditorViewModel(ITransitionEditor transitionEditor, IProjectManager projectManager) + { + _transitionEditor = transitionEditor; + _projectManager = projectManager; + + SaveCommand = ReactiveCommand.Create(Save); + + _transitionEditor + .Transition + .Subscribe(x => + { + try + { + Transition = x; + Name = x.Name; + + var condition = x.Condition; + Condition = null; + Variable = null; + Value = null; + + VariableMath = null; + MathType = 0; + EventValue = null; + + if (condition is Condition.VariableCondition variableCondition) + { + Condition = variableCondition.ConditionType switch + { + Domain.Models.Condition.VariableCondition.ConditionTypeEnum.Lt => 0, + Domain.Models.Condition.VariableCondition.ConditionTypeEnum.Le => 0, + Domain.Models.Condition.VariableCondition.ConditionTypeEnum.Ne => 1, + Domain.Models.Condition.VariableCondition.ConditionTypeEnum.Gt => 2, + Domain.Models.Condition.VariableCondition.ConditionTypeEnum.Ge => 3, + _ => 0, + }; + Console.WriteLine(Condition); + + Variable = variableCondition.VariableGuid.ToString(); + Value = variableCondition.Value.ToString(); + } + + if (x.Event is Event.VariableMath math) + { + VariableMath = math.VariableGuid.ToString(); + MathType = math.MathType switch + { + Event.VariableMath.MathTypeEnum.Div => 0, + Event.VariableMath.MathTypeEnum.Sub => 1, + Event.VariableMath.MathTypeEnum.Sum => 2, + _ => 3, + }; + EventValue = math.Value.ToString(); + } + } + catch (Exception e) + { + Console.WriteLine(e); + } + }); + + projectManager + .StateMachine + .Subscribe(x => { Variables = x.Variables.ConvertAll(y => y.Guid.ToString()); } + ); + } + + private ITransitionEditor _transitionEditor; + private IProjectManager _projectManager; + [Reactive] private Transition? Transition { get; set; } + + [Reactive] public string Name { get; set; } + + [Reactive] public List Variables { get; set; } + [Reactive] public string Variable { get; set; } + + [Reactive] public int? Condition { get; set; } + + [Reactive] public string Value { get; set; } + + + [Reactive] public string VariableMath { get; set; } + [Reactive] public int MathType { get; set; } + [Reactive] public string EventValue { get; set; } + + public ICommand SaveCommand { get; } + + private void Save() + { + if (Transition == null) return; + Condition? condition = null; + Event? @event = null; + + if (Variable != null && Value != null) + { + Console.WriteLine(Condition); + var type = Condition switch + { + 4 => Domain.Models.Condition.VariableCondition.ConditionTypeEnum.Lt, + 5 => Domain.Models.Condition.VariableCondition.ConditionTypeEnum.Le, + 0 => Domain.Models.Condition.VariableCondition.ConditionTypeEnum.Eq, + 1 => Domain.Models.Condition.VariableCondition.ConditionTypeEnum.Ne, + 2 => Domain.Models.Condition.VariableCondition.ConditionTypeEnum.Gt, + 3 => Domain.Models.Condition.VariableCondition.ConditionTypeEnum.Ge, + _ => Domain.Models.Condition.VariableCondition.ConditionTypeEnum.Ge, + }; + condition = new Condition.VariableCondition( + VariableGuid: Guid.Parse(Variable), + ConditionType: type, + Value: VariableValueBuilder.fromString(Value) + ); + } + + if (VariableMath != null && EventValue != null) + { + var type = MathType switch + { + 0 => Event.VariableMath.MathTypeEnum.Sum, + 1 => Event.VariableMath.MathTypeEnum.Sub, + 2 => Event.VariableMath.MathTypeEnum.Mul, + _ => Event.VariableMath.MathTypeEnum.Div, + }; + @event = new Event.VariableMath( + VariableGuid: Guid.Parse(VariableMath), + MathType: type, + Value: VariableValueBuilder.fromString(EventValue) + ); + } + + + var newTransition = Transition with { Name = Name, Condition = condition, Event = @event }; + _transitionEditor.Update(newTransition); + } +} \ No newline at end of file diff --git a/src/Stater/ViewModels/Editors/VariableEditorViewModel.cs b/src/Stater/ViewModels/Editors/VariableEditorViewModel.cs new file mode 100644 index 0000000..97c6a70 --- /dev/null +++ b/src/Stater/ViewModels/Editors/VariableEditorViewModel.cs @@ -0,0 +1,55 @@ +using System; +using System.Windows.Input; +using ReactiveUI; +using ReactiveUI.Fody.Helpers; +using Stater.Domain.Models; +using Stater.Models.Editors; + +namespace Stater.ViewModels.Editors; + +public class VariableEditorViewModel : ReactiveObject +{ + public VariableEditorViewModel(IVariableEditor variableEditor) + { + _variableEditor = variableEditor; + Console.WriteLine(variableEditor); + + _variableEditor + .Variable + .Subscribe(x => + { + try + { + Variable = x; + Name = x.Name; + Value = x.StartValue.ToString(); + } + catch (Exception e) + { + Console.WriteLine(e); + } + }); + + SaveCommand = ReactiveCommand.Create(Save); + } + + private readonly IVariableEditor _variableEditor; + + public ICommand SaveCommand { get; } + + private void Save() + { + if (Variable == null) return; + var variable = Variable with + { + Name = Name, + StartValue = VariableValueBuilder.fromString(Value) + }; + _variableEditor.Update(variable); + } + + [Reactive] private Variable? Variable { get; set; } + + [Reactive] public string Name { get; set; } + [Reactive] public string Value { get; set; } +} \ No newline at end of file diff --git a/src/Stater/ViewModels/Execution/ExecutionControlViewModel.cs b/src/Stater/ViewModels/Execution/ExecutionControlViewModel.cs new file mode 100644 index 0000000..78f6bd0 --- /dev/null +++ b/src/Stater/ViewModels/Execution/ExecutionControlViewModel.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Input; +using ReactiveUI; +using ReactiveUI.Fody.Helpers; +using Stater.Models.Executor; + +namespace Stater.ViewModels.Execution; + +public class ExecutionControlViewModel : ReactiveObject +{ + public ExecutionControlViewModel(IExecutor executor) + { + _executor = executor; + + StartCommand = ReactiveCommand.Create(Start); + StopCommand = ReactiveCommand.Create(Stop); + StepCommand = ReactiveCommand.Create(Step); + ResetCommand = ReactiveCommand.Create(Reset); + ClearCommand = ReactiveCommand.Create(Clear); + + _executor.Logs.Subscribe(x => { Logs = x.Logs.ToList(); }); + } + + private readonly IExecutor _executor; + + public ICommand StartCommand { get; } + public ICommand StopCommand { get; } + public ICommand StepCommand { get; } + public ICommand ResetCommand { get; } + public ICommand ClearCommand { get; } + + [Reactive] public string StepTime { get; set; } + [Reactive] public List Logs { get; set; } + + private void Start() => _executor.Start(int.Parse(StepTime)); + private void Stop() => _executor.Stop(); + private void Step() => _executor.Step(); + private void Reset() => _executor.Reset(); + private void Clear() => _executor.ClearLog(); +} \ No newline at end of file diff --git a/src/Stater/ViewModels/Execution/ExecutionGroupViewModel.cs b/src/Stater/ViewModels/Execution/ExecutionGroupViewModel.cs new file mode 100644 index 0000000..2e220e9 --- /dev/null +++ b/src/Stater/ViewModels/Execution/ExecutionGroupViewModel.cs @@ -0,0 +1,8 @@ +using ReactiveUI; + +namespace Stater.ViewModels.Execution; + +public class ExecutionGroupViewModel : ReactiveObject +{ + +} \ No newline at end of file diff --git a/src/Stater/ViewModels/Execution/VariablesViewModel.cs b/src/Stater/ViewModels/Execution/VariablesViewModel.cs new file mode 100644 index 0000000..6950623 --- /dev/null +++ b/src/Stater/ViewModels/Execution/VariablesViewModel.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Input; +using ReactiveUI; +using ReactiveUI.Fody.Helpers; +using Stater.Domain.Models; +using Stater.Models; +using Stater.Models.Editors; + +namespace Stater.ViewModels.Execution; + +public class VariablesViewModel : ReactiveObject +{ + public VariablesViewModel(IProjectManager projectManager, IEditorManager editorManager) + { + projectManager + .StateMachine + .Subscribe(x => + { + if (Variables != null && + Variables.Count == x.Variables.Count && + Variables.All(x.Variables.Contains) && + x.Variables.All(Variables.Contains)) return; + Variables = x.Variables.ToList(); + }); + _projectManager = projectManager; + _editorManager = editorManager; + + CreateVariableCommand = ReactiveCommand.Create(CreateVariable); + } + + private IProjectManager _projectManager; + private IEditorManager _editorManager; + + [Reactive] public List Variables { get; set; } + + private Variable _variable; + private StateMachine? stateMachine; + + public Variable Variable + { + get => _variable; + set + { + this.RaiseAndSetIfChanged(ref _variable, value); + _editorManager.DoSelectVariable(value); + } + } + + public ICommand CreateVariableCommand { get; } + + private void CreateVariable() => _projectManager.CreateVariable(); +} \ No newline at end of file diff --git a/src/Stater/ViewModels/MainWindowViewModel.cs b/src/Stater/ViewModels/MainWindowViewModel.cs new file mode 100644 index 0000000..6f3865d --- /dev/null +++ b/src/Stater/ViewModels/MainWindowViewModel.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.Reactive; +using System.Windows.Input; +using DynamicData; +using ReactiveUI.Fody.Helpers; +using Stater.Models; +using ReactiveUI; +using Stater.Domain.Models; +using Stater.Models.Editors; +using Stater.Plugin; + +namespace Stater.ViewModels; + +public record PathPluginDto( + ButtonFilePlugin Plugin, string Path +); + +public class MainWindowViewModel : ReactiveObject +{ + public MainWindowViewModel(IProjectManager projectManager, IEditorManager editorManager) + { + _projectManager = projectManager; + _editorManager = editorManager; + + projectManager + .StateMachines + .Bind(out _stateMachines) + .Subscribe(); + + projectManager + .Project + .Subscribe(x => Project = x); + + projectManager + .StateMachine + .Subscribe(x => { StateMachine = x; }); + + NewCommand = ReactiveCommand.Create(NewProject); + OpenCommand = ReactiveCommand.Create(OpenProject); + SaveCommand = ReactiveCommand.Create(SaveProject); + NewStateMachineCommand = ReactiveCommand.Create(NewStateMachine); + NewStateCommand = ReactiveCommand.Create(NewState); + UndoCommand = ReactiveCommand.Create(Undo); + RedoCommand = ReactiveCommand.Create(Redo); + OpenCodeGeneration = ReactiveCommand.Create(() => _editorManager.DoSelectCodeGeneration()); + PluginButtinCommand = ReactiveCommand.Create(StartButtonFilePlugin); + } + + private readonly IProjectManager _projectManager; + private readonly IEditorManager _editorManager; + + [Reactive] public Project Project { get; private set; } + + public List Plugins => + new() + { + new SLXPlugin(), + new JsonCodeImportPlugin(), + new JsonCodeExportPlugin() + }; + + private StateMachine _stateMachine; + + public StateMachine? StateMachine + { + get => _stateMachine; + set + { + if (value == null) return; + this.RaiseAndSetIfChanged(ref _stateMachine, value); + var openStateMachine = _projectManager.OpenStateMachine(value.Guid); + if (openStateMachine != null) + _editorManager.DoSelectStateMachine(openStateMachine); + } + } + + + private readonly ReadOnlyObservableCollection _stateMachines; + public ReadOnlyObservableCollection StateMachines => _stateMachines; + + public ICommand NewCommand { get; } + public ReactiveCommand OpenCommand { get; } + public ReactiveCommand SaveCommand { get; } + public ReactiveCommand PluginButtinCommand { get; } + public ICommand NewStateMachineCommand { get; } + public ICommand NewStateCommand { get; } + public ICommand UndoCommand { get; } + public ICommand RedoCommand { get; } + + public ICommand OpenCodeGeneration { get; } + + + private void OpenProject(StreamReader sr) + { + _projectManager.LoadProject(sr); + } + + private void NewProject() + { + _projectManager.CreateProject("New Project"); + } + + private void SaveProject(StreamWriter sw) + { + _projectManager.SaveProject(sw); + } + + private void NewStateMachine() + { + var stateMachine = _projectManager.CreateStateMachine(); + _editorManager.DoSelectStateMachine(stateMachine); + } + + private void NewState() + { + var state = _projectManager.CreateState(); + if (state != null) _editorManager.DoSelectState(state); + } + + private void Undo() => _projectManager.Undo(); + private void Redo() => _projectManager.Redo(); + + private void StartButtonFilePlugin(PathPluginDto pathPluginDto) + { + var input = new PluginInput( + Project: _projectManager.GetProject(), + StateMachine: _projectManager.GetStateMachine(), + StateMachines: _projectManager.GetStateMachines(), + ProjectManager: _projectManager + ); + var res = pathPluginDto.Plugin.Start(input, pathPluginDto.Path); + + _projectManager.ChangeStateMachines(res.ChangedStateMachines); + } +} \ No newline at end of file diff --git a/src/Stater/ViewModels/Plugins/CodeGenerationViewModel.cs b/src/Stater/ViewModels/Plugins/CodeGenerationViewModel.cs new file mode 100644 index 0000000..c1a85f8 --- /dev/null +++ b/src/Stater/ViewModels/Plugins/CodeGenerationViewModel.cs @@ -0,0 +1,64 @@ +using System; +using System.Reactive; +using ReactiveUI; +using ReactiveUI.Fody.Helpers; +using Stater.CodeGeneration; +using Stater.CodeGeneration.Entity; +using Stater.Domain.Models; +using Stater.Models; + +namespace Stater.ViewModels.Plugins; + +public class CodeGenerationViewModel : ReactiveObject +{ + public CodeGenerationViewModel(IProjectManager projectManager) + { + projectManager + .StateMachine + .Subscribe(x => { StateMachine = x; }); + GenerateCommand = ReactiveCommand.Create(Generate); + } + + + [Reactive] public StateMachine? StateMachine { get; private set; } + + [Reactive] public int LanguageIndex { get; set; } + [Reactive] public int ModeIndex { get; set; } + [Reactive] public bool GenerateStates { get; set; } + [Reactive] public bool GenerateContext { get; set; } + [Reactive] public bool GenerateInterface { get; set; } + + private FileGenerator fileGenerator = new(); + + public ReactiveCommand GenerateCommand { get; } + + private void Generate(string outputPath) + { + if (StateMachine == null) return; + var language = LanguageIndex switch + { + 0 => Language.Java, + 1 => Language.Kotlin, + 2 => Language.JavaScript, + 3 => Language.TypeScript, + 4 => Language.Python3, + 5 => Language.CSharp, + _ => Language.CPlusPlus + }; + + var mode = ModeIndex switch + { + 0 => Mode.Clazz, + _ => Mode.Builder, + }; + fileGenerator.GenerateCode( + language, + StateMachine, + outputPath, + mode, + GenerateStates, + GenerateContext, + GenerateInterface + ); + } +} \ No newline at end of file diff --git a/src/Stater/ViewModels/ViewModelBase.cs b/src/Stater/ViewModels/ViewModelBase.cs new file mode 100644 index 0000000..f8ba182 --- /dev/null +++ b/src/Stater/ViewModels/ViewModelBase.cs @@ -0,0 +1,7 @@ +using ReactiveUI; + +namespace Stater.ViewModels; + +public class ViewModelBase : ReactiveObject +{ +} \ No newline at end of file diff --git a/src/Stater/Views/Board/BoardCanvas.axaml b/src/Stater/Views/Board/BoardCanvas.axaml new file mode 100644 index 0000000..967e6d0 --- /dev/null +++ b/src/Stater/Views/Board/BoardCanvas.axaml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Stater/Views/Board/BoardCanvas.axaml.cs b/src/Stater/Views/Board/BoardCanvas.axaml.cs new file mode 100644 index 0000000..455d999 --- /dev/null +++ b/src/Stater/Views/Board/BoardCanvas.axaml.cs @@ -0,0 +1,192 @@ +using System; +using System.Numerics; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.Shapes; +using Avalonia.Input; +using Avalonia.Media; +using Splat; +using Stater.Domain.Models; +using Stater.Models; +using Stater.Models.Editors; +using Stater.ViewModels.Board; + +namespace Stater.Views.Board; + +public partial class BoardCanvas : UserControl +{ + private const double ScaleFactor = 1.01; + private double scale = 1; + private const double MaxScale = 3; + private const double MinScale = 0.5; + + private const double TranslateXFactor = 1; + private double x; + private double _x; + private double startX; + + private const double TranslateYFactor = 1; + private double y; + private double _y; + private double startY; + + private bool pressed; + + private const double StateTranslateXFactor = 1; + private double stateX; + private double _stateX; + + private const double StateTranslateYFactor = 1; + private double stateY; + private double _stateY; + private bool statePressed; + + private const int GridLineRangeX = 40; + private const int GridLineRangeY = 40; + private readonly Color gridLineColor = Color.Parse("Gray"); + private const int GridLineSize = 1; + + public BoardCanvas() + { + InitializeComponent(); + var projectManager = Locator.Current.GetService(); + var editorManager = Locator.Current.GetService(); + DataContext = new BoardCanvasViewModel(projectManager!, editorManager!); + drawGrid(); + } + + private void drawGrid() + { + var canvas = TheCanvas; + + var height = canvas.Height; + var width = canvas.Width; + + for (var i = GridLineRangeX; i < width; i += GridLineRangeX) + { + Line line = new() + { + StartPoint = new Point(i, 0), + EndPoint = new Point(i, height), + Stroke = new SolidColorBrush + { + Color = gridLineColor + }, + StrokeThickness = GridLineSize, + ZIndex=-1 + }; + canvas.Children.Add(line); + } + + for (var i = GridLineRangeY; i < height; i += GridLineRangeY) + { + Line line = new() + { + StartPoint = new Point(0, i), + EndPoint = new Point(width, i), + Stroke = new SolidColorBrush + { + Color = gridLineColor + }, + StrokeThickness = GridLineSize, + ZIndex=-1 + }; + canvas.Children.Add(line); + } + } + + private void UpdateCanvasMatrix() + { + // TODO: Check scale and x, y ranges + + TheCanvas.RenderTransform = + new MatrixTransform(Matrix.CreateScale(scale, scale) * Matrix.CreateTranslation(x, y)); + } + + private void InputElement_OnPointerWheelChanged(object? sender, PointerWheelEventArgs e) + { + if (e.Delta.Y >= 0 && scale < MaxScale) + { + scale *= ScaleFactor; + UpdateCanvasMatrix(); + } + else if (scale > MinScale) + { + scale /= ScaleFactor; + UpdateCanvasMatrix(); + } + + } + + private void InputElement_OnPointerPressed(object? sender, PointerPressedEventArgs e) + { + if (statePressed) return; + pressed = true; + var point = e.GetCurrentPoint(TheCanvasPanel); + _x = point.Position.X; + _y = point.Position.Y; + startX = x; + startY = y; + } + + private void InputElement_OnPointerMoved(object? sender, PointerEventArgs e) + { + if (!pressed || sender == null) return; + var point = e.GetCurrentPoint(TheCanvasPanel); + var positionX = point.Position.X; + var positionY = point.Position.Y; + x = startX - (_x - positionX) * TranslateXFactor; + y = startY - (_y - positionY) * TranslateYFactor; + UpdateCanvasMatrix(); + } + + private void InputElement_OnPointerReleased(object? sender, PointerReleasedEventArgs e) + { + pressed = false; + } + + private void State_OnPointerPressed(object? sender, PointerPressedEventArgs e) + { + var rectangle = (Control)sender; + if (rectangle?.DataContext is not State state) return; + var context = (BoardCanvasViewModel)DataContext; + context?.StateClickCommand.Execute(state).Subscribe(); + statePressed = true; + + var canvas = TheCanvasPanel; + var point = e.GetCurrentPoint(canvas); + stateX = 0; + stateY = 0; + _stateX = point.Position.X; + _stateY = point.Position.Y; + } + + private void State_OnPointerMoved(object? sender, PointerEventArgs e) + { + if (!statePressed || sender == null) return; + var rectangle = (Control)sender!; + var canvas = TheCanvasPanel; + var point = e.GetCurrentPoint(canvas); + var positionX = point.Position.X; + var positionY = point.Position.Y; + stateX = (positionX - _stateX) * StateTranslateXFactor / scale; + stateY = (positionY - _stateY) * StateTranslateYFactor / scale; + rectangle.RenderTransform = + new MatrixTransform(Matrix.CreateTranslation(stateX, stateY)); + } + + private void State_OnPointerReleased(object? sender, PointerReleasedEventArgs e) + { + statePressed = false; + var context = (BoardCanvasViewModel)DataContext; + context?.UpdateStateCoordsCommand.Execute(new Vector2((float)stateX, (float)stateY)).Subscribe(); + } + + private void Transition_OnPointerPressed(object? sender, PointerPressedEventArgs e) + { + var rectangle = (Control)sender; + if (rectangle?.DataContext is not AssociateTransition transition) return; + var context = (BoardCanvasViewModel)DataContext; + context?.TransitionClickCommand.Execute(transition.Transition).Subscribe(); + } +} \ No newline at end of file diff --git a/src/Stater/Views/Editors/MainEditor.axaml b/src/Stater/Views/Editors/MainEditor.axaml new file mode 100644 index 0000000..d275986 --- /dev/null +++ b/src/Stater/Views/Editors/MainEditor.axaml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Stater/Views/Editors/MainEditor.axaml.cs b/src/Stater/Views/Editors/MainEditor.axaml.cs new file mode 100644 index 0000000..c8db1ee --- /dev/null +++ b/src/Stater/Views/Editors/MainEditor.axaml.cs @@ -0,0 +1,18 @@ +using Avalonia.Controls; +using Splat; +using Stater.Models.Editors; +using Stater.ViewModels.Editors; + +namespace Stater.Views.Editors; + +public partial class MainEditor : UserControl +{ + public MainEditor() + { + InitializeComponent(); + var editorManager = Locator.Current.GetService(); + DataContext = new MainEditorViewModel( + editorManager! + ); + } +} \ No newline at end of file diff --git a/src/Stater/Views/Editors/StateEditor.axaml b/src/Stater/Views/Editors/StateEditor.axaml new file mode 100644 index 0000000..d849e64 --- /dev/null +++ b/src/Stater/Views/Editors/StateEditor.axaml @@ -0,0 +1,90 @@ + + + + + Data + + + Name: + + Description: + + Type: + + Common + Start + End + + + + + + + + + + + Transitions + + + + + + + + + + + + + + + + + + + + + + + + + + + + Add transition + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Stater/Views/Editors/StateEditor.axaml.cs b/src/Stater/Views/Editors/StateEditor.axaml.cs new file mode 100644 index 0000000..0aa973d --- /dev/null +++ b/src/Stater/Views/Editors/StateEditor.axaml.cs @@ -0,0 +1,33 @@ +using System; +using Avalonia.Controls; +using Avalonia.Interactivity; +using Splat; +using Stater.Models; +using Stater.Models.Editors; +using Stater.ViewModels.Editors; + +namespace Stater.Views.Editors; + +public partial class StateEditor : UserControl +{ + public StateEditor() + { + InitializeComponent(); + var stateEditor = Locator.Current.GetService(); + var projectManager = Locator.Current.GetService(); + var editorManage = Locator.Current.GetService(); + DataContext = new StateEditorViewModel( + stateEditor!, + projectManager!, + editorManage! + ); + } + + private void Button_OnClick(object? sender, RoutedEventArgs e) + { + var button = (Button)sender; + var transition = (AssociateTransition)button.DataContext; + var context = (StateEditorViewModel)DataContext; + context?.RemoveTransitionCommand.Execute(transition.Transition).Subscribe(); + } +} \ No newline at end of file diff --git a/src/Stater/Views/Editors/StateMachineEditor.axaml b/src/Stater/Views/Editors/StateMachineEditor.axaml new file mode 100644 index 0000000..6b6040d --- /dev/null +++ b/src/Stater/Views/Editors/StateMachineEditor.axaml @@ -0,0 +1,16 @@ + + + Name: + + + + \ No newline at end of file diff --git a/src/Stater/Views/Editors/StateMachineEditor.axaml.cs b/src/Stater/Views/Editors/StateMachineEditor.axaml.cs new file mode 100644 index 0000000..8fd14d3 --- /dev/null +++ b/src/Stater/Views/Editors/StateMachineEditor.axaml.cs @@ -0,0 +1,18 @@ +using Avalonia.Controls; +using Splat; +using Stater.Models.Editors; +using Stater.ViewModels.Editors; + +namespace Stater.Views.Editors; + +public partial class StateMachineEditor : UserControl +{ + public StateMachineEditor() + { + InitializeComponent(); + var stateMachineEditor = Locator.Current.GetService(); + DataContext = new StateMachineEditorViewModel( + stateMachineEditor! + ); + } +} \ No newline at end of file diff --git a/src/Stater/Views/Editors/TransitionEditor.axaml b/src/Stater/Views/Editors/TransitionEditor.axaml new file mode 100644 index 0000000..822235a --- /dev/null +++ b/src/Stater/Views/Editors/TransitionEditor.axaml @@ -0,0 +1,57 @@ + + + Name: + + + Condition: + + Variable + + + Source Variable: + + + + Condition: + + + + == + != + > + >= + + + Value: + + + Event: + + VariableMath + + + + + + - + * + / + + + + + + \ No newline at end of file diff --git a/src/Stater/Views/Editors/TransitionEditor.axaml.cs b/src/Stater/Views/Editors/TransitionEditor.axaml.cs new file mode 100644 index 0000000..127e0ab --- /dev/null +++ b/src/Stater/Views/Editors/TransitionEditor.axaml.cs @@ -0,0 +1,21 @@ +using Avalonia.Controls; +using Splat; +using Stater.Models; +using Stater.Models.Editors; +using Stater.ViewModels.Editors; + +namespace Stater.Views.Editors; + +public partial class TransitionEditor : UserControl +{ + public TransitionEditor() + { + InitializeComponent(); + var transitionEditor = Locator.Current.GetService(); + var projectManager = Locator.Current.GetService(); + DataContext = new TransitionEditorViewModel( + transitionEditor!, + projectManager! + ); + } +} \ No newline at end of file diff --git a/src/Stater/Views/Editors/VariableEditor.axaml b/src/Stater/Views/Editors/VariableEditor.axaml new file mode 100644 index 0000000..816084f --- /dev/null +++ b/src/Stater/Views/Editors/VariableEditor.axaml @@ -0,0 +1,19 @@ + + + Name: + + + Start value: + + + + \ No newline at end of file diff --git a/src/Stater/Views/Editors/VariableEditor.axaml.cs b/src/Stater/Views/Editors/VariableEditor.axaml.cs new file mode 100644 index 0000000..dd7fede --- /dev/null +++ b/src/Stater/Views/Editors/VariableEditor.axaml.cs @@ -0,0 +1,16 @@ +using Avalonia.Controls; +using Splat; +using Stater.Models.Editors; +using Stater.ViewModels.Editors; + +namespace Stater.Views.Editors; + +public partial class VariableEditor : UserControl +{ + public VariableEditor() + { + InitializeComponent(); + var variableEditor = Locator.Current.GetService(); + DataContext = new VariableEditorViewModel(variableEditor!); + } +} \ No newline at end of file diff --git a/src/Stater/Views/Execution/ExecutionControl.axaml b/src/Stater/Views/Execution/ExecutionControl.axaml new file mode 100644 index 0000000..4fbbd2d --- /dev/null +++ b/src/Stater/Views/Execution/ExecutionControl.axaml @@ -0,0 +1,39 @@ + + + + Step Time: + + + + + + + + + + + + + + + + + - + + + + + + + + + + + \ No newline at end of file diff --git a/src/Stater/Views/Execution/ExecutionControl.axaml.cs b/src/Stater/Views/Execution/ExecutionControl.axaml.cs new file mode 100644 index 0000000..2adc00a --- /dev/null +++ b/src/Stater/Views/Execution/ExecutionControl.axaml.cs @@ -0,0 +1,16 @@ +using Avalonia.Controls; +using Splat; +using Stater.Models.Executor; +using Stater.ViewModels.Execution; + +namespace Stater.Views.Execution; + +public partial class ExecutionControl : UserControl +{ + public ExecutionControl() + { + InitializeComponent(); + var executor = Locator.Current.GetService(); + DataContext = new ExecutionControlViewModel(executor!); + } +} \ No newline at end of file diff --git a/src/Stater/Views/Execution/ExecutionGroup.axaml b/src/Stater/Views/Execution/ExecutionGroup.axaml new file mode 100644 index 0000000..0c257e3 --- /dev/null +++ b/src/Stater/Views/Execution/ExecutionGroup.axaml @@ -0,0 +1,16 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/Stater/Views/Execution/ExecutionGroup.axaml.cs b/src/Stater/Views/Execution/ExecutionGroup.axaml.cs new file mode 100644 index 0000000..ff9c1b5 --- /dev/null +++ b/src/Stater/Views/Execution/ExecutionGroup.axaml.cs @@ -0,0 +1,11 @@ +using Avalonia.Controls; + +namespace Stater.Views.Execution; + +public partial class ExecutionGroup : UserControl +{ + public ExecutionGroup() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/src/Stater/Views/Execution/Variables.axaml b/src/Stater/Views/Execution/Variables.axaml new file mode 100644 index 0000000..5d58994 --- /dev/null +++ b/src/Stater/Views/Execution/Variables.axaml @@ -0,0 +1,27 @@ + + + + Variables: + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Stater/Views/Execution/Variables.axaml.cs b/src/Stater/Views/Execution/Variables.axaml.cs new file mode 100644 index 0000000..b8a1d64 --- /dev/null +++ b/src/Stater/Views/Execution/Variables.axaml.cs @@ -0,0 +1,18 @@ +using Avalonia.Controls; +using Splat; +using Stater.Models; +using Stater.Models.Editors; +using Stater.ViewModels.Execution; + +namespace Stater.Views.Execution; + +public partial class Variables : UserControl +{ + public Variables() + { + InitializeComponent(); + var projectManager = Locator.Current.GetService(); + var editorManager = Locator.Current.GetService(); + DataContext = new VariablesViewModel(projectManager!, editorManager!); + } +} \ No newline at end of file diff --git a/src/Stater/Views/MainWindow.axaml b/src/Stater/Views/MainWindow.axaml new file mode 100644 index 0000000..82aaf67 --- /dev/null +++ b/src/Stater/Views/MainWindow.axaml @@ -0,0 +1,91 @@ + + + + + a + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Stater/Views/MainWindow.axaml.cs b/src/Stater/Views/MainWindow.axaml.cs new file mode 100644 index 0000000..d82f71b --- /dev/null +++ b/src/Stater/Views/MainWindow.axaml.cs @@ -0,0 +1,93 @@ +using System; +using System.IO; +using Avalonia.Controls; +using Avalonia.Interactivity; +using Avalonia.Platform.Storage; +using Stater.Plugin; +using Stater.ViewModels; + +namespace Stater.Views; + +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + } + + private async void OpenFileButton_Clicked(object sender, RoutedEventArgs args) + { + var topLevel = GetTopLevel(this); + var files = await topLevel.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions + { + Title = "Open Project", + AllowMultiple = false + }); + + if (files.Count < 1) return; + await using var stream = await files[0].OpenReadAsync(); + using var streamReader = new StreamReader(stream); + var context = (MainWindowViewModel)DataContext; + context?.OpenCommand.Execute(streamReader).Subscribe(); + } + + private async void SaveFileButton_Clicked(object sender, RoutedEventArgs args) + { + var topLevel = GetTopLevel(this); + var file = await topLevel.StorageProvider.SaveFilePickerAsync(new FilePickerSaveOptions + { + Title = "Save Project" + }); + if (file is null) return; + await using var stream = await file.OpenWriteAsync(); + await using var streamWriter = new StreamWriter(stream); + var context = (MainWindowViewModel)DataContext; + context?.SaveCommand.Execute(streamWriter).Subscribe(); + } + + private async void MenuItem_OnClick(object? sender, RoutedEventArgs e) + { + var pluginMenu = (MenuItem)sender; + var plugin = (ButtonFilePlugin)pluginMenu.DataContext; + var topLevel = GetTopLevel(this); + + + if (plugin.Directory) + { + var files = await topLevel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions + { + Title = "Open Folder", + AllowMultiple = false + }); + + if (files.Count < 1) return; + + var context = (MainWindowViewModel)DataContext; + context?.PluginButtinCommand.Execute( + new PathPluginDto( + Plugin: plugin, + Path: files[0].Path.ToString().Replace("file:/", "") + ) + ).Subscribe(); + } + else + { + + var files = await topLevel.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions + { + Title = "Open File", + AllowMultiple = false + }); + + if (files.Count < 1) return; + + var context = (MainWindowViewModel)DataContext; + context?.PluginButtinCommand.Execute( + new PathPluginDto( + Plugin: plugin, + Path: files[0].Path.ToString().Replace("file:/", "") + ) + ).Subscribe(); + } + } +} \ No newline at end of file diff --git a/src/Stater/Views/Plugins/CodeGeneration.axaml b/src/Stater/Views/Plugins/CodeGeneration.axaml new file mode 100644 index 0000000..7511d21 --- /dev/null +++ b/src/Stater/Views/Plugins/CodeGeneration.axaml @@ -0,0 +1,32 @@ + + + + + Java + Kotlin + JavaScript + TypeScript + Python3 + C# + C++ + + + + + + Class + Builder + + Generate states + Generate context + Generate interface + + + \ No newline at end of file diff --git a/src/Stater/Views/Plugins/CodeGeneration.axaml.cs b/src/Stater/Views/Plugins/CodeGeneration.axaml.cs new file mode 100644 index 0000000..40bf565 --- /dev/null +++ b/src/Stater/Views/Plugins/CodeGeneration.axaml.cs @@ -0,0 +1,41 @@ +using System; +using Avalonia.Controls; +using Avalonia.Interactivity; +using Avalonia.Platform.Storage; +using Splat; +using Stater.Models; +using Stater.ViewModels.Plugins; +using Avalonia; +using Avalonia.VisualTree; + +namespace Stater.Views.Plugins; + +public partial class CodeGeneration : UserControl +{ + public CodeGeneration() + { + InitializeComponent(); + var projectManager = Locator.Current.GetService(); + DataContext = new CodeGenerationViewModel( + projectManager! + ); + } + + private async void Button_OnClick(object? sender, RoutedEventArgs e) + { + var topLevel = this.GetVisualRoot() as TopLevel; + var files = await topLevel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions + { + Title = "Open Folder", + AllowMultiple = false, + }); + + if (files.Count < 1) return; + + var context = (CodeGenerationViewModel)DataContext; + Console.WriteLine(files[0].Path.ToString()); + context?.GenerateCommand.Execute( + files[0].Path.ToString().Replace("file:/", "") + ).Subscribe(); + } +} \ No newline at end of file diff --git a/src/Stater/app.manifest b/src/Stater/app.manifest new file mode 100644 index 0000000..27aee3d --- /dev/null +++ b/src/Stater/app.manifest @@ -0,0 +1,18 @@ + + + + + + + + + + + + + +