/*
* Copyright 2014 Splunk, Inc.
*
* Licensed 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.
*/
package com.splunk;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
import java.util.*;
public class DataModelTest extends SDKTestCase {
@After
public void tearDown() throws Exception {
Collection<DataModel> dataModels = service.getDataModels().values();
for (DataModel d : dataModels) {
if (d.getName().startsWith("delete-me")) {
d.remove();
}
}
super.tearDown();
}
@Test
public void testDataModelCollectionCreateAndDelete() {
EntityCollection<DataModel> dataModels = service.getDataModels();
DataModelArgs args = new DataModelArgs();
args.setRawJsonDescription(streamToString(openResource("data/datamodels/empty_data_model.json")));
int initialN = dataModels.size();
DataModel dataModel = dataModels.create(createTemporaryName(), args);
Assert.assertEquals(initialN+1, dataModels.size());
dataModel.remove();
dataModels.refresh();
Assert.assertEquals(initialN, dataModels.size());
}
@Test
public void testDataModelObjectFetchNotNull() {
DataModelCollection dataModelCollection = service.getDataModels();
DataModel model = dataModelCollection.get("internal_audit_logs");
DataModelObject searches = model.getObject("searches");
Assert.assertNotNull(searches);
}
@Test
public void testDataModelWithZeroObjects() {
EntityCollection<DataModel> dataModels = service.getDataModels();
DataModelArgs args = new DataModelArgs();
args.setRawJsonDescription(streamToString(openResource("data/datamodels/empty_data_model.json")));
DataModel model = dataModels.create(createTemporaryName(), args);
Assert.assertEquals(0, model.getObjects().size());
// Make sure this works after refresh as well.
model.refresh();
Assert.assertEquals(0, model.getObjects().size());
}
@Test
public void testDataModelWithOneObject() {
EntityCollection<DataModel> dataModels = service.getDataModels();
DataModelArgs args = new DataModelArgs();
args.setRawJsonDescription(streamToString(openResource("data/datamodels/object_with_one_search.json")));
DataModel model = dataModels.create(createTemporaryName(), args);
Assert.assertEquals(1, model.getObjects().size());
// Make sure this works after refresh as well.
model.refresh();
Assert.assertEquals(1, model.getObjects().size());
}
@Test
public void testDataModelWithTwoObjects() {
EntityCollection<DataModel> dataModels = service.getDataModels();
DataModelArgs args = new DataModelArgs();
args.setRawJsonDescription(streamToString(openResource("data/datamodels/object_with_two_searches.json")));
DataModel model = dataModels.create(createTemporaryName(), args);
Assert.assertEquals(2, model.getObjects().size());
// Make sure this works after refresh as well.
model.refresh();
Assert.assertEquals(2, model.getObjects().size());
}
@Test
public void testGetAndContainsObjectWork() {
EntityCollection<DataModel> dataModels = service.getDataModels();
DataModelArgs args = new DataModelArgs();
args.setRawJsonDescription(streamToString(openResource("data/datamodels/object_with_two_searches.json")));
DataModel model = dataModels.create(createTemporaryName(), args);
Assert.assertTrue(model.containsObject("search1"));
Assert.assertTrue(model.containsObject("search2"));
DataModelObject search1 = model.getObject("search1");
Assert.assertNotNull(search1);
Assert.assertEquals("\u0bf5\u0bf1\u0bf0\u0bef - search 1", search1.getDisplayName());
DataModelObject search2 = model.getObject("search2");
Assert.assertNotNull(search2);
Assert.assertEquals("\u0bf5\u0bf1\u0bf0\u0bef - search 2", search2.getDisplayName());
}
@Test
public void testDataModelWithUnicodeAttributes() {
EntityCollection<DataModel> dataModels = service.getDataModels();
String modelName = createTemporaryName();
DataModelArgs args = new DataModelArgs();
args.setRawJsonDescription(streamToString(openResource("data/datamodels/model_with_unicode_headers.json")));
DataModel model = dataModels.create(modelName, args);
Assert.assertEquals(modelName, model.getName());
Assert.assertEquals("\u1029\u1699\u0bf5", model.getDisplayName());
Assert.assertEquals("\u0bf5\u0bf1\u0bf0\u0bef", model.getDescription());
}
@Test
public void testDataModelWithEmptyAttributes() {
EntityCollection<DataModel> dataModels = service.getDataModels();
String modelName = createTemporaryName();
DataModelArgs args = new DataModelArgs();
args.setRawJsonDescription(streamToString(openResource("data/datamodels/model_with_empty_headers.json")));
DataModel model = dataModels.create(modelName, args);
Assert.assertEquals(modelName, model.getName());
Assert.assertEquals("", model.getDisplayName());
Assert.assertEquals("", model.getDescription());
}
@Test
public void testAccelerationSettings() {
Args serviceArgs = new Args();
serviceArgs.put("host", service.getHost());
serviceArgs.put("port", service.getPort());
serviceArgs.put("scheme", service.getScheme());
serviceArgs.put("token", service.getToken());
serviceArgs.put("owner", "nobody");
serviceArgs.put("app", "search");
Service nonprivateService = new Service(serviceArgs);
EntityCollection<DataModel> dataModels = nonprivateService.getDataModels();
DataModelArgs args = new DataModelArgs();
args.setRawJsonDescription(streamToString(openResource("data/datamodels/data_model_with_test_objects.json")));
DataModel model = dataModels.create(createTemporaryName(), args);
model.setAcceleration(true);
model.setEarliestAcceleratedTime("-2mon");
model.setAccelerationCronSchedule("5/* * * * *");
model.update();
Assert.assertTrue(model.isAccelerated());
Assert.assertEquals("-2mon", model.getEarliestAcceleratedTime());
Assert.assertEquals("5/* * * * *", model.getAccelerationCronSchedule());
Assert.assertFalse(model.isManualRebuilds());
model.update(); // An empty update should also work
model.refresh();
Assert.assertTrue(model.isAccelerated());
Assert.assertEquals("-2mon", model.getEarliestAcceleratedTime());
Assert.assertEquals("5/* * * * *", model.getAccelerationCronSchedule());
Assert.assertFalse(model.isManualRebuilds());
model.setAcceleration(false);
model.setEarliestAcceleratedTime("-1mon");
model.setAccelerationCronSchedule("* * * * *");
model.update();
Assert.assertFalse(model.isAccelerated());
Assert.assertEquals("-1mon", model.getEarliestAcceleratedTime());
Assert.assertEquals("* * * * *", model.getAccelerationCronSchedule());
Assert.assertFalse(model.isManualRebuilds());
model.setManualRebuilds(true);
model.update();
Assert.assertFalse(model.isAccelerated());
Assert.assertEquals("-1mon", model.getEarliestAcceleratedTime());
Assert.assertEquals("* * * * *", model.getAccelerationCronSchedule());
Assert.assertTrue(model.isManualRebuilds());
}
@Test
public void testObjectMetadata() {
DataModelCollection models = service.getDataModels();
DataModelArgs args = new DataModelArgs();
args.setRawJsonDescription(streamToString(openResource("data/datamodels/data_model_with_test_objects.json")));
DataModel model = models.create(createTemporaryName(), args);
DataModelObject object = model.getObject("event1");
Assert.assertNotNull(object);
Assert.assertEquals("event1 \u1029\u1699", object.getDisplayName());
Assert.assertEquals("event1", object.getName());
Assert.assertEquals(model, object.getDataModel());
}
@Test
public void testParentOnChild() {
DataModelCollection models = service.getDataModels();
DataModelArgs args = new DataModelArgs();
args.setRawJsonDescription(streamToString(openResource("data/datamodels/data_model_with_test_objects.json")));
DataModel model = models.create(createTemporaryName(), args);
DataModelObject object = model.getObject("event1");
Assert.assertNotNull(object);
object.getParent();
}
@Test
public void testLineage() {
DataModelCollection models = service.getDataModels();
DataModelArgs args = new DataModelArgs();
args.setRawJsonDescription(streamToString(openResource("data/datamodels/inheritance_test_data.json")));
DataModel model = models.create(createTemporaryName(), args);
Collection<DataModelObject> children;
DataModelObject object = model.getObject("level_0");
Assert.assertNotNull(object);
Assert.assertArrayEquals(new String[]{"level_0"}, object.getLineage());
Assert.assertEquals("BaseEvent", object.getParentName());
object = model.getObject("level_1");
Assert.assertNotNull(object);
Assert.assertArrayEquals(new String[]{"level_0", "level_1"}, object.getLineage());
Assert.assertEquals("level_0", object.getParentName());
object = model.getObject("level_2");
Assert.assertNotNull(object);
Assert.assertArrayEquals(new String[]{"level_0", "level_1", "level_2"}, object.getLineage());
Assert.assertEquals("level_1", object.getParentName());
}
@Test
public void testObjectFields() {
DataModelCollection models = service.getDataModels();
DataModelArgs args = new DataModelArgs();
args.setRawJsonDescription(streamToString(openResource("data/datamodels/inheritance_test_data.json")));
DataModel model = models.create(createTemporaryName(), args);
DataModelObject object = model.getObject("level_2");
Assert.assertNotNull(object);
Assert.assertEquals(5, object.getAutoExtractedFields().size());
DataModelField f = object.getField("_time");
Assert.assertEquals("BaseEvent", f.getOwnerName());
Assert.assertArrayEquals(new String[]{"BaseEvent"}, f.getOwnerLineage());
Assert.assertEquals(FieldType.TIMESTAMP, f.getType());
Assert.assertEquals("_time", f.getName());
Assert.assertEquals("_time", f.getDisplayName());
Assert.assertEquals(false, f.isRequired());
Assert.assertEquals(false, f.isMultivalued());
Assert.assertEquals(false, f.isHidden());
Assert.assertEquals(false, f.isEditable());
Assert.assertEquals("", f.getComment());
f = object.getField("level_2");
Assert.assertEquals("level_2", f.getOwnerName());
Assert.assertArrayEquals(new String[]{"level_0", "level_1", "level_2"}, f.getOwnerLineage());
Assert.assertEquals(FieldType.OBJECTCOUNT, f.getType());
Assert.assertEquals("level_2", f.getName());
Assert.assertEquals("level 2", f.getDisplayName());
Assert.assertEquals(false, f.isRequired());
Assert.assertEquals(false, f.isMultivalued());
Assert.assertEquals(false, f.isHidden());
Assert.assertEquals(false, f.isEditable());
Assert.assertEquals("", f.getComment());
}
@Test
public void testOutputObjectFields() {
DataModelCollection models = service.getDataModels();
DataModelArgs args = new DataModelArgs();
args.setRawJsonDescription(streamToString(openResource("data/datamodels/data_model_for_pivot.json")));
DataModel model = models.create(createTemporaryName(), args);
DataModelObject object = model.getObject("test_data");
Assert.assertEquals(5, object.getAutoExtractedFields().size());
Assert.assertEquals(10, object.getFields().size());
Assert.assertTrue(object.containsField("has_boris"));
Assert.assertTrue(object.containsField("_time"));
}
@Test
public void testCreateLocalAccelerationJob() {
DataModelCollection models = service.getDataModels();
String dataModelName = createTemporaryName();
DataModelArgs args = new DataModelArgs();
args.setRawJsonDescription(streamToString(openResource("data/datamodels/inheritance_test_data.json")));
DataModel model = models.create(dataModelName, args);
DataModelObject object = model.getObject("level_2");
Assert.assertNotNull(object);
final Job accelerationJob = object.createLocalAccelerationJob();
try {
assertEventuallyTrue(new EventuallyTrueBehavior() {
@Override
public boolean predicate() {
return accelerationJob.isReady();
}
});
Assert.assertEquals(
"| datamodel " + dataModelName + " level_2 search | tscollect",
accelerationJob.getSearch()
);
} finally {
accelerationJob.cancel();
}
}
@Test
public void testCreateLocalAccelerationJobWithEarliestTime() {
DataModelCollection models = service.getDataModels();
String dataModelName = createTemporaryName();
DataModelArgs args = new DataModelArgs();
args.setRawJsonDescription(streamToString(openResource("data/datamodels/inheritance_test_data.json")));
DataModel model = models.create(dataModelName, args);
DataModelObject object = model.getObject("level_2");
Assert.assertNotNull(object);
final Job accelerationJob = object.createLocalAccelerationJob("-1d");
try {
assertEventuallyTrue(new EventuallyTrueBehavior() {
@Override
public boolean predicate() {
return accelerationJob.isReady();
}
});
Assert.assertEquals(
"| datamodel " + dataModelName + " level_2 search | tscollect",
accelerationJob.getSearch()
);
} finally {
accelerationJob.cancel();
}
// I don't have a good way of getting a date two weeks ago in Java, so
// the earliest time part of this is simply untested.
}
@Test
public void testConstraints() {
EntityCollection<DataModel> dataModels = service.getDataModels();
DataModelArgs args = new DataModelArgs();
args.setRawJsonDescription(streamToString(openResource("data/datamodels/data_model_with_test_objects.json")));
DataModel model = dataModels.create(createTemporaryName(), args);
DataModelObject object = model.getObject("event1");
Assert.assertNotNull(object);
Assert.assertEquals(1, object.getConstraints().size());
boolean only_one = true;
for (DataModelConstraint c : object.getConstraints()) {
Assert.assertTrue(only_one);
only_one = false;
Assert.assertEquals("event1", c.getOwner());
Assert.assertEquals("uri=\"*.php\" OR uri=\"*.py\"\n" +
"NOT (referer=null OR referer=\"-\")", c.getQuery());
}
}
@Test
public void testCalculations() {
EntityCollection<DataModel> dataModels = service.getDataModels();
DataModelArgs args = new DataModelArgs();
args.setRawJsonDescription(streamToString(openResource("data/datamodels/data_model_with_test_objects.json")));
DataModel model = dataModels.create(createTemporaryName(), args);
DataModelObject object = model.getObject("event1");
Assert.assertNotNull(object);
Map<String, DataModelCalculation> calculations = object.getCalculations();
Assert.assertEquals(4, calculations.size());
EvalDataModelCalculation c = (EvalDataModelCalculation)calculations.get("93fzsv03wa7");
Assert.assertEquals("event1", c.getOwner());
Assert.assertArrayEquals(new String[]{"event1"}, c.getLineage());
Assert.assertEquals("", c.getComment());
Assert.assertEquals(true, c.isEditable());
Assert.assertEquals(
"if(cidrmatch(\"192.0.0.0/16\", clientip), \"local\", \"other\")",
c.getExpression()
);
Assert.assertEquals(1, c.getGeneratedFields().size());
DataModelField f = c.getGeneratedField("new_field");
Assert.assertNotNull(f);
Assert.assertEquals("My New Field", f.getDisplayName());
LookupDataModelCalculation lc = (LookupDataModelCalculation)calculations.get("sr3mc8o3mjr");
Assert.assertEquals("event1", lc.getOwner());
Assert.assertArrayEquals(new String[]{"event1"}, lc.getLineage());
Assert.assertEquals("", lc.getComment());
Assert.assertEquals(true, lc.isEditable());
List<LookupDataModelCalculation.LookupFieldMapping> expectedFieldMappings =
new ArrayList<LookupDataModelCalculation.LookupFieldMapping>();
expectedFieldMappings.add(new LookupDataModelCalculation.LookupFieldMapping() {{
inputField = "host";
lookupField = "a_lookup_field";
}});
Assert.assertEquals("dnslookup", lc.getLookupName());
RegexpDataModelCalculation rc = (RegexpDataModelCalculation)calculations.get("a5v1k82ymic");
Assert.assertEquals(2, rc.getGeneratedFields().size());
Assert.assertEquals("_raw", rc.getInputField());
Assert.assertEquals(" From: (?<from>.*) To: (?<to>.*) ", rc.getExpression());
GeoIPDataModelCalculation gc = (GeoIPDataModelCalculation)calculations.get("pbe9bd0rp4");
Assert.assertEquals("\u1029\u1699\u0bf5 comment of pbe9bd0rp4", gc.getComment());
Assert.assertEquals(5, gc.getGeneratedFields().size());
Assert.assertEquals("output_from_reverse_hostname", gc.getInputField());
}
@Test
public void testRunQuery() {
DataModel dataModel = service.getDataModels().get("internal_audit_logs");
DataModelObject searches = dataModel.getObject("searches");
Job job = null;
try {
final Job j = searches.runQuery();
job = j;
assertEventuallyTrue(new EventuallyTrueBehavior() {
@Override
public boolean predicate() {
return j.isReady();
}
});
Assert.assertEquals("| datamodel " + dataModel.getName() + " " + searches.getName() + " search", job.getSearch());
} finally {
if (job != null) {
job.cancel();
}
}
job = null;
try {
job = searches.runQuery("| head 3", new JobArgs() {{
setEnableLookups(false);
put("status_buckets", "5");
}});
final Job j = job;
assertEventuallyTrue(new EventuallyTrueBehavior() {
@Override
public boolean predicate() {
return j.isReady();
}
});
Assert.assertEquals("| datamodel " + dataModel.getName() + " " + searches.getName() + " search| head 3", job.getSearch());
Assert.assertEquals(5, job.getInteger("statusBuckets"));
} finally {
if (job != null) {
job.cancel();
}
}
}
@Test
public void testBaseSearchProperlyParsed() {
EntityCollection<DataModel> dataModels = service.getDataModels();
DataModelArgs args = new DataModelArgs();
args.setRawJsonDescription(streamToString(openResource("data/datamodels/model_with_multiple_types.json")));
DataModel model = dataModels.create(createTemporaryName(), args);
DataModelObject object = model.getObject("search1");
Assert.assertNotNull(object);
Assert.assertTrue(object instanceof DataModelSearch);
DataModelSearch s = (DataModelSearch)object;
Assert.assertEquals("BaseSearch", s.getParentName());
Assert.assertEquals("search index=_internal | head 10", s.getBaseSearch());
}
@Test
public void testBaseTransactionProperlyParsed() {
EntityCollection<DataModel> dataModels = service.getDataModels();
DataModelArgs args = new DataModelArgs();
args.setRawJsonDescription(streamToString(openResource("data/datamodels/model_with_multiple_types.json")));
DataModel model = dataModels.create(createTemporaryName(), args);
DataModelObject object = model.getObject("transaction1");
Assert.assertNotNull(object);
Assert.assertTrue(object instanceof DataModelTransaction);
DataModelTransaction t = (DataModelTransaction)object;
Assert.assertArrayEquals(new String[] {"event1"}, t.getObjectsToGroup().toArray());
Assert.assertArrayEquals(new String[] {"host", "from"}, t.getGroupByFields().toArray());
Assert.assertEquals("25s", t.getMaxPause());
Assert.assertEquals("100m", t.getMaxSpan());
}
}