1 module unit_threaded.ut.issues; 2 3 import unit_threaded; 4 import unit_threaded.asserts; 5 6 7 interface ICalcView { 8 @property string total() @safe pure; 9 @property void total(string t) @safe pure; 10 } 11 12 class CalcController { 13 private ICalcView view; 14 15 this(ICalcView view) @safe pure { 16 this.view = view; 17 } 18 19 void onClick(int number) @safe pure { 20 import std.conv: to; 21 view.total = number.to!string; 22 } 23 } 24 25 26 @("54") 27 @safe pure unittest { 28 auto m = mock!ICalcView; 29 m.expect!"total"("42"); 30 31 auto ctrl = new CalcController(m); 32 ctrl.onClick(42); 33 34 m.verify; 35 } 36 37 38 @("82") 39 // @system because of Object member functions are @system 40 @system unittest { 41 42 import std.exception: assertThrown; 43 44 static class A { 45 string x; 46 47 override string toString() @safe const { 48 return x; 49 } 50 } 51 52 class B : A {} 53 54 auto actual = new B; 55 auto expected = new B; 56 57 actual.x = "foo"; 58 expected.x = "bar"; 59 60 assertThrown(actual.shouldEqual(expected)); 61 } 62 63 64 @("124") 65 @safe pure unittest { 66 static struct Array { 67 68 alias opSlice this; 69 70 private int[] ints; 71 72 bool opCast(T)() const if(is(T == bool)) { 73 return ints.length != 0; 74 } 75 76 inout(int)[] opSlice() @safe inout { 77 return ints; 78 } 79 80 string toString() @safe pure const { 81 import std.conv: text; 82 return text(this); 83 } 84 } 85 86 87 static huh() @safe { 88 import std.conv: to; 89 return Array([1, 2, 3]).to!string; 90 } 91 92 { 93 auto arr = Array([1, 2, 3]); 94 arr.shouldEqual([1, 2, 3]); 95 } 96 97 { 98 const arr = Array([1, 2, 3]); 99 arr.shouldEqual([1, 2, 3]); 100 } 101 102 } 103 104 105 @("138") 106 @safe unittest { 107 import std.exception: assertThrown; 108 109 static class Class { 110 private string foo; 111 override bool opEquals(scope Object b) @safe @nogc pure nothrow scope const { 112 return foo == (cast(Class)b).foo; 113 } 114 } 115 116 auto a = new Class; 117 auto b = new Class; 118 119 a.foo = "1"; 120 b.foo = "2"; 121 122 // Object.opEquals isn't scope and therefore not @safe 123 assertThrown(() @trusted { a.should == b; }()); 124 } 125 126 127 @("146") 128 @safe unittest { 129 version(unitThreadedLight) {} 130 else { 131 assertExceptionMsg(shouldApproxEqual(42000.301, 42000.302, 1e-9), 132 ` tests/unit_threaded/ut/issues.d:123 - Expected approx: 42000.302000` ~ "\n" ~ 133 ` tests/unit_threaded/ut/issues.d:123 - Got : 42000.301000`); 134 } 135 } 136 137 138 version(unitThreadedLight) {} 139 else { 140 141 // should not compile for @safe 142 @("176.0") 143 @safe pure unittest { 144 145 int* ptr; 146 bool func(int a) { 147 *(ptr + 256) = 42; 148 return a % 2 == 0; 149 } 150 151 static assert(!__traits(compiles, check!func(100))); 152 } 153 154 @("176.1") 155 @safe unittest { 156 import std.traits: isSafe; 157 158 int* ptr; 159 bool func(int a) { 160 *(ptr + 256) = 42; 161 return a % 2 == 0; 162 } 163 164 static assert(!isSafe!({ check!func(100); })); 165 } 166 } 167 168 169 @("182") 170 // not @safe or pure because the InputRange interface member functions aren't 171 @system unittest { 172 import std.range: inputRangeObject; 173 auto a = [1, 2, 3]; 174 auto b = [1, 2, 3]; 175 a.inputRangeObject.should == b; 176 } 177 178 179 @("184.0") 180 @safe pure unittest { 181 182 import std.traits; 183 184 auto obviouslySystem = { 185 int* foo = cast(int*) 42; 186 *foo = 42; 187 }; 188 189 static assert(!isSafe!(obviouslySystem)); 190 191 void oops()() { 192 shouldThrow(obviouslySystem); 193 } 194 195 // oops; // uncomment to ever check the compiler error message 196 static assert(!isSafe!(oops!()), 197 "Passing @system functions to shouldThrow should not be @safe"); 198 } 199 200 201 @("184.1") 202 @safe pure unittest { 203 204 import std.traits: isUnsafe; 205 206 auto obviouslySystem = { 207 int* foo = cast(int*) 42; 208 *foo = 42; 209 }; 210 211 static assert(isUnsafe!(obviouslySystem)); 212 213 void oops()() { 214 shouldThrowExactly!Exception(obviouslySystem); 215 } 216 217 // oops; // uncomment to ever check the compiler error message 218 static assert(isUnsafe!(oops!()), 219 "Passing @system functions to shouldThrowExactly should not be @safe"); 220 } 221 222 223 @("185") 224 @safe pure unittest { 225 static struct S { 226 227 int i; 228 229 bool opEquals(T...)(T whatever) /* not const */ { 230 return true; 231 } 232 } 233 234 S(42).should == S(33); 235 } 236 237 238 version(unitThreadedLight) {} 239 else { 240 @("186") 241 @safe pure unittest { 242 243 import std.traits: isUnsafe; 244 245 static struct Key { 246 247 int val; 248 249 string toString () const @system { 250 int* ptr = cast(int*) 42; 251 *ptr = 42; 252 return "Oops"; 253 } 254 } 255 256 Key a = Key(42); 257 Key b = Key(84); 258 259 void impl()() { 260 a.should == b; 261 } 262 263 // unsafe due to unsafe toString 264 static assert(isUnsafe!(impl!())); 265 } 266 } 267 268 269 @("shouldEqual.enum.text") 270 @safe pure unittest { 271 static enum Enum { 272 text, 273 } 274 275 Enum.init.should == Enum.init; 276 } 277 278 279 @("212.0") 280 // not pure because of float comparison 281 @safe unittest { 282 float[] lhs = [2f, 4, 6, 8, 10, 12]; 283 float[6] rhs = [2f, 4, 6, 8, 10, 12]; 284 285 lhs.should == rhs; 286 rhs.should == lhs; 287 } 288 289 290 @("212.1") 291 @safe pure unittest { 292 int[] lhs = [2, 4, 6, 8, 10, 12]; 293 int[6] rhs = [2, 4, 6, 8, 10, 12]; 294 295 lhs.should == rhs; 296 rhs.should == lhs; 297 }