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 }