1 module dud.resolve.confstests; 2 3 import core.exception : AssertError; 4 import std.algorithm.iteration : map, joiner, filter; 5 import std.algorithm.searching : canFind; 6 import std.exception : enforce; 7 import std.format : format; 8 import std.stdio; 9 10 import dud.resolve.conf; 11 import dud.resolve.confs; 12 import dud.resolve.positive; 13 import dud.semver.versionrange; 14 15 private: 16 17 const c1 = Conf("foo", IsPositive.yes); 18 const c2 = Conf("foo", IsPositive.no); 19 const c3 = Conf("bar", IsPositive.yes); 20 const c4 = Conf("bar", IsPositive.no); 21 const c5 = Conf("", IsPositive.yes); 22 const c6 = Conf("", IsPositive.no); 23 const c7 = Conf("conf1", IsPositive.yes); 24 25 const(Confs) c12 = Confs([c1, c2]); 26 const(Confs) c13 = Confs([c1, c3]); 27 const(Confs) c14 = Confs([c1, c4]); 28 const(Confs) c15 = Confs([c1, c5]); 29 const(Confs) c16 = Confs([c1, c6]); 30 31 const(Confs) c23 = Confs([c2, c3]); 32 const(Confs) c24 = Confs([c2, c4]); 33 const(Confs) c25 = Confs([c2, c5]); 34 const(Confs) c26 = Confs([c2, c6]); 35 36 const(Confs) c34 = Confs([c3, c4]); 37 const(Confs) c35 = Confs([c3, c5]); 38 const(Confs) c36 = Confs([c3, c6]); 39 40 const(Confs) c45 = Confs([c4, c5]); 41 const(Confs) c46 = Confs([c4, c6]); 42 43 const(Confs) c56 = Confs([c5, c6]); 44 45 Confs[] cs; 46 47 static this() { 48 cs = buildConfs(); 49 } 50 51 unittest { 52 auto a = Confs([c5]); 53 auto b = Confs([c1]); 54 55 assert(allowsAny(c5, c1), format("\n%s\n%s", c5, c6)); 56 testAllowAny(a, b, true); 57 } 58 59 Confs[] buildConfs() { 60 Confs[] ret; 61 const cs = [c1, c2, c3, c4, c5, c6]; 62 foreach(it; cs) { 63 foreach(jt; cs) { 64 foreach(kt; cs) { 65 auto tmp = Confs([it, jt, kt]); 66 if(tmp == Confs.init) { 67 continue; 68 } 69 Confs d = tmp.dup(); 70 assert(d == tmp, format("\nold: %s\nnew: %s", tmp, d)); 71 ret ~= tmp; 72 } 73 } 74 } 75 return ret; 76 } 77 78 // invert 79 80 unittest { 81 void testInvert(const(Confs) a, const(Confs) exp, int line = __LINE__) { 82 const inv = a.invert(); 83 enforce!AssertError(inv == exp, format("\n a: %s\nexp: %s\nrst: %s", a, 84 exp, inv), __FILE__, line); 85 } 86 87 testInvert(c12, Confs([])); 88 testInvert(c13, c24); 89 testInvert(c14, c23); 90 testInvert(c15, Confs([c6])); // c5 is special 91 testInvert(c16, Confs([c5])); // c6 makes everything false 92 93 testInvert(c23, c14); 94 testInvert(c24, c13); 95 testInvert(c25, Confs([c6])); 96 testInvert(c26, Confs([c5])); 97 98 testInvert(c34, Confs([])); 99 testInvert(c35, Confs([c6])); 100 testInvert(c36, Confs([c5])); 101 102 testInvert(c45, Confs([c6])); 103 testInvert(c46, Confs([c5])); 104 105 testInvert(c56, Confs([c5])); 106 } 107 108 unittest { 109 const c = Confs([c1]).invert(); 110 const e = Confs([c2]); 111 assert(c == e, format("\n%s\n%s", c, e)); 112 } 113 114 // allowAll 115 116 unittest { 117 void testAllowAll(const(Confs) a, const(Confs) b, const bool exp, 118 int line = __LINE__) 119 { 120 struct Indivitual { 121 @safe pure: 122 const(Conf) a; 123 const(Conf) b; 124 125 string toString() const { 126 return format("\ta: %s\tb: %s\t%s", a, b, allowsAll(a, b)); 127 } 128 } 129 130 const bool rslt = allowsAll(a, b); 131 enforce!AssertError(rslt == exp, 132 format("\na: %s\nb: %s\nexp: %s\nrsl: %s\nall:\n%(%s\n%)", a, b, 133 exp, 134 rslt, 135 a.confs 136 .map!(it => b.confs.map!(jt => Indivitual(it, jt))) 137 .joiner), 138 __FILE__, line); 139 } 140 141 testAllowAll(Confs.init, Confs.init, true); 142 testAllowAll(Confs([c1, c5]), Confs([c1]), true); 143 testAllowAll(Confs([c5]), Confs([c1, c5]), true); 144 testAllowAll(Confs([c5]), Confs([c1, c3]), true); 145 testAllowAll(Confs([c1]), Confs([c1, c3, c5]), true); 146 testAllowAll(Confs([c3]), Confs([c1, c3, c5]), true); 147 testAllowAll(Confs([c3]), Confs([c3]), true); 148 testAllowAll(Confs([c1]), Confs([c1]), true); 149 testAllowAll(Confs([c2]), Confs([c2]), false); 150 testAllowAll(Confs([c2]), Confs([c1]), false); 151 testAllowAll(Confs([c2]), Confs([c3]), false); 152 testAllowAll(Confs([c2]), Confs([c4]), false); 153 testAllowAll(Confs([c2]), Confs([c5]), true); 154 testAllowAll(Confs([c2]), Confs([c6]), false); 155 156 foreach(it; cs) { 157 testAllowAll(Confs.init, it, false); 158 foreach(jt; cs) { 159 allowsAll(it, jt); 160 } 161 } 162 } 163 164 unittest { 165 void testAllowAll(const(Confs) a, const(Conf) b, const bool exp, 166 int line = __LINE__) 167 { 168 struct Indivitual { 169 @safe pure: 170 const(Conf) a; 171 const(Conf) b; 172 173 string toString() const { 174 return format("\ta: %s\tb: %s\t%s", a, b, allowsAll(a, b)); 175 } 176 } 177 178 const bool rslt = allowsAll(a, b); 179 enforce!AssertError(rslt == exp, 180 format("\na: %s\nb: %s\nexp: %s\nrsl: %s\nall:\n%(%s\n%)", a, b, exp, 181 rslt, a.confs.map!(it => Indivitual(it, b))), 182 __FILE__, line); 183 } 184 185 testAllowAll(c12, c1, false); 186 testAllowAll(c12, c2, false); 187 testAllowAll(c12, c3, false); 188 testAllowAll(c12, c4, false); 189 testAllowAll(c12, c5, false); 190 testAllowAll(c12, c6, false); 191 192 testAllowAll(c13, c1, true); 193 testAllowAll(c13, c2, false); 194 testAllowAll(c13, c3, true); 195 testAllowAll(c13, c4, false); 196 testAllowAll(c13, c5, false); 197 testAllowAll(c13, c6, false); 198 199 testAllowAll(c24, c1, false); 200 testAllowAll(c24, c2, false); 201 testAllowAll(c24, c3, false); 202 testAllowAll(c24, c4, false); 203 testAllowAll(c24, c5, false); 204 testAllowAll(c24, c6, false); 205 206 const(Confs) c22 = Confs([c2, c2]); 207 testAllowAll(c22, c2, false); 208 } 209 210 // allowsAny 211 struct IndivitualAny { 212 @safe pure: 213 const(Conf) a; 214 const(Conf) b; 215 216 string toString() const { 217 return format("\ta: %s\tb: %s\t%s", a, b, allowsAny(a, b)); 218 } 219 } 220 221 void testAllowAny(const(Confs) a, const(Conf) b, const bool exp, 222 int line = __LINE__) 223 { 224 const rsl = allowsAny(a, b); 225 enforce!AssertError(rsl == exp, format( 226 "\na: %s\nb: %s\nint: %s\nexp: %s\neach:%(%s\n%)", a, b, rsl, exp, 227 a.confs 228 .map!(aIt => IndivitualAny(aIt, b))), 229 __FILE__, line); 230 } 231 232 unittest { 233 testAllowAny(c13, c1, true); 234 testAllowAny(c13, c3, true); 235 testAllowAny(c13, c5, true); 236 testAllowAny(c12, c5, false); 237 } 238 239 void testAllowAny(const(Confs) a, const(Confs) b, const bool exp, 240 int line = __LINE__) 241 { 242 const rsl = allowsAny(a, b); 243 enforce!AssertError(rsl == exp, format( 244 "\na: %s\nb: %s\nint: %s\nexp: %s\neach:%(%s\n%)", a, b, rsl, exp, 245 a.confs 246 .map!(aIt => b.confs.map!(bIt => IndivitualAny(aIt, bIt))) 247 .joiner), 248 __FILE__, line); 249 } 250 251 unittest { 252 testAllowAny(c12, c12, true); 253 testAllowAny(c12, c13, false); 254 testAllowAny(c12, c14, false); 255 testAllowAny(c12, c15, false); 256 testAllowAny(c12, c16, false); 257 258 testAllowAny(c13, c14, true); 259 } 260 261 unittest { 262 foreach(it; cs) { 263 foreach(c; it.confs.filter!(it => it.isPositive == IsPositive.yes)) { 264 testAllowAny(it, c, true); 265 } 266 } 267 } 268 269 // intersectionOf 270 271 void testInter(const(Conf) a, const(Conf) b, const(Confs) exp, 272 int line = __LINE__) 273 { 274 const inter = intersectionOf(a, b); 275 enforce!AssertError(inter == exp, format( 276 "\na: %s\nb: %s\nint: %s\nexp: %s", a, b, inter, exp), 277 __FILE__, line); 278 } 279 280 unittest { 281 testInter(c7, c6, Confs([c6])); 282 } 283 284 void testInter(const(Confs) a, const(Confs) b, const(Confs) exp, 285 int line = __LINE__) 286 { 287 const inter = intersectionOf(a, b); 288 enforce!AssertError(inter == exp, format( 289 "\na: %s\nb: %s\nint: %s\nexp: %s", a, b, inter, exp), 290 __FILE__, line); 291 } 292 293 unittest { 294 testInter(Confs([c1, c3]), Confs([c1]), Confs([c1])); 295 testInter(Confs([c1]), Confs([c1]), Confs([c1])); 296 testInter(Confs([c3]), Confs([c1]), Confs([])); 297 } 298 299 unittest { 300 testInter(c13, c13, c13); 301 testInter(c13, c35, Confs([c1, c3])); 302 testInter(c35, c35, Confs([c3, c5])); 303 testInter(c56, c56, Confs([c6])); 304 305 Confs a = Confs([c1, c3]); 306 Confs b = Confs([c1, c3, c5]); 307 308 testInter(a, b, a); 309 } 310 311 unittest { 312 const a = Confs([c1]); 313 const b = Confs([c3]); 314 315 testInter(a, b, Confs([])); 316 } 317 318 // differenceOf 319 320 unittest { 321 const c11 = Confs([c1]); 322 const c33 = Confs([c3]); 323 const c13 = differenceOf(c11, c33); 324 } 325 326 unittest { 327 const none = Confs([Conf("", IsPositive.no)]); 328 foreach(it; cs) { 329 foreach(jt; cs) { 330 const r = differenceOf(it, jt); 331 if(it == jt && it != none) { 332 allowsAny(r, it); 333 allowsAny(r, jt); 334 } 335 } 336 } 337 } 338 339 // additional 340 341 unittest { 342 auto a = Confs([Conf("", IsPositive.no)]); 343 auto b = Confs([]); 344 345 assert(allowsAll(a, b)); 346 assert(allowsAny(a, b)); 347 }