diff --git a/services/core/java/com/android/server/integrity/model/AtomicFormula.java b/services/core/java/com/android/server/integrity/model/AtomicFormula.java index a75752841cbce..70ab98c86cda3 100644 --- a/services/core/java/com/android/server/integrity/model/AtomicFormula.java +++ b/services/core/java/com/android/server/integrity/model/AtomicFormula.java @@ -177,6 +177,14 @@ public abstract class AtomicFormula implements Formula { dest.writeInt(mOperator); } + public int getValue() { + return mValue; + } + + public int getOperator() { + return mOperator; + } + private int getMetadataValueByKey(AppInstallMetadata appInstallMetadata) { switch (getKey()) { case VERSION_CODE: @@ -271,6 +279,10 @@ public abstract class AtomicFormula implements Formula { dest.writeStringNoHelper(mValue); } + public String getValue() { + return mValue; + } + private String getMetadataValueByKey(AppInstallMetadata appInstallMetadata) { switch (getKey()) { case PACKAGE_NAME: @@ -367,6 +379,10 @@ public abstract class AtomicFormula implements Formula { dest.writeByte((byte) (mValue ? 1 : 0)); } + public boolean getValue() { + return mValue; + } + private boolean getMetadataValueByKey(AppInstallMetadata appInstallMetadata) { switch (getKey()) { case PRE_INSTALLED: diff --git a/services/core/java/com/android/server/integrity/parser/RuleParseException.java b/services/core/java/com/android/server/integrity/parser/RuleParseException.java new file mode 100644 index 0000000000000..c0f36a66528a8 --- /dev/null +++ b/services/core/java/com/android/server/integrity/parser/RuleParseException.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * 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.android.server.integrity.parser; + +import android.annotation.NonNull; + +/** + * Thrown when rule parsing fails. + */ +public class RuleParseException extends Exception { + public RuleParseException(@NonNull String message) { + super(message); + } + + public RuleParseException(@NonNull String message, @NonNull Throwable cause) { + super(message, cause); + } +} diff --git a/services/core/java/com/android/server/integrity/parser/RuleParser.java b/services/core/java/com/android/server/integrity/parser/RuleParser.java index bfffc70bb12cf..08e0a5db8c204 100644 --- a/services/core/java/com/android/server/integrity/parser/RuleParser.java +++ b/services/core/java/com/android/server/integrity/parser/RuleParser.java @@ -25,8 +25,8 @@ import java.util.List; public interface RuleParser { /** Parse rules from a string. */ - List parse(String ruleText); + List parse(String ruleText) throws RuleParseException; /** Parse rules from an input stream. */ - List parse(InputStream inputStream); + List parse(InputStream inputStream) throws RuleParseException; } diff --git a/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java b/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java index bf31bb2c3665f..ef5bb6ee1e798 100644 --- a/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java +++ b/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java @@ -16,9 +16,11 @@ package com.android.server.integrity.parser; -import android.util.Slog; import android.util.Xml; +import com.android.server.integrity.model.AtomicFormula; +import com.android.server.integrity.model.Formula; +import com.android.server.integrity.model.OpenFormula; import com.android.server.integrity.model.Rule; import org.xmlpull.v1.XmlPullParser; @@ -38,34 +40,41 @@ public final class RuleXmlParser implements RuleParser { public static final String TAG = "RuleXmlParser"; + // TODO: Use XML attributes private static final String RULE_LIST_TAG = "RuleList"; private static final String RULE_TAG = "Rule"; + private static final String OPEN_FORMULA_TAG = "OpenFormula"; + private static final String ATOMIC_FORMULA_TAG = "AtomicFormula"; + private static final String EFFECT_TAG = "Effect"; + private static final String KEY_TAG = "Key"; + private static final String OPERATOR_TAG = "Operator"; + private static final String VALUE_TAG = "Value"; + private static final String CONNECTOR_TAG = "Connector"; @Override - public List parse(String ruleText) { + public List parse(String ruleText) throws RuleParseException { try { XmlPullParser xmlPullParser = Xml.newPullParser(); xmlPullParser.setInput(new StringReader(ruleText)); return parseRules(xmlPullParser); - } catch (XmlPullParserException | IOException e) { - Slog.e(TAG, String.format("Unable to read rules from string: %s", ruleText), e); + } catch (Exception e) { + throw new RuleParseException(e.getMessage(), e); } - return null; } @Override - public List parse(InputStream inputStream) { + public List parse(InputStream inputStream) throws RuleParseException { try { XmlPullParser xmlPullParser = Xml.newPullParser(); xmlPullParser.setInput(inputStream, StandardCharsets.UTF_8.name()); return parseRules(xmlPullParser); - } catch (XmlPullParserException | IOException e) { - Slog.e(TAG, "Unable to read rules from stream", e); + } catch (Exception e) { + throw new RuleParseException(e.getMessage(), e); } - return null; } - private List parseRules(XmlPullParser parser) throws IOException, XmlPullParserException { + private static List parseRules(XmlPullParser parser) + throws IOException, XmlPullParserException { List rules = new ArrayList<>(); // Skipping the first event type, which is always {@link XmlPullParser.START_DOCUMENT} @@ -89,17 +98,150 @@ public final class RuleXmlParser implements RuleParser { if (eventType != XmlPullParser.START_TAG || !nodeName.equals(RULE_TAG)) { continue; } - Rule parsedRule = parseRule(parser); - if (parsedRule != null) { - rules.add(parsedRule); - } + rules.add(parseRule(parser)); } return rules; } - private Rule parseRule(XmlPullParser parser) { - // TODO: Implement rule parser. - return null; + private static Rule parseRule(XmlPullParser parser) throws IOException, XmlPullParserException { + Formula formula = null; + @Rule.Effect int effect = 0; + + int eventType; + while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT) { + String nodeName = parser.getName(); + + if (eventType == XmlPullParser.END_TAG && parser.getName().equals(RULE_TAG)) { + break; + } + + if (eventType == XmlPullParser.START_TAG) { + switch (nodeName) { + case OPEN_FORMULA_TAG: + formula = parseOpenFormula(parser); + break; + case ATOMIC_FORMULA_TAG: + formula = parseAtomicFormula(parser); + break; + case EFFECT_TAG: + effect = Integer.parseInt(extractValue(parser)); + break; + default: + throw new RuntimeException( + String.format("Found unexpected tag: %s", nodeName)); + } + } else { + throw new RuntimeException( + String.format("Found unexpected event type: %d", eventType)); + } + } + + return new Rule(formula, effect); + } + + private static Formula parseOpenFormula(XmlPullParser parser) + throws IOException, XmlPullParserException { + @OpenFormula.Connector int connector = 0; + List formulas = new ArrayList<>(); + + int eventType; + while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT) { + String nodeName = parser.getName(); + + if (eventType == XmlPullParser.END_TAG && parser.getName().equals(OPEN_FORMULA_TAG)) { + break; + } + + if (eventType == XmlPullParser.START_TAG) { + switch (nodeName) { + case CONNECTOR_TAG: + connector = Integer.parseInt(extractValue(parser)); + break; + case ATOMIC_FORMULA_TAG: + formulas.add(parseAtomicFormula(parser)); + break; + case OPEN_FORMULA_TAG: + formulas.add(parseOpenFormula(parser)); + break; + default: + throw new RuntimeException( + String.format("Found unexpected tag: %s", nodeName)); + } + } else { + throw new RuntimeException( + String.format("Found unexpected event type: %d", eventType)); + } + } + + return new OpenFormula(connector, formulas); + } + + private static Formula parseAtomicFormula(XmlPullParser parser) + throws IOException, XmlPullParserException { + @AtomicFormula.Key int key = 0; + @AtomicFormula.Operator int operator = 0; + String value = null; + + int eventType; + while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT) { + String nodeName = parser.getName(); + + if (eventType == XmlPullParser.END_TAG && parser.getName().equals(ATOMIC_FORMULA_TAG)) { + break; + } + + if (eventType == XmlPullParser.START_TAG) { + switch (nodeName) { + case KEY_TAG: + key = Integer.parseInt(extractValue(parser)); + break; + case OPERATOR_TAG: + operator = Integer.parseInt(extractValue(parser)); + break; + case VALUE_TAG: + value = extractValue(parser); + break; + default: + throw new RuntimeException( + String.format("Found unexpected tag: %s", nodeName)); + } + } else { + throw new RuntimeException( + String.format("Found unexpected event type: %d", eventType)); + } + } + return constructAtomicFormulaBasedOnKey(key, operator, value); + } + + private static Formula constructAtomicFormulaBasedOnKey(@AtomicFormula.Key int key, + @AtomicFormula.Operator int operator, String value) { + switch (key) { + case AtomicFormula.PACKAGE_NAME: + case AtomicFormula.INSTALLER_NAME: + case AtomicFormula.APP_CERTIFICATE: + case AtomicFormula.INSTALLER_CERTIFICATE: + return new AtomicFormula.StringAtomicFormula(key, value); + case AtomicFormula.PRE_INSTALLED: + return new AtomicFormula.BooleanAtomicFormula(key, Boolean.parseBoolean(value)); + case AtomicFormula.VERSION_CODE: + return new AtomicFormula.IntAtomicFormula(key, operator, Integer.parseInt(value)); + default: + throw new RuntimeException(String.format("Found unexpected key: %d", key)); + } + } + + private static String extractValue(XmlPullParser parser) + throws IOException, XmlPullParserException { + String value; + int eventType = parser.next(); + if (eventType == XmlPullParser.TEXT) { + value = parser.getText(); + eventType = parser.next(); + if (eventType == XmlPullParser.END_TAG) { + return value; + } + } + throw new RuntimeException(String.format("Found unexpected event type: %d", eventType)); } } diff --git a/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java b/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java index 86e544d409fe4..3b1c3c2b5e8b1 100644 --- a/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java +++ b/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java @@ -18,9 +18,10 @@ package com.android.server.integrity.parser; import static com.android.server.testutils.TestUtils.assertExpectException; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static com.google.common.truth.Truth.assertThat; +import com.android.server.integrity.model.AtomicFormula; +import com.android.server.integrity.model.OpenFormula; import com.android.server.integrity.model.Rule; import org.junit.Test; @@ -29,63 +30,393 @@ import org.junit.runners.JUnit4; import java.io.ByteArrayInputStream; import java.io.InputStream; +import java.util.Arrays; +import java.util.Collections; import java.util.List; @RunWith(JUnit4.class) public class RuleXmlParserTest { - private static final String VALID_RULE_XML = "" - + "" - + "" - + "NOT" - + "" - + "PACKAGE_NAME" - + "EQ" - + "com.app.test" - + "" - + "" - + "DENY" - + "" - + ""; - @Test - public void testXmlString_validRule() { + public void testXmlStream_validOpenFormula() throws Exception { + String ruleXmlOpenFormula = "" + + "" + + "" + + "" + OpenFormula.NOT + "" + + "" + + "" + AtomicFormula.PACKAGE_NAME + "" + + "" + AtomicFormula.EQ + "" + + "com.app.test" + + "" + + "" + + "" + Rule.DENY + "" + + "" + + ""; RuleParser xmlParser = new RuleXmlParser(); - - List rules = xmlParser.parse(VALID_RULE_XML); - - assertNotNull(rules); - assertTrue(rules.isEmpty()); - } - - @Test - public void testXmlStream_validRule() { - RuleParser xmlParser = new RuleXmlParser(); - InputStream inputStream = new ByteArrayInputStream(VALID_RULE_XML.getBytes()); + InputStream inputStream = new ByteArrayInputStream(ruleXmlOpenFormula.getBytes()); + Rule expectedRule = new Rule(new OpenFormula(OpenFormula.NOT, Collections.singletonList( + new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "com.app.test"))), + Rule.DENY); List rules = xmlParser.parse(inputStream); - assertNotNull(rules); - assertTrue(rules.isEmpty()); + assertThat(rules).isEqualTo(Collections.singletonList(expectedRule)); + } + + @Test + public void testXmlString_validOpenFormula_notConnector() throws Exception { + String ruleXmlOpenFormula = "" + + "" + + "" + + "" + OpenFormula.NOT + "" + + "" + + "" + AtomicFormula.PACKAGE_NAME + "" + + "" + AtomicFormula.EQ + "" + + "com.app.test" + + "" + + "" + + "" + Rule.DENY + "" + + "" + + ""; + RuleParser xmlParser = new RuleXmlParser(); + Rule expectedRule = new Rule(new OpenFormula(OpenFormula.NOT, Collections.singletonList( + new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "com.app.test"))), + Rule.DENY); + + List rules = xmlParser.parse(ruleXmlOpenFormula); + + assertThat(rules).isEqualTo(Collections.singletonList(expectedRule)); + } + + @Test + public void testXmlString_validOpenFormula_andConnector() throws Exception { + String ruleXmlOpenFormula = "" + + "" + + "" + + "" + OpenFormula.AND + "" + + "" + + "" + AtomicFormula.PACKAGE_NAME + "" + + "" + AtomicFormula.EQ + "" + + "com.app.test" + + "" + + "" + + "" + AtomicFormula.APP_CERTIFICATE + "" + + "" + AtomicFormula.EQ + "" + + "test_cert" + + "" + + "" + + "" + Rule.DENY + "" + + "" + + ""; + RuleParser xmlParser = new RuleXmlParser(); + Rule expectedRule = new Rule(new OpenFormula(OpenFormula.AND, Arrays.asList( + new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "com.app.test"), + new AtomicFormula.StringAtomicFormula(AtomicFormula.APP_CERTIFICATE, "test_cert"))), + Rule.DENY); + + List rules = xmlParser.parse(ruleXmlOpenFormula); + + assertThat(rules).isEqualTo(Collections.singletonList(expectedRule)); + } + + @Test + public void testXmlString_validOpenFormula_orConnector() throws Exception { + String ruleXmlOpenFormula = "" + + "" + + "" + + "" + OpenFormula.OR + "" + + "" + + "" + AtomicFormula.PACKAGE_NAME + "" + + "" + AtomicFormula.EQ + "" + + "com.app.test" + + "" + + "" + + "" + AtomicFormula.APP_CERTIFICATE + "" + + "" + AtomicFormula.EQ + "" + + "test_cert" + + "" + + "" + + "" + Rule.DENY + "" + + "" + + ""; + RuleParser xmlParser = new RuleXmlParser(); + Rule expectedRule = new Rule(new OpenFormula(OpenFormula.OR, Arrays.asList( + new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "com.app.test"), + new AtomicFormula.StringAtomicFormula(AtomicFormula.APP_CERTIFICATE, "test_cert"))), + Rule.DENY); + + List rules = xmlParser.parse(ruleXmlOpenFormula); + + assertThat(rules).isEqualTo(Collections.singletonList(expectedRule)); + } + + @Test + public void testXmlString_validOpenFormula_differentTagOrder() throws Exception { + String ruleXmlOpenFormula = "" + + "" + + "" + + "" + + "" + AtomicFormula.PACKAGE_NAME + "" + + "" + AtomicFormula.EQ + "" + + "com.app.test" + + "" + + "" + OpenFormula.NOT + "" + + "" + + "" + Rule.DENY + "" + + "" + + ""; + RuleParser xmlParser = new RuleXmlParser(); + Rule expectedRule = new Rule(new OpenFormula(OpenFormula.NOT, Collections.singletonList( + new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "com.app.test"))), + Rule.DENY); + + List rules = xmlParser.parse(ruleXmlOpenFormula); + + assertThat(rules).isEqualTo(Collections.singletonList(expectedRule)); + } + + @Test + public void testXmlString_invalidOpenFormula_invalidNumberOfFormulas() throws Exception { + String ruleXmlOpenFormula = "" + + "" + + "" + + "" + OpenFormula.NOT + "" + + "" + + "" + AtomicFormula.PACKAGE_NAME + "" + + "" + AtomicFormula.EQ + "" + + "com.app.test" + + "" + + "" + + "" + AtomicFormula.VERSION_CODE + "" + + "" + AtomicFormula.EQ + "" + + "1" + + "" + + "" + + "" + Rule.DENY + "" + + "" + + ""; + RuleParser xmlParser = new RuleXmlParser(); + + assertExpectException( + RuleParseException.class, + /* expectedExceptionMessageRegex */ "Connector NOT must have 1 formula only", + () -> xmlParser.parse(ruleXmlOpenFormula)); + } + + @Test + public void testXmlString_invalidOpenFormula_invalidOperator() throws Exception { + String ruleXmlOpenFormula = "" + + "" + + "" + + "" + OpenFormula.NOT + "" + + "" + + "" + AtomicFormula.PACKAGE_NAME + "" + + "INVALID_OPERATOR" + + "com.app.test" + + "" + + "" + + "" + Rule.DENY + "" + + "" + + ""; + RuleParser xmlParser = new RuleXmlParser(); + + assertExpectException( + RuleParseException.class, + /* expectedExceptionMessageRegex */ "For input string: \"INVALID_OPERATOR\"", + () -> xmlParser.parse(ruleXmlOpenFormula)); + } + + @Test + public void testXmlString_invalidOpenFormula_invalidEffect() throws Exception { + String ruleXmlOpenFormula = "" + + "" + + "" + + "" + OpenFormula.NOT + "" + + "" + + "" + AtomicFormula.PACKAGE_NAME + "" + + "" + AtomicFormula.EQ + "" + + "com.app.test" + + "" + + "" + + "INVALID_EFFECT" + + "" + + ""; + RuleParser xmlParser = new RuleXmlParser(); + + assertExpectException( + RuleParseException.class, + /* expectedExceptionMessageRegex */ "For input string: \"INVALID_EFFECT\"", + () -> xmlParser.parse(ruleXmlOpenFormula)); + } + + @Test + public void testXmlString_invalidOpenFormula_invalidTags() throws Exception { + String ruleXmlOpenFormula = "" + + "" + + "" + + "" + OpenFormula.NOT + "" + + "" + + "" + AtomicFormula.PACKAGE_NAME + "" + + "" + AtomicFormula.EQ + "" + + "com.app.test" + + "" + + "" + + "" + Rule.DENY + "" + + "" + + ""; + RuleParser xmlParser = new RuleXmlParser(); + + assertExpectException( + RuleParseException.class, + /* expectedExceptionMessageRegex */ "Found unexpected tag: InvalidConnector", + () -> xmlParser.parse(ruleXmlOpenFormula)); + } + + @Test + public void testXmlString_validAtomicFormula_stringValue() throws Exception { + String ruleXmlAtomicFormula = "" + + "" + + "" + + "" + AtomicFormula.PACKAGE_NAME + "" + + "" + AtomicFormula.EQ + "" + + "com.app.test" + + "" + + "" + Rule.DENY + "" + + "" + + ""; + RuleParser xmlParser = new RuleXmlParser(); + Rule expectedRule = new Rule( + new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "com.app.test"), + Rule.DENY); + + List rules = xmlParser.parse(ruleXmlAtomicFormula); + + assertThat(rules).isEqualTo(Collections.singletonList(expectedRule)); + } + + @Test + public void testXmlString_validAtomicFormula_integerValue() throws Exception { + String ruleXmlAtomicFormula = "" + + "" + + "" + + "" + AtomicFormula.VERSION_CODE + "" + + "" + AtomicFormula.EQ + "" + + "1" + + "" + + "" + Rule.DENY + "" + + "" + + ""; + RuleParser xmlParser = new RuleXmlParser(); + Rule expectedRule = new Rule( + new AtomicFormula.IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 1), + Rule.DENY); + + List rules = xmlParser.parse(ruleXmlAtomicFormula); + + assertThat(rules).isEqualTo(Collections.singletonList(expectedRule)); + } + + @Test + public void testXmlString_validAtomicFormula_booleanValue() throws Exception { + String ruleXmlAtomicFormula = "" + + "" + + "" + + "" + AtomicFormula.PRE_INSTALLED + "" + + "" + AtomicFormula.EQ + "" + + "true" + + "" + + "" + Rule.DENY + "" + + "" + + ""; + RuleParser xmlParser = new RuleXmlParser(); + Rule expectedRule = new Rule( + new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true), + Rule.DENY); + + List rules = xmlParser.parse(ruleXmlAtomicFormula); + + assertThat(rules).isEqualTo(Collections.singletonList(expectedRule)); + } + + @Test + public void testXmlString_validAtomicFormula_differentTagOrder() throws Exception { + String ruleXmlAtomicFormula = "" + + "" + + "" + + "" + AtomicFormula.EQ + "" + + "com.app.test" + + "" + AtomicFormula.PACKAGE_NAME + "" + + "" + + "" + Rule.DENY + "" + + "" + + ""; + RuleParser xmlParser = new RuleXmlParser(); + Rule expectedRule = new Rule( + new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "com.app.test"), + Rule.DENY); + + List rules = xmlParser.parse(ruleXmlAtomicFormula); + + assertThat(rules).isEqualTo(Collections.singletonList(expectedRule)); + } + + @Test + public void testXmlString_invalidAtomicFormula_invalidTags() throws Exception { + String ruleXmlAtomicFormula = "" + + "" + + "" + + "" + AtomicFormula.PACKAGE_NAME + "" + + "" + AtomicFormula.EQ + "" + + "com.app.test" + + "" + + "" + Rule.DENY + "" + + "" + + ""; + RuleParser xmlParser = new RuleXmlParser(); + + assertExpectException( + RuleParseException.class, + /* expectedExceptionMessageRegex */ "Found unexpected tag: BadKey", + () -> xmlParser.parse(ruleXmlAtomicFormula)); + } + + @Test + public void testXmlString_invalidAtomicFormula() throws Exception { + String ruleXmlAtomicFormula = "" + + "" + + "" + + "" + AtomicFormula.VERSION_CODE + "" + + "" + AtomicFormula.EQ + "" + + "com.app.test" + + "" + + "" + Rule.DENY + "" + + "" + + ""; + RuleParser xmlParser = new RuleXmlParser(); + + assertExpectException( + RuleParseException.class, + /* expectedExceptionMessageRegex */ "For input string: \"com.app.test\"", + () -> xmlParser.parse(ruleXmlAtomicFormula)); } @Test public void testXmlString_withNoRuleList() { String ruleXmlWithNoRuleList = "" + "" - + "NOT" + + "" + OpenFormula.NOT + "" + "" - + "PACKAGE_NAME" - + "EQ" + + "" + AtomicFormula.PACKAGE_NAME + "" + + "" + AtomicFormula.EQ + "" + "com.app.test" + "" + "" - + "DENY" + + "" + Rule.DENY + "" + ""; RuleParser xmlParser = new RuleXmlParser(); assertExpectException( - RuntimeException.class, + RuleParseException.class, /* expectedExceptionMessageRegex */ "Rules must start with tag.", () -> xmlParser.parse(ruleXmlWithNoRuleList)); } @@ -94,20 +425,20 @@ public class RuleXmlParserTest { public void testXmlStream_withNoRuleList() { String ruleXmlWithNoRuleList = "" + "" - + "NOT" + + "" + OpenFormula.NOT + "" + "" - + "PACKAGE_NAME" - + "EQ" + + "" + AtomicFormula.PACKAGE_NAME + "" + + "" + AtomicFormula.EQ + "" + "com.app.test" + "" + "" - + "DENY" + + "" + Rule.DENY + "" + ""; InputStream inputStream = new ByteArrayInputStream(ruleXmlWithNoRuleList.getBytes()); RuleParser xmlParser = new RuleXmlParser(); assertExpectException( - RuntimeException.class, + RuleParseException.class, /* expectedExceptionMessageRegex */ "Rules must start with tag.", () -> xmlParser.parse(inputStream)); }