27void check(
bool ok,
const std::string &what) {
32 std::cerr <<
" FAIL: " << what <<
"\n";
36template <
typename Call>
38 const std::string &what) {
42 }
catch (
const std::exception &e) {
43 if (std::string(e.what()).find(contains) != std::string::npos)
46 std::cerr <<
" FAIL: " << what <<
": message was " << e.what();
50 std::cerr <<
" FAIL: " << what <<
": nothing was thrown\n";
55 std::size_t d_count = 2;
56 double d_length = 1.5;
57 std::string d_method =
"central_difference";
59 double d_optional = -1.;
61 static const std::vector<inp::Field<SampleDeck>> &
fields() {
62 static const std::vector<inp::Field<SampleDeck>> f = {
64 "How many of them", {{}, std::size_t(1), std::size_t(3)}),
67 std::string(
"central_difference"),
"Time discretization",
68 {{
"central_difference",
"velocity_verlet"}, {}, {}}),
72 inp::field<SampleDeck, double>(
74 {}, [](
const double &v) {
return v > 0.; }),
81 std::cout <<
"defaults and schema\n";
83 check(d.at(
"Count") == 2,
"Count default is written");
84 check(d.at(
"Method") ==
"central_difference",
"Method default is written");
85 check(d.find(
"Optional") == d.end(),
86 "a field whose emit condition is false is absent");
89 check(s.size() == 5,
"schema reports one entry per field");
90 check(s.at(0).at(
"key") ==
"Count",
"schema reports the key");
91 check(s.at(0).at(
"type") ==
"size_t",
"schema reports the type");
92 check(s.at(0).at(
"default") == 2,
"schema reports the default");
93 check(s.at(0).at(
"doc") ==
"How many of them",
"schema reports the doc");
94 check(s.at(4).find(
"default") == s.at(4).end(),
95 "schema omits the default of a field that is not written");
99 std::cout <<
"read and write\n";
104 check(d.d_count == 3,
"Count is read");
105 check(d.d_length == 2.25,
"Length is read");
106 check(d.d_method ==
"central_difference",
"Method keeps its default");
107 check(d.d_write,
"Write keeps its default");
109 json out = json::object();
111 check(out == j,
"writing what was read gives the block back");
116 check(empty.
d_count == 2,
"an absent key leaves the default");
120 std::cout <<
"accepted values and bounds\n";
127 "must be one of",
"a value outside the accepted set is rejected");
132 "must be at most",
"a value above the upper bound is rejected");
137 "must be at least",
"a value below the lower bound is rejected");
141 std::cout <<
"keys are named and checked\n";
143 "Closest declared field is Count",
144 "a misspelled key names the closest field");
146 "no field named Horizon",
"an unrelated key is rejected");
148 "name and value pairs",
149 "a list of values without names is rejected");
154 check(j.find(
"Nested") != j.end(),
"a key named in extra is kept");
158 std::cout <<
"values are checked when a deck is built\n";
162 "a value above the bound is rejected when the deck is built");
169 "a value outside the accepted set is rejected when the deck is built");
172 check(ok.at(
"Count") == 3,
"an accepted value is kept");
176 check(given.find(
"Optional") == given.end(),
177 "giving a value the field does not write leaves it out");
179 check(set.at(
"Optional") == 2.5,
"giving a value the field writes keeps it");
183 std::cout <<
"printed form\n";
185 std::ostringstream oss;
187 const std::string s = oss.str();
188 check(s.find(
" Count = 2") != std::string::npos,
189 "the printed form has Count after the tab prefix");
190 check(s.find(
" Method = central_difference") != std::string::npos,
191 "the printed form has Method after the tab prefix");
195 std::cout <<
"quantities given in more than one way\n";
196 const std::vector<inp::OneOf> groups = {
197 {
"the horizon", {
"Horizon",
"Horizon_Mesh_Ratio"}},
198 {
"the contact stiffness", {
"Kn",
"V_Max"},
false},
207 "a required group with neither key is rejected");
211 json{{
"Horizon", 6.0e-4}, {
"Horizon_Mesh_Ratio", 3.0}}, groups);
213 "These were given: Horizon Horizon_Mesh_Ratio",
214 "a group with both keys is rejected and names them");
218 std::cout <<
"edit distance\n";
224void run(
void (*fn)(),
const std::string &name) {
227 }
catch (
const std::exception &e) {
230 std::cerr <<
" FAIL: " << name <<
" threw: " << e.what() <<
"\n";
237 std::cout <<
"Deck field table\n"
238 <<
"----------------\n";
248 std::cout <<
"----------------\n"
nlohmann::ordered_json json
void check(bool ok, const std::string &what)
void testDefaultsAndSchema()
void checkThrows(Call call, const std::string &contains, const std::string &what)
Fails unless the call throws with a message containing contains.
void testValuesCheckedWhenBuilt()
std::size_t editDistance(const std::string &a, const std::string &b)
Number of single character edits between two strings.
Field< Deck > field(T Deck::*m, std::string key, T def, std::string doc, Accepts< T > accepts={}, std::function< bool(const T &)> emitIf=[](const T &) { return true;})
Declares a field that maps one key to one member.
void readFields(Deck &d, const json &j, const std::vector< Field< Deck > > &fs)
Reads every field of the table from the block.
json defaultsJson(const std::vector< Field< Deck > > &fs)
The block with every field at its default.
void writeFields(const Deck &d, json &j, const std::vector< Field< Deck > > &fs)
Writes every field of the table into the block.
void printFields(const Deck &d, std::ostringstream &oss, const std::vector< Field< Deck > > &fs, const std::string &tab="")
Appends every field of the table to a stream.
json applyGiven(const json &given, const std::vector< Field< Deck > > &fs, const std::vector< std::string > &extra={})
The default block with the given keys replaced.
void checkGroups(const json &block, const std::vector< OneOf > &groups)
Checks that each group has exactly one of its keys.
json schemaJson(const std::vector< Field< Deck > > &fs)
Key, type, default and description of every field.
A deck with one field of each kind the tables have to handle.
static const std::vector< inp::Field< SampleDeck > > & fields()