Skip to content

Commit

Permalink
[Security Solution] Add unit test for all hosts (#76752)
Browse files Browse the repository at this point in the history
* add unit test for all hosts

* fix types

Co-authored-by: Elastic Machine <[email protected]>
angorayc and elasticmachine authored Sep 7, 2020

Unverified

This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
1 parent d16c239 commit 8556427
Showing 6 changed files with 946 additions and 11 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { HostsEdges } from '../../../../../../common/search_strategy/security_solution';

import { formatHostEdgesData } from './helpers';
import { mockBuckets } from './__mocks__';

describe('#formatHostsData', () => {
test('it formats a host with a source of name correctly', () => {
const mockFields: readonly string[] = ['host.name'];
const data = formatHostEdgesData(mockFields, mockBuckets);
const expected: HostsEdges = {
cursor: { tiebreaker: null, value: 'zeek-london' },
node: { host: { name: ['zeek-london'] }, _id: 'zeek-london' },
};

expect(data).toEqual(expected);
});

test('it formats a host with a source of os correctly', () => {
const mockFields: readonly string[] = ['host.os.name'];
const data = formatHostEdgesData(mockFields, mockBuckets);
const expected: HostsEdges = {
cursor: { tiebreaker: null, value: 'zeek-london' },
node: { host: { os: { name: ['Ubuntu'] } }, _id: 'zeek-london' },
};

expect(data).toEqual(expected);
});

test('it formats a host with a source of version correctly', () => {
const mockFields: readonly string[] = ['host.os.version'];
const data = formatHostEdgesData(mockFields, mockBuckets);
const expected: HostsEdges = {
cursor: { tiebreaker: null, value: 'zeek-london' },
node: { host: { os: { version: ['18.04.2 LTS (Bionic Beaver)'] } }, _id: 'zeek-london' },
};

expect(data).toEqual(expected);
});

test('it formats a host with a source of id correctly', () => {
const mockFields: readonly string[] = ['host.name'];
const data = formatHostEdgesData(mockFields, mockBuckets);
const expected: HostsEdges = {
cursor: { tiebreaker: null, value: 'zeek-london' },
node: { _id: 'zeek-london', host: { name: ['zeek-london'] } },
};

expect(data).toEqual(expected);
});

test('it formats a host with a source of name, lastBeat, os, and version correctly', () => {
const mockFields: readonly string[] = ['host.name', 'host.os.name', 'host.os.version'];
const data = formatHostEdgesData(mockFields, mockBuckets);
const expected: HostsEdges = {
cursor: { tiebreaker: null, value: 'zeek-london' },
node: {
_id: 'zeek-london',
host: {
name: ['zeek-london'],
os: { name: ['Ubuntu'], version: ['18.04.2 LTS (Bionic Beaver)'] },
},
},
};

expect(data).toEqual(expected);
});

test('it formats a host without any data if mockFields are empty', () => {
const mockFields: readonly string[] = [];
const data = formatHostEdgesData(mockFields, mockBuckets);
const expected: HostsEdges = {
cursor: {
tiebreaker: null,
value: '',
},
node: {},
};

expect(data).toEqual(expected);
});
});
Original file line number Diff line number Diff line change
@@ -9,22 +9,29 @@ import { hostFieldsMap } from '../../../../../../common/ecs/ecs_fields';
import { HostsEdges } from '../../../../../../common/search_strategy/security_solution/hosts';

import { HostAggEsItem, HostBuckets, HostValue } from '../../../../../lib/hosts/types';
import { toArray } from '../../../../helpers/to_array';

const HOSTS_FIELDS = ['_id', 'lastSeen', 'host.id', 'host.name', 'host.os.name', 'host.os.version'];
export const HOSTS_FIELDS: readonly string[] = [
'_id',
'lastSeen',
'host.id',
'host.name',
'host.os.name',
'host.os.version',
];

export const formatHostEdgesData = (bucket: HostAggEsItem): HostsEdges =>
HOSTS_FIELDS.reduce<HostsEdges>(
export const formatHostEdgesData = (
fields: readonly string[] = HOSTS_FIELDS,
bucket: HostAggEsItem
): HostsEdges =>
fields.reduce<HostsEdges>(
(flattenedFields, fieldName) => {
const hostId = get('key', bucket);
flattenedFields.node._id = hostId || null;
flattenedFields.cursor.value = hostId || '';
const fieldValue = getHostFieldValue(fieldName, bucket);
if (fieldValue != null) {
return set(
`node.${fieldName}`,
Array.isArray(fieldValue) ? fieldValue : [fieldValue],
flattenedFields
);
return set(`node.${fieldName}`, toArray(fieldValue), flattenedFields);
}
return flattenedFields;
},
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { DEFAULT_MAX_TABLE_QUERY_SIZE } from '../../../../../../common/constants';

import { HostsRequestOptions } from '../../../../../../common/search_strategy/security_solution';
import * as buildQuery from './query.all_hosts.dsl';
import { allHosts } from '.';
import {
mockOptions,
mockSearchStrategyResponse,
formattedSearchStrategyResponse,
} from './__mocks__';

describe('allHosts search strategy', () => {
const buildAllHostsQuery = jest.spyOn(buildQuery, 'buildHostsQuery');

afterEach(() => {
buildAllHostsQuery.mockClear();
});

describe('buildDsl', () => {
test('should build dsl query', () => {
allHosts.buildDsl(mockOptions);
expect(buildAllHostsQuery).toHaveBeenCalledWith(mockOptions);
});

test('should throw error if query size is greater equal than DEFAULT_MAX_TABLE_QUERY_SIZE ', () => {
const overSizeOptions = {
...mockOptions,
pagination: {
...mockOptions.pagination,
querySize: DEFAULT_MAX_TABLE_QUERY_SIZE,
},
} as HostsRequestOptions;

expect(() => {
allHosts.buildDsl(overSizeOptions);
}).toThrowError(`No query size above ${DEFAULT_MAX_TABLE_QUERY_SIZE}`);
});
});

describe('parse', () => {
test('should parse data correctly', async () => {
const result = await allHosts.parse(mockOptions, mockSearchStrategyResponse);
expect(result).toMatchObject(formattedSearchStrategyResponse);
});
});
});
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ import {
import { inspectStringifyObject } from '../../../../../utils/build_query';
import { SecuritySolutionFactory } from '../../types';
import { buildHostsQuery } from './query.all_hosts.dsl';
import { formatHostEdgesData } from './helpers';
import { formatHostEdgesData, HOSTS_FIELDS } from './helpers';

export const allHosts: SecuritySolutionFactory<HostsQueries.hosts> = {
buildDsl: (options: HostsRequestOptions) => {
@@ -38,12 +38,11 @@ export const allHosts: SecuritySolutionFactory<HostsQueries.hosts> = {
'aggregations.host_data.buckets',
response.rawResponse
);
const hostsEdges = buckets.map((bucket) => formatHostEdgesData(bucket));
const hostsEdges = buckets.map((bucket) => formatHostEdgesData(HOSTS_FIELDS, bucket));
const fakeTotalCount = fakePossibleCount <= totalCount ? fakePossibleCount : totalCount;
const edges = hostsEdges.splice(cursorStart, querySize - cursorStart);
const inspect = {
dsl: [inspectStringifyObject(buildHostsQuery(options))],
response: [inspectStringifyObject(response)],
};
const showMorePagesIndicator = totalCount > fakeTotalCount;

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { buildHostsQuery } from './query.all_hosts.dsl';
import { mockOptions, expectedDsl } from './__mocks__/';

describe('buildHostsQuery', () => {
test('build query from options correctly', () => {
expect(buildHostsQuery(mockOptions)).toEqual(expectedDsl);
});
});

0 comments on commit 8556427

Please sign in to comment.