mirror of
https://github.com/JHUAPL/kami.git
synced 2026-01-10 20:18:00 -05:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4db95f925 | ||
|
|
0727030bcb | ||
|
|
85aede0721 | ||
|
|
06e98b1f94 | ||
|
|
8613bc29b3 | ||
|
|
67cdf9bc29 | ||
|
|
e7a5f342bf | ||
|
|
9333e1c2fa | ||
|
|
f18e2c99da | ||
|
|
d884e603cb | ||
|
|
78aca204f4 | ||
|
|
50b147beca | ||
|
|
3dff3afb6e | ||
|
|
80f98bdde0 | ||
|
|
72f0074d81 | ||
|
|
f6967d0ec3 | ||
|
|
318f6dfecf | ||
|
|
05995525f1 | ||
|
|
d1ba71b416 |
2
.github/workflows/build-develop.yml
vendored
2
.github/workflows/build-develop.yml
vendored
@@ -34,7 +34,7 @@ jobs:
|
||||
conan profile update settings.compiler.libcxx=libstdc++11 default
|
||||
|
||||
- name: Conan Install Dependencies
|
||||
run: conan install -if build .
|
||||
run: conan install -if build . --build=missing
|
||||
|
||||
- name: Configure CMake
|
||||
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
||||
|
||||
2
.github/workflows/build-main.yml
vendored
2
.github/workflows/build-main.yml
vendored
@@ -34,7 +34,7 @@ jobs:
|
||||
conan profile update settings.compiler.libcxx=libstdc++11 default
|
||||
|
||||
- name: Conan Install Dependencies
|
||||
run: conan install -if build .
|
||||
run: conan install -if build . --build=missing
|
||||
|
||||
- name: Configure CMake
|
||||
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
||||
|
||||
@@ -5,8 +5,8 @@ cmake_minimum_required(VERSION 3.13)
|
||||
set(PROJECT_NAME "kami")
|
||||
|
||||
set(VERSION_MAJOR 0)
|
||||
set(VERSION_MINOR 5)
|
||||
set(VERSION_PATCH 1)
|
||||
set(VERSION_MINOR 6)
|
||||
set(VERSION_PATCH 0)
|
||||
set(VERSION_STRING ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
|
||||
|
||||
project(${PROJECT_NAME}
|
||||
@@ -23,9 +23,6 @@ conan_basic_setup()
|
||||
|
||||
set(PROJECT_NAMESPACE ${PROJECT_NAME})
|
||||
|
||||
find_package(spdlog)
|
||||
find_package(Threads)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
option(ENABLE_COVERAGE "Enable coverage reporting for gcc/clang" FALSE)
|
||||
endif()
|
||||
|
||||
@@ -3,7 +3,7 @@ from conans import ConanFile, CMake
|
||||
|
||||
class KamiConan(ConanFile):
|
||||
name = "kami"
|
||||
version = "0.5.1"
|
||||
version = "0.6.0"
|
||||
license = "MIT"
|
||||
author = "James P. Howard, II <james.howard@jhu.edu>"
|
||||
url = "https://github.com/jhuapl/kami"
|
||||
@@ -44,8 +44,8 @@ class KamiConan(ConanFile):
|
||||
|
||||
|
||||
def requirements(self):
|
||||
self.requires("fmt/7.1.3")
|
||||
self.requires("spdlog/1.8.5")
|
||||
self.requires("cli11/1.9.1")
|
||||
self.requires("fmt/9.0.0")
|
||||
self.requires("spdlog/1.10.0")
|
||||
self.requires("cli11/2.2.0")
|
||||
self.requires("neargye-semver/0.3.0")
|
||||
self.requires("gtest/cci.20210126")
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
- :release:`0.6.0 <2022.08.19>`
|
||||
- :feature:`0` Added a to do list to the documentation
|
||||
- :feature:`0` Completed basic unit tests
|
||||
- :feature:`0` Removed step()/run() from Model interface
|
||||
- :feature:`0` Revised interfaces to the grids
|
||||
- :feature:`0` Updated all support packages to most current versions
|
||||
|
||||
- :release:`0.5.1 <2022.08.11>`
|
||||
- :support:`0` Completed initial unit tests
|
||||
- :support:`0` Added background info to READ ME
|
||||
|
||||
@@ -18,13 +18,49 @@ Introduction
|
||||
|
||||
Kami is Agent-Based Modeling in Modern C++.
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
Agent-based models (ABMs) are models for simulating the actions of
|
||||
individual actors within a provided environment to understand the
|
||||
behavior of the agents, most individually and collectively. ABMs
|
||||
are particularly suited for addressing problems governed by nonlinear
|
||||
processes or where there is a wide variety of potential responses
|
||||
an individual agent may provide depending on the environment and
|
||||
behavior of other agents. Because of this, ABMs have become powerful
|
||||
tools in both simulation and modeling, especially in public health
|
||||
and ecology, where they are also known as individual-based models.
|
||||
ABMs also provide support in economic, business, robotics, and many
|
||||
other fields.
|
||||
|
||||
Design Objectives
|
||||
-----------------
|
||||
|
||||
Kami provides agent-based modeling modern C++. The objectives in
|
||||
writing Kami are that it be lightweight, memory-efficient, and fast.
|
||||
It should be possible to develop a simple working model in under
|
||||
one hour of C++ development time. Accordingly, the platform is
|
||||
modeled on the Mesa_ library in Python, which itself was inspired
|
||||
by the MASON_ library in Java.
|
||||
|
||||
Many ABM platforms are designed around interaction and real time
|
||||
observation of the agent dynamics. Kami does not provide a
|
||||
visualization interface. Instead, Kami is meant to be used for
|
||||
ABMs requiring many runs with different starting conditions.
|
||||
Accordingly, Kami is single-threaded and multiple cores should be
|
||||
taken advantage of through multiple parallel runs of the supervising
|
||||
model.
|
||||
|
||||
.. _MASON: https://cs.gmu.edu/~eclab/projects/mason/
|
||||
.. _Mesa: https://mesa.readthedocs.io
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
:maxdepth: 2
|
||||
|
||||
overview
|
||||
installation
|
||||
tutorial
|
||||
api/library_root
|
||||
changelog
|
||||
todo
|
||||
license
|
||||
@@ -1,37 +0,0 @@
|
||||
Overview
|
||||
========
|
||||
|
||||
Agent-based models (ABMs) are models for simulating the actions of
|
||||
individual actors within a provided environment to understand the
|
||||
behavior of the agents, most individually and collectively. ABMs
|
||||
are particularly suited for addressing problems governed by nonlinear
|
||||
processes or where there is a wide variety of potential responses
|
||||
an individual agent may provide depending on the environment and
|
||||
behavior of other agents. Because of this, ABMs have become powerful
|
||||
tools in both simulation and modeling, especially in public health
|
||||
and ecology, where they are also known as individual-based models.
|
||||
ABMs also provide support in economic, business, robotics, and many
|
||||
other fields.
|
||||
|
||||
Design Objectives
|
||||
-----------------
|
||||
|
||||
Kami provides agent-based modeling modern C++. The objectives in
|
||||
writing Kami are that it be lightweight, memory-efficient, and fast.
|
||||
It should be possible to develop a simple working model in under
|
||||
one hour of C++ development time. Accordingly, the platform is
|
||||
modeled on the Mesa_ library in Python, which itself was inspired
|
||||
by the MASON_ library in Java.
|
||||
|
||||
Many ABM platforms are designed around interaction and real time
|
||||
observation of the agent dynamics. Kami does not provide a
|
||||
visualization interface. Instead, Kami is meant to be used for
|
||||
ABMs requiring many runs with different starting conditions.
|
||||
Accordingly, Kami is single-threaded and multiple cores should be
|
||||
taken advantage of through multiple parallel runs of the supervising
|
||||
model.
|
||||
|
||||
.. _MASON: https://cs.gmu.edu/~eclab/projects/mason/
|
||||
.. _Mesa: https://mesa.readthedocs.io
|
||||
|
||||
.. toctree::
|
||||
24
docs/todo.rst
Normal file
24
docs/todo.rst
Normal file
@@ -0,0 +1,24 @@
|
||||
To Do List
|
||||
==========
|
||||
|
||||
Must Dos
|
||||
--------
|
||||
The list below is a list of things considered necessary before
|
||||
a 1.0 release. This list is *not* static.
|
||||
|
||||
- Network domain
|
||||
- Data collection process
|
||||
- Demonstration of data collection process
|
||||
- Tutorial write up
|
||||
|
||||
Wishlist
|
||||
--------
|
||||
The list below is a list of things considered nice to have at
|
||||
any point.
|
||||
|
||||
- Revise unit tests to take advantage of fixtures
|
||||
- Documentation with basic introduction to ABMs
|
||||
- Network Boltzmann model example
|
||||
- Additional examples as appropriate
|
||||
|
||||
.. toctree::
|
||||
@@ -3,5 +3,5 @@
|
||||
Each folder in here is automatically traversed by the root level cmake list file.
|
||||
|
||||
1. Copy one of the existing folders to a new name.
|
||||
2. The name of the folder will be the name of the library
|
||||
2. The name of the folder will be the name of the example
|
||||
3. Change the source file list.
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
# Set minimum version of CMake.
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
find_package(spdlog)
|
||||
|
||||
set(EXAMPLE_NAME "boltzmann1d")
|
||||
|
||||
project(${EXAMPLE_NAME} LANGUAGES CXX)
|
||||
|
||||
@@ -26,15 +26,14 @@
|
||||
#include "boltzmann1d.h"
|
||||
|
||||
#include <exception>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <random>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <CLI/App.hpp>
|
||||
#include <CLI/Config.hpp>
|
||||
#include <CLI/Formatter.hpp>
|
||||
#include <CLI/CLI.hpp>
|
||||
|
||||
#include <spdlog/sinks/stdout_color_sinks.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
@@ -78,7 +77,7 @@ kami::AgentID MoneyAgent1D::step(std::shared_ptr<kami::Model> model) {
|
||||
return this->get_agent_id();
|
||||
}
|
||||
|
||||
kami::GridCoord1D MoneyAgent1D::move_agent(std::shared_ptr<kami::Model> model) {
|
||||
std::optional<kami::GridCoord1D> MoneyAgent1D::move_agent(std::shared_ptr<kami::Model> model) {
|
||||
console->trace("Entering move_agent");
|
||||
auto agent_id = get_agent_id();
|
||||
|
||||
@@ -87,9 +86,12 @@ kami::GridCoord1D MoneyAgent1D::move_agent(std::shared_ptr<kami::Model> model) {
|
||||
throw (std::domain_error("model is missing domain"));
|
||||
auto world = std::static_pointer_cast<kami::MultiGrid1D>(domain.value());
|
||||
|
||||
auto move_list = world->get_neighborhood(agent_id, false);
|
||||
auto move_list_opt = world->get_neighborhood(agent_id, false);
|
||||
if (!move_list_opt)
|
||||
return std::nullopt;
|
||||
auto move_list = move_list_opt.value();
|
||||
std::uniform_int_distribution<int> dist(0, (int) move_list->size() - 1);
|
||||
auto new_location = move_list->at(dist(*rng));
|
||||
auto new_location = *std::next(move_list->begin(), dist(*rng));
|
||||
|
||||
console->trace("Moving Agent {} to location {}", agent_id, new_location);
|
||||
world->move_agent(agent_id, new_location);
|
||||
@@ -113,13 +115,17 @@ std::optional<kami::AgentID> MoneyAgent1D::give_money(std::shared_ptr<kami::Mode
|
||||
auto population = std::static_pointer_cast<kami::Population>(agents.value());
|
||||
|
||||
auto location = world->get_location_by_agent(agent_id);
|
||||
auto cell_mates = world->get_location_contents(location.value());
|
||||
auto cell_mates_opt = world->get_location_contents(location.value());
|
||||
|
||||
if (!cell_mates_opt)
|
||||
return std::nullopt;
|
||||
|
||||
auto cell_mates = cell_mates_opt.value();
|
||||
if (cell_mates->size() < 2)
|
||||
return std::nullopt;
|
||||
|
||||
std::uniform_int_distribution<int> dist(0, (int) cell_mates->size() - 1);
|
||||
kami::AgentID other_agent_id = cell_mates->at(dist(*rng));
|
||||
auto other_agent_id = *std::next(cell_mates->begin(), dist(*rng));
|
||||
auto other_agent = std::static_pointer_cast<MoneyAgent1D>(population->get_agent_by_id(other_agent_id).value());
|
||||
|
||||
console->trace("Agent {} giving unit of wealth to agent {}", agent_id, other_agent_id);
|
||||
@@ -157,12 +163,6 @@ BoltzmannWealthModel1D::BoltzmannWealthModel1D(unsigned int number_agents, unsig
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<kami::Model> BoltzmannWealthModel1D::run(unsigned int steps) {
|
||||
for (auto i = 0; i < steps; i++)
|
||||
step();
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
std::shared_ptr<kami::Model> BoltzmannWealthModel1D::step() {
|
||||
console->trace("Executing model step {}", ++_step_count);
|
||||
_sched->step(shared_from_this());
|
||||
@@ -175,8 +175,14 @@ int main(int argc, char **argv) {
|
||||
CLI::App app{ident};
|
||||
unsigned int x_size = 16, agent_count = x_size, max_steps = 100, initial_seed = 42;
|
||||
|
||||
// This exercise is really stupid.
|
||||
auto levels_list = std::make_unique<std::list<std::string>>();
|
||||
for (auto &level_name: SPDLOG_LEVEL_NAMES)
|
||||
levels_list->push_back(std::string(level_name.data(), level_name.size()));
|
||||
|
||||
app.add_option("-c", agent_count, "Set the number of agents")->check(CLI::PositiveNumber);
|
||||
app.add_option("-l", log_level_option, "Set the logging level")->check(CLI::IsMember(SPDLOG_LEVEL_NAMES));
|
||||
app.add_option("-l", log_level_option, "Set the logging level")->check(
|
||||
CLI::IsMember(levels_list.get(), CLI::ignore_case));
|
||||
app.add_option("-n", max_steps, "Set the number of steps to run the model")->check(CLI::PositiveNumber);
|
||||
app.add_option("-s", initial_seed, "Set the initial seed")->check(CLI::Number);
|
||||
app.add_option("-x", x_size, "Set the number of columns")->check(CLI::PositiveNumber);
|
||||
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
/**
|
||||
* Move the agent to a random location on the world
|
||||
*/
|
||||
kami::GridCoord1D move_agent(std::shared_ptr<kami::Model> model);
|
||||
std::optional<kami::GridCoord1D> move_agent(std::shared_ptr<kami::Model> model);
|
||||
|
||||
/**
|
||||
* Give money to a random agent
|
||||
@@ -96,14 +96,7 @@ public:
|
||||
/**
|
||||
* Execute a single time-step for the model.
|
||||
*/
|
||||
std::shared_ptr<kami::Model> step() override;
|
||||
|
||||
/**
|
||||
* Execute a number of time-steps for the model.
|
||||
*
|
||||
* @param[in] n the number of steps to execute.
|
||||
*/
|
||||
std::shared_ptr<kami::Model> run(unsigned int n) override;
|
||||
std::shared_ptr<kami::Model> step();
|
||||
|
||||
private:
|
||||
unsigned int _step_count;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
# Set minimum version of CMake.
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
find_package(spdlog)
|
||||
|
||||
set(EXAMPLE_NAME "boltzmann2d")
|
||||
|
||||
project(${EXAMPLE_NAME} LANGUAGES CXX)
|
||||
|
||||
@@ -26,15 +26,14 @@
|
||||
#include "boltzmann2d.h"
|
||||
|
||||
#include <exception>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <random>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <CLI/App.hpp>
|
||||
#include <CLI/Config.hpp>
|
||||
#include <CLI/Formatter.hpp>
|
||||
#include <CLI/CLI.hpp>
|
||||
|
||||
#include <spdlog/sinks/stdout_color_sinks.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
@@ -78,7 +77,7 @@ kami::AgentID MoneyAgent2D::step(std::shared_ptr<kami::Model> model) {
|
||||
return this->get_agent_id();
|
||||
}
|
||||
|
||||
kami::GridCoord2D MoneyAgent2D::move_agent(std::shared_ptr<kami::Model> model) {
|
||||
std::optional<kami::GridCoord2D> MoneyAgent2D::move_agent(std::shared_ptr<kami::Model> model) {
|
||||
console->trace("Entering move_agent");
|
||||
auto agent_id = get_agent_id();
|
||||
|
||||
@@ -87,9 +86,12 @@ kami::GridCoord2D MoneyAgent2D::move_agent(std::shared_ptr<kami::Model> model) {
|
||||
throw (std::domain_error("model is missing domain"));
|
||||
auto world = std::static_pointer_cast<kami::MultiGrid2D>(domain.value());
|
||||
|
||||
auto move_list = world->get_neighborhood(agent_id, false, kami::GridNeighborhoodType::Moore);
|
||||
auto move_list_opt = world->get_neighborhood(agent_id, false, kami::GridNeighborhoodType::VonNeumann);
|
||||
if (!move_list_opt)
|
||||
return std::nullopt;
|
||||
auto move_list = move_list_opt.value();
|
||||
std::uniform_int_distribution<int> dist(0, (int) move_list->size() - 1);
|
||||
auto new_location = move_list->at(dist(*rng));
|
||||
auto new_location = *std::next(move_list->begin(), dist(*rng));
|
||||
|
||||
console->trace("Moving Agent {} to location {}", agent_id, new_location);
|
||||
world->move_agent(agent_id, new_location);
|
||||
@@ -113,13 +115,17 @@ std::optional<kami::AgentID> MoneyAgent2D::give_money(std::shared_ptr<kami::Mode
|
||||
auto population = std::static_pointer_cast<kami::Population>(agents.value());
|
||||
|
||||
auto location = world->get_location_by_agent(agent_id);
|
||||
auto cell_mates = world->get_location_contents(location.value());
|
||||
auto cell_mates_opt = world->get_location_contents(location.value());
|
||||
|
||||
if (!cell_mates_opt)
|
||||
return std::nullopt;
|
||||
|
||||
auto cell_mates = cell_mates_opt.value();
|
||||
if (cell_mates->size() < 2)
|
||||
return std::nullopt;
|
||||
|
||||
std::uniform_int_distribution<int> dist(0, (int) cell_mates->size() - 1);
|
||||
kami::AgentID other_agent_id = cell_mates->at(dist(*rng));
|
||||
auto other_agent_id = *std::next(cell_mates->begin(), dist(*rng));
|
||||
auto other_agent = std::static_pointer_cast<MoneyAgent2D>(population->get_agent_by_id(other_agent_id).value());
|
||||
|
||||
console->trace("Agent {} giving unit of wealth to agent {}", agent_id, other_agent_id);
|
||||
@@ -158,12 +164,6 @@ BoltzmannWealthModel2D::BoltzmannWealthModel2D(unsigned int number_agents, unsig
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<kami::Model> BoltzmannWealthModel2D::run(unsigned int steps) {
|
||||
for (auto i = 0; i < steps; i++)
|
||||
step();
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
std::shared_ptr<kami::Model> BoltzmannWealthModel2D::step() {
|
||||
console->trace("Executing model step {}", _step_count++);
|
||||
_sched->step(shared_from_this());
|
||||
@@ -176,8 +176,14 @@ int main(int argc, char **argv) {
|
||||
CLI::App app{ident};
|
||||
unsigned int x_size = 16, y_size = 16, agent_count = x_size * y_size, max_steps = 100, initial_seed = 42;
|
||||
|
||||
// This exercise is really stupid.
|
||||
auto levels_list = std::make_unique<std::list<std::string>>();
|
||||
for (auto &level_name: SPDLOG_LEVEL_NAMES)
|
||||
levels_list->push_back(std::string(level_name.data(), level_name.size()));
|
||||
|
||||
app.add_option("-c", agent_count, "Set the number of agents")->check(CLI::PositiveNumber);
|
||||
app.add_option("-l", log_level_option, "Set the logging level")->check(CLI::IsMember(SPDLOG_LEVEL_NAMES));
|
||||
app.add_option("-l", log_level_option, "Set the logging level")->check(
|
||||
CLI::IsMember(levels_list.get(), CLI::ignore_case));
|
||||
app.add_option("-n", max_steps, "Set the number of steps to run the model")->check(CLI::PositiveNumber);
|
||||
app.add_option("-s", initial_seed, "Set the initial seed")->check(CLI::Number);
|
||||
app.add_option("-x", x_size, "Set the number of columns")->check(CLI::PositiveNumber);
|
||||
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
/**
|
||||
* Move the agent to a random location on the world
|
||||
*/
|
||||
kami::GridCoord2D move_agent(std::shared_ptr<kami::Model> model);
|
||||
std::optional<kami::GridCoord2D> move_agent(std::shared_ptr<kami::Model> model);
|
||||
|
||||
/**
|
||||
* Give money to a random agent
|
||||
@@ -99,14 +99,7 @@ public:
|
||||
/**
|
||||
* Execute a single time-step for the model.
|
||||
*/
|
||||
std::shared_ptr<kami::Model> step() override;
|
||||
|
||||
/**
|
||||
* Execute a number of time-steps for the model.
|
||||
*
|
||||
* @param[in] n the number of steps to execute.
|
||||
*/
|
||||
std::shared_ptr<kami::Model> run(unsigned int n) override;
|
||||
std::shared_ptr<kami::Model> step();
|
||||
|
||||
private:
|
||||
unsigned int _step_count;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
# Set minimum version of CMake.
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
find_package(spdlog)
|
||||
|
||||
set(EXAMPLE_NAME "starter")
|
||||
|
||||
project(${EXAMPLE_NAME} LANGUAGES CXX)
|
||||
|
||||
@@ -25,13 +25,12 @@
|
||||
|
||||
#include "starter.h"
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <random>
|
||||
|
||||
#include <CLI/App.hpp>
|
||||
#include <CLI/Config.hpp>
|
||||
#include <CLI/Formatter.hpp>
|
||||
#include <CLI/CLI.hpp>
|
||||
|
||||
#include <spdlog/sinks/stdout_color_sinks.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
@@ -80,7 +79,7 @@ StarterModel::StarterModel(unsigned int number_agents, unsigned int new_seed) {
|
||||
|
||||
_step_count = 0;
|
||||
|
||||
for (unsigned int i = 0; i < number_agents; i++) {
|
||||
for (auto i = 0; i < number_agents; i++) {
|
||||
auto new_agent = std::make_shared<StarterAgent>();
|
||||
|
||||
console->trace("Initializing agent with AgentID {}", new_agent->get_agent_id());
|
||||
@@ -88,11 +87,6 @@ StarterModel::StarterModel(unsigned int number_agents, unsigned int new_seed) {
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<kami::Model> StarterModel::run(unsigned int steps) {
|
||||
for (auto i = 0; i < steps; i++) step();
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
std::shared_ptr<kami::Model> StarterModel::step() {
|
||||
console->trace("Executing model step {}", ++_step_count);
|
||||
_sched->step(shared_from_this());
|
||||
@@ -105,8 +99,14 @@ int main(int argc, char **argv) {
|
||||
CLI::App app{ident};
|
||||
unsigned int agent_count = 100, max_steps = 100, initial_seed = 8675309;
|
||||
|
||||
// This exercise is really stupid.
|
||||
auto levels_list = std::make_unique<std::list<std::string>>();
|
||||
for (auto &level_name: SPDLOG_LEVEL_NAMES)
|
||||
levels_list->push_back(std::string(level_name.data(), level_name.size()));
|
||||
|
||||
app.add_option("-c", agent_count, "Set the number of agents")->check(CLI::PositiveNumber);
|
||||
app.add_option("-l", log_level_option, "Set the logging level")->check(CLI::IsMember(SPDLOG_LEVEL_NAMES));
|
||||
app.add_option("-l", log_level_option, "Set the logging level")->check(
|
||||
CLI::IsMember(levels_list.get(), CLI::ignore_case));
|
||||
app.add_option("-n", max_steps, "Set the number of steps to run the model")->check(CLI::PositiveNumber);
|
||||
app.add_option("-s", initial_seed, "Set the initial seed")->check(CLI::Number);
|
||||
CLI11_PARSE(app, argc, argv);
|
||||
|
||||
@@ -82,14 +82,7 @@ public:
|
||||
/**
|
||||
* Execute a single time-step for the model.
|
||||
*/
|
||||
std::shared_ptr<kami::Model> step() override;
|
||||
|
||||
/**
|
||||
* Execute a number of time-steps for the model.
|
||||
*
|
||||
* @param[in] n the number of steps to execute.
|
||||
*/
|
||||
std::shared_ptr<kami::Model> run(unsigned int n) override;
|
||||
std::shared_ptr<kami::Model> step();
|
||||
};
|
||||
|
||||
#endif // STARTER_H
|
||||
|
||||
@@ -32,8 +32,9 @@
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <kami/domain.h>
|
||||
#include <kami/grid.h>
|
||||
@@ -171,12 +172,13 @@ namespace kami {
|
||||
*
|
||||
* @param[in] coord the coordinates of the query.
|
||||
*
|
||||
* @return a pointer to a `vector` of `AgentID`s. The pointer is to the
|
||||
* @return a pointer to a `set` of `AgentID`s. The pointer is to the
|
||||
* internal copy of the agent list at the location, therefore, any changes
|
||||
* to that object will update the state of the gird. Further, the pointer
|
||||
* should not be deleted when no longer used.
|
||||
*/
|
||||
[[nodiscard]] std::unique_ptr<std::vector<AgentID>> get_location_contents(const GridCoord1D &coord) const;
|
||||
[[nodiscard]] std::optional<std::shared_ptr<std::set<AgentID>>>
|
||||
get_location_contents(const GridCoord1D &coord) const;
|
||||
|
||||
/**
|
||||
* @brief Inquire to whether the grid wraps in the `x` dimension.
|
||||
@@ -192,10 +194,10 @@ namespace kami {
|
||||
* @param[in] include_center should the center-point, occupied by the agent,
|
||||
* be in the list.
|
||||
*
|
||||
* @return a vector of `GridCoord1D` that includes all of the coordinates
|
||||
* @return an `unordered_set` of `GridCoord1D` that includes all of the coordinates
|
||||
* for all adjacent points.
|
||||
*/
|
||||
[[nodiscard]] std::unique_ptr<std::vector<GridCoord1D>>
|
||||
[[nodiscard]] std::optional<std::shared_ptr<std::unordered_set<GridCoord1D>>>
|
||||
get_neighborhood(const AgentID agent_id, const bool include_center) const;
|
||||
|
||||
/**
|
||||
@@ -205,10 +207,10 @@ namespace kami {
|
||||
* @param[in] include_center should the center-point, occupied by the agent,
|
||||
* be in the list.
|
||||
*
|
||||
* @return a vector of `GridCoord1D` that includes all of the coordinates
|
||||
* @return an `unordered_set` of `GridCoord1D` that includes all of the coordinates
|
||||
* for all adjacent points.
|
||||
*/
|
||||
[[nodiscard]] std::unique_ptr<std::vector<GridCoord1D>>
|
||||
[[nodiscard]] std::optional<std::shared_ptr<std::unordered_set<GridCoord1D>>>
|
||||
get_neighborhood(const GridCoord1D &coord, const bool include_center) const;
|
||||
|
||||
/**
|
||||
@@ -220,7 +222,7 @@ namespace kami {
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief A vector containing the `AgentID`s of all agents assigned to this
|
||||
* @brief An `unordered_set` containing the `AgentID`s of all agents assigned to this
|
||||
* grid.
|
||||
*/
|
||||
std::unique_ptr<std::unordered_multimap<GridCoord1D, AgentID>> _agent_grid;
|
||||
|
||||
@@ -31,9 +31,10 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <kami/domain.h>
|
||||
#include <kami/grid.h>
|
||||
@@ -181,12 +182,13 @@ namespace kami {
|
||||
*
|
||||
* @param[in] coord the coordinates of the query.
|
||||
*
|
||||
* @return a pointer to a `vector` of `AgentID`s. The pointer is to the
|
||||
* @return a pointer to a `set` of `AgentID`s. The pointer is to the
|
||||
* internal copy of the agent list at the location, therefore, any changes
|
||||
* to that object will update the state of the gird. Further, the pointer
|
||||
* should not be deleted when no longer used.
|
||||
*/
|
||||
[[nodiscard]] std::unique_ptr<std::vector<AgentID>> get_location_contents(const GridCoord2D &coord) const;
|
||||
[[nodiscard]] std::optional<std::shared_ptr<std::set<AgentID>>>
|
||||
get_location_contents(const GridCoord2D &coord) const;
|
||||
|
||||
/**
|
||||
* @brief Inquire to whether the grid wraps in the `x` dimension.
|
||||
@@ -210,12 +212,12 @@ namespace kami {
|
||||
* @param[in] include_center should the center-point, occupied by the agent,
|
||||
* be in the list.
|
||||
*
|
||||
* @return a vector of `GridCoord1D` that includes all of the coordinates
|
||||
* @return a set of `GridCoord1D` that includes all of the coordinates
|
||||
* for all adjacent points.
|
||||
*
|
||||
* @see `NeighborhoodType`
|
||||
*/
|
||||
[[nodiscard]] std::unique_ptr<std::vector<GridCoord2D>>
|
||||
[[nodiscard]] std::optional<std::shared_ptr<std::unordered_set<GridCoord2D>>>
|
||||
get_neighborhood(AgentID agent_id, bool include_center, GridNeighborhoodType neighborhood_type) const;
|
||||
|
||||
/**
|
||||
@@ -226,12 +228,12 @@ namespace kami {
|
||||
* @param[in] include_center should the center-point, occupied by the agent,
|
||||
* be in the list.
|
||||
*
|
||||
* @return a vector of `GridCoord1D` that includes all of the coordinates
|
||||
* @return a set of `GridCoord2D` that includes all of the coordinates
|
||||
* for all adjacent points.
|
||||
*
|
||||
* @see `NeighborhoodType`
|
||||
*/
|
||||
[[nodiscard]] std::unique_ptr<std::vector<GridCoord2D>>
|
||||
[[nodiscard]] std::optional<std::shared_ptr<std::unordered_set<GridCoord2D>>>
|
||||
get_neighborhood(const GridCoord2D &coord, bool include_center, GridNeighborhoodType neighborhood_type) const;
|
||||
|
||||
/**
|
||||
@@ -250,7 +252,7 @@ namespace kami {
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief A vector containing the `AgentID`s of all agents assigned to this
|
||||
* @brief A map containing the `AgentID`s of all agents assigned to this
|
||||
* grid.
|
||||
*/
|
||||
std::unique_ptr<std::unordered_multimap<GridCoord2D, AgentID>> _agent_grid;
|
||||
|
||||
@@ -45,27 +45,6 @@ namespace kami {
|
||||
class LIBKAMI_EXPORT Model : public std::enable_shared_from_this<Model> {
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Execute a fixed number of time-steps for the model.
|
||||
*
|
||||
* @details This function should execute a fixed number of time-steps for the model.
|
||||
*
|
||||
* @param[in] n the number of time steps to execute.
|
||||
*
|
||||
* @returns a shared pointer to this instance of `Model`
|
||||
*/
|
||||
virtual std::shared_ptr<Model> run(unsigned int n) = 0;
|
||||
|
||||
/**
|
||||
* @brief Execute a single time-step for the model.
|
||||
*
|
||||
* @details This function should step the model instance. Any activities that the
|
||||
* model should perform as part of its time step should be in this function.
|
||||
*
|
||||
* @returns a shared pointer to this instance of `Model`
|
||||
*/
|
||||
virtual std::shared_ptr<Model> step() = 0;
|
||||
|
||||
/**
|
||||
* @brief Get the `Domain` associated with this model
|
||||
*
|
||||
|
||||
@@ -88,9 +88,9 @@ namespace kami {
|
||||
* @param rng [in] A uniform random number generator of type `std::mt19937`,
|
||||
* used as the source of randomness.
|
||||
*
|
||||
* @returns a shared pointer to this instance of `RandomScheduler`
|
||||
* @returns a shared pointer to the random number generator
|
||||
*/
|
||||
std::shared_ptr<RandomScheduler> set_rng(std::shared_ptr<std::ranlux24> rng);
|
||||
std::shared_ptr<std::ranlux24> set_rng(std::shared_ptr<std::ranlux24> rng);
|
||||
|
||||
/**
|
||||
* @brief Get the RNG
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace kami {
|
||||
*
|
||||
* @returns returns vector of agents successfully stepped
|
||||
*/
|
||||
std::optional<std::shared_ptr<std::vector<AgentID>>> step(std::shared_ptr<Model> model) override;
|
||||
std::optional<std::shared_ptr<std::vector<AgentID>>> step(std::shared_ptr<Model> model) override;
|
||||
|
||||
/**
|
||||
* @brief Execute a single time step.
|
||||
|
||||
@@ -30,9 +30,10 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace kami {
|
||||
|
||||
@@ -109,51 +110,54 @@ namespace kami {
|
||||
return add_agent(agent_id, coord);
|
||||
}
|
||||
|
||||
std::unique_ptr<std::vector<GridCoord1D>>
|
||||
std::optional<std::shared_ptr<std::unordered_set<GridCoord1D>>>
|
||||
Grid1D::get_neighborhood(const AgentID agent_id, const bool include_center) const {
|
||||
auto coord = get_location_by_agent(agent_id);
|
||||
if (!coord)
|
||||
return std::nullopt;
|
||||
|
||||
return std::move(get_neighborhood(coord.value(), include_center));
|
||||
}
|
||||
|
||||
std::unique_ptr<std::vector<GridCoord1D>>
|
||||
std::optional<std::shared_ptr<std::unordered_set<GridCoord1D>>>
|
||||
Grid1D::get_neighborhood(const GridCoord1D &coord, const bool include_center) const {
|
||||
auto neighborhood = std::make_unique<std::vector<GridCoord1D>>();
|
||||
auto neighborhood = std::make_shared<std::unordered_set<GridCoord1D>>();
|
||||
auto x = coord.get_x_location();
|
||||
|
||||
// We assume our starting position is valid
|
||||
if (include_center)
|
||||
neighborhood->push_back(coord);
|
||||
neighborhood->insert(coord);
|
||||
|
||||
// E, W
|
||||
{
|
||||
auto new_location = coord_wrap(GridCoord1D(x + 1));
|
||||
if (is_location_valid(new_location))
|
||||
neighborhood->push_back(coord_wrap(new_location));
|
||||
neighborhood->insert(coord_wrap(new_location));
|
||||
}
|
||||
{
|
||||
auto new_location = coord_wrap(GridCoord1D(x - 1));
|
||||
if (is_location_valid(new_location))
|
||||
neighborhood->push_back(coord_wrap(new_location));
|
||||
neighborhood->insert(coord_wrap(new_location));
|
||||
}
|
||||
|
||||
return std::move(neighborhood);
|
||||
}
|
||||
|
||||
std::unique_ptr<std::vector<AgentID>> Grid1D::get_location_contents(const GridCoord1D &coord) const {
|
||||
auto agent_ids = std::make_unique<std::vector<AgentID>>();
|
||||
std::optional<std::shared_ptr<std::set<AgentID>>> Grid1D::get_location_contents(const GridCoord1D &coord) const {
|
||||
auto agent_ids = std::make_shared<std::set<AgentID>>();
|
||||
|
||||
if (!is_location_valid(coord))
|
||||
return std::move(agent_ids);
|
||||
return std::nullopt;
|
||||
if (is_location_empty(coord))
|
||||
return std::move(agent_ids);
|
||||
return agent_ids;
|
||||
|
||||
auto agent_range = _agent_grid->equal_range(coord);
|
||||
if (agent_range.first == agent_range.second)
|
||||
return std::move(agent_ids);
|
||||
return agent_ids;
|
||||
|
||||
for (auto i = agent_range.first; i != agent_range.second; i++)
|
||||
agent_ids->push_back(i->second);
|
||||
return std::move(agent_ids);
|
||||
agent_ids->insert(i->second);
|
||||
return agent_ids;
|
||||
}
|
||||
|
||||
bool Grid1D::get_wrap_x() const { return _wrap_x; }
|
||||
|
||||
@@ -118,45 +118,47 @@ namespace kami {
|
||||
return add_agent(agent_id, coord);
|
||||
}
|
||||
|
||||
std::unique_ptr<std::vector<GridCoord2D>>
|
||||
std::optional<std::shared_ptr<std::unordered_set<GridCoord2D>>>
|
||||
Grid2D::get_neighborhood(const AgentID agent_id, const bool include_center,
|
||||
const GridNeighborhoodType neighborhood_type) const {
|
||||
auto coord = get_location_by_agent(agent_id);
|
||||
if (!coord)
|
||||
return std::nullopt;
|
||||
|
||||
return std::move(get_neighborhood(coord.value(), include_center, neighborhood_type));
|
||||
}
|
||||
|
||||
std::unique_ptr<std::vector<GridCoord2D>>
|
||||
std::optional<std::shared_ptr<std::unordered_set<GridCoord2D>>>
|
||||
Grid2D::get_neighborhood(const GridCoord2D &coord, const bool include_center,
|
||||
const GridNeighborhoodType neighborhood_type) const {
|
||||
auto neighborhood = std::make_unique<std::vector<GridCoord2D>>();
|
||||
auto neighborhood = std::make_unique<std::unordered_set<GridCoord2D>>();
|
||||
auto x = coord.get_x_location();
|
||||
auto y = coord.get_y_location();
|
||||
|
||||
// We assume our starting position is valid
|
||||
if (include_center)
|
||||
neighborhood->push_back(coord);
|
||||
neighborhood->insert(coord);
|
||||
|
||||
// N, E, S, W
|
||||
{
|
||||
auto new_location = coord_wrap(GridCoord2D(x, y - 1));
|
||||
if (is_location_valid(new_location))
|
||||
neighborhood->push_back(coord_wrap(new_location));
|
||||
neighborhood->insert(coord_wrap(new_location));
|
||||
}
|
||||
{
|
||||
auto new_location = coord_wrap(GridCoord2D(x, y + 1));
|
||||
if (is_location_valid(new_location))
|
||||
neighborhood->push_back(coord_wrap(new_location));
|
||||
neighborhood->insert(coord_wrap(new_location));
|
||||
}
|
||||
{
|
||||
auto new_location = coord_wrap(GridCoord2D(x + 1, y));
|
||||
if (is_location_valid(new_location))
|
||||
neighborhood->push_back(coord_wrap(new_location));
|
||||
neighborhood->insert(coord_wrap(new_location));
|
||||
}
|
||||
{
|
||||
auto new_location = coord_wrap(GridCoord2D(x - 1, y));
|
||||
if (is_location_valid(new_location))
|
||||
neighborhood->push_back(coord_wrap(new_location));
|
||||
neighborhood->insert(coord_wrap(new_location));
|
||||
}
|
||||
|
||||
if (neighborhood_type == GridNeighborhoodType::Moore) {
|
||||
@@ -164,42 +166,43 @@ namespace kami {
|
||||
{
|
||||
auto new_location = coord_wrap(GridCoord2D(x + 1, y - 1));
|
||||
if (is_location_valid(new_location))
|
||||
neighborhood->push_back(coord_wrap(new_location));
|
||||
neighborhood->insert(coord_wrap(new_location));
|
||||
}
|
||||
{
|
||||
auto new_location = coord_wrap(GridCoord2D(x + 1, y + 1));
|
||||
if (is_location_valid(new_location))
|
||||
neighborhood->push_back(coord_wrap(new_location));
|
||||
neighborhood->insert(coord_wrap(new_location));
|
||||
}
|
||||
{
|
||||
auto new_location = coord_wrap(GridCoord2D(x - 1, y + 1));
|
||||
if (is_location_valid(new_location))
|
||||
neighborhood->push_back(coord_wrap(new_location));
|
||||
neighborhood->insert(coord_wrap(new_location));
|
||||
}
|
||||
{
|
||||
auto new_location = coord_wrap(GridCoord2D(x - 1, y - 1));
|
||||
if (is_location_valid(new_location))
|
||||
neighborhood->push_back(coord_wrap(new_location));
|
||||
neighborhood->insert(coord_wrap(new_location));
|
||||
}
|
||||
}
|
||||
|
||||
return std::move(neighborhood);
|
||||
}
|
||||
|
||||
std::unique_ptr<std::vector<AgentID>> Grid2D::get_location_contents(const GridCoord2D &coord) const {
|
||||
auto agent_ids = std::make_unique<std::vector<AgentID>>();
|
||||
std::optional<std::shared_ptr<std::set<AgentID>>> Grid2D::get_location_contents(const GridCoord2D &coord) const {
|
||||
auto agent_ids = std::make_shared<std::set<AgentID>>();
|
||||
|
||||
if (!is_location_valid(coord))
|
||||
return std::move(agent_ids);
|
||||
return std::nullopt;
|
||||
if (is_location_empty(coord))
|
||||
return std::move(agent_ids);
|
||||
return agent_ids;
|
||||
|
||||
auto agent_range = _agent_grid->equal_range(coord);
|
||||
if (agent_range.first == agent_range.second)
|
||||
return std::move(agent_ids);
|
||||
return agent_ids;
|
||||
|
||||
for (auto i = agent_range.first; i != agent_range.second; i++)
|
||||
agent_ids->push_back(i->second);
|
||||
return std::move(agent_ids);
|
||||
agent_ids->insert(i->second);
|
||||
return agent_ids;
|
||||
}
|
||||
|
||||
bool Grid2D::get_wrap_x() const { return _wrap_x; }
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <random>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <kami/model.h>
|
||||
@@ -40,13 +41,16 @@ namespace kami {
|
||||
}
|
||||
|
||||
std::optional<std::shared_ptr<std::vector<AgentID>>> RandomScheduler::step(std::shared_ptr<Model> model, std::shared_ptr<std::vector<AgentID>> agent_list) {
|
||||
shuffle(agent_list->begin(),agent_list->end(), *_rng);
|
||||
if (_rng == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
shuffle(agent_list->begin(), agent_list->end(), *_rng);
|
||||
return std::move(this->SequentialScheduler::step(model, agent_list));
|
||||
}
|
||||
|
||||
std::shared_ptr<RandomScheduler> RandomScheduler::set_rng(std::shared_ptr<std::ranlux24> rng) {
|
||||
std::shared_ptr<std::ranlux24> RandomScheduler::set_rng(std::shared_ptr<std::ranlux24> rng) {
|
||||
this->_rng = std::move(rng);
|
||||
return shared_from_this();
|
||||
return _rng;
|
||||
}
|
||||
|
||||
std::shared_ptr<std::ranlux24> RandomScheduler::get_rng() { return (this->_rng); }
|
||||
|
||||
@@ -5,42 +5,14 @@
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
create_test(
|
||||
NAME unit-kami-agent
|
||||
SOURCES unit-kami-agent.cc
|
||||
PUBLIC_LINKED_TARGETS gmock gtest kami::libkami Threads::Threads
|
||||
COMMAND unit-kami-agent
|
||||
PUBLIC_COMPILE_FEATURES ${COVERAGE_FLAGS}
|
||||
)
|
||||
|
||||
create_test(
|
||||
NAME unit-kami-agentid
|
||||
SOURCES unit-kami-agentid.cc
|
||||
PUBLIC_LINKED_TARGETS gmock gtest kami::libkami Threads::Threads
|
||||
COMMAND unit-kami-agentid
|
||||
PUBLIC_COMPILE_FEATURES ${COVERAGE_FLAGS}
|
||||
)
|
||||
|
||||
create_test(
|
||||
NAME unit-kami-model
|
||||
SOURCES unit-kami-model.cc
|
||||
PUBLIC_LINKED_TARGETS gmock gtest kami::libkami Threads::Threads
|
||||
COMMAND unit-kami-model
|
||||
PUBLIC_COMPILE_FEATURES ${COVERAGE_FLAGS}
|
||||
)
|
||||
|
||||
create_test(
|
||||
NAME unit-kami-multigrid1d
|
||||
SOURCES unit-kami-multigrid1d.cc
|
||||
PUBLIC_LINKED_TARGETS gmock gtest kami::libkami Threads::Threads
|
||||
COMMAND unit-kami-multigrid1d
|
||||
PUBLIC_COMPILE_FEATURES ${COVERAGE_FLAGS}
|
||||
)
|
||||
|
||||
create_test(
|
||||
NAME unit-kami-stagedagent
|
||||
SOURCES unit-kami-stagedagent.cc
|
||||
PUBLIC_LINKED_TARGETS gmock gtest kami::libkami Threads::Threads
|
||||
COMMAND unit-kami-stagedagent
|
||||
PUBLIC_COMPILE_FEATURES ${COVERAGE_FLAGS}
|
||||
)
|
||||
file(GLOB test_modules "${CMAKE_CURRENT_SOURCE_DIR}/*.cc")
|
||||
FOREACH (test_module ${test_modules})
|
||||
cmake_path(GET test_module STEM test_src)
|
||||
create_test(
|
||||
NAME ${test_src}
|
||||
SOURCES ${test_src}.cc
|
||||
PUBLIC_LINKED_TARGETS gmock gtest kami::libkami Threads::Threads
|
||||
COMMAND ${test_src}
|
||||
PUBLIC_COMPILE_FEATURES ${COVERAGE_FLAGS}
|
||||
)
|
||||
ENDFOREACH ()
|
||||
|
||||
@@ -30,22 +30,17 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
class TestAgent : public kami::Agent {
|
||||
using namespace kami;
|
||||
using namespace std;
|
||||
|
||||
class TestAgent : public Agent {
|
||||
public:
|
||||
kami::AgentID step(std::shared_ptr<kami::Model> model) override {
|
||||
AgentID step(shared_ptr<Model> model) override {
|
||||
return get_agent_id();
|
||||
}
|
||||
};
|
||||
|
||||
class TestModel : public kami::Model {
|
||||
public:
|
||||
std::shared_ptr<kami::Model> step() override {
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
std::shared_ptr<kami::Model> run(unsigned int) override {
|
||||
return shared_from_this();
|
||||
}
|
||||
class TestModel : public Model {
|
||||
};
|
||||
|
||||
TEST(Agent, DefaultConstructor) {
|
||||
@@ -67,7 +62,7 @@ TEST(Agent, get_agent_id) {
|
||||
TEST(Agent, step) {
|
||||
TestAgent agent_foo;
|
||||
TestAgent agent_bar;
|
||||
auto model_world = std::make_shared<TestModel>();
|
||||
auto model_world = make_shared<TestModel>();
|
||||
|
||||
EXPECT_EQ(agent_foo.get_agent_id(), agent_foo.step(model_world));
|
||||
EXPECT_NE(agent_bar.get_agent_id(), agent_foo.step(model_world));
|
||||
|
||||
@@ -28,25 +28,27 @@
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace kami;
|
||||
|
||||
TEST(AgentID, DefaultConstructor) {
|
||||
const kami::AgentID agent_id_foo;
|
||||
const kami::AgentID agent_id_bar;
|
||||
const AgentID agent_id_foo;
|
||||
const AgentID agent_id_bar;
|
||||
|
||||
EXPECT_EQ(agent_id_foo, agent_id_foo);
|
||||
EXPECT_NE(agent_id_foo, agent_id_bar);
|
||||
}
|
||||
|
||||
TEST(AgentID, to_string) {
|
||||
const kami::AgentID agent_id_foo;
|
||||
const kami::AgentID agent_id_bar;
|
||||
const AgentID agent_id_foo;
|
||||
const AgentID agent_id_bar;
|
||||
|
||||
EXPECT_THAT(agent_id_foo.to_string(), testing::MatchesRegex("[0-9]+"));
|
||||
EXPECT_THAT(agent_id_bar.to_string(), testing::MatchesRegex("[0-9]+"));
|
||||
}
|
||||
|
||||
TEST(AgentID, Equality) {
|
||||
const kami::AgentID agent_id_foo;
|
||||
const kami::AgentID agent_id_bar;
|
||||
const AgentID agent_id_foo;
|
||||
const AgentID agent_id_bar;
|
||||
|
||||
EXPECT_TRUE(agent_id_foo == agent_id_foo);
|
||||
EXPECT_TRUE(agent_id_bar == agent_id_bar);
|
||||
@@ -54,16 +56,16 @@ TEST(AgentID, Equality) {
|
||||
}
|
||||
|
||||
TEST(AgentID, Inequality) {
|
||||
const kami::AgentID agent_id_foo;
|
||||
const kami::AgentID agent_id_bar;
|
||||
const AgentID agent_id_foo;
|
||||
const AgentID agent_id_bar;
|
||||
|
||||
EXPECT_TRUE(agent_id_foo != agent_id_bar);
|
||||
EXPECT_FALSE(agent_id_bar != agent_id_bar);
|
||||
}
|
||||
|
||||
TEST(AgentID, Ordering) {
|
||||
const kami::AgentID agent_id_foo;
|
||||
const kami::AgentID agent_id_bar;
|
||||
const AgentID agent_id_foo;
|
||||
const AgentID agent_id_bar;
|
||||
|
||||
EXPECT_TRUE(agent_id_foo < agent_id_bar);
|
||||
EXPECT_FALSE(agent_id_bar < agent_id_foo);
|
||||
|
||||
107
test/unit-kami-gridcoord1d.cc
Normal file
107
test/unit-kami-gridcoord1d.cc
Normal file
@@ -0,0 +1,107 @@
|
||||
/*-
|
||||
* Copyright (c) 2022 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <kami/grid1d.h>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace kami;
|
||||
|
||||
TEST(GridCoord1D, DefaultConstructor) {
|
||||
const GridCoord1D gridcoord1d_foo(0);
|
||||
const GridCoord1D gridcoord1d_bar(1);
|
||||
const GridCoord1D gridcoord1d_baz(-1);
|
||||
const GridCoord1D gridcoord1d_qux(0);
|
||||
|
||||
EXPECT_EQ(gridcoord1d_foo, gridcoord1d_foo);
|
||||
EXPECT_EQ(gridcoord1d_foo, gridcoord1d_qux);
|
||||
|
||||
EXPECT_NE(gridcoord1d_foo, gridcoord1d_bar);
|
||||
EXPECT_NE(gridcoord1d_foo, gridcoord1d_baz);
|
||||
EXPECT_NE(gridcoord1d_bar, gridcoord1d_baz);
|
||||
}
|
||||
|
||||
TEST(GridCoord1D, to_string) {
|
||||
const GridCoord1D gridcoord1d_foo(0);
|
||||
const GridCoord1D gridcoord1d_bar(1);
|
||||
const GridCoord1D gridcoord1d_baz(-1);
|
||||
|
||||
EXPECT_THAT(gridcoord1d_foo.to_string(), "(0)");
|
||||
EXPECT_THAT(gridcoord1d_bar.to_string(), "(1)");
|
||||
EXPECT_THAT(gridcoord1d_baz.to_string(), "(-1)");
|
||||
}
|
||||
|
||||
TEST(GridCoord1D, Equality) {
|
||||
const GridCoord1D gridcoord1d_foo(0);
|
||||
const GridCoord1D gridcoord1d_bar(1);
|
||||
const GridCoord1D gridcoord1d_baz(-1);
|
||||
const GridCoord1D gridcoord1d_qux(0);
|
||||
|
||||
EXPECT_TRUE(gridcoord1d_foo == gridcoord1d_foo);
|
||||
EXPECT_TRUE(gridcoord1d_foo == gridcoord1d_qux);
|
||||
|
||||
EXPECT_FALSE(gridcoord1d_foo == gridcoord1d_bar);
|
||||
EXPECT_FALSE(gridcoord1d_foo == gridcoord1d_baz);
|
||||
EXPECT_FALSE(gridcoord1d_bar == gridcoord1d_baz);
|
||||
}
|
||||
|
||||
TEST(GridCoord1D, Inequality) {
|
||||
const GridCoord1D gridcoord1d_foo(0);
|
||||
const GridCoord1D gridcoord1d_bar(1);
|
||||
const GridCoord1D gridcoord1d_baz(-1);
|
||||
const GridCoord1D gridcoord1d_qux(0);
|
||||
|
||||
EXPECT_FALSE(gridcoord1d_foo != gridcoord1d_foo);
|
||||
EXPECT_FALSE(gridcoord1d_foo != gridcoord1d_qux);
|
||||
|
||||
EXPECT_TRUE(gridcoord1d_foo != gridcoord1d_bar);
|
||||
EXPECT_TRUE(gridcoord1d_foo != gridcoord1d_baz);
|
||||
EXPECT_TRUE(gridcoord1d_bar != gridcoord1d_baz);
|
||||
}
|
||||
|
||||
TEST(GridCoord1D, get_x_location) {
|
||||
const GridCoord1D gridcoord1d_foo(0);
|
||||
const GridCoord1D gridcoord1d_bar(1);
|
||||
const GridCoord1D gridcoord1d_baz(-1);
|
||||
const GridCoord1D gridcoord1d_qux(0);
|
||||
|
||||
EXPECT_TRUE(gridcoord1d_foo.get_x_location() == 0);
|
||||
EXPECT_TRUE(gridcoord1d_bar.get_x_location() == 1);
|
||||
EXPECT_TRUE(gridcoord1d_baz.get_x_location() == -1);
|
||||
|
||||
EXPECT_TRUE(gridcoord1d_foo.get_x_location() == gridcoord1d_foo.get_x_location());
|
||||
EXPECT_TRUE(gridcoord1d_foo.get_x_location() == gridcoord1d_qux.get_x_location());
|
||||
|
||||
EXPECT_FALSE(gridcoord1d_foo.get_x_location() == gridcoord1d_bar.get_x_location());
|
||||
EXPECT_FALSE(gridcoord1d_foo.get_x_location() == gridcoord1d_baz.get_x_location());
|
||||
EXPECT_FALSE(gridcoord1d_bar.get_x_location() == gridcoord1d_baz.get_x_location());
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
149
test/unit-kami-gridcoord2d.cc
Normal file
149
test/unit-kami-gridcoord2d.cc
Normal file
@@ -0,0 +1,149 @@
|
||||
/*-
|
||||
* Copyright (c) 2022 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <kami/grid2d.h>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace kami;
|
||||
|
||||
TEST(GridCoord2D, DefaultConstructor) {
|
||||
const GridCoord2D gridcoord2d_foo(0, 0);
|
||||
const GridCoord2D gridcoord2d_bar(1, 1);
|
||||
const GridCoord2D gridcoord2d_baz(-1, -1);
|
||||
const GridCoord2D gridcoord2d_qux(0, 1);
|
||||
const GridCoord2D gridcoord2d_qu2(1, 0);
|
||||
|
||||
EXPECT_EQ(gridcoord2d_foo, gridcoord2d_foo);
|
||||
|
||||
EXPECT_NE(gridcoord2d_foo, gridcoord2d_bar);
|
||||
EXPECT_NE(gridcoord2d_foo, gridcoord2d_baz);
|
||||
EXPECT_NE(gridcoord2d_bar, gridcoord2d_baz);
|
||||
EXPECT_NE(gridcoord2d_foo, gridcoord2d_qux);
|
||||
EXPECT_NE(gridcoord2d_foo, gridcoord2d_qu2);
|
||||
|
||||
}
|
||||
|
||||
TEST(GridCoord2D, to_string) {
|
||||
const GridCoord2D gridcoord2d_foo(0, 0);
|
||||
const GridCoord2D gridcoord2d_bar(1, 1);
|
||||
const GridCoord2D gridcoord2d_baz(-1, -1);
|
||||
const GridCoord2D gridcoord2d_qux(0, 1);
|
||||
const GridCoord2D gridcoord2d_qu2(1, 0);
|
||||
|
||||
EXPECT_THAT(gridcoord2d_foo.to_string(), "(0, 0)");
|
||||
EXPECT_THAT(gridcoord2d_bar.to_string(), "(1, 1)");
|
||||
EXPECT_THAT(gridcoord2d_baz.to_string(), "(-1, -1)");
|
||||
EXPECT_THAT(gridcoord2d_qux.to_string(), "(0, 1)");
|
||||
EXPECT_THAT(gridcoord2d_qu2.to_string(), "(1, 0)");
|
||||
}
|
||||
|
||||
TEST(GridCoord2D, Equality) {
|
||||
const GridCoord2D gridcoord2d_foo(0, 0);
|
||||
const GridCoord2D gridcoord2d_bar(1, 1);
|
||||
const GridCoord2D gridcoord2d_baz(-1, -1);
|
||||
const GridCoord2D gridcoord2d_qux(0, 1);
|
||||
const GridCoord2D gridcoord2d_qu2(1, 0);
|
||||
|
||||
EXPECT_TRUE(gridcoord2d_foo == gridcoord2d_foo);
|
||||
|
||||
EXPECT_FALSE(gridcoord2d_foo == gridcoord2d_bar);
|
||||
EXPECT_FALSE(gridcoord2d_foo == gridcoord2d_baz);
|
||||
EXPECT_FALSE(gridcoord2d_bar == gridcoord2d_baz);
|
||||
EXPECT_FALSE(gridcoord2d_foo == gridcoord2d_qux);
|
||||
EXPECT_FALSE(gridcoord2d_qux == gridcoord2d_qu2);
|
||||
EXPECT_FALSE(gridcoord2d_qux == gridcoord2d_qu2);
|
||||
}
|
||||
|
||||
TEST(GridCoord2D, Inequality) {
|
||||
const GridCoord2D gridcoord2d_foo(0, 0);
|
||||
const GridCoord2D gridcoord2d_bar(1, 1);
|
||||
const GridCoord2D gridcoord2d_baz(-1, -1);
|
||||
const GridCoord2D gridcoord2d_qux(0, 1);
|
||||
const GridCoord2D gridcoord2d_qu2(1, 0);
|
||||
|
||||
EXPECT_FALSE(gridcoord2d_foo != gridcoord2d_foo);
|
||||
|
||||
EXPECT_TRUE(gridcoord2d_foo != gridcoord2d_qux);
|
||||
EXPECT_TRUE(gridcoord2d_foo != gridcoord2d_bar);
|
||||
EXPECT_TRUE(gridcoord2d_foo != gridcoord2d_baz);
|
||||
EXPECT_TRUE(gridcoord2d_bar != gridcoord2d_baz);
|
||||
EXPECT_TRUE(gridcoord2d_qux != gridcoord2d_qu2);
|
||||
}
|
||||
|
||||
TEST(GridCoord2D, get_x_location) {
|
||||
const GridCoord2D gridcoord2d_foo(0, 0);
|
||||
const GridCoord2D gridcoord2d_bar(1, 1);
|
||||
const GridCoord2D gridcoord2d_baz(-1, -1);
|
||||
const GridCoord2D gridcoord2d_qux(0, 1);
|
||||
const GridCoord2D gridcoord2d_qu2(1, 0);
|
||||
|
||||
EXPECT_TRUE(gridcoord2d_foo.get_x_location() == 0);
|
||||
EXPECT_TRUE(gridcoord2d_bar.get_x_location() == 1);
|
||||
EXPECT_TRUE(gridcoord2d_baz.get_x_location() == -1);
|
||||
EXPECT_FALSE(gridcoord2d_qux.get_x_location() == -1);
|
||||
EXPECT_FALSE(gridcoord2d_qu2.get_x_location() == -1);
|
||||
|
||||
EXPECT_TRUE(gridcoord2d_foo.get_x_location() == gridcoord2d_foo.get_x_location());
|
||||
EXPECT_TRUE(gridcoord2d_foo.get_x_location() == gridcoord2d_qux.get_x_location());
|
||||
EXPECT_TRUE(gridcoord2d_bar.get_x_location() == gridcoord2d_qu2.get_x_location());
|
||||
|
||||
EXPECT_FALSE(gridcoord2d_foo.get_x_location() == gridcoord2d_bar.get_x_location());
|
||||
EXPECT_FALSE(gridcoord2d_foo.get_x_location() == gridcoord2d_baz.get_x_location());
|
||||
EXPECT_FALSE(gridcoord2d_bar.get_x_location() == gridcoord2d_baz.get_x_location());
|
||||
EXPECT_FALSE(gridcoord2d_foo.get_x_location() == gridcoord2d_baz.get_x_location());
|
||||
EXPECT_FALSE(gridcoord2d_qux.get_x_location() == gridcoord2d_qu2.get_x_location());
|
||||
}
|
||||
|
||||
TEST(GridCoord2D, get_y_location) {
|
||||
const GridCoord2D gridcoord2d_foo(0, 0);
|
||||
const GridCoord2D gridcoord2d_bar(1, 1);
|
||||
const GridCoord2D gridcoord2d_baz(-1, -1);
|
||||
const GridCoord2D gridcoord2d_qux(0, 1);
|
||||
const GridCoord2D gridcoord2d_qu2(1, 0);
|
||||
|
||||
EXPECT_TRUE(gridcoord2d_foo.get_y_location() == 0);
|
||||
EXPECT_TRUE(gridcoord2d_bar.get_y_location() == 1);
|
||||
EXPECT_TRUE(gridcoord2d_baz.get_y_location() == -1);
|
||||
EXPECT_FALSE(gridcoord2d_qux.get_y_location() == -1);
|
||||
EXPECT_FALSE(gridcoord2d_qu2.get_y_location() == -1);
|
||||
|
||||
EXPECT_TRUE(gridcoord2d_foo.get_y_location() == gridcoord2d_foo.get_y_location());
|
||||
EXPECT_TRUE(gridcoord2d_bar.get_y_location() == gridcoord2d_qux.get_y_location());
|
||||
|
||||
EXPECT_FALSE(gridcoord2d_foo.get_y_location() == gridcoord2d_bar.get_y_location());
|
||||
EXPECT_FALSE(gridcoord2d_foo.get_y_location() == gridcoord2d_baz.get_y_location());
|
||||
EXPECT_FALSE(gridcoord2d_bar.get_y_location() == gridcoord2d_baz.get_y_location());
|
||||
EXPECT_FALSE(gridcoord2d_foo.get_y_location() == gridcoord2d_baz.get_y_location());
|
||||
EXPECT_FALSE(gridcoord2d_qux.get_y_location() == gridcoord2d_qu2.get_y_location());
|
||||
EXPECT_FALSE(gridcoord2d_bar.get_y_location() == gridcoord2d_qu2.get_y_location());
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
@@ -33,20 +33,19 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
class TestAgent : public kami::Agent {
|
||||
using namespace kami;
|
||||
using namespace std;
|
||||
|
||||
class TestAgent : public Agent {
|
||||
public:
|
||||
kami::AgentID step(std::shared_ptr<kami::Model> model) override {
|
||||
AgentID step(shared_ptr<Model> model) override {
|
||||
return get_agent_id();
|
||||
}
|
||||
};
|
||||
|
||||
class TestModel : public kami::Model {
|
||||
class TestModel : public Model {
|
||||
public:
|
||||
std::shared_ptr<kami::Model> step() override {
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
std::shared_ptr<kami::Model> run(unsigned int) override {
|
||||
shared_ptr<Model> step() {
|
||||
return shared_from_this();
|
||||
}
|
||||
};
|
||||
@@ -61,16 +60,16 @@ TEST(Model, DefaultConstructor) {
|
||||
}
|
||||
|
||||
TEST(Model, set_population) {
|
||||
auto model_foo = std::make_shared<TestModel>();
|
||||
auto popul_foo = std::make_shared<kami::Population>();
|
||||
auto model_foo = make_shared<TestModel>();
|
||||
auto popul_foo = make_shared<Population>();
|
||||
|
||||
auto popul_bar = model_foo->set_population(popul_foo);
|
||||
EXPECT_EQ(popul_foo, popul_bar);
|
||||
}
|
||||
|
||||
TEST(Model, get_population) {
|
||||
auto model_foo = std::make_shared<TestModel>();
|
||||
auto popul_foo = std::make_shared<kami::Population>();
|
||||
auto model_foo = make_shared<TestModel>();
|
||||
auto popul_foo = make_shared<Population>();
|
||||
|
||||
auto popul_nul = model_foo->get_population();
|
||||
|
||||
@@ -83,16 +82,16 @@ TEST(Model, get_population) {
|
||||
}
|
||||
|
||||
TEST(Model, set_scheduler) {
|
||||
auto model_foo = std::make_shared<TestModel>();
|
||||
auto sched_foo = std::make_shared<kami::SequentialScheduler>();
|
||||
auto model_foo = make_shared<TestModel>();
|
||||
auto sched_foo = make_shared<SequentialScheduler>();
|
||||
|
||||
auto sched_bar = model_foo->set_scheduler(sched_foo);
|
||||
EXPECT_EQ(sched_foo, sched_bar);
|
||||
}
|
||||
|
||||
TEST(Model, get_scheduler) {
|
||||
auto model_foo = std::make_shared<TestModel>();
|
||||
auto sched_foo = std::make_shared<kami::SequentialScheduler>();
|
||||
auto model_foo = make_shared<TestModel>();
|
||||
auto sched_foo = make_shared<SequentialScheduler>();
|
||||
|
||||
auto sched_nul = model_foo->get_scheduler();
|
||||
EXPECT_FALSE(sched_nul);
|
||||
@@ -106,16 +105,16 @@ TEST(Model, get_scheduler) {
|
||||
}
|
||||
|
||||
TEST(Model, set_domain) {
|
||||
auto model_foo = std::make_shared<TestModel>();
|
||||
auto grid2_foo = std::make_shared<kami::MultiGrid2D>(10, 10, true, true);
|
||||
auto model_foo = make_shared<TestModel>();
|
||||
auto grid2_foo = make_shared<MultiGrid2D>(10, 10, true, true);
|
||||
|
||||
auto grid2_bar = model_foo->set_domain(grid2_foo);
|
||||
EXPECT_EQ(grid2_foo, grid2_bar);
|
||||
}
|
||||
|
||||
TEST(Model, get_domain) {
|
||||
auto model_foo = std::make_shared<TestModel>();
|
||||
auto grid2_foo = std::make_shared<kami::MultiGrid2D>(10, 10, true, true);
|
||||
auto model_foo = make_shared<TestModel>();
|
||||
auto grid2_foo = make_shared<MultiGrid2D>(10, 10, true, true);
|
||||
|
||||
auto grid2_nul = model_foo->get_domain();
|
||||
EXPECT_FALSE(grid2_nul);
|
||||
|
||||
@@ -23,25 +23,33 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/multigrid1d.h>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace kami;
|
||||
using namespace std;
|
||||
|
||||
TEST(MultiGrid1D, DefaultConstructor) {
|
||||
// There is really no way this can go wrong, but
|
||||
// we add this check anyway in case of future
|
||||
// changes.
|
||||
EXPECT_NO_THROW(
|
||||
kami::MultiGrid1D multigrid1d_foo(10, true);
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
);
|
||||
}
|
||||
|
||||
TEST(MultiGrid1D, add_agent) {
|
||||
kami::MultiGrid1D multigrid1d_foo(10, true);
|
||||
const kami::AgentID agent_id_foo, agent_id_bar;
|
||||
const kami::GridCoord1D coord2(2), coord3(3);
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord1D coord2(2), coord3(3);
|
||||
|
||||
{
|
||||
auto agent_id_baz = multigrid1d_foo.add_agent(agent_id_foo, coord2);
|
||||
@@ -60,6 +68,398 @@ TEST(MultiGrid1D, add_agent) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MultiGrid1D, delete_agent) {
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord1D coord2(2), coord3(3);
|
||||
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
auto agent_id_baz = multigrid1d_foo.delete_agent(agent_id_foo);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = multigrid1d_foo.delete_agent(agent_id_foo);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = multigrid1d_foo.delete_agent(agent_id_bar);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_bar);
|
||||
}
|
||||
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
auto agent_id_baz = multigrid1d_foo.delete_agent(agent_id_foo, coord2);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = multigrid1d_foo.delete_agent(agent_id_foo, coord2);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = multigrid1d_foo.delete_agent(agent_id_bar, coord2);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_bar);
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
auto agent_id_baz = multigrid1d_foo.delete_agent(agent_id_foo, coord3);
|
||||
EXPECT_FALSE(agent_id_baz);
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = multigrid1d_foo.delete_agent(agent_id_foo, coord3);
|
||||
EXPECT_FALSE(agent_id_baz);
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = multigrid1d_foo.delete_agent(agent_id_bar, coord3);
|
||||
EXPECT_FALSE(agent_id_baz);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MultiGrid1D, is_location_valid) {
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord1D coordm1(-1), coord0(0), coord2(2), coord3(3), coord10(10), coord100(100);
|
||||
|
||||
{
|
||||
EXPECT_TRUE(multigrid1d_foo.is_location_valid(coord0));
|
||||
EXPECT_TRUE(multigrid1d_foo.is_location_valid(coord2));
|
||||
EXPECT_TRUE(multigrid1d_foo.is_location_valid(coord2));
|
||||
|
||||
EXPECT_FALSE(multigrid1d_foo.is_location_valid(coordm1));
|
||||
EXPECT_FALSE(multigrid1d_foo.is_location_valid(coord10));
|
||||
EXPECT_FALSE(multigrid1d_foo.is_location_valid(coord100));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MultiGrid1D, is_location_empty) {
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord1D coord2(2), coord3(3);
|
||||
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
|
||||
EXPECT_TRUE(multigrid1d_foo.is_location_empty(coord2));
|
||||
EXPECT_TRUE(multigrid1d_foo.is_location_empty(coord3));
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
EXPECT_FALSE(multigrid1d_foo.is_location_empty(coord2));
|
||||
EXPECT_TRUE(multigrid1d_foo.is_location_empty(coord3));
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_bar, coord2));
|
||||
EXPECT_FALSE(multigrid1d_foo.is_location_empty(coord2));
|
||||
EXPECT_TRUE(multigrid1d_foo.is_location_empty(coord3));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MultiGrid1D, move_agent) {
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord1D coord2(2), coord3(3), coord7(7), coord10(10);
|
||||
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
auto agent_id_baz = multigrid1d_foo.move_agent(agent_id_foo, coord7);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
auto agent_id_baz = multigrid1d_foo.move_agent(agent_id_foo, coord10);
|
||||
EXPECT_FALSE(agent_id_baz);
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = multigrid1d_foo.move_agent(agent_id_foo, coord2);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = multigrid1d_foo.move_agent(agent_id_foo, coord7);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MultiGrid1D, get_neighborhood) {
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord1D coord0(0), coord1(1), coord2(2), coord3(3), coord9(9);
|
||||
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord1, coord9});
|
||||
auto rval = multigrid1d_foo.get_neighborhood(coord0, true);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord1, coord2});
|
||||
auto rval = multigrid1d_foo.get_neighborhood(coord1, true);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, false);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord1});
|
||||
auto rval = multigrid1d_foo.get_neighborhood(coord0, true);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, false);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord1, coord2});
|
||||
auto rval = multigrid1d_foo.get_neighborhood(coord1, true);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord1, coord9});
|
||||
auto rval = multigrid1d_foo.get_neighborhood(coord0, false);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord2});
|
||||
auto rval = multigrid1d_foo.get_neighborhood(coord1, false);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, false);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord1});
|
||||
auto rval = multigrid1d_foo.get_neighborhood(coord0, false);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, false);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord2});
|
||||
auto rval = multigrid1d_foo.get_neighborhood(coord1, false);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord1, coord9});
|
||||
auto rval = multigrid1d_foo.get_neighborhood(agent_id_foo, true);
|
||||
|
||||
EXPECT_FALSE(rval);
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
multigrid1d_foo.add_agent(agent_id_foo, coord0);
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord1, coord9});
|
||||
auto rval = multigrid1d_foo.get_neighborhood(agent_id_foo, true);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
multigrid1d_foo.add_agent(agent_id_foo, coord1);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord1, coord2});
|
||||
auto rval = multigrid1d_foo.get_neighborhood(agent_id_foo, true);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, false);
|
||||
multigrid1d_foo.add_agent(agent_id_foo, coord0);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord1});
|
||||
auto rval = multigrid1d_foo.get_neighborhood(agent_id_foo, true);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, false);
|
||||
multigrid1d_foo.add_agent(agent_id_foo, coord1);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord1, coord2});
|
||||
auto rval = multigrid1d_foo.get_neighborhood(agent_id_foo, true);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
multigrid1d_foo.add_agent(agent_id_foo, coord0);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord1, coord9});
|
||||
auto rval = multigrid1d_foo.get_neighborhood(agent_id_foo, false);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
multigrid1d_foo.add_agent(agent_id_foo, coord1);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord2});
|
||||
auto rval = multigrid1d_foo.get_neighborhood(agent_id_foo, false);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, false);
|
||||
multigrid1d_foo.add_agent(agent_id_foo, coord0);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord1});
|
||||
auto rval = multigrid1d_foo.get_neighborhood(agent_id_foo, false);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, false);
|
||||
multigrid1d_foo.add_agent(agent_id_foo, coord1);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord2});
|
||||
auto rval = multigrid1d_foo.get_neighborhood(agent_id_foo, false);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MultiGrid1D, get_location_by_agent) {
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord1D coord2(2), coord3(3);
|
||||
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
|
||||
EXPECT_FALSE(multigrid1d_foo.get_location_by_agent(agent_id_foo));
|
||||
EXPECT_FALSE(multigrid1d_foo.get_location_by_agent(agent_id_bar));
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
auto local = multigrid1d_foo.get_location_by_agent(agent_id_foo);
|
||||
EXPECT_TRUE(local);
|
||||
EXPECT_EQ(local, coord2);
|
||||
EXPECT_FALSE(multigrid1d_foo.get_location_by_agent(agent_id_bar));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MultiGrid1D, get_location_contents) {
|
||||
const AgentID agent_id_foo, agent_id_bar, agent_id_baz;
|
||||
const GridCoord1D coord0(0), coord1(1), coord9(9), coord10(10);
|
||||
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
auto agent_list_foo = multigrid1d_foo.get_location_contents(coord10);
|
||||
|
||||
EXPECT_FALSE(agent_list_foo);
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
|
||||
auto agent_list_foo = multigrid1d_foo.get_location_contents(coord1);
|
||||
|
||||
EXPECT_TRUE(agent_list_foo);
|
||||
EXPECT_TRUE(agent_list_foo.value()->empty());
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_foo, coord1));
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_bar, coord1));
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_baz, coord1));
|
||||
|
||||
auto tval = set<AgentID>({agent_id_foo, agent_id_bar, agent_id_baz});
|
||||
auto rval = multigrid1d_foo.get_location_contents(coord1);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid1D multigrid1d_foo(10, true);
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_foo, coord1));
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_bar, coord1));
|
||||
static_cast<void>(multigrid1d_foo.add_agent(agent_id_baz, coord9));
|
||||
|
||||
auto tval = set<AgentID>({agent_id_foo, agent_id_bar});
|
||||
auto rval = multigrid1d_foo.get_location_contents(coord1);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
728
test/unit-kami-multigrid2d.cc
Normal file
728
test/unit-kami-multigrid2d.cc
Normal file
@@ -0,0 +1,728 @@
|
||||
/*-
|
||||
* Copyright (c) 2022 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/multigrid2d.h>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace kami;
|
||||
using namespace std;
|
||||
|
||||
TEST(MultiGrid2D, DefaultConstructor) {
|
||||
// There is really no way this can go wrong, but
|
||||
// we add this check anyway in case of future
|
||||
// changes.
|
||||
EXPECT_NO_THROW(
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
);
|
||||
}
|
||||
|
||||
TEST(MultiGrid2D, add_agent) {
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord2D coord2(2, 5), coord3(3, 7);
|
||||
|
||||
{
|
||||
auto agent_id_baz = multigrid2d_foo.add_agent(agent_id_foo, coord2);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
auto agent_id_baz = multigrid2d_foo.add_agent(agent_id_bar, coord2);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_bar);
|
||||
}
|
||||
{
|
||||
auto agent_id_baz = multigrid2d_foo.add_agent(agent_id_bar, coord3);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_bar);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MultiGrid2D, delete_agent) {
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord2D coord2(2, 5), coord3(3, 7);
|
||||
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
auto agent_id_baz = multigrid2d_foo.delete_agent(agent_id_foo);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = multigrid2d_foo.delete_agent(agent_id_foo);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = multigrid2d_foo.delete_agent(agent_id_bar);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_bar);
|
||||
}
|
||||
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
auto agent_id_baz = multigrid2d_foo.delete_agent(agent_id_foo, coord2);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = multigrid2d_foo.delete_agent(agent_id_foo, coord2);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = multigrid2d_foo.delete_agent(agent_id_bar, coord2);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_bar);
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
auto agent_id_baz = multigrid2d_foo.delete_agent(agent_id_foo, coord3);
|
||||
EXPECT_FALSE(agent_id_baz);
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = multigrid2d_foo.delete_agent(agent_id_foo, coord3);
|
||||
EXPECT_FALSE(agent_id_baz);
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = multigrid2d_foo.delete_agent(agent_id_bar, coord3);
|
||||
EXPECT_FALSE(agent_id_baz);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MultiGrid2D, is_location_valid) {
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord2D coordm1(-1, -1), coord0(0, 0), coord2(2, 5), coord3(3, 7), coord10(10, 5), coord100(100, 100);
|
||||
|
||||
{
|
||||
EXPECT_TRUE(multigrid2d_foo.is_location_valid(coord0));
|
||||
EXPECT_TRUE(multigrid2d_foo.is_location_valid(coord2));
|
||||
EXPECT_TRUE(multigrid2d_foo.is_location_valid(coord2));
|
||||
|
||||
EXPECT_FALSE(multigrid2d_foo.is_location_valid(coordm1));
|
||||
EXPECT_FALSE(multigrid2d_foo.is_location_valid(coord10));
|
||||
EXPECT_FALSE(multigrid2d_foo.is_location_valid(coord100));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MultiGrid2D, is_location_empty) {
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord2D coord2(2, 5), coord3(3, 7);
|
||||
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
EXPECT_TRUE(multigrid2d_foo.is_location_empty(coord2));
|
||||
EXPECT_TRUE(multigrid2d_foo.is_location_empty(coord3));
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
EXPECT_FALSE(multigrid2d_foo.is_location_empty(coord2));
|
||||
EXPECT_TRUE(multigrid2d_foo.is_location_empty(coord3));
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_bar, coord2));
|
||||
EXPECT_FALSE(multigrid2d_foo.is_location_empty(coord2));
|
||||
EXPECT_TRUE(multigrid2d_foo.is_location_empty(coord3));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MultiGrid2D, move_agent) {
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord2D coord2(2, 5), coord3(3, 7), coord7(7, 2), coord10(10, 5);
|
||||
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
auto agent_id_baz = multigrid2d_foo.move_agent(agent_id_foo, coord7);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
auto agent_id_baz = multigrid2d_foo.move_agent(agent_id_foo, coord10);
|
||||
EXPECT_FALSE(agent_id_baz);
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = multigrid2d_foo.move_agent(agent_id_foo, coord2);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = multigrid2d_foo.move_agent(agent_id_foo, coord7);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MultiGrid2D, get_neighborhood_VonNeumann) {
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord2D coord0(0, 0), coord1(1, 1), coord2(2, 5), coord3(3, 7), coord9(9, 4);
|
||||
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{0, 1},
|
||||
{0, 1},
|
||||
{9, 0},
|
||||
{0, 9},
|
||||
{1, 0},
|
||||
{0, 0}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(coord0, true, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 2},
|
||||
{2, 1},
|
||||
{1, 0},
|
||||
{0, 1},
|
||||
{1, 1}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(coord1, true, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, false, false);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{0, 1},
|
||||
{1, 0},
|
||||
{0, 0}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(coord0, true, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, false, false);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 2},
|
||||
{2, 1},
|
||||
{1, 0},
|
||||
{0, 1},
|
||||
{1, 1}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(coord1, true, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 0},
|
||||
{0, 1},
|
||||
{9, 0},
|
||||
{0, 9}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(coord0, false, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 0},
|
||||
{0, 1},
|
||||
{9, 0},
|
||||
{0, 9}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(coord0, false, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, false, false);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 0},
|
||||
{0, 1}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(coord0, false, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, false, false);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 0},
|
||||
{0, 1}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(coord0, false, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
auto rval = multigrid2d_foo.get_neighborhood(agent_id_foo, true, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_FALSE(rval);
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
multigrid2d_foo.add_agent(agent_id_foo, coord0);
|
||||
auto tval = unordered_set<GridCoord2D>({{0, 1},
|
||||
{9, 0},
|
||||
{0, 9},
|
||||
{1, 0},
|
||||
{0, 0}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(agent_id_foo, true, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
multigrid2d_foo.add_agent(agent_id_foo, coord1);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 2},
|
||||
{2, 1},
|
||||
{1, 0},
|
||||
{0, 1},
|
||||
{1, 1}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(agent_id_foo, true, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, false, false);
|
||||
multigrid2d_foo.add_agent(agent_id_foo, coord0);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{0, 1},
|
||||
{1, 0},
|
||||
{0, 0}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(agent_id_foo, true, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, false, false);
|
||||
multigrid2d_foo.add_agent(agent_id_foo, coord1);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 2},
|
||||
{2, 1},
|
||||
{1, 0},
|
||||
{0, 1},
|
||||
{1, 1}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(agent_id_foo, true, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
multigrid2d_foo.add_agent(agent_id_foo, coord0);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 0},
|
||||
{0, 1},
|
||||
{9, 0},
|
||||
{0, 9}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(agent_id_foo, false, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
multigrid2d_foo.add_agent(agent_id_foo, coord1);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{0, 1},
|
||||
{1, 2},
|
||||
{2, 1},
|
||||
{1, 0}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(agent_id_foo, false, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, false, false);
|
||||
multigrid2d_foo.add_agent(agent_id_foo, coord0);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 0},
|
||||
{0, 1}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(agent_id_foo, false, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, false, false);
|
||||
multigrid2d_foo.add_agent(agent_id_foo, coord1);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{0, 1},
|
||||
{1, 2},
|
||||
{2, 1},
|
||||
{1, 0}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(agent_id_foo, false, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MultiGrid2D, get_neighborhood_Moore) {
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord2D coord0(0, 0), coord1(1, 1), coord2(2, 5), coord3(3, 7), coord9(9, 4);
|
||||
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{9, 9},
|
||||
{9, 1},
|
||||
{1, 1},
|
||||
{0, 1},
|
||||
{9, 0},
|
||||
{1, 9},
|
||||
{0, 9},
|
||||
{1, 0},
|
||||
{0, 0}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(coord0, true, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{2, 2},
|
||||
{0, 2},
|
||||
{1, 2},
|
||||
{0, 0},
|
||||
{2, 1},
|
||||
{1, 0},
|
||||
{2, 0},
|
||||
{0, 1},
|
||||
{1, 1}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(coord1, true, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, false, false);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 1},
|
||||
{0, 1},
|
||||
{1, 0},
|
||||
{0, 0}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(coord0, true, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, false, false);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{2, 2},
|
||||
{0, 2},
|
||||
{1, 2},
|
||||
{0, 0},
|
||||
{2, 1},
|
||||
{1, 0},
|
||||
{2, 0},
|
||||
{0, 1},
|
||||
{1, 1}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(coord1, true, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{9, 9},
|
||||
{9, 1},
|
||||
{1, 0},
|
||||
{1, 1},
|
||||
{0, 1},
|
||||
{0, 9},
|
||||
{1, 9},
|
||||
{9, 0}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(coord0, false, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{9, 9},
|
||||
{9, 1},
|
||||
{1, 0},
|
||||
{1, 1},
|
||||
{0, 1},
|
||||
{0, 9},
|
||||
{1, 9},
|
||||
{9, 0}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(coord0, false, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, false, false);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 0},
|
||||
{1, 1},
|
||||
{0, 1}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(coord0, false, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, false, false);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 0},
|
||||
{1, 1},
|
||||
{0, 1}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(coord0, false, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
auto rval = multigrid2d_foo.get_neighborhood(agent_id_foo, true, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_FALSE(rval);
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
multigrid2d_foo.add_agent(agent_id_foo, coord0);
|
||||
auto tval = unordered_set<GridCoord2D>({{9, 9},
|
||||
{9, 1},
|
||||
{1, 1},
|
||||
{0, 1},
|
||||
{9, 0},
|
||||
{1, 9},
|
||||
{0, 9},
|
||||
{1, 0},
|
||||
{0, 0}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(agent_id_foo, true, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
multigrid2d_foo.add_agent(agent_id_foo, coord1);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{2, 2},
|
||||
{0, 2},
|
||||
{1, 2},
|
||||
{0, 0},
|
||||
{2, 1},
|
||||
{1, 0},
|
||||
{2, 0},
|
||||
{0, 1},
|
||||
{1, 1}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(agent_id_foo, true, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, false, false);
|
||||
multigrid2d_foo.add_agent(agent_id_foo, coord0);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 1},
|
||||
{0, 1},
|
||||
{1, 0},
|
||||
{0, 0}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(agent_id_foo, true, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, false, false);
|
||||
multigrid2d_foo.add_agent(agent_id_foo, coord1);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{2, 2},
|
||||
{0, 2},
|
||||
{1, 2},
|
||||
{0, 0},
|
||||
{2, 1},
|
||||
{1, 0},
|
||||
{2, 0},
|
||||
{0, 1},
|
||||
{1, 1}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(agent_id_foo, true, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
multigrid2d_foo.add_agent(agent_id_foo, coord0);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{9, 9},
|
||||
{9, 1},
|
||||
{1, 0},
|
||||
{1, 1},
|
||||
{0, 1},
|
||||
{0, 9},
|
||||
{1, 9},
|
||||
{9, 0}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(agent_id_foo, false, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
multigrid2d_foo.add_agent(agent_id_foo, coord1);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{2, 2},
|
||||
{2, 0},
|
||||
{0, 1},
|
||||
{0, 2},
|
||||
{1, 2},
|
||||
{0, 0},
|
||||
{2, 1},
|
||||
{1, 0}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(agent_id_foo, false, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, false, false);
|
||||
multigrid2d_foo.add_agent(agent_id_foo, coord0);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 0},
|
||||
{1, 1},
|
||||
{0, 1}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(agent_id_foo, false, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, false, false);
|
||||
multigrid2d_foo.add_agent(agent_id_foo, coord1);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{2, 2},
|
||||
{2, 0},
|
||||
{0, 1},
|
||||
{0, 2},
|
||||
{1, 2},
|
||||
{0, 0},
|
||||
{2, 1},
|
||||
{1, 0}});
|
||||
auto rval = multigrid2d_foo.get_neighborhood(agent_id_foo, false, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MultiGrid2D, get_location_by_agent) {
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord2D coord2(2, 5), coord3(3, 7);
|
||||
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
EXPECT_FALSE(multigrid2d_foo.get_location_by_agent(agent_id_foo));
|
||||
EXPECT_FALSE(multigrid2d_foo.get_location_by_agent(agent_id_bar));
|
||||
}
|
||||
{
|
||||
MultiGrid2D multigrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(multigrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
auto local = multigrid2d_foo.get_location_by_agent(agent_id_foo);
|
||||
EXPECT_TRUE(local);
|
||||
EXPECT_EQ(local, coord2);
|
||||
EXPECT_FALSE(multigrid2d_foo.get_location_by_agent(agent_id_bar));
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
197
test/unit-kami-population.cc
Normal file
197
test/unit-kami-population.cc
Normal file
@@ -0,0 +1,197 @@
|
||||
/*-
|
||||
* Copyright (c) 2022 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/population.h>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace kami;
|
||||
using namespace std;
|
||||
|
||||
class TestAgent : public Agent {
|
||||
private:
|
||||
int _x;
|
||||
|
||||
public:
|
||||
explicit TestAgent(int x) : _x(x) {};
|
||||
|
||||
AgentID step(shared_ptr<Model> model) override {
|
||||
return get_agent_id();
|
||||
}
|
||||
|
||||
int getval() {
|
||||
return _x;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(Population, DefaultConstructor) {
|
||||
// There is really no way this can go wrong, but
|
||||
// we add this check anyway in case of future
|
||||
// changes.
|
||||
EXPECT_NO_THROW(
|
||||
const Population population_foo;
|
||||
);
|
||||
}
|
||||
|
||||
TEST(Population, add_agent) {
|
||||
Population population_foo;
|
||||
auto agent_foo = make_shared<TestAgent>(8675309);
|
||||
auto agent_bar = make_shared<TestAgent>(1729);
|
||||
|
||||
{
|
||||
auto agent_id_baz = population_foo.add_agent(agent_foo);
|
||||
EXPECT_EQ(agent_id_baz, agent_foo->get_agent_id());
|
||||
}
|
||||
{
|
||||
auto agent_id_baz = population_foo.add_agent(agent_bar);
|
||||
EXPECT_EQ(agent_id_baz, agent_bar->get_agent_id());
|
||||
}
|
||||
{
|
||||
auto agent_id_baz = population_foo.add_agent(agent_foo);
|
||||
EXPECT_EQ(agent_id_baz, agent_foo->get_agent_id());
|
||||
auto agent_id_qux = population_foo.add_agent(agent_bar);
|
||||
EXPECT_EQ(agent_id_qux, agent_bar->get_agent_id());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Population, get_agent_by_id) {
|
||||
auto agent_foo = make_shared<TestAgent>(8675309);
|
||||
auto agent_bar = make_shared<TestAgent>(1729);
|
||||
|
||||
{
|
||||
Population population_foo;
|
||||
static_cast<void>(population_foo.add_agent(agent_foo));
|
||||
auto agent_baz_opt = population_foo.get_agent_by_id(agent_foo->get_agent_id());
|
||||
EXPECT_TRUE(agent_baz_opt);
|
||||
|
||||
auto agent_baz = dynamic_pointer_cast<TestAgent>(agent_baz_opt.value());
|
||||
EXPECT_EQ(agent_baz->getval(), 8675309);
|
||||
}
|
||||
{
|
||||
Population population_foo;
|
||||
static_cast<void>(population_foo.add_agent(agent_foo));
|
||||
auto agent_baz_opt = population_foo.get_agent_by_id(agent_bar->get_agent_id());
|
||||
EXPECT_FALSE(agent_baz_opt);
|
||||
}
|
||||
{
|
||||
Population population_foo;
|
||||
static_cast<void>(population_foo.add_agent(agent_foo));
|
||||
static_cast<void>(population_foo.add_agent(agent_bar));
|
||||
|
||||
auto agent_baz_opt = population_foo.get_agent_by_id(agent_foo->get_agent_id());
|
||||
EXPECT_TRUE(agent_baz_opt);
|
||||
|
||||
auto agent_baz = dynamic_pointer_cast<TestAgent>(agent_baz_opt.value());
|
||||
EXPECT_EQ(agent_baz->getval(), 8675309);
|
||||
|
||||
auto agent_qux_opt = population_foo.get_agent_by_id(agent_bar->get_agent_id());
|
||||
EXPECT_TRUE(agent_qux_opt);
|
||||
|
||||
auto agent_qux = dynamic_pointer_cast<TestAgent>(agent_qux_opt.value());
|
||||
EXPECT_EQ(agent_qux->getval(), 1729);
|
||||
}
|
||||
{
|
||||
Population population_foo;
|
||||
static_cast<void>(population_foo.add_agent(agent_foo));
|
||||
static_cast<void>(population_foo.add_agent(agent_bar));
|
||||
|
||||
auto agent_qux_opt = population_foo.get_agent_by_id(agent_bar->get_agent_id());
|
||||
EXPECT_TRUE(agent_qux_opt);
|
||||
|
||||
auto agent_qux = dynamic_pointer_cast<TestAgent>(agent_qux_opt.value());
|
||||
EXPECT_EQ(agent_qux->getval(), 1729);
|
||||
|
||||
auto agent_baz_opt = population_foo.get_agent_by_id(agent_foo->get_agent_id());
|
||||
EXPECT_TRUE(agent_baz_opt);
|
||||
|
||||
auto agent_baz = dynamic_pointer_cast<TestAgent>(agent_baz_opt.value());
|
||||
EXPECT_EQ(agent_baz->getval(), 8675309);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Population, get_agent_list) {
|
||||
auto agent_foo = make_shared<TestAgent>(8675309);
|
||||
auto agent_bar = make_shared<TestAgent>(1729);
|
||||
auto agent_baz = make_shared<TestAgent>(4104);
|
||||
auto agent_qux = make_shared<TestAgent>(196);
|
||||
|
||||
{
|
||||
Population population_foo;
|
||||
auto tval = make_shared<vector<AgentID>>();
|
||||
auto rval = population_foo.get_agent_list();
|
||||
|
||||
EXPECT_EQ(*tval, *rval);
|
||||
}
|
||||
{
|
||||
Population population_foo;
|
||||
auto tval = make_shared<vector<AgentID>>();
|
||||
auto rval = population_foo.get_agent_list();
|
||||
|
||||
tval->push_back(agent_foo->get_agent_id());
|
||||
EXPECT_NE(*tval, *rval);
|
||||
}
|
||||
{
|
||||
Population population_foo;
|
||||
static_cast<void>(population_foo.add_agent(agent_foo));
|
||||
static_cast<void>(population_foo.add_agent(agent_bar));
|
||||
|
||||
auto tval = make_shared<vector<AgentID>>();
|
||||
auto uval = make_shared<vector<AgentID>>();
|
||||
auto rval = population_foo.get_agent_list();
|
||||
|
||||
tval->push_back(agent_foo->get_agent_id());
|
||||
tval->push_back(agent_bar->get_agent_id());
|
||||
EXPECT_EQ(*tval, *rval);
|
||||
|
||||
// Ordering matters
|
||||
uval->push_back(agent_bar->get_agent_id());
|
||||
uval->push_back(agent_foo->get_agent_id());
|
||||
EXPECT_NE(*uval, *rval);
|
||||
}
|
||||
{
|
||||
Population population_foo;
|
||||
static_cast<void>(population_foo.add_agent(agent_foo));
|
||||
static_cast<void>(population_foo.add_agent(agent_bar));
|
||||
static_cast<void>(population_foo.add_agent(agent_baz));
|
||||
static_cast<void>(population_foo.add_agent(agent_qux));
|
||||
|
||||
auto tval = make_shared<vector<AgentID>>();
|
||||
auto rval = population_foo.get_agent_list();
|
||||
|
||||
tval->push_back(agent_foo->get_agent_id());
|
||||
tval->push_back(agent_bar->get_agent_id());
|
||||
tval->push_back(agent_baz->get_agent_id());
|
||||
tval->push_back(agent_qux->get_agent_id());
|
||||
EXPECT_EQ(*tval, *rval);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
152
test/unit-kami-random.cc
Normal file
152
test/unit-kami-random.cc
Normal file
@@ -0,0 +1,152 @@
|
||||
/*-
|
||||
* Copyright (c) 2022 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <random>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/population.h>
|
||||
#include <kami/random.h>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace kami;
|
||||
using namespace std;
|
||||
|
||||
class TestAgent : public Agent {
|
||||
public:
|
||||
AgentID step(shared_ptr<Model> model) override {
|
||||
return get_agent_id();
|
||||
}
|
||||
};
|
||||
|
||||
class TestModel : public Model {
|
||||
public:
|
||||
optional<shared_ptr<vector<AgentID>>> step() {
|
||||
return _sched->step(shared_from_this());
|
||||
}
|
||||
|
||||
optional<shared_ptr<vector<AgentID>>> step(shared_ptr<vector<AgentID>> agent_list) {
|
||||
return _sched->step(shared_from_this(), move(agent_list));
|
||||
}
|
||||
};
|
||||
|
||||
class RandomSchedulerTest : public ::testing::Test {
|
||||
protected:
|
||||
shared_ptr<TestModel> mod = nullptr;
|
||||
shared_ptr<ranlux24> rng = nullptr;
|
||||
|
||||
void SetUp() override {
|
||||
mod = make_shared<TestModel>();
|
||||
rng = make_shared<ranlux24>();
|
||||
auto popul_foo = make_shared<Population>();
|
||||
auto sched_foo = make_shared<RandomScheduler>(rng);
|
||||
|
||||
// Domain is not required for this test
|
||||
static_cast<void>(mod->set_population(popul_foo));
|
||||
static_cast<void>(mod->set_scheduler(sched_foo));
|
||||
|
||||
for (auto i = 0; i < 10; i++) {
|
||||
auto agent_foo = make_shared<TestAgent>();
|
||||
static_cast<void>(popul_foo->add_agent(agent_foo));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TEST(RandomScheduler, DefaultConstructor) {
|
||||
// There is really no way this can go wrong, but
|
||||
// we add this check anyway in case of future
|
||||
// changes.
|
||||
EXPECT_NO_THROW(
|
||||
const RandomScheduler sched_foo;
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(RandomSchedulerTest, step_interface1) {
|
||||
auto tval = mod->get_population().value()->get_agent_list();
|
||||
auto rval = mod->step();
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(rval.value()->size(), 10);
|
||||
|
||||
// Sort both return values and just make sure all of them all the same...
|
||||
// We cannot test permutation since, well, you know...
|
||||
set<AgentID> tval_set = set(tval->begin(), tval->end());
|
||||
set<AgentID> rval_set = set(rval.value()->begin(), rval.value()->end());
|
||||
EXPECT_EQ(tval_set, rval_set);
|
||||
}
|
||||
|
||||
TEST_F(RandomSchedulerTest, step_interface2) {
|
||||
auto tval = mod->get_population().value()->get_agent_list();
|
||||
auto rval = mod->step(tval);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(rval.value()->size(), 10);
|
||||
|
||||
set<AgentID> tval_set = set(tval->begin(), tval->end());
|
||||
set<AgentID> rval_set = set(rval.value()->begin(), rval.value()->end());
|
||||
EXPECT_EQ(tval_set, rval_set);
|
||||
}
|
||||
|
||||
TEST_F(RandomSchedulerTest, step_10000) {
|
||||
auto tval = mod->get_population().value()->get_agent_list();
|
||||
set<AgentID> tval_set = set(tval->begin(), tval->end());
|
||||
|
||||
// Do it a lot...
|
||||
for (auto i = 0; i < 10000; i++) {
|
||||
auto rval = mod->step();
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(rval.value()->size(), 10);
|
||||
|
||||
set<AgentID> rval_set = set(rval.value()->begin(), rval.value()->end());
|
||||
EXPECT_EQ(tval_set, rval_set);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(RandomSchedulerTest, get_rng) {
|
||||
auto rval = static_pointer_cast<RandomScheduler>(mod->get_scheduler().value())->get_rng();
|
||||
|
||||
EXPECT_EQ(rng, rval);
|
||||
}
|
||||
|
||||
TEST_F(RandomSchedulerTest, set_rng) {
|
||||
auto new_rng = make_shared<ranlux24>();
|
||||
auto rval1 = static_pointer_cast<RandomScheduler>(mod->get_scheduler().value())->get_rng();
|
||||
|
||||
static_cast<void>(static_pointer_cast<RandomScheduler>(mod->get_scheduler().value())->set_rng(new_rng));
|
||||
auto rval2 = static_pointer_cast<RandomScheduler>(mod->get_scheduler().value())->get_rng();
|
||||
|
||||
EXPECT_EQ(new_rng, rval2);
|
||||
EXPECT_NE(new_rng, rval1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
121
test/unit-kami-sequential.cc
Normal file
121
test/unit-kami-sequential.cc
Normal file
@@ -0,0 +1,121 @@
|
||||
/*-
|
||||
* Copyright (c) 2022 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/population.h>
|
||||
#include <kami/sequential.h>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace kami;
|
||||
using namespace std;
|
||||
|
||||
class TestAgent : public Agent {
|
||||
public:
|
||||
AgentID step(shared_ptr<Model> model) override {
|
||||
return get_agent_id();
|
||||
}
|
||||
};
|
||||
|
||||
class TestModel : public Model {
|
||||
public:
|
||||
optional<shared_ptr<vector<AgentID>>> step() {
|
||||
return _sched->step(shared_from_this());
|
||||
}
|
||||
|
||||
optional<shared_ptr<vector<AgentID>>> step(shared_ptr<vector<AgentID>> agent_list) {
|
||||
return _sched->step(shared_from_this(), move(agent_list));
|
||||
}
|
||||
};
|
||||
|
||||
class SequentialSchedulerTest : public ::testing::Test {
|
||||
protected:
|
||||
shared_ptr<TestModel> mod = nullptr;
|
||||
|
||||
void SetUp() override {
|
||||
mod = make_shared<TestModel>();
|
||||
auto popul_foo = make_shared<Population>();
|
||||
auto sched_foo = make_shared<SequentialScheduler>();
|
||||
|
||||
// Domain is not required for this test
|
||||
static_cast<void>(mod->set_population(popul_foo));
|
||||
static_cast<void>(mod->set_scheduler(sched_foo));
|
||||
|
||||
for (auto i = 0; i < 10; i++) {
|
||||
auto agent_foo = make_shared<TestAgent>();
|
||||
static_cast<void>(popul_foo->add_agent(agent_foo));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TEST(SequentialScheduler, DefaultConstructor) {
|
||||
// There is really no way this can go wrong, but
|
||||
// we add this check anyway in case of future
|
||||
// changes.
|
||||
EXPECT_NO_THROW(
|
||||
const SequentialScheduler sched_foo;
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(SequentialSchedulerTest, step_interface1) {
|
||||
auto tval = mod->get_population().value()->get_agent_list();
|
||||
auto rval = mod->step();
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(rval.value()->size(), 10);
|
||||
EXPECT_EQ(*rval.value(), *tval);
|
||||
}
|
||||
|
||||
TEST_F(SequentialSchedulerTest, step_interface2) {
|
||||
auto tval = mod->get_population().value()->get_agent_list();
|
||||
auto rval = mod->step(tval);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(rval.value()->size(), 10);
|
||||
EXPECT_EQ(*rval.value(), *tval);
|
||||
}
|
||||
|
||||
TEST_F(SequentialSchedulerTest, step_10000) {
|
||||
auto tval = mod->get_population().value()->get_agent_list();
|
||||
|
||||
// Do it a lot...
|
||||
for (auto i = 0; i < 10000; i++) {
|
||||
auto rval = mod->step();
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(rval.value()->size(), 10);
|
||||
EXPECT_EQ(*rval.value(), *tval);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
465
test/unit-kami-sologrid1d.cc
Normal file
465
test/unit-kami-sologrid1d.cc
Normal file
@@ -0,0 +1,465 @@
|
||||
/*-
|
||||
* Copyright (c) 2022 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/sologrid1d.h>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace kami;
|
||||
using namespace std;
|
||||
|
||||
TEST(SoloGrid1D, DefaultConstructor) {
|
||||
// There is really no way this can go wrong, but
|
||||
// we add this check anyway in case of future
|
||||
// changes.
|
||||
EXPECT_NO_THROW(
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
);
|
||||
}
|
||||
|
||||
TEST(SoloGrid1D, add_agent) {
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord1D coord2(2), coord3(3);
|
||||
|
||||
{
|
||||
auto agent_id_baz = sologrid1d_foo.add_agent(agent_id_foo, coord2);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
auto agent_id_baz = sologrid1d_foo.add_agent(agent_id_bar, coord2);
|
||||
EXPECT_FALSE(agent_id_baz);
|
||||
}
|
||||
{
|
||||
auto agent_id_baz = sologrid1d_foo.add_agent(agent_id_bar, coord3);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_bar);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SoloGrid1D, delete_agent) {
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord1D coord2(2), coord3(3);
|
||||
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
auto agent_id_baz = sologrid1d_foo.delete_agent(agent_id_foo);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = sologrid1d_foo.delete_agent(agent_id_foo);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = sologrid1d_foo.delete_agent(agent_id_bar);
|
||||
EXPECT_FALSE(agent_id_baz);
|
||||
}
|
||||
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
auto agent_id_baz = sologrid1d_foo.delete_agent(agent_id_foo, coord2);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = sologrid1d_foo.delete_agent(agent_id_foo, coord2);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = sologrid1d_foo.delete_agent(agent_id_bar, coord2);
|
||||
EXPECT_FALSE(agent_id_baz);
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
auto agent_id_baz = sologrid1d_foo.delete_agent(agent_id_foo, coord3);
|
||||
EXPECT_FALSE(agent_id_baz);
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = sologrid1d_foo.delete_agent(agent_id_foo, coord3);
|
||||
EXPECT_FALSE(agent_id_baz);
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = sologrid1d_foo.delete_agent(agent_id_bar, coord3);
|
||||
EXPECT_FALSE(agent_id_baz);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SoloGrid1D, is_location_valid) {
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord1D coordm1(-1), coord0(0), coord2(2), coord3(3), coord10(10), coord100(100);
|
||||
|
||||
{
|
||||
EXPECT_TRUE(sologrid1d_foo.is_location_valid(coord0));
|
||||
EXPECT_TRUE(sologrid1d_foo.is_location_valid(coord2));
|
||||
EXPECT_TRUE(sologrid1d_foo.is_location_valid(coord2));
|
||||
|
||||
EXPECT_FALSE(sologrid1d_foo.is_location_valid(coordm1));
|
||||
EXPECT_FALSE(sologrid1d_foo.is_location_valid(coord10));
|
||||
EXPECT_FALSE(sologrid1d_foo.is_location_valid(coord100));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SoloGrid1D, is_location_empty) {
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord1D coord2(2), coord3(3);
|
||||
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
|
||||
EXPECT_TRUE(sologrid1d_foo.is_location_empty(coord2));
|
||||
EXPECT_TRUE(sologrid1d_foo.is_location_empty(coord3));
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
EXPECT_FALSE(sologrid1d_foo.is_location_empty(coord2));
|
||||
EXPECT_TRUE(sologrid1d_foo.is_location_empty(coord3));
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_bar, coord2));
|
||||
EXPECT_FALSE(sologrid1d_foo.is_location_empty(coord2));
|
||||
EXPECT_TRUE(sologrid1d_foo.is_location_empty(coord3));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SoloGrid1D, move_agent) {
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord1D coord2(2), coord3(3), coord7(7), coord10(10);
|
||||
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
auto agent_id_baz = sologrid1d_foo.move_agent(agent_id_foo, coord7);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
auto agent_id_baz = sologrid1d_foo.move_agent(agent_id_foo, coord10);
|
||||
EXPECT_FALSE(agent_id_baz);
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = sologrid1d_foo.move_agent(agent_id_foo, coord2);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = sologrid1d_foo.move_agent(agent_id_foo, coord7);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SoloGrid1D, get_neighborhood) {
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord1D coord0(0), coord1(1), coord2(2), coord3(3), coord9(9);
|
||||
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord1, coord9});
|
||||
auto rval = sologrid1d_foo.get_neighborhood(coord0, true);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord1, coord2});
|
||||
auto rval = sologrid1d_foo.get_neighborhood(coord1, true);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, false);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord1});
|
||||
auto rval = sologrid1d_foo.get_neighborhood(coord0, true);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, false);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord1, coord2});
|
||||
auto rval = sologrid1d_foo.get_neighborhood(coord1, true);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord1, coord9});
|
||||
auto rval = sologrid1d_foo.get_neighborhood(coord0, false);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord2});
|
||||
auto rval = sologrid1d_foo.get_neighborhood(coord1, false);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, false);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord1});
|
||||
auto rval = sologrid1d_foo.get_neighborhood(coord0, false);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, false);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord2});
|
||||
auto rval = sologrid1d_foo.get_neighborhood(coord1, false);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord1, coord9});
|
||||
auto rval = sologrid1d_foo.get_neighborhood(agent_id_foo, true);
|
||||
|
||||
EXPECT_FALSE(rval);
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
sologrid1d_foo.add_agent(agent_id_foo, coord0);
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord1, coord9});
|
||||
auto rval = sologrid1d_foo.get_neighborhood(agent_id_foo, true);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
sologrid1d_foo.add_agent(agent_id_foo, coord1);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord1, coord2});
|
||||
auto rval = sologrid1d_foo.get_neighborhood(agent_id_foo, true);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, false);
|
||||
sologrid1d_foo.add_agent(agent_id_foo, coord0);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord1});
|
||||
auto rval = sologrid1d_foo.get_neighborhood(agent_id_foo, true);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, false);
|
||||
sologrid1d_foo.add_agent(agent_id_foo, coord1);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord1, coord2});
|
||||
auto rval = sologrid1d_foo.get_neighborhood(agent_id_foo, true);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
sologrid1d_foo.add_agent(agent_id_foo, coord0);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord1, coord9});
|
||||
auto rval = sologrid1d_foo.get_neighborhood(agent_id_foo, false);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
sologrid1d_foo.add_agent(agent_id_foo, coord1);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord2});
|
||||
auto rval = sologrid1d_foo.get_neighborhood(agent_id_foo, false);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, false);
|
||||
sologrid1d_foo.add_agent(agent_id_foo, coord0);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord1});
|
||||
auto rval = sologrid1d_foo.get_neighborhood(agent_id_foo, false);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, false);
|
||||
sologrid1d_foo.add_agent(agent_id_foo, coord1);
|
||||
|
||||
auto tval = unordered_set<GridCoord1D>({coord0, coord2});
|
||||
auto rval = sologrid1d_foo.get_neighborhood(agent_id_foo, false);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SoloGrid1D, get_location_by_agent) {
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord1D coord2(2), coord3(3);
|
||||
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
|
||||
EXPECT_FALSE(sologrid1d_foo.get_location_by_agent(agent_id_foo));
|
||||
EXPECT_FALSE(sologrid1d_foo.get_location_by_agent(agent_id_bar));
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_foo, coord2));
|
||||
auto local = sologrid1d_foo.get_location_by_agent(agent_id_foo);
|
||||
EXPECT_TRUE(local);
|
||||
EXPECT_EQ(local, coord2);
|
||||
EXPECT_FALSE(sologrid1d_foo.get_location_by_agent(agent_id_bar));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SoloGrid1D, get_location_contents) {
|
||||
const AgentID agent_id_foo, agent_id_bar, agent_id_baz;
|
||||
const GridCoord1D coord0(0), coord1(1), coord9(9), coord10(10);
|
||||
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
auto agent_list_foo = sologrid1d_foo.get_location_contents(coord10);
|
||||
|
||||
EXPECT_FALSE(agent_list_foo);
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
|
||||
auto agent_list_foo = sologrid1d_foo.get_location_contents(coord1);
|
||||
|
||||
EXPECT_TRUE(agent_list_foo);
|
||||
EXPECT_TRUE(agent_list_foo.value()->empty());
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_foo, coord1));
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_bar, coord1));
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_baz, coord1));
|
||||
|
||||
auto tval = set<AgentID>({agent_id_foo});
|
||||
auto rval = sologrid1d_foo.get_location_contents(coord1);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid1D sologrid1d_foo(10, true);
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_foo, coord1));
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_bar, coord1));
|
||||
static_cast<void>(sologrid1d_foo.add_agent(agent_id_baz, coord9));
|
||||
|
||||
auto tval = set<AgentID>({agent_id_foo});
|
||||
auto rval = sologrid1d_foo.get_location_contents(coord1);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
725
test/unit-kami-sologrid2d.cc
Normal file
725
test/unit-kami-sologrid2d.cc
Normal file
@@ -0,0 +1,725 @@
|
||||
/*-
|
||||
* Copyright (c) 2022 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/sologrid2d.h>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace kami;
|
||||
using namespace std;
|
||||
|
||||
TEST(SoloGrid2D, DefaultConstructor) {
|
||||
// There is really no way this can go wrong, but
|
||||
// we add this check anyway in case of future
|
||||
// changes.
|
||||
EXPECT_NO_THROW(
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
);
|
||||
}
|
||||
|
||||
TEST(SoloGrid2D, add_agent) {
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord2D coord2(2, 5), coord3(3, 7);
|
||||
|
||||
{
|
||||
auto agent_id_baz = sologrid2d_foo.add_agent(agent_id_foo, coord2);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
auto agent_id_baz = sologrid2d_foo.add_agent(agent_id_bar, coord2);
|
||||
EXPECT_FALSE(agent_id_baz);
|
||||
}
|
||||
{
|
||||
auto agent_id_baz = sologrid2d_foo.add_agent(agent_id_bar, coord3);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_bar);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SoloGrid2D, delete_agent) {
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord2D coord2(2, 5), coord3(3, 7);
|
||||
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
auto agent_id_baz = sologrid2d_foo.delete_agent(agent_id_foo);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = sologrid2d_foo.delete_agent(agent_id_foo);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = sologrid2d_foo.delete_agent(agent_id_bar);
|
||||
EXPECT_FALSE(agent_id_baz);
|
||||
}
|
||||
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
auto agent_id_baz = sologrid2d_foo.delete_agent(agent_id_foo, coord2);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = sologrid2d_foo.delete_agent(agent_id_foo, coord2);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = sologrid2d_foo.delete_agent(agent_id_bar, coord2);
|
||||
EXPECT_FALSE(agent_id_baz);
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
auto agent_id_baz = sologrid2d_foo.delete_agent(agent_id_foo, coord3);
|
||||
EXPECT_FALSE(agent_id_baz);
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = sologrid2d_foo.delete_agent(agent_id_foo, coord3);
|
||||
EXPECT_FALSE(agent_id_baz);
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = sologrid2d_foo.delete_agent(agent_id_bar, coord3);
|
||||
EXPECT_FALSE(agent_id_baz);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SoloGrid2D, is_location_valid) {
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord2D coordm1(-1, -1), coord0(0, 0), coord2(2, 5), coord3(3, 7), coord10(10, 5), coord100(100, 100);
|
||||
|
||||
{
|
||||
EXPECT_TRUE(sologrid2d_foo.is_location_valid(coord0));
|
||||
EXPECT_TRUE(sologrid2d_foo.is_location_valid(coord2));
|
||||
EXPECT_TRUE(sologrid2d_foo.is_location_valid(coord2));
|
||||
|
||||
EXPECT_FALSE(sologrid2d_foo.is_location_valid(coordm1));
|
||||
EXPECT_FALSE(sologrid2d_foo.is_location_valid(coord10));
|
||||
EXPECT_FALSE(sologrid2d_foo.is_location_valid(coord100));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SoloGrid2D, is_location_empty) {
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord2D coord2(2, 5), coord3(3, 7);
|
||||
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
EXPECT_TRUE(sologrid2d_foo.is_location_empty(coord2));
|
||||
EXPECT_TRUE(sologrid2d_foo.is_location_empty(coord3));
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
EXPECT_FALSE(sologrid2d_foo.is_location_empty(coord2));
|
||||
EXPECT_TRUE(sologrid2d_foo.is_location_empty(coord3));
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_bar, coord2));
|
||||
EXPECT_FALSE(sologrid2d_foo.is_location_empty(coord2));
|
||||
EXPECT_TRUE(sologrid2d_foo.is_location_empty(coord3));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SoloGrid2D, move_agent) {
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord2D coord2(2, 5), coord3(3, 7), coord7(7, 2), coord10(10, 5);
|
||||
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
auto agent_id_baz = sologrid2d_foo.move_agent(agent_id_foo, coord7);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
auto agent_id_baz = sologrid2d_foo.move_agent(agent_id_foo, coord10);
|
||||
EXPECT_FALSE(agent_id_baz);
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = sologrid2d_foo.move_agent(agent_id_foo, coord2);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_bar, coord2));
|
||||
auto agent_id_baz = sologrid2d_foo.move_agent(agent_id_foo, coord7);
|
||||
EXPECT_TRUE(agent_id_baz);
|
||||
EXPECT_EQ(agent_id_baz.value(), agent_id_foo);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SoloGrid2D, get_neighborhood_VonNeumann) {
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord2D coord0(0, 0), coord1(1, 1), coord2(2, 5), coord3(3, 7), coord9(9, 4);
|
||||
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{0, 1},
|
||||
{0, 1},
|
||||
{9, 0},
|
||||
{0, 9},
|
||||
{1, 0},
|
||||
{0, 0}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(coord0, true, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 2},
|
||||
{2, 1},
|
||||
{1, 0},
|
||||
{0, 1},
|
||||
{1, 1}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(coord1, true, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, false, false);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{0, 1},
|
||||
{1, 0},
|
||||
{0, 0}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(coord0, true, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, false, false);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 2},
|
||||
{2, 1},
|
||||
{1, 0},
|
||||
{0, 1},
|
||||
{1, 1}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(coord1, true, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 0},
|
||||
{0, 1},
|
||||
{9, 0},
|
||||
{0, 9}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(coord0, false, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 0},
|
||||
{0, 1},
|
||||
{9, 0},
|
||||
{0, 9}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(coord0, false, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, false, false);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 0},
|
||||
{0, 1}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(coord0, false, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, false, false);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 0},
|
||||
{0, 1}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(coord0, false, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
auto rval = sologrid2d_foo.get_neighborhood(agent_id_foo, true, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_FALSE(rval);
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
sologrid2d_foo.add_agent(agent_id_foo, coord0);
|
||||
auto tval = unordered_set<GridCoord2D>({{0, 1},
|
||||
{9, 0},
|
||||
{0, 9},
|
||||
{1, 0},
|
||||
{0, 0}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(agent_id_foo, true, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
sologrid2d_foo.add_agent(agent_id_foo, coord1);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 2},
|
||||
{2, 1},
|
||||
{1, 0},
|
||||
{0, 1},
|
||||
{1, 1}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(agent_id_foo, true, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, false, false);
|
||||
sologrid2d_foo.add_agent(agent_id_foo, coord0);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{0, 1},
|
||||
{1, 0},
|
||||
{0, 0}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(agent_id_foo, true, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, false, false);
|
||||
sologrid2d_foo.add_agent(agent_id_foo, coord1);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 2},
|
||||
{2, 1},
|
||||
{1, 0},
|
||||
{0, 1},
|
||||
{1, 1}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(agent_id_foo, true, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
sologrid2d_foo.add_agent(agent_id_foo, coord0);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 0},
|
||||
{0, 1},
|
||||
{9, 0},
|
||||
{0, 9}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(agent_id_foo, false, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
sologrid2d_foo.add_agent(agent_id_foo, coord1);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{0, 1},
|
||||
{1, 2},
|
||||
{2, 1},
|
||||
{1, 0}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(agent_id_foo, false, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, false, false);
|
||||
sologrid2d_foo.add_agent(agent_id_foo, coord0);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 0},
|
||||
{0, 1}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(agent_id_foo, false, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, false, false);
|
||||
sologrid2d_foo.add_agent(agent_id_foo, coord1);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{0, 1},
|
||||
{1, 2},
|
||||
{2, 1},
|
||||
{1, 0}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(agent_id_foo, false, GridNeighborhoodType::VonNeumann);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SoloGrid2D, get_neighborhood_Moore) {
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord2D coord0(0, 0), coord1(1, 1), coord2(2, 5), coord3(3, 7), coord9(9, 4);
|
||||
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{9, 9},
|
||||
{9, 1},
|
||||
{1, 1},
|
||||
{0, 1},
|
||||
{9, 0},
|
||||
{1, 9},
|
||||
{0, 9},
|
||||
{1, 0},
|
||||
{0, 0}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(coord0, true, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{2, 2},
|
||||
{0, 2},
|
||||
{1, 2},
|
||||
{0, 0},
|
||||
{2, 1},
|
||||
{1, 0},
|
||||
{2, 0},
|
||||
{0, 1},
|
||||
{1, 1}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(coord1, true, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, false, false);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 1},
|
||||
{0, 1},
|
||||
{1, 0},
|
||||
{0, 0}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(coord0, true, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, false, false);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{2, 2},
|
||||
{0, 2},
|
||||
{1, 2},
|
||||
{0, 0},
|
||||
{2, 1},
|
||||
{1, 0},
|
||||
{2, 0},
|
||||
{0, 1},
|
||||
{1, 1}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(coord1, true, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{9, 9},
|
||||
{9, 1},
|
||||
{1, 0},
|
||||
{1, 1},
|
||||
{0, 1},
|
||||
{0, 9},
|
||||
{1, 9},
|
||||
{9, 0}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(coord0, false, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{9, 9},
|
||||
{9, 1},
|
||||
{1, 0},
|
||||
{1, 1},
|
||||
{0, 1},
|
||||
{0, 9},
|
||||
{1, 9},
|
||||
{9, 0}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(coord0, false, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, false, false);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 0},
|
||||
{1, 1},
|
||||
{0, 1}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(coord0, false, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, false, false);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 0},
|
||||
{1, 1},
|
||||
{0, 1}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(coord0, false, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
auto rval = sologrid2d_foo.get_neighborhood(agent_id_foo, true, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_FALSE(rval);
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
sologrid2d_foo.add_agent(agent_id_foo, coord0);
|
||||
auto tval = unordered_set<GridCoord2D>({{9, 9},
|
||||
{9, 1},
|
||||
{1, 1},
|
||||
{0, 1},
|
||||
{9, 0},
|
||||
{1, 9},
|
||||
{0, 9},
|
||||
{1, 0},
|
||||
{0, 0}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(agent_id_foo, true, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
sologrid2d_foo.add_agent(agent_id_foo, coord1);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{2, 2},
|
||||
{0, 2},
|
||||
{1, 2},
|
||||
{0, 0},
|
||||
{2, 1},
|
||||
{1, 0},
|
||||
{2, 0},
|
||||
{0, 1},
|
||||
{1, 1}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(agent_id_foo, true, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, false, false);
|
||||
sologrid2d_foo.add_agent(agent_id_foo, coord0);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 1},
|
||||
{0, 1},
|
||||
{1, 0},
|
||||
{0, 0}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(agent_id_foo, true, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, false, false);
|
||||
sologrid2d_foo.add_agent(agent_id_foo, coord1);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{2, 2},
|
||||
{0, 2},
|
||||
{1, 2},
|
||||
{0, 0},
|
||||
{2, 1},
|
||||
{1, 0},
|
||||
{2, 0},
|
||||
{0, 1},
|
||||
{1, 1}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(agent_id_foo, true, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
sologrid2d_foo.add_agent(agent_id_foo, coord0);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{9, 9},
|
||||
{9, 1},
|
||||
{1, 0},
|
||||
{1, 1},
|
||||
{0, 1},
|
||||
{0, 9},
|
||||
{1, 9},
|
||||
{9, 0}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(agent_id_foo, false, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
sologrid2d_foo.add_agent(agent_id_foo, coord1);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{2, 2},
|
||||
{2, 0},
|
||||
{0, 1},
|
||||
{0, 2},
|
||||
{1, 2},
|
||||
{0, 0},
|
||||
{2, 1},
|
||||
{1, 0}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(agent_id_foo, false, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, false, false);
|
||||
sologrid2d_foo.add_agent(agent_id_foo, coord0);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{1, 0},
|
||||
{1, 1},
|
||||
{0, 1}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(agent_id_foo, false, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, false, false);
|
||||
sologrid2d_foo.add_agent(agent_id_foo, coord1);
|
||||
|
||||
auto tval = unordered_set<GridCoord2D>({{2, 2},
|
||||
{2, 0},
|
||||
{0, 1},
|
||||
{0, 2},
|
||||
{1, 2},
|
||||
{0, 0},
|
||||
{2, 1},
|
||||
{1, 0}});
|
||||
auto rval = sologrid2d_foo.get_neighborhood(agent_id_foo, false, GridNeighborhoodType::Moore);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(tval, *rval.value());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SoloGrid2D, get_location_by_agent) {
|
||||
const AgentID agent_id_foo, agent_id_bar;
|
||||
const GridCoord2D coord2(2, 5), coord3(3, 7);
|
||||
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
EXPECT_FALSE(sologrid2d_foo.get_location_by_agent(agent_id_foo));
|
||||
EXPECT_FALSE(sologrid2d_foo.get_location_by_agent(agent_id_bar));
|
||||
}
|
||||
{
|
||||
SoloGrid2D sologrid2d_foo(10, 10, true, true);
|
||||
|
||||
static_cast<void>(sologrid2d_foo.add_agent(agent_id_foo, coord2));
|
||||
auto local = sologrid2d_foo.get_location_by_agent(agent_id_foo);
|
||||
EXPECT_TRUE(local);
|
||||
EXPECT_EQ(local, coord2);
|
||||
EXPECT_FALSE(sologrid2d_foo.get_location_by_agent(agent_id_bar));
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
125
test/unit-kami-staged.cc
Normal file
125
test/unit-kami-staged.cc
Normal file
@@ -0,0 +1,125 @@
|
||||
/*-
|
||||
* Copyright (c) 2022 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/population.h>
|
||||
#include <kami/staged.h>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace kami;
|
||||
using namespace std;
|
||||
|
||||
class TestAgent : public StagedAgent {
|
||||
public:
|
||||
AgentID step(shared_ptr<Model> model) override {
|
||||
return get_agent_id();
|
||||
}
|
||||
|
||||
AgentID advance(shared_ptr<Model> model) override {
|
||||
return get_agent_id();
|
||||
}
|
||||
};
|
||||
|
||||
class TestModel : public Model {
|
||||
public:
|
||||
optional<shared_ptr<vector<AgentID>>> step() {
|
||||
return _sched->step(shared_from_this());
|
||||
}
|
||||
|
||||
optional<shared_ptr<vector<AgentID>>> step(shared_ptr<vector<AgentID>> agent_list) {
|
||||
return _sched->step(shared_from_this(), move(agent_list));
|
||||
}
|
||||
};
|
||||
|
||||
class StagedSchedulerTest : public ::testing::Test {
|
||||
protected:
|
||||
shared_ptr<TestModel> mod = nullptr;
|
||||
|
||||
void SetUp() override {
|
||||
mod = make_shared<TestModel>();
|
||||
auto popul_foo = make_shared<Population>();
|
||||
auto sched_foo = make_shared<StagedScheduler>();
|
||||
|
||||
// Domain is not required for this test
|
||||
static_cast<void>(mod->set_population(popul_foo));
|
||||
static_cast<void>(mod->set_scheduler(sched_foo));
|
||||
|
||||
for (auto i = 0; i < 10; i++) {
|
||||
auto agent_foo = make_shared<TestAgent>();
|
||||
static_cast<void>(popul_foo->add_agent(agent_foo));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TEST(StagedScheduler, DefaultConstructor) {
|
||||
// There is really no way this can go wrong, but
|
||||
// we add this check anyway in case of future
|
||||
// changes.
|
||||
EXPECT_NO_THROW(
|
||||
const StagedScheduler sched_foo;
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(StagedSchedulerTest, step_interface1) {
|
||||
auto tval = mod->get_population().value()->get_agent_list();
|
||||
auto rval = mod->step();
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(rval.value()->size(), 10);
|
||||
EXPECT_EQ(*rval.value(), *tval);
|
||||
}
|
||||
|
||||
TEST_F(StagedSchedulerTest, step_interface2) {
|
||||
auto tval = mod->get_population().value()->get_agent_list();
|
||||
auto rval = mod->step(tval);
|
||||
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(rval.value()->size(), 10);
|
||||
EXPECT_EQ(*rval.value(), *tval);
|
||||
}
|
||||
|
||||
TEST_F(StagedSchedulerTest, step_10000) {
|
||||
auto tval = mod->get_population().value()->get_agent_list();
|
||||
|
||||
// Do it a lot...
|
||||
for (auto i = 0; i < 10000; i++) {
|
||||
auto rval = mod->step();
|
||||
EXPECT_TRUE(rval);
|
||||
EXPECT_EQ(rval.value()->size(), 10);
|
||||
EXPECT_EQ(*rval.value(), *tval);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
@@ -30,26 +30,21 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
class TestStagedAgent : public kami::StagedAgent {
|
||||
using namespace kami;
|
||||
using namespace std;
|
||||
|
||||
class TestStagedAgent : public StagedAgent {
|
||||
public:
|
||||
kami::AgentID advance(std::shared_ptr<kami::Model> model) override {
|
||||
AgentID advance(shared_ptr<Model> model) override {
|
||||
return get_agent_id();
|
||||
}
|
||||
|
||||
kami::AgentID step(std::shared_ptr<kami::Model> model) override {
|
||||
AgentID step(shared_ptr<Model> model) override {
|
||||
return get_agent_id();
|
||||
}
|
||||
};
|
||||
|
||||
class TestModel : public kami::Model {
|
||||
public:
|
||||
std::shared_ptr<kami::Model> step() override {
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
std::shared_ptr<kami::Model> run(unsigned int) override {
|
||||
return shared_from_this();
|
||||
}
|
||||
class TestModel : public Model {
|
||||
};
|
||||
|
||||
TEST(StagedAgent, DefaultConstructor) {
|
||||
@@ -71,7 +66,7 @@ TEST(StagedAgent, get_agent_id) {
|
||||
TEST(StagedAgent, advance) {
|
||||
TestStagedAgent agent_foo;
|
||||
TestStagedAgent agent_bar;
|
||||
auto model_world = std::make_shared<TestModel>();
|
||||
auto model_world = make_shared<TestModel>();
|
||||
|
||||
EXPECT_EQ(agent_foo.get_agent_id(), agent_foo.advance(model_world));
|
||||
EXPECT_NE(agent_bar.get_agent_id(), agent_foo.advance(model_world));
|
||||
@@ -80,7 +75,7 @@ TEST(StagedAgent, advance) {
|
||||
TEST(StagedAgent, step) {
|
||||
TestStagedAgent agent_foo;
|
||||
TestStagedAgent agent_bar;
|
||||
auto model_world = std::make_shared<TestModel>();
|
||||
auto model_world = make_shared<TestModel>();
|
||||
|
||||
EXPECT_EQ(agent_foo.get_agent_id(), agent_foo.step(model_world));
|
||||
EXPECT_NE(agent_bar.get_agent_id(), agent_foo.step(model_world));
|
||||
|
||||
Reference in New Issue
Block a user