Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,16 @@

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.opensearch.common.collect.Tuple;
import org.opensearch.core.xcontent.XContentLocation;
import org.opensearch.core.xcontent.XContentParser;
import org.opensearch.test.NotEqualMessageBuilder;
import org.opensearch.test.hamcrest.RegexMatcher;

import java.io.IOException;
import java.util.Map;
import java.util.regex.Pattern;

import static org.hamcrest.Matchers.closeTo;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.Assert.assertNotNull;
Expand All @@ -57,14 +58,50 @@
public class MatchAssertion extends Assertion {
public static MatchAssertion parse(XContentParser parser) throws IOException {
XContentLocation location = parser.getTokenLocation();
Tuple<String, Object> stringObjectTuple = ParserUtils.parseTuple(parser);
return new MatchAssertion(location, stringObjectTuple.v1(), stringObjectTuple.v2());
String field = null;
Object expectedValue = null;
Double epsilon = null;

Map<String, Object> fields = ParserUtils.parseFields(parser);

if (fields.size() == 1) {
Map.Entry<String, Object> entry = fields.entrySet().iterator().next();
field = entry.getKey();
expectedValue = entry.getValue();
} else if (fields.size() == 2) {
for (Map.Entry<String, Object> entry : fields.entrySet()) {
if ("epsilon".equals(entry.getKey())) {
if (entry.getValue() instanceof Number) {
epsilon = ((Number) entry.getValue()).doubleValue();
} else {
throw new IllegalArgumentException("epsilon must be a number");
}
} else {
field = entry.getKey();
expectedValue = entry.getValue();
}
}
} else {
throw new IllegalArgumentException("match assertion must have 1 or 2 fields, but found " + fields.size());
}

if (field == null) {
throw new IllegalArgumentException("match assertion must have a field to match");
}

return new MatchAssertion(location, field, expectedValue, epsilon);
}

private static final Logger logger = LogManager.getLogger(MatchAssertion.class);
private final Double epsilon;

public MatchAssertion(XContentLocation location, String field, Object expectedValue) {
this(location, field, expectedValue, null);
}

public MatchAssertion(XContentLocation location, String field, Object expectedValue, Double epsilon) {
super(location, field, expectedValue);
this.epsilon = epsilon;
}

@Override
Expand Down Expand Up @@ -97,18 +134,38 @@ protected void doAssert(Object actualValue, Object expectedValue) {
}
assertNotNull("field [" + getField() + "] is null", actualValue);

if (this.epsilon != null && this.epsilon < 0.0) {
throw new IllegalArgumentException("epsilon must be non-negative, but was: " + this.epsilon);
}

if (actualValue.getClass().equals(safeClass(expectedValue)) == false) {
if (actualValue instanceof Number && expectedValue instanceof Number) {
// Double 1.0 is equal to Integer 1
assertThat(
"field [" + getField() + "] doesn't match the expected value",
((Number) actualValue).doubleValue(),
equalTo(((Number) expectedValue).doubleValue())
);
if (epsilon != null) {
assertThat(
"field [" + getField() + "] doesn't match the expected value within epsilon " + epsilon,
((Number) actualValue).doubleValue(),
closeTo(((Number) expectedValue).doubleValue(), epsilon)
);
} else {
assertThat(
"field [" + getField() + "] doesn't match the expected value",
((Number) actualValue).doubleValue(),
equalTo(((Number) expectedValue).doubleValue())
);
}
return;
}
}

if (epsilon != null && actualValue instanceof Number && expectedValue instanceof Number) {
assertThat(
"field [" + getField() + "] doesn't match the expected value within epsilon " + epsilon,
((Number) actualValue).doubleValue(),
closeTo(((Number) expectedValue).doubleValue(), epsilon)
);
return;
}

if (expectedValue.equals(actualValue) == false) {
NotEqualMessageBuilder message = new NotEqualMessageBuilder();
message.compare(getField(), true, actualValue, expectedValue);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,20 @@ public static Tuple<String, Object> parseTuple(XContentParser parser) throws IOE
return Tuple.tuple(entry.getKey(), entry.getValue());
}

public static Map<String, Object> parseFields(XContentParser parser) throws IOException {
parser.nextToken();
advanceToFieldName(parser);
Map<String, Object> map = parser.map();
assert parser.currentToken() == XContentParser.Token.END_OBJECT;
parser.nextToken();

if (map.size() == 0) {
throw new IllegalArgumentException("expected at least one field but found an empty object");
}

return map;
}

public static void advanceToFieldName(XContentParser parser) throws IOException {
XContentParser.Token token = parser.currentToken();
// we are in the beginning, haven't called nextToken yet
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,37 +31,163 @@

package org.opensearch.test.rest.yaml.section;

import org.opensearch.core.xcontent.XContentLocation;
import org.opensearch.test.OpenSearchTestCase;

import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonMap;
import static org.hamcrest.Matchers.containsString;

public class MatchAssertionTests extends OpenSearchTestCase {

public void testNull() {
XContentLocation xContentLocation = new XContentLocation(0, 0);
{
MatchAssertion matchAssertion = new MatchAssertion(xContentLocation, "field", null);
matchAssertion.doAssert(null, null);
expectThrows(AssertionError.class, () -> matchAssertion.doAssert("non-null", null));
}
{
MatchAssertion matchAssertion = new MatchAssertion(xContentLocation, "field", "non-null");
expectThrows(AssertionError.class, () -> matchAssertion.doAssert(null, "non-null"));
}
{
MatchAssertion matchAssertion = new MatchAssertion(xContentLocation, "field", "/exp/");
expectThrows(AssertionError.class, () -> matchAssertion.doAssert(null, "/exp/"));
}
import org.opensearch.common.xcontent.yaml.YamlXContent;

import java.util.List;
import java.util.Map;

import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.notNullValue;

public class AssertionTests extends AbstractClientYamlTestFragmentParserTestCase {
public void testParseIsTrue() throws Exception {
parser = createParser(YamlXContent.yamlXContent, "get.fields._timestamp");

IsTrueAssertion trueAssertion = IsTrueAssertion.parse(parser);

assertThat(trueAssertion, notNullValue());
assertThat(trueAssertion.getField(), equalTo("get.fields._timestamp"));
}

public void testNullInMap() {
XContentLocation xContentLocation = new XContentLocation(0, 0);
MatchAssertion matchAssertion = new MatchAssertion(xContentLocation, "field", singletonMap("a", null));
matchAssertion.doAssert(singletonMap("a", null), matchAssertion.getExpectedValue());
AssertionError e = expectThrows(AssertionError.class, () -> matchAssertion.doAssert(emptyMap(), matchAssertion.getExpectedValue()));
assertThat(e.getMessage(), containsString("expected [null] but not found"));
public void testParseIsFalse() throws Exception {
parser = createParser(YamlXContent.yamlXContent, "docs.1._source");

IsFalseAssertion falseAssertion = IsFalseAssertion.parse(parser);

assertThat(falseAssertion, notNullValue());
assertThat(falseAssertion.getField(), equalTo("docs.1._source"));
}

public void testParseGreaterThan() throws Exception {
parser = createParser(YamlXContent.yamlXContent, "{ field: 3}");

GreaterThanAssertion greaterThanAssertion = GreaterThanAssertion.parse(parser);
assertThat(greaterThanAssertion, notNullValue());
assertThat(greaterThanAssertion.getField(), equalTo("field"));
assertThat(greaterThanAssertion.getExpectedValue(), instanceOf(Integer.class));
assertThat((Integer) greaterThanAssertion.getExpectedValue(), equalTo(3));
}

public void testParseLessThan() throws Exception {
parser = createParser(YamlXContent.yamlXContent, "{ field: 3}");

LessThanAssertion lessThanAssertion = LessThanAssertion.parse(parser);
assertThat(lessThanAssertion, notNullValue());
assertThat(lessThanAssertion.getField(), equalTo("field"));
assertThat(lessThanAssertion.getExpectedValue(), instanceOf(Integer.class));
assertThat((Integer) lessThanAssertion.getExpectedValue(), equalTo(3));
}

public void testParseLength() throws Exception {
parser = createParser(YamlXContent.yamlXContent, "{ _id: 22}");

LengthAssertion lengthAssertion = LengthAssertion.parse(parser);
assertThat(lengthAssertion, notNullValue());
assertThat(lengthAssertion.getField(), equalTo("_id"));
assertThat(lengthAssertion.getExpectedValue(), instanceOf(Integer.class));
assertThat((Integer) lengthAssertion.getExpectedValue(), equalTo(22));
}

public void testParseMatchSimpleIntegerValue() throws Exception {
parser = createParser(YamlXContent.yamlXContent, "{ field: 10 }");

MatchAssertion matchAssertion = MatchAssertion.parse(parser);

assertThat(matchAssertion, notNullValue());
assertThat(matchAssertion.getField(), equalTo("field"));
assertThat(matchAssertion.getExpectedValue(), instanceOf(Integer.class));
assertThat((Integer) matchAssertion.getExpectedValue(), equalTo(10));
}

public void testParseMatchSimpleStringValue() throws Exception {
parser = createParser(YamlXContent.yamlXContent, "{ foo: bar }");

MatchAssertion matchAssertion = MatchAssertion.parse(parser);

assertThat(matchAssertion, notNullValue());
assertThat(matchAssertion.getField(), equalTo("foo"));
assertThat(matchAssertion.getExpectedValue(), instanceOf(String.class));
assertThat(matchAssertion.getExpectedValue().toString(), equalTo("bar"));
}

public void testParseMatchArray() throws Exception {
parser = createParser(YamlXContent.yamlXContent, "{'matches': ['test_percolator_1', 'test_percolator_2']}");

MatchAssertion matchAssertion = MatchAssertion.parse(parser);

assertThat(matchAssertion, notNullValue());
assertThat(matchAssertion.getField(), equalTo("matches"));
assertThat(matchAssertion.getExpectedValue(), instanceOf(List.class));
List<?> strings = (List<?>) matchAssertion.getExpectedValue();
assertThat(strings.size(), equalTo(2));
assertThat(strings.get(0).toString(), equalTo("test_percolator_1"));
assertThat(strings.get(1).toString(), equalTo("test_percolator_2"));
}

@SuppressWarnings("unchecked")
public void testParseContains() throws Exception {
parser = createParser(YamlXContent.yamlXContent, "{testKey: { someKey: someValue } }");

ContainsAssertion containsAssertion = ContainsAssertion.parse(parser);
assertThat(containsAssertion, notNullValue());
assertThat(containsAssertion.getField(), equalTo("testKey"));
assertThat(containsAssertion.getExpectedValue(), instanceOf(Map.class));
assertThat(((Map<String, String>) containsAssertion.getExpectedValue()).get("someKey"), equalTo("someValue"));
}

@SuppressWarnings("unchecked")
public void testParseMatchSourceValues() throws Exception {
parser = createParser(YamlXContent.yamlXContent, "{ _source: { responses.0.hits.total: 3, foo: bar }}");

MatchAssertion matchAssertion = MatchAssertion.parse(parser);

assertThat(matchAssertion, notNullValue());
assertThat(matchAssertion.getField(), equalTo("_source"));
assertThat(matchAssertion.getExpectedValue(), instanceOf(Map.class));
Map<String, Object> expectedValue = (Map<String, Object>) matchAssertion.getExpectedValue();
assertThat(expectedValue.size(), equalTo(2));
Object o = expectedValue.get("responses.0.hits.total");
assertThat(o, instanceOf(Integer.class));
assertThat((Integer) o, equalTo(3));
o = expectedValue.get("foo");
assertThat(o, instanceOf(String.class));
assertThat(o.toString(), equalTo("bar"));
}

public void testParseMatchWithEpsilon() throws Exception {
parser = createParser(YamlXContent.yamlXContent, "{ field: 10.5, epsilon: 0.1 }");

MatchAssertion matchAssertion = MatchAssertion.parse(parser);

assertThat(matchAssertion, notNullValue());
assertThat(matchAssertion.getField(), equalTo("field"));
assertThat(matchAssertion.getExpectedValue(), instanceOf(Double.class));
assertThat((Double) matchAssertion.getExpectedValue(), equalTo(10.5));
}

public void testParseMatchWithEpsilonReversedOrder() throws Exception {
parser = createParser(YamlXContent.yamlXContent, "{ epsilon: 0.1, field: 10.5 }");

MatchAssertion matchAssertion = MatchAssertion.parse(parser);

assertThat(matchAssertion, notNullValue());
assertThat(matchAssertion.getField(), equalTo("field"));
assertThat(matchAssertion.getExpectedValue(), instanceOf(Double.class));
assertThat((Double) matchAssertion.getExpectedValue(), equalTo(10.5));
}

public void testParseMatchFailsWithInvalidEpsilon() throws Exception {
parser = createParser(YamlXContent.yamlXContent, "{ field: 10.5, epsilon: 'invalid' }");

IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> { MatchAssertion.parse(parser); });
assertThat(exception.getMessage(), equalTo("epsilon must be a number"));
}

public void testParseMatchFailsWithTooManyFields() throws Exception {
parser = createParser(YamlXContent.yamlXContent, "{ field: 10.5, epsilon: 0.1, extra: 'value' }");

IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> { MatchAssertion.parse(parser); });
assertThat(exception.getMessage(), equalTo("match assertion must have 1 or 2 fields, but found 3"));
}
}
Loading