Skip to content

Commit a9233d8

Browse files
[8.18] [ML] Adding tests for file upload merge tools (#209704) (#210026)
# Backport This will backport the following commits from `main` to `8.18`: - [[ML] Adding tests for file upload merge tools (#209704)](#209704) <!--- Backport version: 9.4.3 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"James Gowdy","email":"[email protected]"},"sourceCommit":{"committedDate":"2025-02-06T14:53:14Z","message":"[ML] Adding tests for file upload merge tools (#209704)\n\nAdding tests for the merge tools utility functions.","sha":"42def2d71bcbf5391280cf87ad72bba7b0a9c271","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":[":ml","release_note:skip","test-coverage","v9.0.0","backport:version","v8.18.0","v9.1.0","v8.19.0"],"title":"[ML] Adding tests for file upload merge tools","number":209704,"url":"https://github.com/elastic/kibana/pull/209704","mergeCommit":{"message":"[ML] Adding tests for file upload merge tools (#209704)\n\nAdding tests for the merge tools utility functions.","sha":"42def2d71bcbf5391280cf87ad72bba7b0a9c271"}},"sourceBranch":"main","suggestedTargetBranches":["9.0","8.18","8.x"],"targetPullRequestStates":[{"branch":"9.0","label":"v9.0.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.18","label":"v8.18.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/209704","number":209704,"mergeCommit":{"message":"[ML] Adding tests for file upload merge tools (#209704)\n\nAdding tests for the merge tools utility functions.","sha":"42def2d71bcbf5391280cf87ad72bba7b0a9c271"}},{"branch":"8.x","label":"v8.19.0","branchLabelMappingKey":"^v8.19.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> Co-authored-by: James Gowdy <[email protected]>
1 parent bf94014 commit a9233d8

File tree

1 file changed

+269
-0
lines changed

1 file changed

+269
-0
lines changed
Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import {
9+
createMergedMappings,
10+
getMappingClashInfo,
11+
getFormatClashes,
12+
CLASH_TYPE,
13+
} from './merge_tools';
14+
import type { FileWrapper, FileAnalysis } from './file_wrapper';
15+
16+
describe('merge_tools', () => {
17+
describe('createMergedMappings', () => {
18+
it('should return merged mappings when all mappings are the same', () => {
19+
const files = [
20+
{
21+
getMappings: () => ({ properties: { field1: { type: 'text' } } }),
22+
} as never as FileWrapper,
23+
{
24+
getMappings: () => ({ properties: { field1: { type: 'text' } } }),
25+
} as never as FileWrapper,
26+
];
27+
28+
const result = createMergedMappings(files);
29+
expect(result.mergedMappings).toEqual({ properties: { field1: { type: 'text' } } });
30+
expect(result.mappingClashes).toEqual([]);
31+
});
32+
33+
it('should return merged mappings when a keyword mapping is being merged with a text mapping', () => {
34+
const files = [
35+
{
36+
getMappings: () => ({ properties: { field1: { type: 'text' } } }),
37+
} as never as FileWrapper,
38+
{
39+
getMappings: () => ({ properties: { field1: { type: 'keyword' } } }),
40+
} as never as FileWrapper,
41+
];
42+
43+
const result = createMergedMappings(files);
44+
expect(result.mergedMappings).toEqual({ properties: { field1: { type: 'text' } } });
45+
expect(result.mappingClashes).toEqual([]);
46+
});
47+
48+
it('should return merged mappings when a text mapping is being merged with a keyword mapping', () => {
49+
const files = [
50+
{
51+
getMappings: () => ({ properties: { field1: { type: 'keyword' } } }),
52+
} as never as FileWrapper,
53+
{
54+
getMappings: () => ({ properties: { field1: { type: 'text' } } }),
55+
} as never as FileWrapper,
56+
];
57+
58+
const result = createMergedMappings(files);
59+
expect(result.mergedMappings).toEqual({ properties: { field1: { type: 'text' } } });
60+
expect(result.mappingClashes).toEqual([]);
61+
});
62+
63+
it('should return mapping clashes when mappings are different', () => {
64+
const files = [
65+
{
66+
getFileName: () => 'file1',
67+
getMappings: () => ({ properties: { field1: { type: 'text' } } }),
68+
} as never as FileWrapper,
69+
{
70+
getFileName: () => 'file2',
71+
getMappings: () => ({ properties: { field1: { type: 'number' } } }),
72+
} as never as FileWrapper,
73+
];
74+
75+
const result = createMergedMappings(files);
76+
expect(result.mergedMappings).toEqual({ properties: { field1: { type: 'text' } } });
77+
expect(result.mappingClashes).toEqual([
78+
{
79+
fieldName: 'field1',
80+
existingType: 'text',
81+
clashingType: { fileName: 'file2', newType: 'number', fileIndex: 1 },
82+
},
83+
]);
84+
});
85+
86+
it('should return mapping clashes when first field doesn`t match the others', () => {
87+
const files = [
88+
{
89+
getFileName: () => 'file1',
90+
getMappings: () => ({ properties: { field1: { type: 'text' } } }),
91+
} as never as FileWrapper,
92+
{
93+
getFileName: () => 'file2',
94+
getMappings: () => ({ properties: { field1: { type: 'number' } } }),
95+
} as never as FileWrapper,
96+
{
97+
getFileName: () => 'file3',
98+
getMappings: () => ({ properties: { field1: { type: 'number' } } }),
99+
} as never as FileWrapper,
100+
];
101+
102+
const result = createMergedMappings(files);
103+
104+
expect(result.mergedMappings).toEqual({ properties: { field1: { type: 'text' } } });
105+
expect(result.mappingClashes).toEqual([
106+
{
107+
fieldName: 'field1',
108+
existingType: 'text',
109+
clashingType: {
110+
fileName: 'file2',
111+
newType: 'number',
112+
fileIndex: 1,
113+
},
114+
},
115+
{
116+
fieldName: 'field1',
117+
existingType: 'text',
118+
clashingType: {
119+
fileName: 'file3',
120+
newType: 'number',
121+
fileIndex: 2,
122+
},
123+
},
124+
]);
125+
});
126+
});
127+
128+
describe('getMappingClashInfo', () => {
129+
it('should return file clashes based on mapping clashes', () => {
130+
const mappingClashes = [
131+
{
132+
fieldName: 'field1',
133+
existingType: 'text',
134+
clashingType: {
135+
fileName: 'file2',
136+
newType: 'number',
137+
fileIndex: 1,
138+
},
139+
},
140+
{
141+
fieldName: 'field1',
142+
existingType: 'text',
143+
clashingType: {
144+
fileName: 'file3',
145+
newType: 'number',
146+
fileIndex: 2,
147+
},
148+
},
149+
];
150+
151+
const filesStatus = [
152+
{ fileName: 'file1', supportedFormat: true } as FileAnalysis,
153+
{ fileName: 'file2', supportedFormat: true } as FileAnalysis,
154+
{ fileName: 'file3', supportedFormat: true } as FileAnalysis,
155+
];
156+
157+
const result = getMappingClashInfo(mappingClashes, filesStatus);
158+
159+
expect(result).toEqual([
160+
{ fileName: 'file1', clash: true, clashType: CLASH_TYPE.MAPPING },
161+
{ fileName: 'file2', clash: false, clashType: CLASH_TYPE.MAPPING },
162+
{ fileName: 'file3', clash: false, clashType: CLASH_TYPE.MAPPING },
163+
]);
164+
});
165+
});
166+
167+
describe('getFormatClashes', () => {
168+
it('should return no clashes when all formats are supported', () => {
169+
const files = [
170+
{
171+
getFormat: () => 'semi_structured_text',
172+
getFileName: () => 'file1',
173+
getStatus: () => ({ supportedFormat: true }),
174+
} as FileWrapper,
175+
{
176+
getFormat: () => 'semi_structured_text',
177+
getFileName: () => 'file2',
178+
getStatus: () => ({ supportedFormat: true }),
179+
} as FileWrapper,
180+
];
181+
182+
const result = getFormatClashes(files);
183+
expect(result).toEqual([
184+
{ fileName: 'file1', clash: false },
185+
{ fileName: 'file2', clash: false },
186+
]);
187+
});
188+
189+
it('should return format clashes when formats are different', () => {
190+
const files = [
191+
{
192+
getFormat: () => 'semi_structured_text',
193+
getFileName: () => 'file1',
194+
getStatus: () => ({ supportedFormat: true }),
195+
} as FileWrapper,
196+
{
197+
getFormat: () => 'delimited',
198+
getFileName: () => 'file2',
199+
getStatus: () => ({ supportedFormat: true }),
200+
} as FileWrapper,
201+
];
202+
203+
const result = getFormatClashes(files);
204+
expect(result).toEqual([
205+
{ fileName: 'file1', clash: true, clashType: CLASH_TYPE.FORMAT },
206+
{ fileName: 'file2', clash: true, clashType: CLASH_TYPE.FORMAT },
207+
]);
208+
});
209+
210+
it('should choose the correct file that clashes', () => {
211+
const files = [
212+
{
213+
getFormat: () => 'semi_structured_text',
214+
getFileName: () => 'file1',
215+
getStatus: () => ({ supportedFormat: true }),
216+
} as FileWrapper,
217+
{
218+
getFormat: () => 'semi_structured_text',
219+
getFileName: () => 'file2',
220+
getStatus: () => ({ supportedFormat: true }),
221+
} as FileWrapper,
222+
{
223+
getFormat: () => 'delimited',
224+
getFileName: () => 'file3',
225+
getStatus: () => ({ supportedFormat: true }),
226+
} as FileWrapper,
227+
];
228+
229+
const result = getFormatClashes(files);
230+
231+
expect(result).toEqual([
232+
{ fileName: 'file1', clash: false, clashType: undefined },
233+
{ fileName: 'file2', clash: false, clashType: undefined },
234+
{ fileName: 'file3', clash: true, clashType: 1 },
235+
]);
236+
});
237+
238+
it('should return unsupported format clashes', () => {
239+
const files = [
240+
{
241+
getFormat: () => 'semi_structured_text',
242+
getFileName: () => 'file1',
243+
getStatus: () => ({ supportedFormat: true }),
244+
getMappings: () => ({ properties: { field1: { type: 'text' } } }),
245+
} as unknown as FileWrapper,
246+
{
247+
getFormat: () => 'semi_structured_text',
248+
getFileName: () => 'file2',
249+
getStatus: () => ({ supportedFormat: true }),
250+
getMappings: () => ({ properties: { field1: { type: 'text' } } }),
251+
} as unknown as FileWrapper,
252+
{
253+
getFormat: () => 'unknown',
254+
getFileName: () => 'file3',
255+
getStatus: () => ({ supportedFormat: false }),
256+
getMappings: () => ({ properties: { field1: { type: 'text' } } }),
257+
} as unknown as FileWrapper,
258+
];
259+
260+
const result = getFormatClashes(files);
261+
262+
expect(result).toEqual([
263+
{ fileName: 'file1', clash: false, clashType: undefined },
264+
{ fileName: 'file2', clash: false, clashType: undefined },
265+
{ fileName: 'file3', clash: true, clashType: CLASH_TYPE.UNSUPPORTED },
266+
]);
267+
});
268+
});
269+
});

0 commit comments

Comments
 (0)