1 module dshould.contain; 2 3 import dshould.ShouldType; 4 import dshould.basic : not, should; 5 6 /** 7 * The word `.contain` takes one value, expected to appear in the range on the left hand side. 8 */ 9 public void contain(Should, T)(Should should, T expected, Fence _ = Fence(), string file = __FILE__, size_t line = __LINE__) 10 if (isInstanceOf!(ShouldType, Should)) 11 { 12 should.allowOnlyWords!("not", "only").before!"contain"; 13 14 should.addWord!"contain".checkContain(expected, file, line); 15 } 16 17 /// 18 unittest 19 { 20 [2, 3, 4].should.contain(3); 21 [2, 3, 4].should.not.contain(5); 22 } 23 24 public auto contain(Should)(Should should) 25 if (isInstanceOf!(ShouldType, Should)) 26 { 27 should.allowOnlyWords!("not").before!"contain"; 28 29 return should.addWord!"contain"; 30 } 31 32 /** 33 * The phrase `.contain.only` or `.only.contain` takes a range, the elements of which are expected to be the only 34 * elements appearing in the range on the left hand side. 35 */ 36 public void only(Should, T)(Should should, T expected, Fence _ = Fence(), string file = __FILE__, size_t line = __LINE__) 37 if (isInstanceOf!(ShouldType, Should)) 38 { 39 should.requireWord!"contain".before!"only"; 40 should.allowOnlyWords!("not", "contain").before!"only"; 41 42 should.addWord!"only".checkContain(expected, file, line); 43 } 44 45 /// 46 unittest 47 { 48 [3, 4].should.only.contain([4, 3]); 49 [3, 4].should.only.contain([1, 2, 3, 4]); 50 [3, 4].should.contain.only([4, 3]); 51 [2, 3, 4].should.not.only.contain([4, 3]); 52 } 53 54 public auto only(Should)(Should should) 55 if (isInstanceOf!(ShouldType, Should)) 56 { 57 should.allowOnlyWords!("not").before!"only"; 58 59 return should.addWord!"only"; 60 } 61 62 /** 63 * The phrase `.contain.all` takes a range, all elements of which are expected to appear 64 * in the range on the left hand side. 65 */ 66 public void all(Should, T)(Should should, T expected, Fence _ = Fence(), string file = __FILE__, size_t line = __LINE__) 67 if (isInstanceOf!(ShouldType, Should)) 68 { 69 should.requireWord!"contain".before!"all"; 70 should.allowOnlyWords!("not", "contain").before!"all"; 71 72 should.addWord!"all".checkContain(expected, file, line); 73 } 74 75 /// 76 unittest 77 { 78 [2, 3, 4].should.contain.all([3]); 79 [2, 3, 4].should.contain.all([4, 3]); 80 [2, 3, 4].should.not.contain.all([3, 4, 5]); 81 } 82 83 /** 84 * The phrase `.contain.any` takes a range, at least one element of which is expected to appear 85 * in the range on the left hand side. 86 */ 87 public void any(Should, T)(Should should, T expected, Fence _ = Fence(), string file = __FILE__, size_t line = __LINE__) 88 if (isInstanceOf!(ShouldType, Should)) 89 { 90 should.requireWord!"contain".before!"any"; 91 should.allowOnlyWords!("not", "contain").before!"any"; 92 93 should.addWord!"any".checkContain(expected, file, line); 94 } 95 96 /// 97 unittest 98 { 99 [2, 3, 4].should.contain.any([4, 5]); 100 [2, 3, 4].should.not.contain.any([5, 6]); 101 } 102 103 private void checkContain(Should, T)(Should should, T expected, string file, size_t line) 104 if (isInstanceOf!(ShouldType, Should)) 105 { 106 import std.algorithm : any, all, canFind; 107 import std.range : ElementType, save; 108 109 with (should) 110 { 111 auto got = should.got(); 112 113 enum rhsIsValue = is(T == ElementType!(typeof(got))); 114 115 static if (rhsIsValue) 116 { 117 allowOnlyWords!("not", "only", "contain").before!"contain"; 118 119 static if (hasWord!"only") 120 { 121 static if (hasWord!"not") 122 { 123 mixin(genCheck!("%s.any!(a => a != %s)", ["got", "expected"])); 124 } 125 else 126 { 127 mixin(genCheck!("%s.all!(a => a == %s)", ["got", "expected"])); 128 } 129 } 130 else 131 { 132 static if (hasWord!"not") 133 { 134 mixin(genCheck!("!%s.save.canFind(%s)", ["got", "expected"])); 135 } 136 else 137 { 138 mixin(genCheck!("%s.save.canFind(%s)", ["got", "expected"])); 139 } 140 } 141 } 142 else 143 { 144 static if (hasWord!"only") 145 { 146 static if (hasWord!"not") 147 { 148 mixin(genCheck!("!%s.all!(a => %s.save.canFind(a))", ["got", "expected"])); 149 } 150 else 151 { 152 mixin(genCheck!("%s.all!(a => %s.save.canFind(a))", ["got", "expected"])); 153 } 154 } 155 else static if (hasWord!"all") 156 { 157 static if (hasWord!"not") 158 { 159 mixin(genCheck!("!%s.all!(a => %s.save.canFind(a))", ["expected", "got"])); 160 } 161 else 162 { 163 mixin(genCheck!("%s.all!(a => %s.save.canFind(a))", ["expected", "got"])); 164 } 165 } 166 else static if (hasWord!"any") 167 { 168 static if (hasWord!"not") 169 { 170 mixin(genCheck!("!%s.any!(a => %s.save.canFind(a))", ["expected", "got"])); 171 } 172 else 173 { 174 mixin(genCheck!("%s.any!(a => %s.save.canFind(a))", ["expected", "got"])); 175 } 176 } 177 else 178 { 179 static assert(false, 180 `bad grammar: expected "contain all", "contain any", "contain only" (or "only contain")`); 181 } 182 } 183 } 184 }