Skip to content

Commit 9839573

Browse files
committed
wiring unit tests
1 parent d5d8506 commit 9839573

18 files changed

Lines changed: 2237 additions & 2075 deletions

src/platform/packages/shared/kbn-esql-language/src/language/validation/__tests__/column_existence.test.ts

Lines changed: 2 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -7,52 +7,7 @@
77
* License v3.0 only", or the "Server Side Public License, v 1".
88
*/
99

10-
import { times } from 'lodash';
1110
import { setup } from './helpers';
11+
import { runColumnExistenceValidationSuite } from './column_existence_suite';
1212

13-
describe('column existence checks', () => {
14-
it('looks behind current command', async () => {
15-
const { expectErrors } = await setup();
16-
await expectErrors('FROM index | DROP keywordField | KEEP keywordField', [
17-
'Unknown column "keywordField"',
18-
]);
19-
});
20-
21-
it('treats FORK branches separately', async () => {
22-
const { expectErrors } = await setup();
23-
await expectErrors('FROM index | FORK (DROP keywordField) (KEEP keywordField)', []);
24-
});
25-
26-
it('makes STATS generated columns available after inline WHERE filters', async () => {
27-
const { expectErrors } = await setup();
28-
await expectErrors(
29-
'FROM index | STATS COUNT() WHERE integerField > 0 | EVAL result = `COUNT() WHERE integerField > 0` + 1',
30-
[]
31-
);
32-
});
33-
34-
it('returns a warning instead of an error when unmapped_fields is LOAD or NULLIFY', async () => {
35-
const { expectErrors } = await setup();
36-
await expectErrors(
37-
'SET unmapped_fields = "LOAD"; FROM index | WHERE unmapped == ""',
38-
[],
39-
[
40-
`"unmapped" column isn't mapped in any searched indices.\nIf you are not intentionally referencing an unmapped field,\ncheck that the field exists or that it is spelled correctly in your query.`,
41-
]
42-
);
43-
});
44-
45-
it('returns one warning for each instance of the same unmapped column', async () => {
46-
const { expectErrors } = await setup();
47-
await expectErrors(
48-
'SET unmapped_fields = "LOAD"; FROM index | WHERE unmapped == "" | KEEP unmapped',
49-
[],
50-
51-
times(
52-
2,
53-
() =>
54-
`"unmapped" column isn't mapped in any searched indices.\nIf you are not intentionally referencing an unmapped field,\ncheck that the field exists or that it is spelled correctly in your query.`
55-
)
56-
);
57-
});
58-
});
13+
runColumnExistenceValidationSuite(setup);
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
import { times } from 'lodash';
11+
import type { Setup } from './helpers';
12+
13+
export const runColumnExistenceValidationSuite = (setup: Setup) => {
14+
describe('column existence checks', () => {
15+
it('looks behind current command', async () => {
16+
const { expectErrors } = await setup();
17+
await expectErrors('FROM index | DROP keywordField | KEEP keywordField', [
18+
'Unknown column "keywordField"',
19+
]);
20+
});
21+
22+
it('treats FORK branches separately', async () => {
23+
const { expectErrors } = await setup();
24+
await expectErrors('FROM index | FORK (DROP keywordField) (KEEP keywordField)', []);
25+
});
26+
27+
it('makes STATS generated columns available after inline WHERE filters', async () => {
28+
const { expectErrors } = await setup();
29+
await expectErrors(
30+
'FROM index | STATS COUNT() WHERE integerField > 0 | EVAL result = `COUNT() WHERE integerField > 0` + 1',
31+
[]
32+
);
33+
});
34+
35+
it('returns a warning instead of an error when unmapped_fields is LOAD or NULLIFY', async () => {
36+
const { expectErrors } = await setup();
37+
await expectErrors(
38+
'SET unmapped_fields = "LOAD"; FROM index | WHERE unmapped == ""',
39+
[],
40+
[
41+
`"unmapped" column isn't mapped in any searched indices.\nIf you are not intentionally referencing an unmapped field,\ncheck that the field exists or that it is spelled correctly in your query.`,
42+
]
43+
);
44+
});
45+
46+
it('returns one warning for each instance of the same unmapped column', async () => {
47+
const { expectErrors } = await setup();
48+
await expectErrors(
49+
'SET unmapped_fields = "LOAD"; FROM index | WHERE unmapped == "" | KEEP unmapped',
50+
[],
51+
52+
times(
53+
2,
54+
() =>
55+
`"unmapped" column isn't mapped in any searched indices.\nIf you are not intentionally referencing an unmapped field,\ncheck that the field exists or that it is spelled correctly in your query.`
56+
)
57+
);
58+
});
59+
});
60+
};

src/platform/packages/shared/kbn-esql-language/src/language/validation/__tests__/fields_and_variables.test.ts

Lines changed: 2 additions & 212 deletions
Original file line numberDiff line numberDiff line change
@@ -7,217 +7,7 @@
77
* License v3.0 only", or the "Server Side Public License, v 1".
88
*/
99

10-
import {
11-
type FunctionParameterType,
12-
FunctionDefinitionTypes,
13-
} from '../../../commands/definitions/types';
14-
import { getNoValidCallSignatureError } from '../../../commands/definitions/utils/validation/utils';
15-
import { Location } from '../../../commands/registry/types';
16-
import { setTestFunctions } from '../../../commands/definitions/utils/test_functions';
1710
import { setup } from './helpers';
11+
import { runFieldsAndVariablesValidationSuite } from './fields_and_variables_suite';
1812

19-
describe('column escaping', () => {
20-
it('recognizes escaped fields', async () => {
21-
const { expectErrors } = await setup();
22-
// command level
23-
await expectErrors(
24-
'FROM index | KEEP `kubernetes`.`something`.`something` | EVAL `kubernetes.something.something` + 12',
25-
[]
26-
);
27-
// function argument
28-
await expectErrors('FROM index | EVAL ABS(`kubernetes`.`something`.`something`)', []);
29-
});
30-
31-
it('recognizes field names with spaces and comments', async () => {
32-
const { expectErrors } = await setup();
33-
// command level
34-
await expectErrors('FROM index | KEEP kubernetes . something . /* gotcha! */ something', []);
35-
// function argument
36-
await expectErrors(
37-
'FROM index | EVAL ABS(kubernetes . something . /* gotcha! */ something)',
38-
[]
39-
);
40-
});
41-
42-
it('recognizes escaped user-defined columns', async () => {
43-
const { expectErrors } = await setup();
44-
// command level
45-
await expectErrors('ROW `var$iable` = 1 | EVAL `var$iable`', []);
46-
47-
// command level, different escaping in declaration
48-
await expectErrors(
49-
'ROW variable.`wi#th`.separator = "lolz" | EVAL `variable`.`wi#th`.`separator`',
50-
[]
51-
);
52-
53-
// function arguments
54-
await expectErrors(
55-
'ROW `var$iable` = 1, variable.`wi#th`.separator = "lolz" | EVAL ABS(`var$iable`), TRIM(variable.`wi#th`.`separator`)',
56-
[]
57-
);
58-
59-
// expression user-defined column
60-
await expectErrors('FROM index | EVAL doubleField + 20 | EVAL `doubleField + 20`', []);
61-
await expectErrors('ROW 21 + 20 | STATS AVG(`21 + 20`)', []);
62-
});
63-
64-
it('recognizes user-defined columns with spaces and comments', async () => {
65-
const { expectErrors } = await setup();
66-
// command level
67-
await expectErrors(
68-
'ROW variable.`wi#th`.separator = "lolz" | RENAME variable . /* lolz */ `wi#th` . separator AS foo',
69-
[]
70-
);
71-
// function argument
72-
await expectErrors(
73-
'ROW variable.`wi#th`.separator = "lolz" | EVAL TRIM(variable . /* lolz */ `wi#th` . separator)',
74-
[]
75-
);
76-
});
77-
78-
describe('as part of various commands', () => {
79-
const cases = [
80-
{ name: 'ROW', command: 'ROW `var$iable` = 1, variable.`wi#th`.separator = "lolz"' },
81-
{
82-
name: 'DISSECT',
83-
command: 'ROW `funky`.`stri#$ng` = "lolz" | DISSECT `funky`.`stri#$ng` "%{WORD:firstWord}"',
84-
},
85-
{ name: 'DROP', command: 'FROM index | DROP kubernetes.`something`.`something`' },
86-
{
87-
name: 'ENRICH',
88-
command:
89-
'FROM index | ENRICH policy WITH `new`.name1 = `otherField`, `new.name2` = `yetAnotherField`',
90-
},
91-
{ name: 'EVAL', command: 'FROM index | EVAL kubernetes.`something`.`something` + 12' },
92-
{
93-
name: 'GROK',
94-
command: 'ROW `funky`.`stri#$ng` = "lolz" | GROK `funky`.`stri#$ng` "%{WORD:firstWord}"',
95-
},
96-
{ name: 'KEEP', command: 'FROM index | KEEP kubernetes.`something`.`something`' },
97-
{
98-
name: 'RENAME',
99-
command: 'FROM index | RENAME kubernetes.`something`.`something` as foobar',
100-
},
101-
{ name: 'SORT', command: 'FROM index | SORT kubernetes.`something`.`something` DESC' },
102-
{
103-
name: 'STATS ... BY',
104-
command:
105-
'FROM index | STATS AVG(kubernetes.`something`.`something`) BY `kubernetes`.`something`.`something`',
106-
},
107-
{ name: 'WHERE', command: 'FROM index | WHERE kubernetes.`something`.`something` == 12' },
108-
];
109-
110-
it.each(cases)('$name accepts escaped fields', async ({ command }) => {
111-
const { expectErrors } = await setup();
112-
await expectErrors(command, []);
113-
});
114-
});
115-
});
116-
117-
describe('user-defined column support', () => {
118-
describe('user-defined column data type detection', () => {
119-
beforeAll(() => {
120-
setTestFunctions([
121-
// this test function is just used to test the type of the user-defined column
122-
{
123-
type: FunctionDefinitionTypes.SCALAR,
124-
description: 'Test function',
125-
locationsAvailable: [Location.EVAL],
126-
name: 'test',
127-
signatures: [
128-
{ params: [{ name: 'arg', type: 'cartesian_point' }], returnType: 'cartesian_point' },
129-
],
130-
},
131-
// this test function is used to check that the correct return type is used
132-
// when determining user-defined column types
133-
{
134-
type: FunctionDefinitionTypes.SCALAR,
135-
description: 'Test function',
136-
locationsAvailable: [Location.EVAL],
137-
name: 'return_value',
138-
signatures: [
139-
{ params: [{ name: 'arg', type: 'text' }], returnType: 'text' },
140-
{ params: [{ name: 'arg', type: 'double' }], returnType: 'double' },
141-
{
142-
params: [
143-
{ name: 'arg', type: 'double' },
144-
{ name: 'arg', type: 'text' },
145-
],
146-
returnType: 'long',
147-
},
148-
],
149-
},
150-
]);
151-
});
152-
153-
afterAll(() => {
154-
setTestFunctions([]);
155-
});
156-
157-
const expectType = (type: FunctionParameterType) =>
158-
getNoValidCallSignatureError('test', [type]);
159-
160-
test('literals', async () => {
161-
const { expectErrors } = await setup();
162-
// literal assignment
163-
await expectErrors('FROM index | EVAL var = 1, TEST(var)', [expectType('integer')]);
164-
// literal expression
165-
await expectErrors('FROM index | EVAL 1, TEST(`1`)', [expectType('integer')]);
166-
});
167-
168-
test('fields', async () => {
169-
const { expectErrors } = await setup();
170-
// field assignment
171-
await expectErrors('FROM index | EVAL var = textField, TEST(var)', [
172-
getNoValidCallSignatureError('test', ['text']),
173-
]);
174-
});
175-
176-
test('user-defined columns', async () => {
177-
const { expectErrors } = await setup();
178-
await expectErrors('FROM index | EVAL var = textField, col2 = var, TEST(col2)', [
179-
getNoValidCallSignatureError('test', ['text']),
180-
]);
181-
});
182-
183-
test('inline casting', async () => {
184-
const { expectErrors } = await setup();
185-
// inline cast assignment
186-
await expectErrors('FROM index | EVAL var = doubleField::long, TEST(var)', [
187-
expectType('long'),
188-
]);
189-
// inline cast expression
190-
await expectErrors('FROM index | EVAL doubleField::long, TEST(`doubleField::long`)', [
191-
expectType('long'),
192-
]);
193-
});
194-
195-
test('function results', async () => {
196-
const { expectErrors } = await setup();
197-
// function assignment
198-
await expectErrors('FROM index | EVAL var = RETURN_VALUE(doubleField), TEST(var)', [
199-
expectType('double'),
200-
]);
201-
await expectErrors('FROM index | EVAL var = RETURN_VALUE(textField), TEST(var)', [
202-
expectType('text'),
203-
]);
204-
await expectErrors(
205-
'FROM index | EVAL var = RETURN_VALUE(doubleField, textField), TEST(var)',
206-
[expectType('long')]
207-
);
208-
// function expression
209-
await expectErrors(
210-
'FROM index | EVAL RETURN_VALUE(doubleField), TEST(`RETURN_VALUE(doubleField)`)',
211-
[expectType('double')]
212-
);
213-
await expectErrors(
214-
'FROM index | EVAL RETURN_VALUE(textField), TEST(`RETURN_VALUE(textField)`)',
215-
[expectType('text')]
216-
);
217-
await expectErrors(
218-
'FROM index | EVAL RETURN_VALUE(doubleField, textField), TEST(`RETURN_VALUE(doubleField, textField)`)',
219-
[expectType('long')]
220-
);
221-
});
222-
});
223-
});
13+
runFieldsAndVariablesValidationSuite(setup);

0 commit comments

Comments
 (0)