1 module toml_foolery.decode.set_data_test; 2 3 version(unittest) 4 { 5 import exceeds_expectations; 6 import std.array : staticArray; 7 import toml_foolery.decode.set_data; 8 } 9 10 11 @("setData — simple as beans") 12 unittest 13 { 14 struct S 15 { 16 int a; 17 } 18 19 S s; 20 setData(s, ["a"], -44); 21 expect(s.a).toEqual(-44); 22 } 23 24 @("setData — rather more complex") 25 unittest 26 { 27 struct X 28 { 29 int abc; 30 } 31 32 struct S 33 { 34 string d; 35 X box; 36 } 37 38 S target; 39 setData(target, ["box", "abc"], 525_600); 40 expect(target.box.abc).toEqual(525_600); 41 } 42 43 @("setData — bloody complex") 44 unittest 45 { 46 struct Surprise 47 { 48 int a; 49 int b; 50 int c; 51 } 52 53 struct Ogres 54 { 55 struct Are 56 { 57 struct Like 58 { 59 struct Onions 60 { 61 Surprise bye; 62 } 63 64 Onions onions; 65 } 66 67 Like like; 68 } 69 70 Are are; 71 } 72 73 struct S 74 { 75 Ogres ogres; 76 } 77 78 S s; 79 80 setData(s, ["ogres", "are", "like", "onions", "bye"], Surprise(827, 912, 9)); 81 expect(s.ogres.are.like.onions.bye.a).toEqual(827); 82 expect(s.ogres.are.like.onions.bye.b).toEqual(912); 83 expect(s.ogres.are.like.onions.bye.c).toEqual(9); 84 } 85 86 @("setData — now with methods") 87 unittest 88 { 89 struct S 90 { 91 struct C 92 { 93 int x; 94 } 95 96 int a; 97 C c; 98 99 int noArgs() 100 { 101 return 123; 102 } 103 104 int oneArg(int c) 105 { 106 return c; 107 } 108 109 int oodlesOfArgs(int one, string two, char three) 110 { 111 return one; 112 } 113 114 void proc() { } 115 116 int varargs(int[] x...) 117 { 118 return x.length > 0 ? x[0] : -1; 119 } 120 121 C returnsStruct(C andTakesOneToo) 122 { 123 return andTakesOneToo; 124 } 125 } 126 127 S s; 128 129 setData(s, ["c", "x"], 5); 130 setData(s, ["a"], 9); 131 expect(s.c.x).toEqual(5); 132 expect(s.a).toEqual(9); 133 } 134 135 @("setData — properties") 136 unittest 137 { 138 struct S 139 { 140 int _x; 141 int x() @property const { return _x; } 142 void x(int newX) @property { _x = newX; } 143 } 144 145 S s; 146 setData(s, ["x"], 5); 147 expect(s.x).toEqual(5); 148 } 149 150 @("setData — read-only properties") 151 unittest 152 { 153 struct S 154 { 155 int y; 156 int x() @property const { return y; } 157 } 158 159 S s; 160 // Just needs to compile: 161 setData(s, ["y"], 5); 162 } 163 164 @("setData — fail compilation if struct contains a @property of type struct") 165 unittest 166 { 167 struct S 168 { 169 struct C 170 { 171 int x; 172 } 173 174 C _c; 175 C c() @property const { return _c; } 176 } 177 178 S s; 179 // C returns an rvalue, which cannot be ref, so it should be ignored by setData. 180 // This should compile but c.x can't be changed. 181 static assert (!__traits(compiles, setData(s, ["c", "x"], 5))); 182 } 183 184 @("setData — Static array -> Static array") 185 unittest 186 { 187 struct S 188 { 189 int[4] statArr; 190 int[5] badSizeStatArr; 191 } 192 193 S s; 194 195 setData(s, ["statArr"], staticArray!(int, 4)([27, 92, 71, -34])); 196 expect(s.statArr).toEqual(staticArray!(int, 4)([27, 92, 71, -34])); 197 198 expect({ setData(s, ["badSizeStatArr"], staticArray!(int, 4)([62, 12, 92, 10])); }).toThrow!Exception; 199 200 int[] dynArr = [33, 22, 11, 99]; 201 setData(s, ["statArr"], dynArr); 202 expect(s.statArr).toEqual(staticArray!(int, 4)([33, 22, 11, 99])); 203 } 204 205 @("setData — Into Static Array") 206 unittest 207 { 208 int[5] x; 209 210 setData(x, ["4"], 99); 211 expect(x[4]).toEqual(99); 212 } 213 214 @("setData — Into Static Array (out of range)") 215 unittest 216 { 217 int[5] x; 218 219 setData(x, ["5"], 99); 220 221 expect(x).toEqual((int[5]).init); 222 } 223 224 @("setData — Into Dynamic Array (with resizing)") 225 unittest 226 { 227 int[] x; 228 229 expect(x.length).toEqual(0); 230 setData(x, ["5"], 88); 231 expect(x.length).toEqual(6); 232 expect(x[5]).toEqual(88); 233 } 234 235 @("setData — Into static array of arrays") 236 unittest 237 { 238 int[6][4] x; 239 240 setData(x, ["3", "5"], 88); 241 expect(x[3][5]).toEqual(88); 242 } 243 244 @("setData — Into dynamic array of arrays") 245 unittest 246 { 247 int[][] x; 248 249 setData(x, ["5", "3"], 88); 250 expect(x.length).toEqual(6); 251 expect(x[5].length).toEqual(4); 252 expect(x[5][3]).toEqual(88); 253 } 254 255 @("setData — Into dynamic array of structs") 256 unittest 257 { 258 struct S 259 { 260 int x; 261 } 262 263 S[] s; 264 265 setData(s, ["5", "x"], 88); 266 expect(s.length).toEqual(6); 267 expect(s[5].x).toEqual(88); 268 } 269 270 @("setData — Into static array of structs") 271 unittest 272 { 273 struct S 274 { 275 int x; 276 } 277 278 S[4] s; 279 280 setData(s, ["3", "x"], 88); 281 expect(s[3].x).toEqual(88); 282 } 283 284 @("setData — Into field that is static array of ints") 285 unittest 286 { 287 struct S 288 { 289 int[3] i; 290 } 291 292 S s; 293 setData(s, ["i", "2"], 772); 294 295 expect(s.i[2]).toEqual(772); 296 } 297 298 @("setData — Into field that is static array of structs") 299 unittest 300 { 301 struct Outer 302 { 303 struct Inner 304 { 305 int x; 306 } 307 308 Inner[3] inner; 309 } 310 311 Outer outer; 312 setData(outer, ["inner", "2", "x"], 202); 313 314 expect(outer.inner[2].x).toEqual(202); 315 } 316 317 @("setData — array of struct with array of array of structs") 318 unittest 319 { 320 struct A 321 { 322 struct B 323 { 324 struct C 325 { 326 int x; 327 } 328 329 C[4][2] c; 330 } 331 332 B[3] b; 333 } 334 335 A a; 336 337 setData(a, ["b", "2", "c", "1", "3", "x"], 773); 338 expect(a.b[2].c[1][3].x).toEqual(773); 339 }