libgrading
A simple library for grading C and C++ assignments.
 All Classes Namespaces Files Functions Enumerations Enumerator
checks.cpp
Go to the documentation of this file.
1 
22 #include <libgrading.h>
23 
24 #include <distance.h>
25 
26 #include <cassert>
27 #include <cmath>
28 #include <functional>
29 
30 using std::string;
31 using std::to_string;
32 
33 
34 namespace grading {
35 
36 CheckResult::CheckResult()
37  : reportError_(false), expected_(""), actual_("")
38 {
39 }
40 
41 CheckResult::CheckResult(string message)
42  : reportError_(true), expected_(""), actual_(message)
43 {
44 }
45 
46 CheckResult::CheckResult(string expected, string actual)
47  : reportError_(true), expected_(expected), actual_(actual)
48 {
49 }
50 
51 CheckResult::CheckResult(CheckResult&& other)
52  : reportError_(other.reportError_),
53  expected_(other.expected_), actual_(other.actual_),
54  message_(std::move(other.message_))
55 {
56  other.reportError_ = false;
57 }
58 
59 
60 //
61 // NOTE: CheckResult::~CheckResult() is implementation-specific and is
62 // implemented in posix.cpp, etc.
63 //
64 
65 
66 CheckResult operator && (CheckResult&& x, CheckResult&& y)
67 {
68  if (not x.error() and not y.error())
69  {
70  x.cancel();
71  y.cancel();
72 
73  return CheckResult();
74  }
75 
76  if (not x.error())
77  return std::move(y);
78 
79  else if (not y.error())
80  return std::move(x);
81 
82  const string exp = "(" + x.expected() + " and " + y.expected() + ")";
83  const string actual =
84  (x.actual() == y.actual())
85  ? x.actual()
86  : "(" + x.actual() + " or " + y.actual() + ")"
87  ;
88 
89  x.cancel();
90  y.cancel();
91 
92  return std::move(
93  CheckResult(exp, actual)
94  << x.message() << y.message()
95  );
96 }
97 
98 
99 CheckResult operator && (CheckResult&& x, CheckResult& y)
100 {
101  return std::move(x) and std::move(y);
102 }
103 
104 
105 CheckResult operator || (CheckResult&& x, CheckResult&& y)
106 {
107  if (not x.error() or not y.error())
108  {
109  x.cancel();
110  y.cancel();
111 
112  return CheckResult();
113  }
114 
115  const string exp = "(" + x.expected() + " or " + y.expected() + ")";
116  const string actual =
117  (x.actual() == y.actual())
118  ? x.actual()
119  : "(" + x.actual() + " or " + y.actual() + ")"
120  ;
121 
122  x.cancel();
123  y.cancel();
124 
125  return CheckResult(exp, actual);
126 }
127 
128 
129 CheckResult operator || (CheckResult&& x, CheckResult& y)
130 {
131  return std::move(x) or std::move(y);
132 }
133 
134 
135 CheckResult& CheckResult::operator << (const std::vector<std::string>& v)
136 {
137  message_ << "[ ";
138 
139  for (size_t i = 0; i < v.size(); i++)
140  {
141  message_ << "'" << v[i] << "'";
142  if (i < (v.size() - 1))
143  message_ << ", ";
144  }
145 
146  message_ << " ]";
147 
148  return *this;
149 }
150 
151 
152 //
153 // Checks for tests:
154 //
155 
156 CheckResult Check(bool condition, string description)
157 {
158  if (condition)
159  return CheckResult();
160 
161  return CheckResult(description);
162 }
163 
164 CheckResult CheckInt(int expected, int actual)
165 {
166  if (expected == actual)
167  return CheckResult();
168 
169  return CheckResult(to_string(expected), to_string(actual));
170 }
171 
172 CheckResult CheckFloat(double exp, double actual, double tolerance)
173 {
174  const double error = fabs(actual - exp);
175 
176  if (error < tolerance)
177  return CheckResult();
178 
179  const double relativeTolerance = exp * tolerance;
180 
181  if (error < relativeTolerance)
182  return CheckResult();
183 
184  return CheckResult(to_string(exp), to_string(actual));
185 }
186 
187 CheckResult CheckString(string expected, string actual, size_t maxDistance)
188 {
189  if (expected == actual)
190  return CheckResult();
191 
192  const size_t editDistance = static_cast<size_t>(
193  levenshtein_d(expected.c_str(), expected.length(),
194  actual.c_str(), actual.length()));
195 
196  if (editDistance <= maxDistance)
197  return CheckResult();
198 
199  return CheckResult(expected, actual);
200 }
201 
202 } // namespace grading
A library for grading C- and C++-based assignments.
CheckResult CheckInt(int expected, int actual)
Check that two integers are equal, failing the test if they are not.
Definition: checks.cpp:164
STL namespace.
CheckResult Check(bool, std::string description)
Check an arbitrary condition, failing the test if false.
Definition: checks.cpp:156
CheckResult operator||(CheckResult &&, CheckResult &&)
Combine the results of two checks using a sum (OR): at least one must pass.
Definition: checks.cpp:105
CheckResult CheckString(std::string expected, std::string actual, size_t maxEditDistance=0)
Check that two strings are (approximately) equal.
Definition: checks.cpp:187
CheckResult operator&&(CheckResult &&, CheckResult &&)
Combine the results of two checks using a product (AND): both must pass.
Definition: checks.cpp:66
CheckResult CheckFloat(double exp, double act, double tolerance=0.000001)
Check that two floating-point numbers are equal within some tolerance.
Definition: checks.cpp:172
Container for all libgrading names.
Definition: libgrading.h:34