1 module vision.json.patch.unittesting; 2 3 unittest 4 { 5 import std.json; 6 import vision.json.patch.commons; 7 import vision.json.patch.diff; 8 import vision.json.patch.patch; 9 10 struct RandomDocument 11 { 12 import std.random; 13 14 enum N = 1024; 15 enum maxStringLength = 4; 16 enum maxArrayLength = 10; 17 enum maxObjectLength = 10; 18 19 JsonItem document; 20 auto rnd = Random(0); 21 22 this(float deep, float reducer) 23 { 24 document = getRandomDocument(deep, reducer); 25 } 26 27 JsonItem getRandomDocument(float deep, float reducer) const 28 { 29 final switch(getRandomType(deep)) 30 { 31 case JSON_TYPE.ARRAY: 32 return getRandomArray(deep, reducer); 33 case JSON_TYPE.FALSE: 34 return parseJSON("false"); 35 case JSON_TYPE.FLOAT: 36 return getRandomFloat(); 37 case JSON_TYPE.INTEGER: 38 return getRandomInteger(); 39 case JSON_TYPE.NULL: 40 return parseJSON("null"); 41 case JSON_TYPE.OBJECT: 42 return getRandomObject(deep, reducer); 43 case JSON_TYPE.STRING: 44 return JsonItem(getRandomString()); 45 case JSON_TYPE.TRUE: 46 return parseJSON("true"); 47 case JSON_TYPE.UINTEGER: 48 return getRandomUinteger(); 49 } 50 } 51 52 JsonItem getRandomArray(float deep, float reducer) const 53 { 54 JsonItem[] a; 55 for(auto i=uniform(1, maxArrayLength);--i>0;) 56 a ~= getRandomDocument(deep-reducer, reducer); 57 return JsonItem(a); 58 } 59 60 JsonItem getRandomObject(float deep, float reducer) const 61 { 62 JsonItem[string] a; 63 for(auto i=uniform(1, maxObjectLength);--i>0;) 64 a[getRandomString()] = getRandomDocument(deep-reducer, reducer); 65 return JsonItem(a); 66 } 67 68 JsonItem getRandomFloat() const 69 { 70 return JsonItem(uniform(0.0f, 1e6)); 71 } 72 73 JsonItem getRandomInteger() const 74 { 75 return JsonItem(uniform(int.min, int.max)); 76 } 77 JsonItem getRandomUinteger() const 78 { 79 return JsonItem(uniform(0, int.max)); 80 } 81 82 string getRandomString() const 83 { 84 string s; 85 for(auto i = uniform(1, maxStringLength);--i;) 86 s ~= uniform('a', 'z'); 87 return s; 88 } 89 90 JSON_TYPE getRandomType(float deep) const 91 { 92 return (uniform(0, N) < deep*N/2) 93 ? [JSON_TYPE.OBJECT, JSON_TYPE.ARRAY].choice() 94 : [JSON_TYPE.FALSE, JSON_TYPE.FLOAT,JSON_TYPE.INTEGER, JSON_TYPE.NULL, JSON_TYPE.STRING, JSON_TYPE.TRUE, JSON_TYPE.UINTEGER].choice(); 95 } 96 97 } 98 99 for(auto i=0; i<500; ++i) 100 { 101 auto source = RandomDocument(1.0, 0.2); 102 auto target = RandomDocument(1.0, 0.2); 103 104 auto patch = diff(source.document, target.document).toJson; 105 106 auto patched = source.document; 107 try 108 { 109 patched.patchInPlace(patch); 110 111 if(patched != target.document) 112 throw new Exception("Result incorrect"); 113 } 114 catch(Exception e) 115 { 116 import std.stdio; 117 writeln("Fail:", e.msg); 118 writeln(source.document); 119 writeln(target.document); 120 writeln(patched); 121 writeln(patch); 122 break; 123 } 124 } 125 }