blob: 6c12ed77983ce8aa49cad0dc9df535bae2468f0e [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { QueryBuilder, FilteringMode } from './query-builder';
import { Filter } from 'app/model/filter';
import { TIMESTAMP_FIELD_NAME } from '../../utils/constants';
import { Utils } from 'app/utils/utils';
describe('QueryBuilder', () => {
let queryBuilder: QueryBuilder;
beforeEach(() => {
queryBuilder = new QueryBuilder();
});
it('should be able to handle multiple filters', () => {
queryBuilder.setSearch('alert_status:RESOLVE AND ip_src_addr:0.0.0.0');
expect(queryBuilder.searchRequest.query).toBe(
'(alert_status:RESOLVE OR metron_alert.alert_status:RESOLVE) AND (ip_src_addr:0.0.0.0 OR metron_alert.ip_src_addr:0.0.0.0)'
);
});
it('should be able to handle multiple EXCLUDING filters for the same field', () => {
queryBuilder.setSearch('-alert_status:RESOLVE AND -alert_status:DISMISS');
expect(queryBuilder.searchRequest.query).toBe(
'-(alert_status:RESOLVE OR metron_alert.alert_status:RESOLVE) AND -(alert_status:DISMISS OR metron_alert.alert_status:DISMISS)'
);
});
it('should be able to handle group multiple clauses to a single field, aka. field grouping', () => {
queryBuilder.setSearch('alert_status:(RESOLVE OR DISMISS)');
expect(queryBuilder.searchRequest.query).toBe(
'(alert_status:(RESOLVE OR DISMISS) OR metron_alert.alert_status:(RESOLVE OR DISMISS))'
);
});
it('should trim whitespace', () => {
queryBuilder.setSearch(' alert_status:(RESOLVE OR DISMISS) ');
expect(queryBuilder.searchRequest.query).toBe(
'(alert_status:(RESOLVE OR DISMISS) OR metron_alert.alert_status:(RESOLVE OR DISMISS))'
);
});
it('should remove wildcard', () => {
queryBuilder.setSearch('* alert_status:(RESOLVE OR DISMISS)');
expect(queryBuilder.searchRequest.query).toBe(
'(alert_status:(RESOLVE OR DISMISS) OR metron_alert.alert_status:(RESOLVE OR DISMISS))'
);
});
it('should properly parse excluding filters event with wildcard and whitespaces', () => {
queryBuilder.setSearch('* -alert_status:(RESOLVE OR DISMISS)');
expect(queryBuilder.searchRequest.query).toBe(
'-(alert_status:(RESOLVE OR DISMISS) OR metron_alert.alert_status:(RESOLVE OR DISMISS))'
);
});
it('should remove wildcard from an excluding filter', () => {
queryBuilder.setSearch('* -alert_status:(RESOLVE OR DISMISS)');
expect(queryBuilder.searchRequest.query).toBe(
'-(alert_status:(RESOLVE OR DISMISS) OR metron_alert.alert_status:(RESOLVE OR DISMISS))'
);
});
it('should allow only one timerange filter', () => {
queryBuilder.addOrUpdateFilter(new Filter(TIMESTAMP_FIELD_NAME, '[1552863600000 TO 1552950000000]'));
queryBuilder.addOrUpdateFilter(new Filter(TIMESTAMP_FIELD_NAME, '[1552863700000 TO 1552960000000]'));
expect(queryBuilder.query).toBe('(timestamp:[1552863700000 TO 1552960000000] OR ' +
'metron_alert.timestamp:[1552863700000 TO 1552960000000])');
});
it('should escape : chars in ElasticSearch field names', () => {
queryBuilder.setSearch('source:type:bro');
expect(queryBuilder.searchRequest.query).toBe('(source\\:type:bro OR metron_alert.source\\:type:bro)');
});
it('should escape ALL : chars in ElasticSearch field names', () => {
queryBuilder.setSearch('enrichments:geo:ip_dst_addr:country:US');
expect(queryBuilder.searchRequest.query).toBe('(enrichments\\:geo\\:ip_dst_addr\\:country:US ' +
'OR metron_alert.enrichments\\:geo\\:ip_dst_addr\\:country:US)');
});
it('should not multiply escaping in field name', () => {
queryBuilder.setSearch('source:type:bro');
queryBuilder.setSearch('source:type:bro');
queryBuilder.setSearch('source:type:bro');
expect(queryBuilder.searchRequest.query).toBe('(source\\:type:bro OR metron_alert.source\\:type:bro)');
});
it('removeFilter should remove filter by reference', () => {
const filter1 = new Filter(TIMESTAMP_FIELD_NAME, '[1552863600000 TO 1552950000000]');
const filter2 = new Filter('fieldName', 'value');
queryBuilder.addOrUpdateFilter(filter1);
queryBuilder.addOrUpdateFilter(filter2);
queryBuilder.removeFilter(filter1);
expect(queryBuilder.filters.length).toBe(1);
expect(queryBuilder.filters[0]).toBe(filter2);
});
it('removeFilterByField should remove filter having the passed field name', () => {
const filter1 = new Filter('fruit', 'banana');
const filter2 = new Filter('fruit', 'orange');
const filter3 = new Filter('animal', 'horse');
queryBuilder.addOrUpdateFilter(filter1);
queryBuilder.addOrUpdateFilter(filter2);
queryBuilder.addOrUpdateFilter(filter3);
queryBuilder.removeFilterByField('fruit');
expect(queryBuilder.filters.length).toBe(1);
expect(queryBuilder.filters[0]).toBe(filter3);
});
describe('filter query builder modes', () => {
it('should have a getter for filtering mode', () => {
expect(typeof queryBuilder.getFilteringMode).toBe('function');
});
it('should have a setter for filtering mode', () => {
expect(typeof queryBuilder.setFilteringMode).toBe('function');
expect(queryBuilder.getFilteringMode()).toBe(FilteringMode.BUILDER);
queryBuilder.setFilteringMode(FilteringMode.MANUAL);
expect(queryBuilder.getFilteringMode()).toBe(FilteringMode.MANUAL);
queryBuilder.setFilteringMode(FilteringMode.BUILDER);
expect(queryBuilder.getFilteringMode()).toBe(FilteringMode.BUILDER);
});
it('filtering mode should be builder by default', () => {
expect(queryBuilder.getFilteringMode()).toBe(FilteringMode.BUILDER);
});
it('should have a getter for manual query', () => {
expect(typeof queryBuilder.getManualQuery).toBe('function');
});
it('should have a setter for manual query string', () => {
expect(typeof queryBuilder.setManualQuery).toBe('function');
queryBuilder.setManualQuery('test manual query');
expect(queryBuilder.getManualQuery()).toBe('test manual query');
queryBuilder.setManualQuery('another test manual query');
expect(queryBuilder.getManualQuery()).toBe('another test manual query');
});
it('getManualQuery should return the built query string first', () => {
const expected = '(timestamp:[1552863600000 TO 1552950000000] OR metron_alert.timestamp:[1552863600000 ' +
'TO 1552950000000]) AND (animal:horse OR metron_alert.animal:horse)';
queryBuilder.clearSearch();
queryBuilder.addOrUpdateFilter(new Filter(TIMESTAMP_FIELD_NAME, '[1552863600000 TO 1552950000000]'));
queryBuilder.addOrUpdateFilter(new Filter('animal', 'horse'));
expect(queryBuilder.getManualQuery()).toBe(expected);
queryBuilder.setManualQuery('test:query');
expect(queryBuilder.getManualQuery()).toBe('test:query');
});
it('should use manual query string value in manual mode', () => {
queryBuilder.addOrUpdateFilter(new Filter(TIMESTAMP_FIELD_NAME, '[1552863600000 TO 1552950000000]'));
queryBuilder.addOrUpdateFilter(new Filter('animal', 'horse'));
queryBuilder.setFilteringMode(FilteringMode.MANUAL);
queryBuilder.setManualQuery('test:query');
expect(queryBuilder.searchRequest.query).toBe('test:query');
});
it('should use built query string value in builder mode', () => {
queryBuilder.addOrUpdateFilter(new Filter(TIMESTAMP_FIELD_NAME, '[1552863600000 TO 1552950000000]'));
queryBuilder.addOrUpdateFilter(new Filter('animal', 'horse'));
queryBuilder.setFilteringMode(FilteringMode.BUILDER);
queryBuilder.setManualQuery('test:query');
expect(queryBuilder.searchRequest.query).toBe(
'(timestamp:[1552863600000 TO 1552950000000] OR metron_alert.timestamp:[1552863600000 ' +
'TO 1552950000000]) AND (animal:horse OR metron_alert.animal:horse)'
);
});
it('clearSearch should clear manual query value', () => {
queryBuilder.setFilteringMode(FilteringMode.MANUAL);
queryBuilder.setManualQuery('manual:test:query');
expect(queryBuilder.getManualQuery()).toBe('manual:test:query');
queryBuilder.clearSearch();
expect(queryBuilder.getManualQuery()).toBe('*');
});
});
});