forked from anyaevostinar/SymbulationEmp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSGPHost.test.cc
More file actions
312 lines (264 loc) · 11.6 KB
/
Copy pathSGPHost.test.cc
File metadata and controls
312 lines (264 loc) · 11.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
#include "../../test_utils.h"
#include "../../../default_mode/SymWorld.h"
#include "../../../default_mode/WorldSetup.cc"
#include "../../../default_mode/DataNodes.h"
#include "../../../sgp_mode/SGPWorld.h"
#include "../../../sgp_mode/SGPWorld.cc"
#include "../../../sgp_mode/SGPWorldSetup.cc"
#include "../../../sgp_mode/SGPWorldData.cc"
#include "../../../sgp_mode/SGPW_InteractionMechanismSetup.cc"
#include "../../../sgp_mode/SGPW_TaskProfileSetup.cc"
#include "../../../sgp_mode/ProgramBuilder.h"
#include "../../../catch/catch.hpp"
/**
* This file is dedicated to unit tests for SGPHost
*/
TEST_CASE("Mutate", "[sgp]") {
using world_t = sgpmode::SGPWorld;
using cpu_state_t = sgpmode::CPUState<world_t>;
using hw_spec_t = sgpmode::SGPHardwareSpec<sgpmode::Library, cpu_state_t, world_t>;
using sgp_host_t = sgpmode::SGPHost<hw_spec_t>;
emp::Random random(61);
sgpmode::SymConfigSGP config;
test_utils::SetWellMixed(config, 4, 0);
config.TASK_IO_BANK_SIZE(10);
config.SGP_MUT_PER_BIT_RATE(1.0);
config.TASK_ENV_CFG_PATH("source/test/sgp_mode_test/hardware-test-env.json");
world_t world(random, &config);
world.Setup();
auto& prog_builder = world.GetProgramBuilder();
emp::Ptr<sgp_host_t> uninfected_host = emp::NewPtr<sgp_host_t>(&random, &world, &config, prog_builder.CreateReproProgram(100));
emp::Ptr<sgp_host_t> second_host = emp::NewPtr<sgp_host_t>(&random, &world, &config, prog_builder.CreateReproProgram(100));
REQUIRE(*uninfected_host == *second_host);
THEN("Mutated organism is different") {
for (int i = 0; i < 100; i++) {
uninfected_host->Mutate();
}
REQUIRE(*uninfected_host != *second_host);
}
// clean up organisms since they aren't in the world
uninfected_host.Delete();
second_host.Delete();
}
TEST_CASE("No Mutate", "[sgp]") {
using world_t = sgpmode::SGPWorld;
using cpu_state_t = sgpmode::CPUState<world_t>;
using hw_spec_t = sgpmode::SGPHardwareSpec<sgpmode::Library, cpu_state_t, world_t>;
using sgp_host_t = sgpmode::SGPHost<hw_spec_t>;
emp::Random random(61);
sgpmode::SymConfigSGP config;
test_utils::SetWellMixed(config, 4, 0);
config.TASK_IO_BANK_SIZE(10);
config.SGP_MUT_PER_BIT_RATE(0.0);
config.TASK_ENV_CFG_PATH("source/test/sgp_mode_test/hardware-test-env.json");
world_t world(random, &config);
world.Setup();
auto& prog_builder = world.GetProgramBuilder();
emp::Ptr<sgp_host_t> uninfected_host = emp::NewPtr<sgp_host_t>(&random, &world, &config, prog_builder.CreateReproProgram(100));
emp::Ptr<sgp_host_t> second_host = emp::NewPtr<sgp_host_t>(&random, &world, &config, prog_builder.CreateReproProgram(100));
REQUIRE(*uninfected_host == *second_host);
THEN("Organism mutated with 0 mutation rate is not different") {
for (int i = 0; i < 100; i++) {
uninfected_host->Mutate();
}
REQUIRE(*uninfected_host == *second_host);
}
// clean up organisms since they aren't in the world
uninfected_host.Delete();
second_host.Delete();
}
TEST_CASE("SGPHost destructor cleans up shared pointers and in-progress reproduction", "[sgp][sgp-unit]") {
using world_t = sgpmode::SGPWorld;
using cpu_state_t = sgpmode::CPUState<world_t>;
using hw_spec_t = sgpmode::SGPHardwareSpec<sgpmode::Library, cpu_state_t, world_t>;
using sgp_host_t = sgpmode::SGPHost<hw_spec_t>;
GIVEN("A host") {
emp::Random random(31);
sgpmode::SymConfigSGP config;
test_utils::SetWellMixed(config, 1, 0);
config.TASK_IO_BANK_SIZE(10);
config.TASK_ENV_CFG_PATH("source/test/sgp_mode_test/hardware-test-env.json");
world_t world(random, &config);
world.Setup();
auto& prog_builder = world.GetProgramBuilder();
emp::Ptr<sgp_host_t> host = emp::NewPtr<sgp_host_t>(&random, &world, &config, prog_builder.CreateNotProgram(100));
emp::WorldPosition host_pos = emp::WorldPosition(1, 2);
host->SetLocation(host_pos);
const size_t queue_id = world.GetReproQueue().Enqueue(host->GetHardware().GetCPUState().GetOrgPtr(), host_pos);
host->GetHardware().GetCPUState().MarkReproInProgress(queue_id);
WHEN("The host is destroyed") {
host.Delete();
THEN("The host's position in the reproduction queue is marked as invalid") {
REQUIRE(world.GetReproQueue().GetQueue()[queue_id].valid == false);
}
}
}
}
TEST_CASE("Host == operators", "[sgp][sgp-unit]") {
using world_t = sgpmode::SGPWorld;
using cpu_state_t = sgpmode::CPUState<world_t>;
using hw_spec_t = sgpmode::SGPHardwareSpec<sgpmode::Library, cpu_state_t, world_t>;
using sgp_host_t = sgpmode::SGPHost<hw_spec_t>;
GIVEN("A host") {
emp::Random random(31);
sgpmode::SymConfigSGP config;
config.TASK_ENV_CFG_PATH("source/test/sgp_mode_test/hardware-test-env.json");
config.TASK_IO_BANK_SIZE(10);
world_t world(random, &config);
auto& prog_builder = world.GetProgramBuilder();
emp::Ptr<sgp_host_t> host = emp::NewPtr<sgp_host_t>(&random, &world, &config, prog_builder.CreateNotProgram(100));
WHEN("2 clones of the original host are created") {
emp::Ptr<sgp_host_t> clone1 = emp::NewPtr<sgp_host_t>(*host);
emp::Ptr<sgp_host_t> clone2 = emp::NewPtr<sgp_host_t>(*host);
THEN("host is equal to first clone") {
REQUIRE(*host == *clone1);
}
THEN("The first clone is equal to the second clone") {
REQUIRE(*clone1 == *clone2);
}
clone1.Delete();
clone2.Delete();
}
WHEN("A host that is different to the original is created") {
emp::Ptr<sgp_host_t> different = emp::NewPtr<sgp_host_t>(&random, &world, &config, prog_builder.CreateNotProgram(99)); // For comparing
THEN("The host is not equal to the different host") {
REQUIRE_FALSE(*host == *different);
}
different.Delete();
}
host.Delete();
}
}
TEST_CASE("Host > & < operators", "[sgp][sgp-unit]") {
using world_t = sgpmode::SGPWorld;
using cpu_state_t = sgpmode::CPUState<world_t>;
using hw_spec_t = sgpmode::SGPHardwareSpec<sgpmode::Library, cpu_state_t, world_t>;
using sgp_host_t = sgpmode::SGPHost<hw_spec_t>;
GIVEN("two different hosts") {
emp::Random random(31);
sgpmode::SymConfigSGP config;
config.TASK_ENV_CFG_PATH("source/test/sgp_mode_test/hardware-test-env.json");
config.TASK_IO_BANK_SIZE(10);
world_t world(random, &config);
auto& prog_builder = world.GetProgramBuilder();
emp::Ptr<sgp_host_t> host = emp::NewPtr<sgp_host_t>(&random, &world, &config, prog_builder.CreateNotProgram(100));
emp::Ptr<sgp_host_t> different = emp::NewPtr<sgp_host_t>(&random, &world, &config, prog_builder.CreateNotProgram(99)); // For comparing
WHEN("The two hosts are compared") {
THEN("One host is less then the other host") {
// Can't assert true/false without knowing bitcode ordering,
// assert that bitcode ordering is well-defined
bool lt = *host < *different || *different < *host;
REQUIRE(lt);
}
}
host.Delete();
different.Delete();
}
}
TEST_CASE("MakeNew returns identical host", "[sgp][sgp-unit]") {
using world_t = sgpmode::SGPWorld;
using cpu_state_t = sgpmode::CPUState<world_t>;
using hw_spec_t = sgpmode::SGPHardwareSpec<sgpmode::Library, cpu_state_t, world_t>;
using sgp_host_t = sgpmode::SGPHost<hw_spec_t>;
GIVEN("A host") {
emp::Random random(31);
sgpmode::SymConfigSGP config;
config.TASK_ENV_CFG_PATH("source/test/sgp_mode_test/hardware-test-env.json");
world_t world(random, &config);
emp::Ptr<sgp_host_t> host = emp::NewPtr<sgp_host_t>(&random, &world, &config);
WHEN("A new host is created using the MakeNew function of the first host") {
emp::Ptr<Organism> host_remade = host->MakeNew();
THEN("MakeNew produces an identical host") {
REQUIRE(*host_remade == *host);
}
host_remade.Delete();
}
host.Delete();
}
}
TEST_CASE("SetReproCount & GetReproCount","[sgp][sgp-unit]") {
using world_t = sgpmode::SGPWorld;
using cpu_state_t = sgpmode::CPUState<world_t>;
using hw_spec_t = sgpmode::SGPHardwareSpec<sgpmode::Library, cpu_state_t, world_t>;
using sgp_host_t = sgpmode::SGPHost<hw_spec_t>;
GIVEN("An SGPWorld and a host") {
emp::Random random(31);
sgpmode::SymConfigSGP config;
config.TASK_ENV_CFG_PATH("source/test/sgp_mode_test/hardware-test-env.json");
test_utils::SetWellMixed(config, 4, 0);
config.TASK_IO_BANK_SIZE(10);
world_t world(random, &config);
world.Setup();
auto& prog_builder = world.GetProgramBuilder();
emp::Ptr<sgp_host_t> host = emp::NewPtr<sgp_host_t>(&random, &world, &config, prog_builder.CreateNotProgram(100));
WHEN("The host is added to the world") {
world.AddOrgAt(host, 0);
THEN("Repro count of the host is 0") {
REQUIRE(host->GetReproCount() == 0);
}
WHEN("The host's repro count is increased by 1") {
host->SetReproCount(1);
THEN("Repro count of the host is 1") {
REQUIRE(host->GetReproCount() == 1);
}
}
}
}
}
TEST_CASE("ProcessOutputBuffer", "[sgp][sgp-unit]") {
using world_t = sgpmode::SGPWorld;
using cpu_state_t = sgpmode::CPUState<world_t>;
using hw_spec_t = sgpmode::SGPHardwareSpec<sgpmode::Library, cpu_state_t, world_t>;
using sgp_host_t = sgpmode::SGPHost<hw_spec_t>;
GIVEN("A host with valid values in its input and output buffers") {
emp::Random random(31);
sgpmode::SymConfigSGP config;
config.TASK_ENV_CFG_PATH("source/test/sgp_mode_test/echo-task-env.json");
config.TASK_IO_BANK_SIZE(10);
test_utils::SetWellMixed(config, 1, 0);
world_t world(random, &config);
world.Setup();
auto& prog_builder = world.GetProgramBuilder();
emp::Ptr<sgp_host_t> host = emp::NewPtr<sgp_host_t>(&random, &world, &config, prog_builder.CreateNotProgram(100));
world.AddOrgAt(host, 0);
// save two of the inputs
emp::vector<uint32_t> inputs;
for (int i = 0; i < 2; i++) {
inputs.push_back(host->GetHardware().GetCPUState().GetInputBuffer().read());
}
inputs.push_back(0); // add some incorrect output to make sure they aren't getting points for those
inputs.push_back(1);
host->GetHardware().GetCPUState().SetOutputs(inputs); // set output buffer to inputs with with some extra incorrect outputs
WHEN("ProcessOutputBuffer is called") {
host->ProcessOutputBuffer();
THEN("The output buffer is cleared and host received 10 points for correctly echoing 2 inputs") {
REQUIRE(host->GetHardware().GetCPUState().GetOutputBuffer().empty());
REQUIRE(host->GetPoints() == 10);
}
}
}
}
TEST_CASE("Check that hosts and syms can't have negative points", "[sgp][sgp-unit]"){
using world_t = sgpmode::SGPWorld;
using cpu_state_t = sgpmode::CPUState<world_t>;
using hw_spec_t = sgpmode::SGPHardwareSpec<sgpmode::Library, cpu_state_t, world_t>;
using sgp_host_t = sgpmode::SGPHost<hw_spec_t>;
using sgp_sym_t = sgpmode::SGPSymbiont<hw_spec_t>;
GIVEN("A host and sym starting with zero points"){
emp::Random random(31);
sgpmode::SymConfigSGP config;
config.TASK_ENV_CFG_PATH("source/test/sgp_mode_test/hardware-test-env.json");
world_t world(random, &config);
auto& prog_builder = world.GetProgramBuilder();
emp::Ptr<sgp_host_t> host = emp::NewPtr<sgp_host_t>(&random, &world, &config, prog_builder.CreateReproProgram(100));
emp::Ptr<sgp_sym_t> sym = emp::NewPtr<sgp_sym_t>(&random, &world, &config, prog_builder.CreateNotProgram(100));
WHEN("points are added to make total points negative"){
sym->AddPoints(-100);
host->AddPoints(-100);
THEN("point value should be set to zero"){
REQUIRE(host->GetPoints() == 0);
REQUIRE(sym->GetPoints() == 0);
}
}
}
}