|
5 | 5 | #include <scratchcpp/sprite.h> |
6 | 6 | #include <scratchcpp/stage.h> |
7 | 7 | #include <scratchcpp/costume.h> |
| 8 | +#include <scratchcpp/variable.h> |
8 | 9 | #include <enginemock.h> |
9 | 10 | #include <timermock.h> |
10 | 11 | #include <clockmock.h> |
@@ -706,10 +707,35 @@ TEST_F(SensingBlocksTest, Of) |
706 | 707 | addDropdownField(block20, "PROPERTY", SensingBlocks::PROPERTY, "backdrop name", SensingBlocks::BackdropName); |
707 | 708 | addDropdownInput(block20, "OBJECT", SensingBlocks::OBJECT, "", createNullBlock("ad")); |
708 | 709 |
|
| 710 | + // [some variable] of (Stage) |
| 711 | + auto block21 = std::make_shared<Block>("ae", "sensing_of"); |
| 712 | + addDropdownField(block21, "PROPERTY", SensingBlocks::PROPERTY, "some variable", static_cast<SensingBlocks::FieldValues>(-1)); |
| 713 | + addDropdownInput(block21, "OBJECT", SensingBlocks::OBJECT, "_stage_"); |
| 714 | + |
| 715 | + // [some invalid variable] of (Stage) |
| 716 | + auto block22 = std::make_shared<Block>("af", "sensing_of"); |
| 717 | + addDropdownField(block22, "PROPERTY", SensingBlocks::PROPERTY, "some invalid variable", static_cast<SensingBlocks::FieldValues>(-1)); |
| 718 | + addDropdownInput(block22, "OBJECT", SensingBlocks::OBJECT, "_stage_"); |
| 719 | + |
| 720 | + // [some variable] of (Sprite2) |
| 721 | + auto block23 = std::make_shared<Block>("ag", "sensing_of"); |
| 722 | + addDropdownField(block23, "PROPERTY", SensingBlocks::PROPERTY, "some variable", static_cast<SensingBlocks::FieldValues>(-1)); |
| 723 | + addDropdownInput(block23, "OBJECT", SensingBlocks::OBJECT, "Sprite2"); |
| 724 | + |
| 725 | + // [some invalid variable] of (Sprite2) |
| 726 | + auto block24 = std::make_shared<Block>("ah", "sensing_of"); |
| 727 | + addDropdownField(block24, "PROPERTY", SensingBlocks::PROPERTY, "some invalid variable", static_cast<SensingBlocks::FieldValues>(-1)); |
| 728 | + addDropdownInput(block24, "OBJECT", SensingBlocks::OBJECT, "Sprite2"); |
| 729 | + |
| 730 | + // [some variable] of (null block) |
| 731 | + auto block25 = std::make_shared<Block>("ai", "sensing_of"); |
| 732 | + addDropdownField(block25, "PROPERTY", SensingBlocks::PROPERTY, "some variable", static_cast<SensingBlocks::FieldValues>(-1)); |
| 733 | + addDropdownInput(block25, "OBJECT", SensingBlocks::OBJECT, "", createNullBlock("aj")); |
| 734 | + |
709 | 735 | compiler.init(); |
710 | 736 |
|
711 | | - EXPECT_CALL(m_engineMock, findTarget("Sprite2")).Times(7).WillRepeatedly(Return(6)); |
712 | | - EXPECT_CALL(m_engineMock, findTarget("_stage_")).Times(3).WillRepeatedly(Return(0)); |
| 737 | + EXPECT_CALL(m_engineMock, findTarget("Sprite2")).Times(9).WillRepeatedly(Return(6)); |
| 738 | + EXPECT_CALL(m_engineMock, findTarget("_stage_")).Times(5).WillRepeatedly(Return(0)); |
713 | 739 |
|
714 | 740 | EXPECT_CALL(m_engineMock, functionIndex(&SensingBlocks::xPositionOfSpriteByIndex)).WillOnce(Return(0)); |
715 | 741 | compiler.setBlock(block1); |
@@ -791,6 +817,34 @@ TEST_F(SensingBlocksTest, Of) |
791 | 817 | compiler.setBlock(block20); |
792 | 818 | SensingBlocks::compileOf(&compiler); |
793 | 819 |
|
| 820 | + Stage stage; |
| 821 | + auto v1 = std::make_shared<Variable>("var1", "test"); |
| 822 | + auto v2 = std::make_shared<Variable>("var2", "some variable"); |
| 823 | + stage.addVariable(v1); |
| 824 | + stage.addVariable(v2); |
| 825 | + EXPECT_CALL(m_engineMock, targetAt(0)).WillOnce(Return(&stage)); |
| 826 | + compiler.setBlock(block21); |
| 827 | + SensingBlocks::compileOf(&compiler); |
| 828 | + |
| 829 | + EXPECT_CALL(m_engineMock, targetAt(0)).WillOnce(Return(&stage)); |
| 830 | + compiler.setBlock(block22); |
| 831 | + SensingBlocks::compileOf(&compiler); |
| 832 | + |
| 833 | + Sprite sprite; |
| 834 | + auto v3 = std::make_shared<Variable>("var3", "some variable"); |
| 835 | + sprite.addVariable(v3); |
| 836 | + EXPECT_CALL(m_engineMock, targetAt(6)).WillOnce(Return(&sprite)); |
| 837 | + compiler.setBlock(block23); |
| 838 | + SensingBlocks::compileOf(&compiler); |
| 839 | + |
| 840 | + EXPECT_CALL(m_engineMock, targetAt(6)).WillOnce(Return(&sprite)); |
| 841 | + compiler.setBlock(block24); |
| 842 | + SensingBlocks::compileOf(&compiler); |
| 843 | + |
| 844 | + EXPECT_CALL(m_engineMock, functionIndex(&SensingBlocks::variableOfTarget)).WillOnce(Return(18)); |
| 845 | + compiler.setBlock(block25); |
| 846 | + SensingBlocks::compileOf(&compiler); |
| 847 | + |
794 | 848 | compiler.end(); |
795 | 849 |
|
796 | 850 | ASSERT_EQ( |
@@ -867,8 +921,20 @@ TEST_F(SensingBlocksTest, Of) |
867 | 921 | vm::OP_NULL, |
868 | 922 | vm::OP_EXEC, |
869 | 923 | 17, |
| 924 | + vm::OP_READ_VAR, |
| 925 | + 0, |
| 926 | + vm::OP_NULL, |
| 927 | + vm::OP_READ_VAR, |
| 928 | + 1, |
| 929 | + vm::OP_NULL, |
| 930 | + vm::OP_CONST, |
| 931 | + 10, |
| 932 | + vm::OP_NULL, |
| 933 | + vm::OP_EXEC, |
| 934 | + 18, |
870 | 935 | vm::OP_HALT })); |
871 | | - ASSERT_EQ(compiler.constValues(), std::vector<Value>({ 6, 6, 6, 6, 6, 6, 6, 0, 0, 0 })); |
| 936 | + ASSERT_EQ(compiler.constValues(), std::vector<Value>({ 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, "some variable" })); |
| 937 | + ASSERT_EQ(compiler.variables(), std::vector<Variable *>({ v2.get(), v3.get() })); |
872 | 938 | } |
873 | 939 |
|
874 | 940 | TEST_F(SensingBlocksTest, XPositionOfSprite) |
@@ -1114,6 +1180,75 @@ TEST_F(SensingBlocksTest, VolumeOfTarget) |
1114 | 1180 | ASSERT_EQ(vm.getInput(0, 1)->toDouble(), stage.volume()); |
1115 | 1181 | } |
1116 | 1182 |
|
| 1183 | +TEST_F(SensingBlocksTest, VariableOfTarget) |
| 1184 | +{ |
| 1185 | + static unsigned int bytecode1[] = { vm::OP_START, vm::OP_CONST, 0, vm::OP_CONST, 2, vm::OP_EXEC, 0, vm::OP_HALT }; |
| 1186 | + static unsigned int bytecode2[] = { vm::OP_START, vm::OP_CONST, 1, vm::OP_CONST, 2, vm::OP_EXEC, 0, vm::OP_HALT }; |
| 1187 | + static unsigned int bytecode3[] = { vm::OP_START, vm::OP_CONST, 0, vm::OP_CONST, 3, vm::OP_EXEC, 0, vm::OP_HALT }; |
| 1188 | + static unsigned int bytecode4[] = { vm::OP_START, vm::OP_CONST, 1, vm::OP_CONST, 3, vm::OP_EXEC, 0, vm::OP_HALT }; |
| 1189 | + static unsigned int bytecode5[] = { vm::OP_START, vm::OP_CONST, 0, vm::OP_CONST, 4, vm::OP_EXEC, 0, vm::OP_HALT }; |
| 1190 | + static BlockFunc functions[] = { &SensingBlocks::variableOfTarget }; |
| 1191 | + static Value constValues[] = { "variable", "invalid variable", "Sprite2", "_stage_", "test" }; |
| 1192 | + |
| 1193 | + Sprite sprite; |
| 1194 | + auto v1 = std::make_shared<Variable>("var1", "variable", 64.13); |
| 1195 | + sprite.addVariable(v1); |
| 1196 | + |
| 1197 | + Stage stage; |
| 1198 | + auto v2 = std::make_shared<Variable>("var2", "test", 98); |
| 1199 | + auto v3 = std::make_shared<Variable>("var3", "variable", -0.85); |
| 1200 | + stage.addVariable(v2); |
| 1201 | + stage.addVariable(v3); |
| 1202 | + |
| 1203 | + VirtualMachine vm(nullptr, &m_engineMock, nullptr); |
| 1204 | + vm.setFunctions(functions); |
| 1205 | + vm.setConstValues(constValues); |
| 1206 | + |
| 1207 | + EXPECT_CALL(m_engineMock, findTarget("Sprite2")).WillOnce(Return(6)); |
| 1208 | + EXPECT_CALL(m_engineMock, targetAt(6)).WillOnce(Return(&sprite)); |
| 1209 | + vm.setBytecode(bytecode1); |
| 1210 | + vm.run(); |
| 1211 | + |
| 1212 | + ASSERT_EQ(vm.registerCount(), 1); |
| 1213 | + ASSERT_EQ(vm.getInput(0, 1)->toDouble(), v1->value().toDouble()); |
| 1214 | + |
| 1215 | + EXPECT_CALL(m_engineMock, findTarget("Sprite2")).WillOnce(Return(6)); |
| 1216 | + EXPECT_CALL(m_engineMock, targetAt(6)).WillOnce(Return(&sprite)); |
| 1217 | + vm.reset(); |
| 1218 | + vm.setBytecode(bytecode2); |
| 1219 | + vm.run(); |
| 1220 | + |
| 1221 | + ASSERT_EQ(vm.registerCount(), 1); |
| 1222 | + ASSERT_EQ(vm.getInput(0, 1)->toDouble(), 0); |
| 1223 | + |
| 1224 | + EXPECT_CALL(m_engineMock, findTarget("_stage_")).WillOnce(Return(0)); |
| 1225 | + EXPECT_CALL(m_engineMock, targetAt(0)).WillOnce(Return(&stage)); |
| 1226 | + vm.reset(); |
| 1227 | + vm.setBytecode(bytecode3); |
| 1228 | + vm.run(); |
| 1229 | + |
| 1230 | + ASSERT_EQ(vm.registerCount(), 1); |
| 1231 | + ASSERT_EQ(vm.getInput(0, 1)->toDouble(), v3->value().toDouble()); |
| 1232 | + |
| 1233 | + EXPECT_CALL(m_engineMock, findTarget("_stage_")).WillOnce(Return(0)); |
| 1234 | + EXPECT_CALL(m_engineMock, targetAt(0)).WillOnce(Return(&stage)); |
| 1235 | + vm.reset(); |
| 1236 | + vm.setBytecode(bytecode4); |
| 1237 | + vm.run(); |
| 1238 | + |
| 1239 | + ASSERT_EQ(vm.registerCount(), 1); |
| 1240 | + ASSERT_EQ(vm.getInput(0, 1)->toDouble(), 0); |
| 1241 | + |
| 1242 | + EXPECT_CALL(m_engineMock, findTarget("test")).WillOnce(Return(-1)); |
| 1243 | + EXPECT_CALL(m_engineMock, targetAt(-1)).WillOnce(Return(nullptr)); |
| 1244 | + vm.reset(); |
| 1245 | + vm.setBytecode(bytecode5); |
| 1246 | + vm.run(); |
| 1247 | + |
| 1248 | + ASSERT_EQ(vm.registerCount(), 1); |
| 1249 | + ASSERT_EQ(vm.getInput(0, 1)->toDouble(), 0); |
| 1250 | +} |
| 1251 | + |
1117 | 1252 | TEST_F(SensingBlocksTest, BackdropNumberOfStage) |
1118 | 1253 | { |
1119 | 1254 | static unsigned int bytecode1[] = { vm::OP_START, vm::OP_CONST, 0, vm::OP_EXEC, 0, vm::OP_HALT }; |
|
0 commit comments