# HG changeset patch # User Jacob Carlborg # Date 1290161695 -3600 # Node ID fc315d786f2469cc423fd40952c245a16a21ced2 # Parent 78e5fef4bbf2ce72ad86dd9b674dc97af407d4dc Added unit testing. diff -r 78e5fef4bbf2 -r fc315d786f24 .hgignore --- a/.hgignore Tue Oct 19 10:22:10 2010 +0200 +++ b/.hgignore Fri Nov 19 11:14:55 2010 +0100 @@ -16,4 +16,5 @@ *.framework kandil lib -import \ No newline at end of file +import +unittest \ No newline at end of file diff -r 78e5fef4bbf2 -r fc315d786f24 dsss.conf --- a/dsss.conf Tue Oct 19 10:22:10 2010 +0200 +++ b/dsss.conf Fri Nov 19 11:14:55 2010 +0100 @@ -1,3 +1,11 @@ #[orange/serialization/Serializer.d] -[main.d] -#[orange] \ No newline at end of file + +#[main.d] + + +#[orange] + +[tests/all.d] +buildflags += -unittest +target = unittest +version += OrangeUnitTest \ No newline at end of file diff -r 78e5fef4bbf2 -r fc315d786f24 orange/_.d --- a/orange/_.d Tue Oct 19 10:22:10 2010 +0200 +++ b/orange/_.d Fri Nov 19 11:14:55 2010 +0100 @@ -8,6 +8,7 @@ public: +import orange.core._; import orange.serialization._; import orange.serialization.archives._; import orange.util._; \ No newline at end of file diff -r 78e5fef4bbf2 -r fc315d786f24 orange/core/string.d --- a/orange/core/string.d Tue Oct 19 10:22:10 2010 +0200 +++ b/orange/core/string.d Fri Nov 19 11:14:55 2010 +0100 @@ -48,6 +48,8 @@ alias std.string.toString fromStringz; } +import orange.util.Traits; + version (Tango) { /** @@ -885,4 +887,54 @@ return i; } +} + +T[] replace (T) (T[] source, dchar match, dchar replacement) +{ + static assert(isChar!(T), `The type "` ~ T.stringof ~ `" is not a valid type for this function only strings are accepted`); + + dchar endOfCodeRange; + + static if (is(T == wchar)) + { + const encodedLength = 2; + endOfCodeRange = wchar.init; + } + + else static if (is(T == char)) + { + const encodedLength = 4; + endOfCodeRange = '\x7F'; + } + + if (replacement <= endOfCodeRange && match <= endOfCodeRange) + { + foreach (ref c ; source) + if (c == match) + c = replacement; + + return source; + } + + else + { + static if (!is(T == dchar)) + { + T[encodedLength] encodedMatch; + T[encodedLength] encodedReplacement; + + version (Tango) + return source.substitute(encode(encodedMatch, match), encode(encodedReplacement, replacement)); + + else + { + auto matchLength = encode(encodedMatch, match); + auto replacementLength = encode(encodedReplacement, replacement); + + return std.string.replace(source, encodedMatch[0 .. matchLength], encodedReplacement[0 .. replacementLength]); + } + } + } + + return source; } \ No newline at end of file diff -r 78e5fef4bbf2 -r fc315d786f24 orange/serialization/Serializer Binary file orange/serialization/Serializer has changed diff -r 78e5fef4bbf2 -r fc315d786f24 orange/serialization/Serializer.d --- a/orange/serialization/Serializer.d Tue Oct 19 10:22:10 2010 +0200 +++ b/orange/serialization/Serializer.d Fri Nov 19 11:14:55 2010 +0100 @@ -956,103 +956,20 @@ return annotations; } } - - - -debug (OrangeUnitTest) -{ - import orange.serialization.archives.XMLArchive; - - enum Foo { a, b, c } - typedef int Int; - - class A {} - struct B {} - class C { string str; } - class D { int[] arr; } - class E { int[int] aa; } - class F { int value; int* ptr; } - class G { Foo foo; } - - class H - { - bool bool_; - byte byte_; - //cdouble cdouble_; // currently not suppported by to!() - //cent cent_; // currently not implemented but a reserved keyword - //cfloat cfloat_; // currently not suppported by to!() - char char_; - //creal creal_; // currently not suppported by to!() - dchar dchar_; - double double_; - float float_; - //idouble idouble_; // currently not suppported by to!() - //ifloat ifloat_; // currently not suppported by to!() - int int_; - //ireal ireal_; // currently not suppported by to!() - long long_; - real real_; - short short_; - ubyte ubyte_; - //ucent ucent_; // currently not implemented but a reserved keyword - uint uint_; - ulong ulong_; - ushort ushort_; - wchar wchar_; - - equals_t opEquals (Object other) - { - if (auto o = cast(H) other) - { - return bool_ == o.bool_ && - byte_ == o.byte_ && - //cdouble_ == o.cdouble_ && // currently not suppported by to!() - //cent_ == o.cent_ && // currently not implemented but a reserved keyword - //cfloat_ == o.cfloat_ && // currently not suppported by to!() - char_ == o.char_ && - //creal_ == o.creal_ && // currently not suppported by to!() - dchar_ == o.dchar_ && - double_ == o.double_ && - float_ == o.float_ && - //idouble_ == o.idouble_ && // currently not suppported by to!() - //ifloat_ == o.ifloat_ && // currently not suppported by to!() - int_ == o.int_ && - //ireal_ == o.ireal_ && // currently not suppported by to!() - long_ == o.long_ && - real_ == o.real_ && - short_ == o.short_ && - ubyte_ == o.ubyte_ && - //ucent_ == o.ucent_ && // currently not implemented but a reserved keyword - uint_ == o.uint_ && - ulong_ == o.ulong_ && - ushort_ == o.ushort_ && - wchar_ == o.wchar_; - } - - return false; - } - } - - class I - { - Int a; - } - +version (none): void main () { - auto archive = new XMLArchive!(char); - auto serializer = new Serializer(archive); - string data; + void serializeObject () { serializer.reset; data = ` - - - - -`; + + + + + `; serializer.serialize(B()); assert(archive.data == data); @@ -1062,11 +979,11 @@ { serializer.reset; data = ` - - - - -`; + + + + + `; serializer.serialize(B()); assert(archive.data == data); @@ -1080,13 +997,13 @@ serializer.reset; data = ` - - - - foo - - -`; + + + + foo + + + `; auto c = new C; c.str = "foo"; @@ -1099,23 +1016,23 @@ assert(c.str == cDeserialized.str); // Array - + serializer.reset; data = ` - - - - - 27 - 382 - 283 - 3820 - 32 - 832 - - - -`; + + + + + 27 + 382 + 283 + 3820 + 32 + 832 + + + + `; auto d = new D; d.arr = [27, 382, 283, 3820, 32, 832]; @@ -1131,38 +1048,38 @@ serializer.reset(); data = ` - - - - - - 1 - - - 2 - - - 3 - - - 4 - - - 6 - - - 7 - - - 39 - - - 472 - - - - -`; + + + + + + 1 + + + 2 + + + 3 + + + 4 + + + 6 + + + 7 + + + 39 + + + 472 + + + + + `; auto e = new E; e.aa = [3 : 4, 1 : 2, 39 : 472, 6 : 7]; @@ -1178,16 +1095,16 @@ serializer.reset(); data = ` - - - - - 9 - - 9 - - -`; + + + + + 9 + + 9 + + + `; auto f = new F; f.value = 9; @@ -1204,13 +1121,13 @@ serializer.reset(); data = ` - - - - 1 - - -`; + + + + 1 + + + `; auto g = new G; g.foo = Foo.b; @@ -1226,27 +1143,27 @@ serializer.reset; data = ` - - - - 1 - a - b - 0 - 0 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 1 - c - true - - -`; + + + + 1 + a + b + 0 + 0 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 1 + c + true + + + `; auto h = new H; @@ -1284,15 +1201,15 @@ serializer.reset(); data = ` - - - - - 1 - - - -`; + + + + + 1 + + + + `; auto i = new I; i.a = 1; @@ -1306,4 +1223,3 @@ println("unit tests successful"); } -} \ No newline at end of file diff -r 78e5fef4bbf2 -r fc315d786f24 orange/test/UnitTester.d --- a/orange/test/UnitTester.d Tue Oct 19 10:22:10 2010 +0200 +++ b/orange/test/UnitTester.d Fri Nov 19 11:14:55 2010 +0100 @@ -6,56 +6,215 @@ */ module orange.test.UnitTester; +version (Tango) +{ + import tango.io.device.File; + import tango.io.stream.Lines; + import tango.util.Convert; + import tango.sys.Environment; +} + + +else + import std.conv; + import tango.core.Exception; +import tango.io.FilePath; import orange.core._; import orange.util._; +Use!(void delegate (), string) describe (string message) +{ + return UnitTester.instance.describe(message); +} + +Use!(void delegate (), string) it (string message) +{ + return UnitTester.instance.test(message); +} + +void delegate () before () +{ + return UnitTester.instance.before; +} + +void delegate () before (void delegate () before) +{ + return UnitTester.instance.before = before; +} + +void delegate () after () +{ + return UnitTester.instance.after; +} + +void delegate () after (void delegate () after) +{ + return UnitTester.instance.after = after; +} + +void run () +{ + UnitTester.instance.run; +} + +private: + class UnitTester { - private + private: + + struct DescriptionManager { - struct Test + Description[] descriptions; + size_t lastIndex = size_t.max; + + void opCatAssign (Description description) + { + descriptions ~= description; + lastIndex++; + } + + void opCatAssign (Test test) { - void delegate () test; - string message; - AssertException exception; + last.tests ~= test; + } + + Description opIndex (size_t i) + { + return descriptions[i]; + } + + Description last () + { + return descriptions[$ - 1]; + } + + Description first () + { + return descriptions[0]; + } + + int opApply (int delegate(ref Description) dg) + { + int result = 0; - bool failed () + foreach (desc ; descriptions) { - return !succeeded; - } - - bool succeeded () - { - return !exception; + result = dg(desc); + + if (result) + return result; } - void run () - { - if (!isPending) - test(); - } - - bool isPending () - { - return test is null; - } + return result; + } + + size_t length () + { + return descriptions.length; + } + } + + class Description + { + private + { + DescriptionManager descriptions; + Test[] tests; + Test[] failures; + Test[] pending; + size_t lastIndex = size_t.max; + string message; + void delegate () description; + } + + this (string message) + { + this.message = message; + } + + void run () + { + if (shouldRun) + description(); + } + + bool shouldRun () + { + return description !is null; + } + } + + struct Test + { + void delegate () test; + string message; + AssertException exception; + + bool failed () + { + return !succeeded; } - Test[] tests; - AssertException[] exceptions; - void delegate () pre_; - void delegate () post_; - size_t failures; - size_t pending; - size_t lastIndex = size_t.max; - } + bool succeeded () + { + if (exception is null) + return true; + + return false; + } + + void run () + { + if (!isPending) + test(); + } + + bool isPending () + { + return test is null; + } + } + + static UnitTester instance_; + + DescriptionManager descriptions; + Description currentDescription; + + void delegate () before_; + void delegate () after_; + + size_t numberOfFailures; + size_t numberOfPending; + size_t numberOfTests; + size_t failureId; + + string defaultIndentation = " "; + string indentation; + + static UnitTester instance () + { + if (instance_) + return instance_; + + return instance_ = new UnitTester; + } + + Use!(void delegate (), string) describe (string message) + { + addDescription(message); + Use!(void delegate (), string) use; + + use.args[0] = &internalDescribe; + use.args[1] = message; + + return use; + } Use!(void delegate (), string) test (string message) { - tests ~= Test(null, message); - lastIndex++; - + addTest(message); Use!(void delegate (), string) use; use.args[0] = &internalTest; @@ -65,101 +224,298 @@ } void run () - { - foreach (test ; tests) - { - if (test.isPending) - pending++; - - try - { - execute in { - test.run(); - }; - } - - catch (AssertException e) - { - exceptions ~= e; - failures++; - } - } - + { + foreach (description ; descriptions) + runDescription(description); + printResult; } - void delegate () pre () + void runDescription (Description description) { - return pre_; + restore(currentDescription) in { + currentDescription = description; + description.run; + + foreach (desc ; description.descriptions) + runDescription(desc); + + foreach (ref test ; description.tests) + { + if (test.isPending) + addPendingTest(description, test); + + try + { + execute in { + test.run(); + }; + } + + catch (AssertException e) + handleFailure(description, test, e); + } + }; } - void delegate () pre (void delegate () pre) + void delegate () before () { - return pre_ = pre; + return before_; + } + + void delegate () before (void delegate () before) + { + return before_ = before; } - void delegate () post () + void delegate () after () { - return post_; + return after_; } - void delegate () post (void delegate () post) + void delegate () after (void delegate () after) + { + return after_ = after; + } + + void addTest (string message) { - return post_ = post; + numberOfTests++; + currentDescription.tests ~= Test(null, message); + } + + void addDescription (string message) + { + if (currentDescription) + currentDescription.descriptions ~= new Description(message); + + else + descriptions ~= new Description(message); } - private void internalTest (void delegate () dg, string message) + void addPendingTest (Description description, ref Test test) { - tests[lastIndex] = Test(dg, message); + numberOfPending++; + description.pending ~= test; + } + + void handleFailure (Description description, ref Test test, AssertException exception) + { + numberOfFailures++; + test.exception = exception; + description.failures ~= test; } - private void printResult () + void internalDescribe (void delegate () dg, string message) + { + if (currentDescription) + currentDescription.descriptions.last.description = dg; + + else + descriptions.last.description = dg; + } + + void internalTest (void delegate () dg, string message) + { + currentDescription.tests[$ - 1] = Test(dg, message); + } + + void printResult () { if (isAllTestsSuccessful) return printSuccess(); - foreach (test ; tests) + foreach (description ; descriptions) { - print("- ", test.message); - - if (test.isPending) - print(" ", "(PENDING: Not Yet Implemented)"); - - println(); + printDescription(description); + printResultImpl(description.descriptions); } - print("\n", tests.length, " test, ", failures, " failures"); - printPending(); + failureId = 0; + + printPending; + printFailures; + + print("\n", numberOfTests, " ", "test".pluralize(numberOfTests),", ", numberOfFailures, " ", "failure".pluralize(numberOfFailures)); + printNumberOfPending; println(); } - private void printPending () + void printResultImpl (DescriptionManager descriptions) + { + restore(indentation) in { + indentation ~= defaultIndentation; + + foreach (description ; descriptions) + { + printDescription(description); + printResultImpl(description.descriptions); + } + }; + } + + void printDescription (Description description) { - if (hasPending) - print(", ", pending, " pending"); + println(indentation, description.message); + + restore(indentation) in { + indentation ~= defaultIndentation; + + foreach (i, ref test ; description.tests) + { + print(indentation, "- ", test.message); + + if (test.isPending) + print(" (PENDING: Not Yet Implemented)"); + + if (test.failed) + print(" (FAILED - ", ++failureId, ')'); + + println(); + } + }; + } + + void printPending () + { + if (!hasPending) + return; + + println("\nPending:"); + + restore(indentation) in { + indentation ~= defaultIndentation; + + foreach (description ; descriptions) + { + printPendingDescription(description); + printPendingImpl(description.descriptions); + } + }; + } + + void printPendingImpl (DescriptionManager descriptions) + { + foreach (description ; descriptions) + { + printPendingDescription(description); + printPendingImpl(description.descriptions); + } + } + + void printPendingDescription (Description description) + { + foreach (test ; description.pending) + println(indentation, description.message, " ", test.message, "\n", indentation, indentation, "# Not Yet Implemented"); } - private void printSuccess () + void printFailures () + { + if (!hasFailures) + return; + + println("\nFailures:"); + + restore(indentation) in { + indentation ~= defaultIndentation; + + foreach (description ; descriptions) + { + printFailuresDescription(description); + printFailuresImpl(description.descriptions); + } + }; + } + + void printFailuresImpl (DescriptionManager descriptions) { - println("All ", tests.length, " tests passed successfully."); + foreach (description ; descriptions) + { + printFailuresDescription(description); + printFailuresImpl(description.descriptions); + } + } + + void printFailuresDescription (Description description) + { + foreach (test ; description.failures) + { + auto str = indentation ~ to!(string)(++failureId) ~ ") "; + auto whitespace = toWhitespace(str.length); + + println(str, description.message, " ", test.message); + println(whitespace, "# ", test.exception.file, ".d:", test.exception.line); + println(whitespace, "Stack trace:"); + print(whitespace); + test.exception.writeOut(&printStackTrace); + println(); + //println(readFailedTest(test, 0)); + } } - private bool isAllTestsSuccessful () + void printStackTrace (string str) + { + return print(str); + + /*if (str.find("start") < size_t.max || + str.find("main") < size_t.max || + str.find("rt.compiler.") < size_t.max || + str.find("orange.") || + str.find(":0") || + str.find("_d_assert") || + str.find("onAssertError") || + str.find("tango.core.Exception.AssertException._ctor ") || + str.find("object.") || + str.find("tango.core.tools.")) + return;*/ + } + + string readFailedTest (ref Test test, int numberOfSurroundingLines = 3) + { + auto filename = test.exception.file.dup.replace('.', '/'); + + filename ~= ".d"; + filename = Environment.toAbsolute(filename); + auto lineNumber = test.exception.line; + string str; + auto file = new File(filename); + + foreach (i, line ; new Lines!(char)(file)) + if (i >= (lineNumber - 1) - numberOfSurroundingLines && i <= (lineNumber - 1) + numberOfSurroundingLines) + str ~= line ~ '\n'; + + file.close; + + return str; + } + + void printNumberOfPending () + { + if (hasPending) + print(", ", numberOfPending, " pending"); + } + + void printSuccess () + { + println("All ", numberOfTests, " test".pluralize(numberOfTests), " passed successfully."); + } + + bool isAllTestsSuccessful () { return !hasPending && !hasFailures; } - private bool hasPending () + bool hasPending () { - return pending > 0; + return numberOfPending > 0; } - private bool hasFailures () + bool hasFailures () { - return failures > 0; + return numberOfFailures > 0; } - private Use!(void delegate ()) execute () + Use!(void delegate ()) execute () { Use!(void delegate ()) use; @@ -168,10 +524,31 @@ return use; } - private void executeImpl (void delegate () dg) + void executeImpl (void delegate () dg) + { + auto before = this.before; + auto after = this.after; + + if (before) before(); + if (dg) dg(); + if (after) after(); + } + + string toWhitespace (size_t value) { - if (pre) pre(); - if (dg) dg(); - if (post) post(); + string str; + + for (size_t i = 0; i < value; i++) + str ~= ' '; + + return str; + } + + string pluralize (string str, int value) + { + if (value == 1) + return str; + + return str ~ "s"; } } \ No newline at end of file diff -r 78e5fef4bbf2 -r fc315d786f24 orange/util/Traits.d --- a/orange/util/Traits.d Tue Oct 19 10:22:10 2010 +0200 +++ b/orange/util/Traits.d Fri Nov 19 11:14:55 2010 +0100 @@ -28,6 +28,8 @@ version = Phobos; } +import orange.core.string; + template isPrimitive (T) { const bool isPrimitive = is(T == bool) || @@ -91,7 +93,7 @@ template isString (T) { - const bool isString = is(T : char[]) || is(T : wchar[]) || is(T : dchar[]); + const bool isString = is(T : string) || is(T : wstring) || is(T : dstring); } template isAssociativeArray (T) diff -r 78e5fef4bbf2 -r fc315d786f24 orange/util/collection/Array.d --- a/orange/util/collection/Array.d Tue Oct 19 10:22:10 2010 +0200 +++ b/orange/util/collection/Array.d Fri Nov 19 11:14:55 2010 +0100 @@ -19,7 +19,10 @@ version = Phobos; import std.c.string : memmove; -} +} + +import orange.core.string; +import orange.util.Traits; /** * Inserts the specified element at the specified position in the array. Shifts the @@ -276,6 +279,36 @@ } /** + * Returns $(D_KEYWORD true) if the array contains the given pattern. + * + * Params: + * arr = the array to check if it contains the element + * pattern = the pattern whose presence in the array is to be tested + * + * Returns: $(D_KEYWORD true) if the array contains the given pattern + */ +bool contains (T) (T[] arr, T[] pattern) +{ + static if (isChar!(T)) + { + version (Tango) + return tango.text.Util.containsPattern(arr, pattern); + + else + return stdString.indexOf(arr, element) != -1; + } + + else + { + version (Tango) + return tango.core.Array.contains(arr, pattern); + + else + return !algorithm.find(arr, pattern).empty; + } +} + +/** * Returns $(D_KEYWORD true) if this array contains no elements. * * Params: @@ -433,7 +466,7 @@ * * Returns: the array */ -T[] replace (T, U = size_t) (ref T[] arr, U pos, U n, T[] elements) +/*T[] replace (T, U = size_t) (ref T[] arr, U pos, U n, T[] elements) in { assert(pos <= arr.length, "mambo.collection.Array.replace: The position was greter than the length of the array"); @@ -491,9 +524,54 @@ } return arr; +}*/ + +/** + * Replaces all the occurences of $(D_PARAM pattern) with $(D_PARAM replacement) + * + * Params: + * arr = the array to do the raplce in + * pattern = the pattern to match + * replacement = the values to subsitute + * + * Returns: the passed in array with all the patterns subsituted + */ +T[] replace (T : wchar) (T[] arr, dchar pattern, dchar replacement) +{ + foreach (i, dchar e ; arr) + if (e == pattern) + arr[i] = replacement; + + return arr; } /** + * Replaces all the occurences of $(D_PARAM pattern) with $(D_PARAM replacement) + * + * Params: + * arr = the array to do the raplce in + * pattern = the pattern to match + * replacement = the values to subsitute + * + * Returns: the passed in array with all the patterns subsituted + */ +/*T[] replace (T) (T[] arr, T pattern, T replacement) +{ + version (Tango) + tango.core.Array.replace(arr, pattern, replacement); + + + else + { + foreach (ref e ; arr) + if (e == pattern) + e = replacement; + } + + return arr; +}*/ + +/** * Erases a part of the array content, shortening the length of the array. * * Params: diff -r 78e5fef4bbf2 -r fc315d786f24 tests/Serializer.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/Serializer.d Fri Nov 19 11:14:55 2010 +0100 @@ -0,0 +1,508 @@ + +/** + * Copyright: Copyright (c) 2010 Jacob Carlborg. All rights reserved. + * Authors: Jacob Carlborg + * Version: Initial created: Nov 5, 2010 + * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) + */ +module tests.Serializer; + +private: + +import orange.serialization.Serializer; +import orange.serialization.archives.XMLArchive; +import orange.core.io; +import orange.core.string; + +bool containsDefaultXmlContent (string source) +{ + return source.containsXmlHeader() && + source.containsArchive() && + source.containsXmlTag("data"); +} + +bool containsXmlHeader (string source) +{ + return source.contains(``); +} + +bool containsArchive (string source) +{ + return source.containsArchiveHeader() && source.contains(""); +} + +bool containsArchiveHeader (string source) +{ + return source.contains(``); +} + +bool containsXmlTag (string source, string tag, bool simple = false) +{ + return source.containsXmlTag(tag, null, null, simple); +} + +bool containsXmlTag (string source, string tag, string attributes, bool simple = false) +{ + return source.containsXmlTag(tag, attributes, null, simple); +} + +bool containsXmlTag (string source, string tag, string attributes, string content, bool simple = false) +{ + string pattern = '<' ~ tag; + + if (attributes.length > 0) + pattern ~= ' ' ~ attributes; + + if (simple) + return source.contains(pattern ~ "/>"); + + if (content.length > 0) + return source.contains(pattern ~ '>' ~ content ~ "'); + + return source.contains(pattern ~ '>') && source.contains("'); +} + +enum Foo { a, b, c } +typedef int Int; + +class A +{ + equals_t opEquals (Object other) + { + if (auto o = cast(A) other) + return true; + + return false; + } +} + +struct B +{ + equals_t opEquals (B b) + { + return true; + } +} + +class C { string str; } +class D { int[] arr; } +class E { int[int] aa; } +class F { int value; int* ptr; } +class G { Foo foo; } + +class H +{ + bool bool_; + byte byte_; + //cdouble cdouble_; // currently not suppported by to!() + //cent cent_; // currently not implemented but a reserved keyword + //cfloat cfloat_; // currently not suppported by to!() + char char_; + //creal creal_; // currently not suppported by to!() + dchar dchar_; + double double_; + float float_; + //idouble idouble_; // currently not suppported by to!() + //ifloat ifloat_; // currently not suppported by to!() + int int_; + //ireal ireal_; // currently not suppported by to!() + long long_; + real real_; + short short_; + ubyte ubyte_; + //ucent ucent_; // currently not implemented but a reserved keyword + uint uint_; + ulong ulong_; + ushort ushort_; + wchar wchar_; + + equals_t opEquals (Object other) + { + if (auto o = cast(H) other) + { + return bool_ == o.bool_ && + byte_ == o.byte_ && + //cdouble_ == o.cdouble_ && // currently not suppported by to!() + //cent_ == o.cent_ && // currently not implemented but a reserved keyword + //cfloat_ == o.cfloat_ && // currently not suppported by to!() + char_ == o.char_ && + //creal_ == o.creal_ && // currently not suppported by to!() + dchar_ == o.dchar_ && + double_ == o.double_ && + float_ == o.float_ && + //idouble_ == o.idouble_ && // currently not suppported by to!() + //ifloat_ == o.ifloat_ && // currently not suppported by to!() + int_ == o.int_ && + //ireal_ == o.ireal_ && // currently not suppported by to!() + long_ == o.long_ && + real_ == o.real_ && + short_ == o.short_ && + ubyte_ == o.ubyte_ && + //ucent_ == o.ucent_ && // currently not implemented but a reserved keyword + uint_ == o.uint_ && + ulong_ == o.ulong_ && + ushort_ == o.ushort_ && + wchar_ == o.wchar_; + } + + return false; + } +} + +class I +{ + Int a; +} + +class J +{ + string firstSource; + string firstSlice; + + string secondSlice; + string secondSource; +} + +class K +{ + int[int] a; + int[int] b; +} + +import orange.test.UnitTester; +Serializer serializer; +XMLArchive!(char) archive; + +A a; +B b; +C c; +D d; +E e; +F f; +G g; +H h; +I i; +J j; +J jDeserialized; +K k; + +string data; + +unittest +{ + archive = new XMLArchive!(char); + serializer = new Serializer(archive); + + a = new A; + + c = new C; + c.str = "foo"; + + d = new D; + d.arr = [27, 382, 283, 3820, 32, 832].dup; + + e = new E; + e.aa = [3 : 4, 1 : 2, 39 : 472, 6 : 7]; + + f = new F; + f.value = 9; + f.ptr = &f.value; + + g = new G; + g.foo = Foo.b; + + h = new H; + h.bool_ = true; + h.byte_ = 1; + h.char_ = 'a'; + //h.cdouble_ = 0.0 + 0.0 * 1.0i; // currently not supported by to!() + //h.cfloat_ = 0.0f + 0.0f * 1.0i; // currently not supported by to!() + //h.creal_ = 0.0 + 0.0 * 1.0i; // currently not supported by to!() + h.dchar_ = 'b'; + h.double_ = 0.0; + h.float_ = 0.0f; + //h.idouble_ = 0.0 * 1.0i; // currently not supported by to!() + //h.ifloat_ = 0.0f * 1.0i; // currently not supported by to!() + h.int_ = 1; + //h.ireal_ = 0.0 * 1.0i; // currently not supported by to!() + h.long_ = 1L; + h.real_ = 0.0; + h.short_ = 1; + h.ubyte_ = 1U; + h.uint_ = 1U; + h.ulong_ = 1LU; + h.ushort_ = 1U; + h.wchar_ = 'c'; + + i = new I; + i.a = 1; + + j = new J; + j.firstSource = "0123456789"; + j.firstSlice = j.firstSource[3 .. 7]; + j.secondSource = "abcdefg"; + j.secondSlice = j.secondSource[1 .. 4]; + + k = new K; + k.a = [3 : 4, 1 : 2, 39 : 472, 6 : 7]; + k.b = k.a; + + describe("Serializer") in { + describe("serialize object") in { + it("should return a serialized object") in { + serializer.reset; + serializer.serialize(a); + + assert(archive.data().containsDefaultXmlContent()); + assert(archive.data().contains(``)); + }; + }; + + describe("deserialize object") in { + it("should return a deserialized object equal to the original object") in { + auto aDeserialized = serializer.deserialize!(A)(archive.data); + assert(a == aDeserialized); + }; + }; + + describe("serialize struct") in { + it("should return a serialized struct") in { + serializer.reset; + serializer.serialize(B()); + + assert(archive.data().containsDefaultXmlContent()); + assert(archive.data().contains(``)); + }; + }; + + describe("deserialize struct") in { + it("should return a deserialized struct equal to the original struct") in { + auto bDeserialized = serializer.deserialize!(B)(archive.data); + assert(b == bDeserialized); + }; + }; + + describe("serialize string") in { + it("should return a serialized string") in { + serializer.reset; + + serializer.serialize(c); + assert(archive.data().containsDefaultXmlContent()); + assert(archive.data().containsXmlTag("object", `runtimeType="tests.Serializer.C" type="C" key="0" id="0"`)); + assert(archive.data().containsXmlTag("string", `type="char" length="3" key="str" id="1"`, "foo")); + }; + }; + + describe("deserialize string") in { + it("should return a deserialized string equal to the original string") in { + auto cDeserialized = serializer.deserialize!(C)(archive.data); + assert(c.str == cDeserialized.str); + }; + }; + + describe("serialize array") in { + it("should return a serialized array") in { + serializer.reset; + serializer.serialize(d); + + assert(archive.data().containsDefaultXmlContent()); + assert(archive.data().containsXmlTag("object", `runtimeType="tests.Serializer.D" type="D" key="0" id="0"`)); + assert(archive.data().containsXmlTag("int", `key="0"`, "27")); + assert(archive.data().containsXmlTag("int", `key="1"`, "382")); + assert(archive.data().containsXmlTag("int", `key="2"`, "283")); + assert(archive.data().containsXmlTag("int", `key="3"`, "3820")); + assert(archive.data().containsXmlTag("int", `key="4"`, "32")); + assert(archive.data().containsXmlTag("int", `key="5"`, "832")); + }; + }; + + describe("deserialize array") in { + it("should return a deserialize array equal to the original array") in { + auto dDeserialized = serializer.deserialize!(D)(archive.data); + assert(d.arr == dDeserialized.arr); + }; + }; + + describe("serialize associative array") in { + it("should return a serialized associative array") in { + serializer.reset(); + serializer.serialize(e); + + assert(archive.data().containsDefaultXmlContent()); + assert(archive.data().containsXmlTag("object", `runtimeType="tests.Serializer.E" type="E" key="0" id="0"`)); + assert(archive.data().containsXmlTag("associativeArray", `keyType="int" valueType="int" length="4" key="aa"`)); + + assert(archive.data().containsXmlTag("key", `key="0"`)); + assert(archive.data().containsXmlTag("int", `key="0"`, "1")); + assert(archive.data().containsXmlTag("value", `key="0"`)); + assert(archive.data().containsXmlTag("int", `key="0"`, "2")); + + assert(archive.data().containsXmlTag("key", `key="1"`)); + assert(archive.data().containsXmlTag("int", `key="1"`, "3")); + assert(archive.data().containsXmlTag("value", `key="1"`)); + assert(archive.data().containsXmlTag("int", `key="1"`, "4")); + + assert(archive.data().containsXmlTag("key", `key="2"`)); + assert(archive.data().containsXmlTag("int", `key="2"`, "6")); + assert(archive.data().containsXmlTag("value", `key="2"`)); + assert(archive.data().containsXmlTag("int", `key="2"`, "7")); + + assert(archive.data().containsXmlTag("key", `key="3"`)); + assert(archive.data().containsXmlTag("int", `key="3"`, "39")); + assert(archive.data().containsXmlTag("value", `key="3"`)); + assert(archive.data().containsXmlTag("int", `key="3"`, "472")); + }; + }; + + describe("deserialize associative array") in { + it("should return an associative array equal to the original associative array") in { + auto eDeserialized = serializer.deserialize!(E)(archive.data); + + foreach (k, v ; eDeserialized.aa) + assert(e.aa[k] == v); + + //assert(e.aa == eDeserialized.aa); // cannot compare associative array + }; + }; + + describe("serialize pointer") in { + it("should return a serialized pointer") in { + serializer.reset(); + + serializer.serialize(f); + assert(archive.data().containsDefaultXmlContent()); + assert(archive.data().containsXmlTag("object", `runtimeType="tests.Serializer.F" type="F" key="0" id="0"`)); + assert(archive.data().containsXmlTag("pointer", `key="ptr" id="2"`)); + assert(archive.data().containsXmlTag("int", `key="1"`, "9")); + assert(archive.data().containsXmlTag("int", `key="value"`, "9")); + }; + }; + + describe("deserialize pointer") in { + it("should return a deserialized pointer equal to the original pointer") in { + auto fDeserialized = serializer.deserialize!(F)(archive.data); + assert(*f.ptr == *fDeserialized.ptr); + }; + }; + + describe("serialize enum") in { + it("should return a serialized enum") in { + serializer.reset(); + serializer.serialize(g); + assert(archive.data().containsDefaultXmlContent()); + assert(archive.data().containsXmlTag("object", `runtimeType="tests.Serializer.G" type="G" key="0" id="0"`)); + assert(archive.data().containsXmlTag("enum", `type="Foo" baseType="int" key="foo"`, "1")); + }; + }; + + + describe("deserialize enum") in { + it("should return an enum equal to the original enum") in { + auto gDeserialized = serializer.deserialize!(G)(archive.data); + assert(g.foo == gDeserialized.foo); + }; + }; + + describe("serialize primitives") in { + it("should return serialized primitives") in { + serializer.reset; + + serializer.serialize(h); + assert(archive.data().containsDefaultXmlContent()); + assert(archive.data().containsXmlTag("object", `runtimeType="tests.Serializer.H" type="H" key="0" id="0"`)); + assert(archive.data().containsXmlTag("byte", `key="byte_"`, "1")); + assert(archive.data().containsXmlTag("char", `key="char_"`, "a")); + assert(archive.data().containsXmlTag("dchar", `key="dchar_"`, "b")); + assert(archive.data().containsXmlTag("double", `key="double_"`, "0")); + assert(archive.data().containsXmlTag("float", `key="float_"`, "0")); + assert(archive.data().containsXmlTag("int", `key="int_"`, "1")); + assert(archive.data().containsXmlTag("long", `key="long_"`, "1")); + assert(archive.data().containsXmlTag("real", `key="real_"`, "0")); + assert(archive.data().containsXmlTag("short", `key="short_"`, "1")); + assert(archive.data().containsXmlTag("ubyte", `key="ubyte_"`, "1")); + assert(archive.data().containsXmlTag("uint", `key="uint_"`, "1")); + assert(archive.data().containsXmlTag("ulong", `key="ulong_"`, "1")); + assert(archive.data().containsXmlTag("ushort", `key="ushort_"`, "1")); + assert(archive.data().containsXmlTag("wchar", `key="wchar_"`, "c")); + assert(archive.data().containsXmlTag("bool", `key="bool_"`, "true")); + }; + }; + + describe("deserialize primitives") in { + it("should return deserialized primitives equal to the original primitives") in { + auto hDeserialized = serializer.deserialize!(H)(archive.data); + assert(h == hDeserialized); + }; + }; + + describe("serialize typedef") in { + it("should return a serialized typedef") in { + serializer.reset(); + serializer.serialize(i); + assert(archive.data().containsDefaultXmlContent()); + assert(archive.data().containsXmlTag("object", `runtimeType="tests.Serializer.I" type="I" key="0" id="0"`)); + assert(archive.data().containsXmlTag("typedef", `type="Int" key="a"`)); + assert(archive.data().containsXmlTag("int", `key="1"`, "1")); + }; + }; + + describe("deserialize typedef") in { + it("should return a deserialized typedef equal to the original typedef") in { + auto iDeserialized = serializer.deserialize!(I)(archive.data); + assert(i.a == iDeserialized.a); + }; + }; + + describe("serialize slices") in { + it("should return serialized slices") in { + serializer.reset(); + serializer.serialize(j); + + assert(archive.data().containsDefaultXmlContent()); + assert(archive.data().containsXmlTag("object", `runtimeType="tests.Serializer.J" type="J" key="0" id="0"`)); + assert(archive.data().containsXmlTag("string", `type="char" length="10" key="firstSource" id="1"`, "0123456789")); + assert(archive.data().containsXmlTag("slice", `key="firstSlice" offset="3" length="4"`, "1")); + assert(archive.data().containsXmlTag("slice", `key="secondSlice" offset="1" length="3"`, "4")); + assert(archive.data().containsXmlTag("string", `type="char" length="7" key="secondSource" id="4"`, "abcdefg")); + }; + }; + + describe("deserialize slices") in { + jDeserialized = serializer.deserialize!(J)(archive.data); + + it("should return deserialized strings equal to the original strings") in { + assert(j.firstSource == jDeserialized.firstSource); + assert(j.secondSource == jDeserialized.secondSource); + }; + + it("should return deserialized slices equal to the original slices") in { + assert(j.firstSlice == jDeserialized.firstSlice); + assert(j.secondSlice == jDeserialized.secondSlice); + }; + + it("the slices should be equal to a slice of the original sources") in { + assert(jDeserialized.firstSource[3 .. 7] == jDeserialized.firstSlice); + assert(jDeserialized.secondSource[1 .. 4] == jDeserialized.secondSlice); + + assert(j.firstSource[3 .. 7] == jDeserialized.firstSlice); + assert(j.secondSource[1 .. 4] == jDeserialized.secondSlice); + }; + + it("the slices should be able to modify the sources") in { + jDeserialized.firstSlice[0] = 'a'; + jDeserialized.secondSlice[0] = '0'; + + assert(jDeserialized.firstSource == "012a456789"); + assert(jDeserialized.secondSource == "a0cdefg"); + }; + }; + + describe("associative array references") in { + it("should return ") in { + serializer.reset(); + serializer.serialize(k); + println(archive.data); + }; + }; + }; +} \ No newline at end of file diff -r 78e5fef4bbf2 -r fc315d786f24 tests/all.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/all.d Fri Nov 19 11:14:55 2010 +0100 @@ -0,0 +1,15 @@ +/** + * Copyright: Copyright (c) 2010 Jacob Carlborg. All rights reserved. + * Authors: Jacob Carlborg + * Version: Initial created: Nov 5, 2010 + * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) + */ +module tests.all; + +import orange.test.UnitTester; +import tests.Serializer; + +void main () +{ + run; +} \ No newline at end of file