Skip to content

Commit fa41f53

Browse files
authored
[Security Solution] Add unit tests for Network search strategy (#77416) (#77442)
* init tests * add unit tests for network * add more tests * remove reponse from inspect for hostDetails
1 parent 4d4dd79 commit fa41f53

31 files changed

+3345
-892
lines changed

x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/__mocks__/index.ts

Lines changed: 205 additions & 886 deletions
Large diffs are not rendered by default.

x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,8 @@ export const hostDetails: SecuritySolutionFactory<HostsQueries.details> = {
2929
const aggregations: HostAggEsItem = get('aggregations', response.rawResponse) || {};
3030
const inspect = {
3131
dsl: [inspectStringifyObject(buildHostDetailsQuery(options))],
32-
response: [inspectStringifyObject(response)],
3332
};
3433
const formattedHostItem = formatHostItem(aggregations);
35-
3634
return { ...response, inspect, hostDetails: formattedHostItem };
3735
},
3836
};

x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/query.host_details.dsl.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
* or more contributor license agreements. Licensed under the Elastic License;
44
* you may not use this file except in compliance with the Elastic License.
55
*/
6-
import { buildHostDetailsQuery as buildQuery } from './query.host_details.dsl';
6+
import { buildHostDetailsQuery } from './query.host_details.dsl';
77
import { mockOptions, expectedDsl } from './__mocks__/';
88

9-
describe('buildQuery', () => {
9+
describe('buildHostDetailsQuery', () => {
1010
test('build query from options correctly', () => {
11-
expect(buildQuery(mockOptions)).toEqual(expectedDsl);
11+
expect(buildHostDetailsQuery(mockOptions)).toEqual(expectedDsl);
1212
});
1313
});

x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/details/__mocks__/index.ts

Lines changed: 377 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import * as buildQuery from './query.details_network.dsl';
8+
import { networkDetails } from '.';
9+
import {
10+
mockOptions,
11+
mockSearchStrategyResponse,
12+
formattedSearchStrategyResponse,
13+
} from './__mocks__';
14+
15+
describe('networkDetails search strategy', () => {
16+
const buildNetworkDetailsQuery = jest.spyOn(buildQuery, 'buildNetworkDetailsQuery');
17+
18+
afterEach(() => {
19+
buildNetworkDetailsQuery.mockClear();
20+
});
21+
22+
describe('buildDsl', () => {
23+
test('should build dsl query', () => {
24+
networkDetails.buildDsl(mockOptions);
25+
expect(buildNetworkDetailsQuery).toHaveBeenCalledWith(mockOptions);
26+
});
27+
});
28+
29+
describe('parse', () => {
30+
test('should parse data correctly', async () => {
31+
const result = await networkDetails.parse(mockOptions, mockSearchStrategyResponse);
32+
expect(result).toMatchObject(formattedSearchStrategyResponse);
33+
});
34+
});
35+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
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+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
import { buildNetworkDetailsQuery } from './query.details_network.dsl';
7+
import { mockOptions, expectedDsl } from './__mocks__';
8+
9+
describe('buildNetworkDetailsQuery', () => {
10+
test('build query from options correctly', () => {
11+
expect(buildNetworkDetailsQuery(mockOptions)).toEqual(expectedDsl);
12+
});
13+
});
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
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+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { IEsSearchResponse } from '../../../../../../../../../../src/plugins/data/common';
8+
9+
import {
10+
Direction,
11+
NetworkDnsFields,
12+
NetworkDnsRequestOptions,
13+
NetworkQueries,
14+
} from '../../../../../../../common/search_strategy';
15+
16+
export const mockOptions: NetworkDnsRequestOptions = {
17+
defaultIndex: [
18+
'apm-*-transaction*',
19+
'auditbeat-*',
20+
'endgame-*',
21+
'filebeat-*',
22+
'logs-*',
23+
'packetbeat-*',
24+
'winlogbeat-*',
25+
],
26+
factoryQueryType: NetworkQueries.dns,
27+
filterQuery: '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}',
28+
isPtrIncluded: false,
29+
pagination: { activePage: 0, cursorStart: 0, fakePossibleCount: 50, querySize: 10 },
30+
sort: { field: NetworkDnsFields.uniqueDomains, direction: Direction.desc },
31+
timerange: { interval: '12h', from: '2020-09-13T09:00:43.249Z', to: '2020-09-14T09:00:43.249Z' },
32+
};
33+
34+
export const mockSearchStrategyResponse: IEsSearchResponse<unknown> = {
35+
isPartial: false,
36+
isRunning: false,
37+
rawResponse: {
38+
took: 28,
39+
timed_out: false,
40+
_shards: { total: 21, successful: 21, skipped: 0, failed: 0 },
41+
hits: { max_score: 0, hits: [], total: 0 },
42+
aggregations: {
43+
dns_count: { value: 2 },
44+
dns_name_query_count: {
45+
doc_count_error_upper_bound: 0,
46+
sum_other_doc_count: 0,
47+
buckets: [
48+
{
49+
key: 'google.com',
50+
doc_count: 1,
51+
unique_domains: { value: 1 },
52+
dns_bytes_in: { value: 0 },
53+
dns_bytes_out: { value: 0 },
54+
},
55+
{
56+
key: 'google.internal',
57+
doc_count: 1,
58+
unique_domains: { value: 1 },
59+
dns_bytes_in: { value: 0 },
60+
dns_bytes_out: { value: 0 },
61+
},
62+
],
63+
},
64+
},
65+
},
66+
total: 21,
67+
loaded: 21,
68+
};
69+
70+
export const formattedSearchStrategyResponse = {
71+
isPartial: false,
72+
isRunning: false,
73+
rawResponse: {
74+
took: 28,
75+
timed_out: false,
76+
_shards: { total: 21, successful: 21, skipped: 0, failed: 0 },
77+
hits: { max_score: 0, hits: [] },
78+
aggregations: {
79+
dns_count: { value: 2 },
80+
dns_name_query_count: {
81+
doc_count_error_upper_bound: 0,
82+
sum_other_doc_count: 0,
83+
buckets: [
84+
{
85+
key: 'google.com',
86+
doc_count: 1,
87+
unique_domains: { value: 1 },
88+
dns_bytes_in: { value: 0 },
89+
dns_bytes_out: { value: 0 },
90+
},
91+
{
92+
key: 'google.internal',
93+
doc_count: 1,
94+
unique_domains: { value: 1 },
95+
dns_bytes_in: { value: 0 },
96+
dns_bytes_out: { value: 0 },
97+
},
98+
],
99+
},
100+
},
101+
},
102+
total: 21,
103+
loaded: 21,
104+
edges: [
105+
{
106+
node: {
107+
_id: 'google.com',
108+
dnsBytesIn: 0,
109+
dnsBytesOut: 0,
110+
dnsName: 'google.com',
111+
queryCount: 1,
112+
uniqueDomains: 1,
113+
},
114+
cursor: { value: 'google.com', tiebreaker: null },
115+
},
116+
{
117+
node: {
118+
_id: 'google.internal',
119+
dnsBytesIn: 0,
120+
dnsBytesOut: 0,
121+
dnsName: 'google.internal',
122+
queryCount: 1,
123+
uniqueDomains: 1,
124+
},
125+
cursor: { value: 'google.internal', tiebreaker: null },
126+
},
127+
],
128+
inspect: {
129+
dsl: [
130+
'{\n "allowNoIndices": true,\n "index": [\n "apm-*-transaction*",\n "auditbeat-*",\n "endgame-*",\n "filebeat-*",\n "logs-*",\n "packetbeat-*",\n "winlogbeat-*"\n ],\n "ignoreUnavailable": true,\n "body": {\n "aggregations": {\n "dns_count": {\n "cardinality": {\n "field": "dns.question.registered_domain"\n }\n },\n "dns_name_query_count": {\n "terms": {\n "field": "dns.question.registered_domain",\n "size": 10,\n "order": {\n "unique_domains": "desc"\n }\n },\n "aggs": {\n "unique_domains": {\n "cardinality": {\n "field": "dns.question.name"\n }\n },\n "dns_bytes_in": {\n "sum": {\n "field": "source.bytes"\n }\n },\n "dns_bytes_out": {\n "sum": {\n "field": "destination.bytes"\n }\n }\n }\n }\n },\n "query": {\n "bool": {\n "filter": [\n "{\\"bool\\":{\\"must\\":[],\\"filter\\":[{\\"match_all\\":{}}],\\"should\\":[],\\"must_not\\":[]}}",\n {\n "range": {\n "@timestamp": {\n "gte": "2020-09-13T09:00:43.249Z",\n "lte": "2020-09-14T09:00:43.249Z",\n "format": "strict_date_optional_time"\n }\n }\n }\n ],\n "must_not": [\n {\n "term": {\n "dns.question.type": {\n "value": "PTR"\n }\n }\n }\n ]\n }\n }\n },\n "size": 0,\n "track_total_hits": false\n}',
131+
],
132+
},
133+
pageInfo: { activePage: 0, fakeTotalCount: 2, showMorePagesIndicator: false },
134+
totalCount: 2,
135+
};
136+
137+
export const expectedDsl = {
138+
allowNoIndices: true,
139+
index: [
140+
'apm-*-transaction*',
141+
'auditbeat-*',
142+
'endgame-*',
143+
'filebeat-*',
144+
'logs-*',
145+
'packetbeat-*',
146+
'winlogbeat-*',
147+
],
148+
ignoreUnavailable: true,
149+
body: {
150+
aggregations: {
151+
dns_count: { cardinality: { field: 'dns.question.registered_domain' } },
152+
dns_name_query_count: {
153+
terms: {
154+
field: 'dns.question.registered_domain',
155+
size: 10,
156+
order: { unique_domains: 'desc' },
157+
},
158+
aggs: {
159+
unique_domains: { cardinality: { field: 'dns.question.name' } },
160+
dns_bytes_in: { sum: { field: 'source.bytes' } },
161+
dns_bytes_out: { sum: { field: 'destination.bytes' } },
162+
},
163+
},
164+
},
165+
query: {
166+
bool: {
167+
filter: [
168+
'{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}',
169+
{
170+
range: {
171+
'@timestamp': {
172+
gte: '2020-09-13T09:00:43.249Z',
173+
lte: '2020-09-14T09:00:43.249Z',
174+
format: 'strict_date_optional_time',
175+
},
176+
},
177+
},
178+
],
179+
must_not: [{ term: { 'dns.question.type': { value: 'PTR' } } }],
180+
},
181+
},
182+
},
183+
size: 0,
184+
track_total_hits: false,
185+
};
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import * as buildQuery from './query.dns_network.dsl';
8+
import { networkDns } from '.';
9+
import {
10+
mockOptions,
11+
mockSearchStrategyResponse,
12+
formattedSearchStrategyResponse,
13+
} from './__mocks__';
14+
15+
describe('networkDns search strategy', () => {
16+
const mockBuildDnsQuery = jest.spyOn(buildQuery, 'buildDnsQuery');
17+
18+
afterEach(() => {
19+
mockBuildDnsQuery.mockClear();
20+
});
21+
22+
describe('buildDsl', () => {
23+
test('should build dsl query', () => {
24+
networkDns.buildDsl(mockOptions);
25+
expect(mockBuildDnsQuery).toHaveBeenCalledWith(mockOptions);
26+
});
27+
});
28+
29+
describe('parse', () => {
30+
test('should parse data correctly', async () => {
31+
const result = await networkDns.parse(mockOptions, mockSearchStrategyResponse);
32+
expect(result).toMatchObject(formattedSearchStrategyResponse);
33+
});
34+
});
35+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
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+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
import { buildDnsQuery } from './query.dns_network.dsl';
7+
import { mockOptions, expectedDsl } from './__mocks__';
8+
9+
describe('buildDnsQuery', () => {
10+
test('build query from options correctly', () => {
11+
expect(buildDnsQuery(mockOptions)).toEqual(expectedDsl);
12+
});
13+
});

0 commit comments

Comments
 (0)