-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathbasic_dict_ops.cpp
113 lines (98 loc) · 3.6 KB
/
basic_dict_ops.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// #define CATCH_CONFIG_MAIN
#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers.hpp>
#include "dict.hpp"
using Dict = cppdict::Dict<int, double, std::string>;
TEST_CASE("Can (depp)copy nodes with operator=", "[simple cppdict::Dict<int, double, std::string>]")
{
Dict dict;
dict["this"]["is"]["the"]["source"] = 3.14;
dict["destination"] = dict["this"];
REQUIRE(dict["destination"]["is"]["the"]["source"].to<double>() == 3.14);
}
TEST_CASE("Can add values and retrieve them", "[simple cppdict::Dict<int, double, std::string>]")
{
Dict dict;
dict["first"] = 3.14;
dict["second"] = 1;
dict["third"] = std::string{"hello"};
SECTION("Added values should be retrievable")
{
REQUIRE(dict["first"].to<double>() == 3.14);
REQUIRE(dict["second"].to<int>() == 1);
REQUIRE(dict["third"].to<std::string>() == std::string{"hello"});
}
SECTION("Values are retrieved with the exact type")
{
REQUIRE_THROWS_WITH(dict["first"].to<int>(), "cppdict: to<T> invalid type");
REQUIRE_THROWS_WITH(dict["second"].to<double>(), "cppdict: to<T> invalid type");
}
SECTION("Dictionaries are also hierarchical")
{
dict["level1"]["level2"]["level3"] = std::string{"some data"};
REQUIRE(dict["level1"]["level2"]["level3"].to<std::string>() == std::string{"some data"});
}
}
TEST_CASE("Deals with both references and values",
"[simple cppdict::Dict<int, double, std::string>]")
{
Dict dict;
dict["0"]["1"] = 3.5;
dict["0"]["2"]["1"] = 55.;
dict["0"]["2"]["2"] = 56.;
dict["0"]["2"]["3"]["1"]["1"] = 666.;
SECTION("Values acces by value does a copy")
{
auto v = dict["0"]["1"].to<double>();
v = 10.;
REQUIRE(v != dict["0"]["1"].to<double>());
}
SECTION("Values access by ref doesn't copy")
{
auto& v = dict["0"]["1"].to<double>();
v = 10.;
REQUIRE(v == dict["0"]["1"].to<double>());
}
SECTION("Nodes access by value does copy")
{
auto node = dict["0"];
node["1"] = 100;
REQUIRE(dict["0"]["1"].to<double>() == 3.5);
node = dict["2"];
node["3"]["1"]["1"] = 42;
REQUIRE(dict["0"]["2"]["3"]["1"]["1"].to<double>() == 666.);
}
SECTION("Nodes access by ref doesn't copy")
{
auto& node = dict["0"];
node["1"] = 100;
node["2"]["3"]["1"]["1"] = 42;
REQUIRE(dict["0"]["1"].to<int>() == 100);
REQUIRE(dict["0"]["2"]["3"]["1"]["1"].to<int>() == 42);
}
}
TEST_CASE("Contains expects true or false", "[simple cppdict::Dict<int, double, std::string>]")
{
Dict dict;
dict["this"]["is"]["the"]["source"] = 3.14;
REQUIRE(dict["this"].contains("is"));
REQUIRE(!dict.contains("is"));
REQUIRE(dict["this"]["is"]["the"].contains("source"));
REQUIRE(!dict["this"]["is"]["the"]["source"].contains("nothing"));
}
TEST_CASE("Dict const accessor", "[simple cppdict::Dict<int>]")
{
Dict dict;
dict["first"] = 3.14;
dict["second"]["third"] = 3;
auto const& dictRef = dict;
REQUIRE(dictRef["first"].to<double>() == 3.14);
REQUIRE_THROWS_WITH(dictRef["second"].to<double>(), "cppdict: to<T> invalid type");
REQUIRE_THROWS_WITH(dictRef["one"]["two"].to<double>(), "cppdict: invalid key: one");
}
TEST_CASE("Can get_value key by delimiter if exists", "or default if missing")
{
Dict dict;
dict["this"]["is"]["pi"] = 3.14;
REQUIRE(cppdict::get_value(dict, "this/is/e", 2.71) == 2.71);
}