From 318f811fead95c4a363d776e968b0b1a4a112c86 Mon Sep 17 00:00:00 2001 From: Pawel Zawitowski Date: Tue, 3 Sep 2019 20:50:48 +0200 Subject: [PATCH] Bytecode pattern #553 (#896) * Added bytecode pattern * Diagram changed and added licence information * Added bytecode module to main pom. * Fixed missing dependency error --- bytecode/README.md | 25 +++ bytecode/etc/bytecode.png | Bin 0 -> 19866 bytes bytecode/etc/bytecode.ucls | 49 ++++++ bytecode/pom.xml | 45 +++++ .../main/java/com/iluwatar/bytecode/App.java | 79 +++++++++ .../com/iluwatar/bytecode/Instruction.java | 65 ++++++++ .../com/iluwatar/bytecode/VirtualMachine.java | 142 ++++++++++++++++ .../java/com/iluwatar/bytecode/Wizard.java | 83 ++++++++++ .../util/InstructionConverterUtil.java | 76 +++++++++ .../java/com/iluwatar/bytecode/AppTest.java | 37 +++++ .../iluwatar/bytecode/VirtualMachineTest.java | 154 ++++++++++++++++++ .../util/InstructionConverterUtilTest.java | 63 +++++++ pom.xml | 1 + 13 files changed, 819 insertions(+) create mode 100644 bytecode/README.md create mode 100644 bytecode/etc/bytecode.png create mode 100644 bytecode/etc/bytecode.ucls create mode 100644 bytecode/pom.xml create mode 100644 bytecode/src/main/java/com/iluwatar/bytecode/App.java create mode 100644 bytecode/src/main/java/com/iluwatar/bytecode/Instruction.java create mode 100644 bytecode/src/main/java/com/iluwatar/bytecode/VirtualMachine.java create mode 100644 bytecode/src/main/java/com/iluwatar/bytecode/Wizard.java create mode 100644 bytecode/src/main/java/com/iluwatar/bytecode/util/InstructionConverterUtil.java create mode 100644 bytecode/src/test/java/com/iluwatar/bytecode/AppTest.java create mode 100644 bytecode/src/test/java/com/iluwatar/bytecode/VirtualMachineTest.java create mode 100644 bytecode/src/test/java/com/iluwatar/bytecode/util/InstructionConverterUtilTest.java diff --git a/bytecode/README.md b/bytecode/README.md new file mode 100644 index 000000000..d2fc45e1e --- /dev/null +++ b/bytecode/README.md @@ -0,0 +1,25 @@ +--- +layout: pattern +title: Bytecode +folder: bytecode +permalink: /patterns/bytecode/ +categories: Behavioral +tags: + - Java + - Difficulty-Beginner +--- + +## Intent +Allows to encode behaviour as instructions for virtual machine. + +## Applicability +Use the Bytecode pattern when you have a lot of behavior you need to define and your +game’s implementation language isn’t a good fit because: + +* it’s too low-level, making it tedious or error-prone to program in. +* iterating on it takes too long due to slow compile times or other tooling issues. +* it has too much trust. If you want to ensure the behavior being defined can’t break the game, you need to sandbox it from the rest of the codebase. + +## Credits + +* [Game programming patterns](http://gameprogrammingpatterns.com/bytecode.html) diff --git a/bytecode/etc/bytecode.png b/bytecode/etc/bytecode.png new file mode 100644 index 0000000000000000000000000000000000000000..31b6bc6edba64cfb51910e5d2c5322be46e7c075 GIT binary patch literal 19866 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

`G1h3pdcwAMtsKKi=qQrS$#qHo8o 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 D@r6J8 literal 0 HcmV?d00001 diff --git a/bytecode/etc/bytecode.ucls b/bytecode/etc/bytecode.ucls new file mode 100644 index 000000000..3ec390458 --- /dev/null +++ b/bytecode/etc/bytecode.ucls @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bytecode/pom.xml b/bytecode/pom.xml new file mode 100644 index 000000000..e9e6247f8 --- /dev/null +++ b/bytecode/pom.xml @@ -0,0 +1,45 @@ + + + + + java-design-patterns + com.iluwatar + 1.21.0-SNAPSHOT + + 4.0.0 + + bytecode + + + org.junit.jupiter + junit-jupiter-engine + test + + + + \ No newline at end of file diff --git a/bytecode/src/main/java/com/iluwatar/bytecode/App.java b/bytecode/src/main/java/com/iluwatar/bytecode/App.java new file mode 100644 index 000000000..90b97bd33 --- /dev/null +++ b/bytecode/src/main/java/com/iluwatar/bytecode/App.java @@ -0,0 +1,79 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bytecode; + +import com.iluwatar.bytecode.util.InstructionConverterUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The intention of Bytecode pattern is to give behavior the flexibility of data by encoding it as instructions + * for a virtual machine. + * An instruction set defines the low-level operations that can be performed. A series of instructions is encoded as + * a sequence of bytes. A virtual machine executes these instructions one at a time, + * using a stack for intermediate values. By combining instructions, complex high-level behavior can be defined. + * + * This pattern should be used when there is a need to define high number of behaviours and implementation engine + * is not a good choice because + * It is too lowe level + * Iterating on it takes too long due to slow compile times or other tooling issues. + * It has too much trust. If you want to ensure the behavior being defined can’t break the game, + * you need to sandbox it from the rest of the codebase. + * + */ +public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + + /** + * Main app method + * @param args command line args + */ + public static void main(String[] args) { + VirtualMachine vm = new VirtualMachine(); + + Wizard wizard = new Wizard(); + wizard.setHealth(45); + wizard.setAgility(7); + wizard.setWisdom(11); + vm.getWizards()[0] = wizard; + + interpretInstruction("LITERAL 0", vm); + interpretInstruction( "LITERAL 0", vm); + interpretInstruction( "GET_HEALTH", vm); + interpretInstruction( "LITERAL 0", vm); + interpretInstruction( "GET_AGILITY", vm); + interpretInstruction( "LITERAL 0", vm); + interpretInstruction( "GET_WISDOM ", vm); + interpretInstruction( "ADD", vm); + interpretInstruction( "LITERAL 2", vm); + interpretInstruction( "DIVIDE", vm); + interpretInstruction( "ADD", vm); + interpretInstruction( "SET_HEALTH", vm); + } + + private static void interpretInstruction(String instruction, VirtualMachine vm) { + InstructionConverterUtil converter = new InstructionConverterUtil(); + vm.execute(converter.convertToByteCode(instruction)); + LOGGER.info(instruction + String.format("%" + (12 - instruction.length()) + "s", "" ) + vm.getStack()); + } +} diff --git a/bytecode/src/main/java/com/iluwatar/bytecode/Instruction.java b/bytecode/src/main/java/com/iluwatar/bytecode/Instruction.java new file mode 100644 index 000000000..2ceb66e3b --- /dev/null +++ b/bytecode/src/main/java/com/iluwatar/bytecode/Instruction.java @@ -0,0 +1,65 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bytecode; + +/** + * Representation of instructions understandable by virtual machine + */ +public enum Instruction { + + LITERAL(1), + SET_HEALTH(2), + SET_WISDOM (3), + SET_AGILITY(4), + PLAY_SOUND(5), + SPAWN_PARTICLES(6), + GET_HEALTH(7), + GET_AGILITY(8), + GET_WISDOM(9), + ADD(10), + DIVIDE (11); + + private int value; + + Instruction(int value) { + this.value = value; + } + + public int getIntValue() { + return value; + } + + /** + * Converts integer value to Instruction + * @param value value of instruction + * @return representation of the instruction + */ + public static Instruction getInstruction(int value) { + for (int i = 0; i < Instruction.values().length; i++) { + if (Instruction.values()[i].getIntValue() == value) { + return Instruction.values()[i]; + } + } + throw new IllegalArgumentException("Invalid instruction value"); + } +} diff --git a/bytecode/src/main/java/com/iluwatar/bytecode/VirtualMachine.java b/bytecode/src/main/java/com/iluwatar/bytecode/VirtualMachine.java new file mode 100644 index 000000000..aedafe514 --- /dev/null +++ b/bytecode/src/main/java/com/iluwatar/bytecode/VirtualMachine.java @@ -0,0 +1,142 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bytecode; + +import java.util.Stack; + +/** + * Implementation of virtual machine + */ +public class VirtualMachine { + + private Stack stack = new Stack(); + + private Wizard[] wizards = new Wizard[2]; + + /** + * Constructor + */ + public VirtualMachine() { + for (int i = 0; i < wizards.length; i++) { + wizards[i] = new Wizard(); + } + } + + /** + * Executes provided bytecode + * @param bytecode to execute + */ + public void execute(int[] bytecode) { + for (int i = 0; i < bytecode.length; i++) { + Instruction instruction = Instruction.getInstruction(bytecode[i]); + int wizard; + int amount; + switch (instruction) { + case LITERAL: + // Read the next byte from the bytecode. + int value = bytecode[++i]; + stack.push(value); + break; + case SET_AGILITY: + amount = stack.pop(); + wizard = stack.pop(); + setAgility(wizard, amount); + break; + case SET_WISDOM: + amount = stack.pop(); + wizard = stack.pop(); + setWisdom(wizard, amount); + break; + case SET_HEALTH: + amount = stack.pop(); + wizard = stack.pop(); + setHealth(wizard, amount); + break; + case GET_HEALTH: + wizard = stack.pop(); + stack.push(getHealth(wizard)); + break; + case GET_AGILITY: + wizard = stack.pop(); + stack.push(getAgility(wizard)); + break; + case GET_WISDOM: + wizard = stack.pop(); + stack.push(getWisdom(wizard)); + break; + case ADD: + int a = stack.pop(); + int b = stack.pop(); + stack.push(a + b); + break; + case DIVIDE: + a = stack.pop(); + b = stack.pop(); + stack.push(b / a); + break; + case PLAY_SOUND: + wizard = stack.pop(); + getWizards()[wizard].playSound(); + break; + case SPAWN_PARTICLES: + wizard = stack.pop(); + getWizards()[wizard].spawnParticles(); + break; + default: + throw new IllegalArgumentException("Invalid instruction value"); + } + } + } + + public Stack getStack() { + return stack; + } + + public void setHealth(int wizard, int amount) { + wizards[wizard].setHealth(amount); + } + + public void setWisdom(int wizard, int amount) { + wizards[wizard].setWisdom(amount); + } + + public void setAgility(int wizard, int amount) { + wizards[wizard].setAgility(amount); + } + + public int getHealth(int wizard) { + return wizards[wizard].getHealth(); + } + + public int getWisdom(int wizard) { + return wizards[wizard].getWisdom(); + } + + public int getAgility(int wizard) { + return wizards[wizard].getAgility(); + } + + public Wizard[] getWizards() { + return wizards; + } +} diff --git a/bytecode/src/main/java/com/iluwatar/bytecode/Wizard.java b/bytecode/src/main/java/com/iluwatar/bytecode/Wizard.java new file mode 100644 index 000000000..ca47fd28f --- /dev/null +++ b/bytecode/src/main/java/com/iluwatar/bytecode/Wizard.java @@ -0,0 +1,83 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bytecode; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This class represent game objects which properties can be changed by instructions interpreted by virtual machine + */ +public class Wizard { + private static final Logger LOGGER = LoggerFactory.getLogger(Wizard.class); + + private int health; + + private int agility; + private int wisdom; + + private int numberOfPlayedSounds; + private int numberOfSpawnedParticles; + + public int getHealth() { + return health; + } + + public void setHealth(int health) { + this.health = health; + } + + public int getAgility() { + return agility; + } + + public void setAgility(int agility) { + this.agility = agility; + } + + public int getWisdom() { + return wisdom; + } + + public void setWisdom(int wisdom) { + this.wisdom = wisdom; + } + + public void playSound() { + LOGGER.info("Playing sound"); + numberOfPlayedSounds++; + } + + public void spawnParticles() { + LOGGER.info("Spawning particles"); + numberOfSpawnedParticles++; + } + + public int getNumberOfPlayedSounds() { + return numberOfPlayedSounds; + } + + public int getNumberOfSpawnedParticles() { + return numberOfSpawnedParticles; + } +} diff --git a/bytecode/src/main/java/com/iluwatar/bytecode/util/InstructionConverterUtil.java b/bytecode/src/main/java/com/iluwatar/bytecode/util/InstructionConverterUtil.java new file mode 100644 index 000000000..202784d5a --- /dev/null +++ b/bytecode/src/main/java/com/iluwatar/bytecode/util/InstructionConverterUtil.java @@ -0,0 +1,76 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bytecode.util; + +import com.iluwatar.bytecode.Instruction; + +/** + * Utility class used for instruction validation and conversion + */ +public class InstructionConverterUtil { + /** + * Converts instructions represented as String + * + * @param instructions to convert + * @return array of int representing bytecode + */ + public static int[] convertToByteCode(String instructions) { + if (instructions == null || instructions.trim().length() == 0) { + return new int[0]; + } + + String[] splitedInstructions = instructions.trim().split(" "); + int[] bytecode = new int[splitedInstructions.length]; + for (int i = 0; i < splitedInstructions.length; i++) { + if (isValidInstruction(splitedInstructions[i])) { + bytecode[i] = Instruction.valueOf(splitedInstructions[i]).getIntValue(); + } else if (isValidInt(splitedInstructions[i])) { + bytecode[i] = Integer.valueOf(splitedInstructions[i]); + } else { + throw new IllegalArgumentException("Invalid instruction or number: " + splitedInstructions[i]); + } + } + + return bytecode; + } + + private static boolean isValidInstruction(String instruction) { + try { + Instruction.valueOf(instruction); + return true; + } catch (IllegalArgumentException e) { + return false; + } + } + + private static boolean isValidInt(String value) { + try { + Integer.parseInt(value); + return true; + } catch (NumberFormatException e) { + return false; + } + } + + +} diff --git a/bytecode/src/test/java/com/iluwatar/bytecode/AppTest.java b/bytecode/src/test/java/com/iluwatar/bytecode/AppTest.java new file mode 100644 index 000000000..014ec7875 --- /dev/null +++ b/bytecode/src/test/java/com/iluwatar/bytecode/AppTest.java @@ -0,0 +1,37 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bytecode; + +import org.junit.jupiter.api.Test; + +/** + * Application test + */ +public class AppTest { + + @Test + public void test() { + String[] args = {}; + App.main(args); + } +} diff --git a/bytecode/src/test/java/com/iluwatar/bytecode/VirtualMachineTest.java b/bytecode/src/test/java/com/iluwatar/bytecode/VirtualMachineTest.java new file mode 100644 index 000000000..e4379c9ed --- /dev/null +++ b/bytecode/src/test/java/com/iluwatar/bytecode/VirtualMachineTest.java @@ -0,0 +1,154 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bytecode; + +import org.junit.jupiter.api.Test; + +import static com.iluwatar.bytecode.Instruction.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +/** + * Test for {@Link VirtualMachine} + */ +public class VirtualMachineTest { + + @Test + public void testLiteral() { + int[] bytecode = new int[2]; + bytecode[0] = LITERAL.getIntValue(); + bytecode[1] = 10; + + VirtualMachine vm = new VirtualMachine(); + vm.execute(bytecode); + + assertEquals(1, vm.getStack().size()); + assertEquals(Integer.valueOf(10), vm.getStack().pop()); + } + + @Test + public void testSetHealth() { + int wizardNumber = 0; + int[] bytecode = new int[5]; + bytecode[0] = LITERAL.getIntValue(); + bytecode[1] = wizardNumber; + bytecode[2] = LITERAL.getIntValue(); + bytecode[3] = 50; // health amount + bytecode[4] = SET_HEALTH.getIntValue(); + + VirtualMachine vm = new VirtualMachine(); + vm.execute(bytecode); + + assertEquals(50, vm.getWizards()[wizardNumber].getHealth()); + } + + @Test + public void testSetAgility() { + int wizardNumber = 0; + int[] bytecode = new int[5]; + bytecode[0] = LITERAL.getIntValue(); + bytecode[1] = wizardNumber; + bytecode[2] = LITERAL.getIntValue(); + bytecode[3] = 50; // agility amount + bytecode[4] = SET_AGILITY.getIntValue(); + + VirtualMachine vm = new VirtualMachine(); + vm.execute(bytecode); + + assertEquals(50, vm.getWizards()[wizardNumber].getAgility()); + } + + @Test + public void testSetWisdom() { + int wizardNumber = 0; + int[] bytecode = new int[5]; + bytecode[0] = LITERAL.getIntValue(); + bytecode[1] = wizardNumber; + bytecode[2] = LITERAL.getIntValue(); + bytecode[3] = 50; // wisdom amount + bytecode[4] = SET_WISDOM.getIntValue(); + + VirtualMachine vm = new VirtualMachine(); + vm.execute(bytecode); + + assertEquals(50, vm.getWizards()[wizardNumber].getWisdom()); + } + + @Test + public void testGetHealth() { + int wizardNumber = 0; + int[] bytecode = new int[8]; + bytecode[0] = LITERAL.getIntValue(); + bytecode[1] = wizardNumber; + bytecode[2] = LITERAL.getIntValue(); + bytecode[3] = 50; // health amount + bytecode[4] = SET_HEALTH.getIntValue(); + bytecode[5] = LITERAL.getIntValue();; + bytecode[6] = wizardNumber; + bytecode[7] = GET_HEALTH.getIntValue(); + + VirtualMachine vm = new VirtualMachine(); + vm.execute(bytecode); + + assertEquals(Integer.valueOf(50), vm.getStack().pop()); + } + + @Test + public void testPlaySound() { + int wizardNumber = 0; + int[] bytecode = new int[3]; + bytecode[0] = LITERAL.getIntValue(); + bytecode[1] = wizardNumber; + bytecode[2] = PLAY_SOUND.getIntValue(); + + VirtualMachine vm = new VirtualMachine(); + vm.execute(bytecode); + + assertEquals(0, vm.getStack().size()); + assertEquals(1, vm.getWizards()[0].getNumberOfPlayedSounds()); + } + + @Test + public void testSpawnParticles() { + int wizardNumber = 0; + int[] bytecode = new int[3]; + bytecode[0] = LITERAL.getIntValue(); + bytecode[1] = wizardNumber; + bytecode[2] = SPAWN_PARTICLES.getIntValue(); + + VirtualMachine vm = new VirtualMachine(); + vm.execute(bytecode); + + assertEquals(0, vm.getStack().size()); + assertEquals(1, vm.getWizards()[0].getNumberOfSpawnedParticles()); + } + + @Test + public void testInvalidInstruction() { + int[] bytecode = new int[1]; + bytecode[0] = 999; + VirtualMachine vm = new VirtualMachine(); + + assertThrows(IllegalArgumentException.class, () -> vm.execute(bytecode)); + } +} diff --git a/bytecode/src/test/java/com/iluwatar/bytecode/util/InstructionConverterUtilTest.java b/bytecode/src/test/java/com/iluwatar/bytecode/util/InstructionConverterUtilTest.java new file mode 100644 index 000000000..4743ac109 --- /dev/null +++ b/bytecode/src/test/java/com/iluwatar/bytecode/util/InstructionConverterUtilTest.java @@ -0,0 +1,63 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.bytecode.util; + +import com.iluwatar.bytecode.Instruction; +import com.iluwatar.bytecode.util.InstructionConverterUtil; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * Test for {@Link InstructionConverterUtil} + */ +public class InstructionConverterUtilTest { + @Test + public void testEmptyInstruction() { + String instruction = ""; + + int[] bytecode = InstructionConverterUtil.convertToByteCode(instruction); + + Assertions.assertEquals(0, bytecode.length); + } + + @Test + public void testInstructions() { + String instructions = + "LITERAL 35 SET_HEALTH SET_WISDOM SET_AGILITY PLAY_SOUND SPAWN_PARTICLES GET_HEALTH ADD DIVIDE"; + + int[] bytecode = InstructionConverterUtil.convertToByteCode(instructions); + + Assertions.assertEquals(10, bytecode.length); + Assertions.assertEquals(Instruction.LITERAL.getIntValue(), bytecode[0]); + Assertions.assertEquals(35, bytecode[1]); + Assertions.assertEquals(Instruction.SET_HEALTH.getIntValue(), bytecode[2]); + Assertions.assertEquals(Instruction.SET_WISDOM.getIntValue(), bytecode[3]); + Assertions.assertEquals(Instruction.SET_AGILITY.getIntValue(), bytecode[4]); + Assertions.assertEquals(Instruction.PLAY_SOUND.getIntValue(), bytecode[5]); + Assertions.assertEquals(Instruction.SPAWN_PARTICLES.getIntValue(), bytecode[6]); + Assertions.assertEquals(Instruction.GET_HEALTH.getIntValue(), bytecode[7]); + Assertions.assertEquals(Instruction.ADD.getIntValue(), bytecode[8]); + Assertions.assertEquals(Instruction.DIVIDE.getIntValue(), bytecode[9]); + } + +} diff --git a/pom.xml b/pom.xml index f305e97d9..c55ed6492 100644 --- a/pom.xml +++ b/pom.xml @@ -171,6 +171,7 @@ priority-queue commander typeobjectpattern + bytecode