Changeset 199
- Timestamp:
- 02/26/09 16:42:42 (3 years ago)
- Files:
-
- dunit/trunk/dunit/assertions/same.d (modified) (1 diff)
- dunit/trunk/dunit/assertions/to_string.d (deleted)
- dunit/trunk/dunit/assertions/variant.d (modified) (4 diffs)
- dunit/trunk/tests/variant.d (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
dunit/trunk/dunit/assertions/same.d
r198 r199 10 10 Result run(ConstraintRunner runner, Variant actual, Variant expected) 11 11 { 12 auto result = new Result(true, "same as ", expected, actual); 13 // How are two variants the same? 14 // At the heart of a Variant is a giant union. 15 // It contains a ubyte. 16 // Look through that for the size of the typeinfo. 17 // Caveat: for large structs, Variant heap-allocates and stores a pointer. 18 auto type = actual.type; 19 auto b = actual.sizeof; 20 if (isStruct(type)) 21 { 22 23 } 12 auto result = new Result(expected.same(actual), "same as", expected, actual); 24 13 return result; 25 14 } dunit/trunk/dunit/assertions/variant.d
r198 r199 3 3 import reflect.RuntimeTraits; 4 4 import tango.text.convert.Format; 5 import tango.text.convert.Float; 6 import tango.io.Stdout; 5 7 6 8 const MaxInline = 16; // I'll store 16 bytes in the variant itself 7 9 10 class VariantTypeMismatchException : Exception 11 { 12 this (char[] message) { super(message); } 13 } 14 8 15 struct Variant 9 16 { 17 uint size; 10 18 /// Data, if I'm storing inline. 11 19 ubyte[MaxInline] data; … … 31 39 obj = cast(Object)value; 32 40 } 41 size = T.sizeof; 33 42 return *this; 34 43 } … … 81 90 int opCmp (Variant other) 82 91 { 83 return type.compare (raw, other.raw); 92 if (obj && other.obj) 93 { 94 return obj.opCmp(other.obj); 95 } 96 else 97 { 98 return type.compare (raw, other.raw); 99 } 84 100 } 85 101 … … 93 109 { 94 110 char[256] buffer; 95 return Format.convertOne(buffer, type, raw).dup; 111 char[] result; 112 if (isFloat(type)) 113 { 114 result = asFloat(buffer); 115 } 116 else 117 { 118 result = Format.convertOne(buffer, type, raw).dup; 119 } 120 return result; 121 } 122 123 private char[] asFloat(char[] dest) 124 { 125 const digits = 10; 126 const exp = 20; 127 char[] result; 128 // NOTE: these cannot go into a switch statement. 129 // Nothing will ever match! 130 if (size == double.sizeof) 131 { 132 result = tango.text.convert.Float.format(dest, force!(double), digits, exp); 133 } 134 else if (size == float.sizeof) 135 { 136 result = tango.text.convert.Float.format(dest, force!(float), digits, exp); 137 } 138 else if (size == real.sizeof) 139 { 140 result = tango.text.convert.Float.format(dest, force!(real), digits, exp); 141 } 142 else 143 { 144 throw new VariantTypeMismatchException("Type " ~ type.toString ~ ": is a floating point type, but not float, double, or real."); 145 } 146 return truncate(result); 147 } 148 149 bool safeCast(TypeInfo dest) 150 { 151 return isImplicitly(type, dest); 152 } 153 154 T to(T)() 155 { 156 if (!safeCast(typeid(T))) 157 { 158 throw new VariantTypeMismatchException("Cannot implicitly convert from type " ~ type.toString ~ " to type " ~ T.stringof); 159 } 160 return force!(T); 161 } 162 163 T force(T)() 164 { 165 static if (is (T == class) || is (T == interface)) 166 { 167 return cast(T)obj; 168 } 169 else 170 { 171 T t; 172 ubyte* ptr = cast(ubyte*)&t; 173 ptr[0..T.sizeof] = raw[0..T.sizeof]; 174 return t; 175 } 96 176 } 97 177 } dunit/trunk/tests/variant.d
r198 r199 12 12 return bytes == other.bytes; 13 13 } 14 15 char[] toString() 16 { 17 return "I am a Foo! Guar!"; 18 } 14 19 } 15 20 … … 23 28 } 24 29 25 int opEquals (Object other)30 override int opEquals (Object other) 26 31 { 27 32 auto bar = cast(Bar) other; 28 33 return (bar) && (name == bar.name); 34 } 35 36 override int opCmp (Object other) 37 { 38 auto bar = cast(Bar) other; 39 if (!bar) return -1; 40 return bar.name[0] - name[0]; 29 41 } 30 42 … … 76 88 }; 77 89 90 tests["comparison, integer"] = 91 { 92 Variant v1 = Variant (5); 93 Variant v2 = Variant (7); 94 assert (v1 < v2, "less than fail"); 95 assert (v2 > v1, "greater than fail"); 96 }; 97 98 tests["set and get, object"] = 99 { 100 Bar foo = new Bar("strontium"); 101 Variant v = Variant (foo); 102 assert (v.to!(Bar)().name == "strontium", "wrong value"); 103 }; 104 105 tests["set and get, large struct"] = 106 { 107 Foo foo; 108 foo.bytes[17] = 92; 109 Variant v = Variant (foo); 110 assert (v.to!(Foo)().bytes[17] == 92, "wrong value"); 111 }; 112 113 tests["set and get, integer"] = 114 { 115 Variant v = Variant (5); 116 assert (v.to!(int) == 5, "wrong value"); 117 }; 118 78 119 tests["set and toString, integer"] = 79 120 { … … 110 151 assert (!(v1.same (v2)), "same when they should not be"); 111 152 }; 153 154 /* These toString tests aren't so essential -- I just use tango's formatting 155 * stuff. But this is a pretty important thing, so I want to spend some time on it. */ 156 tests["toString, bool"] = 157 { 158 assert (Variant(true).toString == "true", Variant(true).toString); 159 assert (Variant(false).toString == "false", Variant(false).toString); 160 }; 161 162 tests["toString, decimal, no trailing zeroes"] = 163 { 164 auto v = Variant(15.0); 165 assert (v.toString == "15", v.toString); 166 }; 167 168 tests["toString, decimal"] = 169 { 170 auto v = Variant(15.625); 171 assert (v.toString == "15.625", v.toString); 172 }; 173 174 tests["toString, class"] = 175 { 176 auto bar = new Bar("hihi"); 177 auto v = Variant(bar); 178 assert (v.toString == bar.toString, v.toString); 179 }; 180 181 tests["toString, struct"] = 182 { 183 Foo bar; 184 auto v = Variant(bar); 185 assert (v.toString == bar.toString, v.toString); 186 }; 187 188 tests["toString, integer"] = 189 { 190 assert (Variant(5).toString == "5", Variant(5).toString); 191 assert (Variant(-109).toString == "-109", Variant(-109).toString); 192 }; 112 193 } 113 194 }
