Skip to content

Commit 390f9ff

Browse files
committed
performance testing approach of having base and generating A and B with differences/conflicts
1 parent 0a713a8 commit 390f9ff

1 file changed

Lines changed: 232 additions & 0 deletions

File tree

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
import path from "path";
2+
import { fileURLToPath } from "url";
3+
import fs from "fs";
4+
import seedrandom from 'seedrandom';
5+
import { JSONValue } from "../../src/utils/jsonHelper.js";
6+
import { pathFromPtr } from "json-refs";
7+
import { writeJson } from "./utils.js";
8+
import * as comparissonMergingService from "../../src/services/comparisonMerging.service.js";
9+
import { InputModels } from "../../src/interfaces/inputmodels.js";
10+
11+
12+
const rng = seedrandom('tt');
13+
14+
function generateConflicts() {
15+
16+
const NUMBER_OF_CONFLICTS = 1
17+
18+
const __filename = fileURLToPath(import.meta.url);
19+
const __dirname = path.dirname(__filename);
20+
const fullPath = path.join(__dirname, '../data/1_MEINS');
21+
const baseFileName = 'base.json'
22+
23+
const base = getModel(path.join(fullPath, baseFileName));
24+
25+
const leftSide = JSON.parse(JSON.stringify(base)) as Record<string, unknown>;
26+
const rightSide = JSON.parse(JSON.stringify(base)) as Record<string, unknown>;
27+
28+
for (let i = 1; i <= NUMBER_OF_CONFLICTS; i++) {
29+
30+
// generateUpdateUpdateConflict(base, leftSide, rightSide);
31+
32+
generateDeleteUpdateConflict(base, leftSide, rightSide);
33+
}
34+
35+
writeJson(fullPath, JSON.stringify(leftSide, null, 2), 'left');
36+
writeJson(fullPath, JSON.stringify(rightSide, null, 2), 'right');
37+
38+
const inputModels: InputModels = {
39+
left: leftSide as JSONValue,
40+
right: rightSide as JSONValue,
41+
original: base
42+
};
43+
44+
const diffmodel = measure(`${fullPath} MODEL - Diff`, () => {
45+
const result = comparissonMergingService.createDiff(inputModels);
46+
// console.log(JSON.stringify((result)))
47+
return result;
48+
});
49+
50+
// maybe compare diffmodel
51+
}
52+
53+
// -------------------------------------------------
54+
55+
function generateDeleteUpdateConflict(base: JSONValue, leftSide: Record<string, unknown>, rightSide: Record<string, unknown>) {
56+
const pathToChange = getRandomNamePath(base);
57+
58+
const pathToDelete = pathToChange.slice(undefined, -1);
59+
60+
const valueToChange = getValue(base as unknown as Record<string, unknown>, pathToChange)
61+
62+
setValue(leftSide, pathToChange, valueToChange + '_ttt');
63+
64+
removeValue(rightSide, pathToDelete);
65+
66+
// OR more complex:
67+
68+
// on one side make sure every ref including this path full or starts with this path, these are deleted
69+
// then deelte this path
70+
71+
// on the other side insert an object at this path
72+
// maybe get random sub path, starting with the deleted path
73+
}
74+
75+
76+
function generateUpdateUpdateConflict(base: JSONValue, leftSide: Record<string, unknown>, rightSide: Record<string, unknown>) {
77+
const pathToChange = getRandomNamePath(base);
78+
79+
const valueToChange = getValue(base as unknown as Record<string, unknown>, pathToChange)
80+
81+
setValue(leftSide, pathToChange, valueToChange + '_ttt')
82+
setValue(rightSide, pathToChange, valueToChange + '_zzz')
83+
}
84+
85+
// special case: delete - insert use
86+
function generateDeleteUseConflict(base: JSONValue, leftSide: Record<string, unknown>, rightSide: Record<string, unknown>) {
87+
// get a path of an array
88+
89+
// insert object at the last position
90+
91+
// reference this object somewhere in the json -> object that has no ref yet
92+
93+
// OR reference in the same array in an object that has no ref yet
94+
}
95+
96+
97+
function generateDeleteMoveConflict(base: JSONValue, leftSide: Record<string, unknown>, rightSide: Record<string, unknown>) {
98+
// get a ref
99+
100+
// ref points to array index normaly
101+
102+
// if index is 1 switch to 2
103+
104+
// if index > 1 then switch to index-1
105+
106+
// change the ref link
107+
108+
// ON THE OTHER SIDE: delete the newly referenced object
109+
}
110+
111+
112+
function generateMoveMoveConflict(base: JSONValue, leftSide: Record<string, unknown>, rightSide: Record<string, unknown>) {
113+
// similar to delete move
114+
115+
// get a ref
116+
// ref points to array index normaly
117+
118+
// filter all where the ref index is in array length > (found index + 3)
119+
120+
// ON THE ONE SIDE switch to index + 1
121+
122+
// ON THE OTHER SIDE switch to index + 2
123+
}
124+
125+
126+
// -------------------------------------------------
127+
128+
129+
function getModel(fullPath: string): JSONValue | null {
130+
131+
const fileContent = fs.readFileSync(fullPath, "utf-8");
132+
133+
if (fileContent === "") return null;
134+
return JSON.parse(fileContent);
135+
}
136+
137+
// return path
138+
function getRandomNamePath(json: JSONValue): string[] {
139+
140+
const flatBase = flatten(json).filter((path) => path.includes('name'));
141+
142+
// console.log(flatBase)
143+
144+
const tempElem = flatBase[getRandomInt(flatBase.length)];
145+
146+
console.log(tempElem)
147+
148+
return pathFromPtr(tempElem)
149+
}
150+
151+
function getRandomObjectPath(json: JSONValue): string[] {
152+
153+
const flatBase = flatten(json).filter((path) => /[0-9]$/.test(path));
154+
155+
// console.log(flatBase)
156+
157+
const tempElem = flatBase[getRandomInt(flatBase.length)];
158+
159+
console.log(tempElem)
160+
161+
return pathFromPtr(tempElem)
162+
}
163+
164+
function getRandomInt(max: number): number {
165+
const min = 1
166+
return Math.floor(rng() * (max - min + 1)) + 1;
167+
}
168+
169+
function flatten(obj: JSONValue, pointer = '#', result: string[] = []): string[] {
170+
171+
if (obj !== null && typeof obj === 'object' && !Array.isArray(obj)) {
172+
for (const [key, value] of Object.entries(obj)) {
173+
const newPointer = `${pointer}/${key}`
174+
flatten(value, newPointer, result)
175+
}
176+
} else if (Array.isArray(obj)) {
177+
obj.forEach((item, index) => {
178+
const newPointer = `${pointer}/${index}`
179+
flatten(item, newPointer, result)
180+
})
181+
} else {
182+
result.push(pointer)
183+
}
184+
185+
return result
186+
}
187+
188+
function getValue(json: Record<string, unknown>, path: string[]) {
189+
const tmp = json[path[0]]
190+
191+
if (path.length > 1) {
192+
return getValue(tmp as Record<string, unknown>, path.slice(1))
193+
}
194+
195+
return tmp;
196+
}
197+
198+
function setValue(json: Record<string, unknown>, path: string[], newValue: unknown) {
199+
const key = path[0]
200+
201+
if (path.length === 1) {
202+
json[key] = newValue
203+
return
204+
}
205+
206+
setValue(json[key] as Record<string, unknown>, path.slice(1), newValue)
207+
}
208+
209+
function removeValue(json: Record<string, unknown> | unknown[], path: string[]): void {
210+
const key = path[0];
211+
212+
if (path.length === 1) {
213+
if (Array.isArray(json)) {
214+
json.splice(Number(key), 1);
215+
} else {
216+
delete json[key];
217+
}
218+
return;
219+
}
220+
221+
removeValue(json[key as keyof typeof json] as Record<string, unknown> | unknown[], path.slice(1));
222+
}
223+
224+
function measure<T>(name: string, fn: () => T): T {
225+
console.time(name);
226+
const result = fn();
227+
console.timeEnd(name);
228+
return result;
229+
}
230+
231+
232+
generateConflicts()

0 commit comments

Comments
 (0)