optional_tests.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. // Copyright (c) 2014-2021 Thomas Fussell
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy
  4. // of this software and associated documentation files (the "Software"), to deal
  5. // in the Software without restriction, including without limitation the rights
  6. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. // copies of the Software, and to permit persons to whom the Software is
  8. // furnished to do so, subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included in
  11. // all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. // THE SOFTWARE
  20. //
  21. // @license: http://www.opensource.org/licenses/mit-license.php
  22. // @author: see AUTHORS file
  23. #include <xlnt/xlnt.hpp>
  24. #include <xlnt/utils/optional.hpp>
  25. #include <helpers/test_suite.hpp>
  26. // test helpers
  27. namespace {
  28. // increments count when constructed, decrements when destructed
  29. // use to ensure correct ctor/dtor pairing
  30. struct alive_count
  31. {
  32. alive_count()
  33. {
  34. ++count;
  35. }
  36. alive_count(const alive_count &)
  37. {
  38. ++count;
  39. }
  40. alive_count(alive_count &&)
  41. {
  42. ++count;
  43. }
  44. ~alive_count()
  45. {
  46. --count;
  47. }
  48. alive_count &operator=(const alive_count &) = default;
  49. alive_count &operator=(alive_count &&) = default;
  50. static int count;
  51. };
  52. int alive_count::count = 0;
  53. // implicitly convertible from int
  54. struct convertible
  55. {
  56. // implicit construction from int
  57. convertible(int i)
  58. : val(i)
  59. {
  60. }
  61. int val;
  62. };
  63. // default ctor deleted
  64. struct no_default
  65. {
  66. no_default() = delete;
  67. int i;
  68. };
  69. } // namespace
  70. class optional_test_suite : public test_suite
  71. {
  72. public:
  73. optional_test_suite()
  74. : test_suite()
  75. {
  76. register_test(test_ctor);
  77. register_test(test_copy_ctor);
  78. register_test(test_move_ctor);
  79. register_test(test_copy_assign);
  80. register_test(test_move_assign);
  81. register_test(test_set_and_get);
  82. register_test(test_equality);
  83. register_test(test_const);
  84. }
  85. void test_ctor()
  86. {
  87. // default
  88. xlnt::optional<int> opt1;
  89. xlnt_assert(!opt1.is_set());
  90. // value
  91. const int test_val = 3;
  92. xlnt::optional<int> opt2(test_val);
  93. xlnt_assert(opt2.is_set());
  94. xlnt_assert_equals(opt2.get(), test_val);
  95. // converting
  96. xlnt::optional<convertible> opt3(test_val);
  97. xlnt_assert(opt3.is_set());
  98. xlnt_assert_equals(opt3.get().val, test_val);
  99. // no default ctor
  100. xlnt::optional<no_default> no_def_opt;
  101. }
  102. void test_copy_ctor()
  103. {
  104. { // copy behaviour
  105. xlnt::optional<int> opt1;
  106. xlnt::optional<int> opt2(opt1);
  107. xlnt_assert_equals(opt1, opt2);
  108. const int test_val = 123;
  109. xlnt::optional<int> opt3(test_val);
  110. xlnt::optional<int> opt4(opt3);
  111. xlnt_assert_equals(opt3, opt4);
  112. }
  113. { // lifetime checks
  114. xlnt::optional<alive_count> opt1(alive_count{});
  115. xlnt_assert_equals(1, alive_count::count);
  116. {
  117. xlnt::optional<alive_count> opt2(opt1);
  118. xlnt_assert_equals(2, alive_count::count);
  119. }
  120. xlnt_assert_equals(1, alive_count::count);
  121. }
  122. xlnt_assert_equals(0, alive_count::count); // dtor test
  123. }
  124. void test_move_ctor()
  125. {
  126. { // move behaviour
  127. xlnt::optional<int> opt1;
  128. xlnt::optional<int> opt2(std::move(opt1));
  129. xlnt_assert_equals(opt2, xlnt::optional<int>{}); // can't test against opt1 so use a temporary
  130. const int test_val = 123;
  131. xlnt::optional<int> opt3(test_val);
  132. xlnt::optional<int> opt4(std::move(opt3));
  133. xlnt_assert(opt4.is_set()); // moved to optional contains the value
  134. xlnt_assert_equals(opt4.get(), test_val);
  135. }
  136. { // lifetime checks
  137. xlnt::optional<alive_count> opt1(alive_count{});
  138. xlnt_assert_equals(1, alive_count::count);
  139. {
  140. xlnt::optional<alive_count> opt2(std::move(opt1));
  141. xlnt_assert_equals(1, alive_count::count); // opt1 is in a no-value state
  142. }
  143. xlnt_assert_equals(0, alive_count::count);
  144. }
  145. xlnt_assert_equals(0, alive_count::count); // dtor test
  146. }
  147. void test_copy_assign()
  148. {
  149. { // copy assign behaviour
  150. xlnt::optional<int> opt1;
  151. xlnt::optional<int> opt_assign1; // to actually test assignment, the value needs to be already created. using '=' is not enough
  152. opt_assign1 = opt1;
  153. xlnt_assert_equals(opt1, opt_assign1);
  154. const int test_val = 123;
  155. xlnt::optional<int> opt2(test_val);
  156. xlnt::optional<int> opt_assign2;
  157. opt_assign2 = opt2;
  158. xlnt_assert_equals(opt2, opt_assign2);
  159. }
  160. { // lifetime checks
  161. xlnt::optional<alive_count> opt1(alive_count{});
  162. xlnt_assert_equals(1, alive_count::count);
  163. {
  164. xlnt::optional<alive_count> opt_assign1;
  165. opt_assign1 = opt1;
  166. xlnt_assert_equals(2, alive_count::count);
  167. }
  168. xlnt_assert_equals(1, alive_count::count);
  169. }
  170. xlnt_assert_equals(0, alive_count::count); // dtor test
  171. }
  172. void test_move_assign()
  173. {
  174. { // copy assign behaviour
  175. xlnt::optional<int> opt1;
  176. xlnt::optional<int> opt_assign1; // to actually test assignment, the value needs to be already created. using '=' is not enough
  177. opt_assign1 = std::move(opt1);
  178. xlnt_assert_equals(opt_assign1, xlnt::optional<int>{}); // can't test against opt1 so use a temporary
  179. const int test_val = 123;
  180. xlnt::optional<int> opt2(test_val);
  181. xlnt::optional<int> opt_assign2;
  182. opt_assign2 = std::move(opt2);
  183. xlnt_assert(opt_assign2.is_set()); // moved to optional contains the value
  184. xlnt_assert_equals(opt_assign2.get(), test_val);
  185. }
  186. { // lifetime checks
  187. xlnt::optional<alive_count> opt1(alive_count{});
  188. xlnt_assert_equals(1, alive_count::count);
  189. {
  190. xlnt::optional<alive_count> opt_assign1;
  191. opt_assign1 = std::move(opt1);
  192. xlnt_assert_equals(1, alive_count::count); // opt1 is in a no-value state
  193. }
  194. xlnt_assert_equals(0, alive_count::count);
  195. }
  196. xlnt_assert_equals(0, alive_count::count); // dtor test
  197. }
  198. void test_set_and_get()
  199. {
  200. {
  201. xlnt::optional<int> test_opt;
  202. xlnt_assert(!test_opt.is_set());
  203. xlnt_assert_throws(test_opt.get(), xlnt::invalid_attribute);
  204. // set
  205. const int test_val1 = 321;
  206. test_opt.set(test_val1);
  207. xlnt_assert(test_opt.is_set());
  208. xlnt_assert_equals(test_opt.get(), test_val1);
  209. // set again
  210. const int test_val2 = 123;
  211. test_opt.set(test_val2);
  212. xlnt_assert(test_opt.is_set());
  213. xlnt_assert_equals(test_opt.get(), test_val2);
  214. // clear
  215. test_opt.clear();
  216. xlnt_assert(!test_opt.is_set());
  217. xlnt_assert_throws(test_opt.get(), xlnt::invalid_attribute);
  218. // set again
  219. const int test_val3 = 3;
  220. test_opt.set(test_val3);
  221. xlnt_assert(test_opt.is_set());
  222. xlnt_assert_equals(test_opt.get(), test_val3);
  223. // operator= set
  224. xlnt::optional<int> test_opt2;
  225. test_opt2 = test_val1;
  226. xlnt_assert_equals(test_opt2.get(), test_val1);
  227. }
  228. { // lifetime checks
  229. xlnt::optional<alive_count> test_opt;
  230. xlnt_assert_equals(0, alive_count::count);
  231. test_opt.set(alive_count());
  232. xlnt_assert_equals(1, alive_count::count);
  233. test_opt.set(alive_count()); // reassignment doesn't somehow skip the dtor
  234. xlnt_assert_equals(1, alive_count::count);
  235. test_opt.clear();
  236. xlnt_assert_equals(0, alive_count::count);
  237. }
  238. }
  239. void test_equality()
  240. {
  241. xlnt::optional<int> test_opt1;
  242. xlnt::optional<int> test_opt2;
  243. // no value opts compare equal
  244. xlnt_assert(test_opt1 == test_opt2);
  245. xlnt_assert(!(test_opt1 != test_opt2));
  246. xlnt_assert(test_opt2 == test_opt1);
  247. xlnt_assert(!(test_opt2 != test_opt1));
  248. // value compares false with no value
  249. const int test_val = 1;
  250. test_opt1.set(test_val);
  251. xlnt_assert(test_opt1 != test_opt2);
  252. xlnt_assert(!(test_opt1 == test_opt2));
  253. xlnt_assert(test_opt2 != test_opt1);
  254. xlnt_assert(!(test_opt2 == test_opt1));
  255. // value compares false with a different value
  256. const int test_val2 = 2;
  257. test_opt2.set(test_val2);
  258. xlnt_assert(test_opt1 != test_opt2);
  259. xlnt_assert(!(test_opt1 == test_opt2));
  260. xlnt_assert(test_opt2 != test_opt1);
  261. xlnt_assert(!(test_opt2 == test_opt1));
  262. // value compares equal with same value
  263. test_opt2.set(test_val);
  264. xlnt_assert(test_opt1 == test_opt2);
  265. xlnt_assert(!(test_opt1 != test_opt2));
  266. xlnt_assert(test_opt2 == test_opt1);
  267. xlnt_assert(!(test_opt2 != test_opt1));
  268. }
  269. void test_const()
  270. {
  271. // functions on a const optional
  272. const int test_val = 1;
  273. const xlnt::optional<int> opt(test_val);
  274. xlnt_assert(opt.is_set());
  275. xlnt_assert(opt.get() == test_val);
  276. xlnt::optional<int> opt2(test_val);
  277. xlnt_assert(opt == opt2);
  278. xlnt_assert(opt2 == opt);
  279. xlnt_assert(!(opt != opt2));
  280. xlnt_assert(!(opt2 != opt));
  281. }
  282. };
  283. static optional_test_suite x;