blob: 975689db5264f86b949574f653e2f083e395cc87 [file] [log] [blame]
/*
* 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 static com.android.server.testutils.TestUtils.assertExpectException;
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;
import org.junit.runner.RunWith;
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 {
@Test
public void testXmlStream_validOpenFormula() throws Exception {
String ruleXmlOpenFormula = "<RL>"
+ "<R>"
+ "<OF>"
+ "<C>" + OpenFormula.NOT + "</C>"
+ "<AF>"
+ "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
+ "<O>" + AtomicFormula.EQ + "</O>"
+ "<V>com.app.test</V>"
+ "</AF>"
+ "</OF>"
+ "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
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<Rule> rules = xmlParser.parse(inputStream);
assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
}
@Test
public void testXmlString_validOpenFormula_notConnector() throws Exception {
String ruleXmlOpenFormula = "<RL>"
+ "<R>"
+ "<OF>"
+ "<C>" + OpenFormula.NOT + "</C>"
+ "<AF>"
+ "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
+ "<O>" + AtomicFormula.EQ + "</O>"
+ "<V>com.app.test</V>"
+ "</AF>"
+ "</OF>"
+ "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
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<Rule> rules = xmlParser.parse(ruleXmlOpenFormula);
assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
}
@Test
public void testXmlString_validOpenFormula_andConnector() throws Exception {
String ruleXmlOpenFormula = "<RL>"
+ "<R>"
+ "<OF>"
+ "<C>" + OpenFormula.AND + "</C>"
+ "<AF>"
+ "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
+ "<O>" + AtomicFormula.EQ + "</O>"
+ "<V>com.app.test</V>"
+ "</AF>"
+ "<AF>"
+ "<K>" + AtomicFormula.APP_CERTIFICATE + "</K>"
+ "<O>" + AtomicFormula.EQ + "</O>"
+ "<V>test_cert</V>"
+ "</AF>"
+ "</OF>"
+ "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
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<Rule> rules = xmlParser.parse(ruleXmlOpenFormula);
assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
}
@Test
public void testXmlString_validOpenFormula_orConnector() throws Exception {
String ruleXmlOpenFormula = "<RL>"
+ "<R>"
+ "<OF>"
+ "<C>" + OpenFormula.OR + "</C>"
+ "<AF>"
+ "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
+ "<O>" + AtomicFormula.EQ + "</O>"
+ "<V>com.app.test</V>"
+ "</AF>"
+ "<AF>"
+ "<K>" + AtomicFormula.APP_CERTIFICATE + "</K>"
+ "<O>" + AtomicFormula.EQ + "</O>"
+ "<V>test_cert</V>"
+ "</AF>"
+ "</OF>"
+ "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
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<Rule> rules = xmlParser.parse(ruleXmlOpenFormula);
assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
}
@Test
public void testXmlString_validOpenFormula_differentTagOrder() throws Exception {
String ruleXmlOpenFormula = "<RL>"
+ "<R>"
+ "<OF>"
+ "<AF>"
+ "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
+ "<O>" + AtomicFormula.EQ + "</O>"
+ "<V>com.app.test</V>"
+ "</AF>"
+ "<C>" + OpenFormula.NOT + "</C>"
+ "</OF>"
+ "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
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<Rule> rules = xmlParser.parse(ruleXmlOpenFormula);
assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
}
@Test
public void testXmlString_invalidOpenFormula_invalidNumberOfFormulas() throws Exception {
String ruleXmlOpenFormula = "<RL>"
+ "<R>"
+ "<OF>"
+ "<C>" + OpenFormula.NOT + "</C>"
+ "<AF>"
+ "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
+ "<O>" + AtomicFormula.EQ + "</O>"
+ "<V>com.app.test</V>"
+ "</AF>"
+ "<AF>"
+ "<K>" + AtomicFormula.VERSION_CODE + "</K>"
+ "<O>" + AtomicFormula.EQ + "</O>"
+ "<V>1</V>"
+ "</AF>"
+ "</OF>"
+ "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
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 = "<RL>"
+ "<R>"
+ "<OF>"
+ "<C>" + OpenFormula.NOT + "</C>"
+ "<AF>"
+ "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
+ "<O>INVALID_OPERATOR</O>"
+ "<V>com.app.test</V>"
+ "</AF>"
+ "</OF>"
+ "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
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 = "<RL>"
+ "<R>"
+ "<OF>"
+ "<C>" + OpenFormula.NOT + "</C>"
+ "<AF>"
+ "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
+ "<O>" + AtomicFormula.EQ + "</O>"
+ "<V>com.app.test</V>"
+ "</AF>"
+ "</OF>"
+ "<E>INVALID_EFFECT</E>"
+ "</R>"
+ "</RL>";
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 = "<RL>"
+ "<R>"
+ "<OF>"
+ "<InvalidConnector>" + OpenFormula.NOT + "</InvalidConnector>"
+ "<AF>"
+ "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
+ "<O>" + AtomicFormula.EQ + "</O>"
+ "<V>com.app.test</V>"
+ "</AF>"
+ "</OF>"
+ "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
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 = "<RL>"
+ "<R>"
+ "<AF>"
+ "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
+ "<O>" + AtomicFormula.EQ + "</O>"
+ "<V>com.app.test</V>"
+ "</AF>"
+ "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
Rule expectedRule = new Rule(
new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "com.app.test"),
Rule.DENY);
List<Rule> rules = xmlParser.parse(ruleXmlAtomicFormula);
assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
}
@Test
public void testXmlString_validAtomicFormula_integerValue() throws Exception {
String ruleXmlAtomicFormula = "<RL>"
+ "<R>"
+ "<AF>"
+ "<K>" + AtomicFormula.VERSION_CODE + "</K>"
+ "<O>" + AtomicFormula.EQ + "</O>"
+ "<V>1</V>"
+ "</AF>"
+ "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
Rule expectedRule = new Rule(
new AtomicFormula.IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 1),
Rule.DENY);
List<Rule> rules = xmlParser.parse(ruleXmlAtomicFormula);
assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
}
@Test
public void testXmlString_validAtomicFormula_booleanValue() throws Exception {
String ruleXmlAtomicFormula = "<RL>"
+ "<R>"
+ "<AF>"
+ "<K>" + AtomicFormula.PRE_INSTALLED + "</K>"
+ "<O>" + AtomicFormula.EQ + "</O>"
+ "<V>true</V>"
+ "</AF>"
+ "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
Rule expectedRule = new Rule(
new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
Rule.DENY);
List<Rule> rules = xmlParser.parse(ruleXmlAtomicFormula);
assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
}
@Test
public void testXmlString_validAtomicFormula_differentTagOrder() throws Exception {
String ruleXmlAtomicFormula = "<RL>"
+ "<R>"
+ "<AF>"
+ "<O>" + AtomicFormula.EQ + "</O>"
+ "<V>com.app.test</V>"
+ "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
+ "</AF>"
+ "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
Rule expectedRule = new Rule(
new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "com.app.test"),
Rule.DENY);
List<Rule> rules = xmlParser.parse(ruleXmlAtomicFormula);
assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
}
@Test
public void testXmlString_invalidAtomicFormula_invalidTags() throws Exception {
String ruleXmlAtomicFormula = "<RL>"
+ "<R>"
+ "<AF>"
+ "<BadKey>" + AtomicFormula.PACKAGE_NAME + "</BadKey>"
+ "<O>" + AtomicFormula.EQ + "</O>"
+ "<V>com.app.test</V>"
+ "</AF>"
+ "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
assertExpectException(
RuleParseException.class,
/* expectedExceptionMessageRegex */ "Found unexpected tag: BadKey",
() -> xmlParser.parse(ruleXmlAtomicFormula));
}
@Test
public void testXmlString_invalidAtomicFormula() throws Exception {
String ruleXmlAtomicFormula = "<RL>"
+ "<R>"
+ "<AF>"
+ "<K>" + AtomicFormula.VERSION_CODE + "</K>"
+ "<O>" + AtomicFormula.EQ + "</O>"
+ "<V>com.app.test</V>"
+ "</AF>"
+ "<E>" + Rule.DENY + "</E>"
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
assertExpectException(
RuleParseException.class,
/* expectedExceptionMessageRegex */ "For input string: \"com.app.test\"",
() -> xmlParser.parse(ruleXmlAtomicFormula));
}
@Test
public void testXmlString_withNoRuleList() {
String ruleXmlWithNoRuleList = "<R>"
+ "<OF>"
+ "<C>" + OpenFormula.NOT + "</C>"
+ "<AF>"
+ "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
+ "<O>" + AtomicFormula.EQ + "</O>"
+ "<V>com.app.test</V>"
+ "</AF>"
+ "</OF>"
+ "<E>" + Rule.DENY + "</E>"
+ "</R>";
RuleParser xmlParser = new RuleXmlParser();
assertExpectException(
RuleParseException.class,
/* expectedExceptionMessageRegex */ "Rules must start with RuleList <RL> tag",
() -> xmlParser.parse(ruleXmlWithNoRuleList));
}
@Test
public void testXmlStream_withNoRuleList() {
String ruleXmlWithNoRuleList = "<R>"
+ "<OF>"
+ "<C>" + OpenFormula.NOT + "</C>"
+ "<AF>"
+ "<K>" + AtomicFormula.PACKAGE_NAME + "</K>"
+ "<O>" + AtomicFormula.EQ + "</O>"
+ "<V>com.app.test</V>"
+ "</AF>"
+ "</OF>"
+ "<E>" + Rule.DENY + "</E>"
+ "</R>";
InputStream inputStream = new ByteArrayInputStream(ruleXmlWithNoRuleList.getBytes());
RuleParser xmlParser = new RuleXmlParser();
assertExpectException(
RuleParseException.class,
/* expectedExceptionMessageRegex */ "Rules must start with RuleList <RL> tag",
() -> xmlParser.parse(inputStream));
}
}