Merge "Add pre-upload style checker for cpp and java code"
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..7786266
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,17 @@
+// Copyright (C) 2017 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.
+
+subdirs = [
+ "api/tun",
+]
diff --git a/api/binder/Android.mk b/api/binder/Android.mk
new file mode 100644
index 0000000..e866f70
--- /dev/null
+++ b/api/binder/Android.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2017 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VtsKernelBinderTest
+include test/vts/tools/build/Android.host_config.mk
diff --git a/api/binder/AndroidTest.xml b/api/binder/AndroidTest.xml
new file mode 100644
index 0000000..f9e7cf4
--- /dev/null
+++ b/api/binder/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<configuration description="Config for VTS VtsKernelBinderTest.">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+ <option name="abort-on-push-failure" value="false"/>
+ <option name="push-group" value="HostDrivenTest.push"/>
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer"/>
+ <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+ <option name="test-module-name" value="VtsKernelBinderTest"/>
+ <option name="binary-test-source" value="_32bit::DATA/nativetest/binderSafeInterfaceTest/binderSafeInterfaceTest" />
+ <option name="binary-test-source" value="_64bit::DATA/nativetest64/binderSafeInterfaceTest/binderSafeInterfaceTest" />
+ <option name="binary-test-source" value="_32bit::DATA/nativetest/binderLibTest/binderLibTest" />
+ <option name="binary-test-source" value="_64bit::DATA/nativetest64/binderLibTest/binderLibTest" />
+ <option name="binary-test-source" value="_32bit::DATA/nativetest/binderDriverInterfaceTest/binderDriverInterfaceTest" />
+ <option name="binary-test-source" value="_64bit::DATA/nativetest64/binderDriverInterfaceTest/binderDriverInterfaceTest" />
+ <option name="binary-test-type" value="gtest"/>
+ <option name="test-timeout" value="10m"/>
+ </test>
+</configuration>
diff --git a/api/hwbinder/Android.mk b/api/hwbinder/Android.mk
new file mode 100644
index 0000000..c9fcaf8
--- /dev/null
+++ b/api/hwbinder/Android.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2017 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VtsKernelHwBinder
+include test/vts/tools/build/Android.host_config.mk
diff --git a/api/hwbinder/AndroidTest.xml b/api/hwbinder/AndroidTest.xml
new file mode 100644
index 0000000..8193b01
--- /dev/null
+++ b/api/hwbinder/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<configuration description="Config for VTS VtsKernelBinderTest.">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+ <option name="push-group" value="HostDrivenTest.push"/>
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer"/>
+ <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+ <option name="test-module-name" value="VtsKernelHwBinder"/>
+ <option name="test-case-path" value="vts/testcases/kernel/api/hwbinder/VtsKernelHwBinderTest" />
+ <option name="test-timeout" value="1m"/>
+ </test>
+</configuration>
diff --git a/api/hwbinder/VtsKernelHwBinderTest.py b/api/hwbinder/VtsKernelHwBinderTest.py
new file mode 100644
index 0000000..8fd24e0
--- /dev/null
+++ b/api/hwbinder/VtsKernelHwBinderTest.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2017 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.
+#
+
+import logging
+
+from vts.runners.host import asserts
+from vts.runners.host import base_test
+from vts.runners.host import const
+from vts.runners.host import test_runner
+from vts.utils.python.controllers import android_device
+from vts.utils.python.file import file_utils
+
+HWBINDER_PATH = "/dev/hwbinder"
+
+class VtsKernelHwBinderTest(base_test.BaseTestClass):
+ """Test case to validate existence of hwbinder node.
+ """
+
+ def setUpClass(self):
+ self.dut = self.registerController(android_device)[0]
+ self.dut.shell.InvokeTerminal(
+ "VtsKernelHwBinderTest") # creates a remote shell instance.
+ self.shell = self.dut.shell.VtsKernelHwBinderTest
+
+ def testHwbinderExistence(self):
+ """Checks that hwbinder node exists.
+ """
+ logging.info("Testing existence of %s", HWBINDER_PATH)
+ asserts.assertTrue(
+ file_utils.Exists(HWBINDER_PATH, self.shell),
+ "%s: File does not exist." % HWBINDER_PATH)
+
+ try:
+ permissions = file_utils.GetPermission(HWBINDER_PATH, self.shell)
+ asserts.assertTrue(file_utils.IsReadWrite(permissions),
+ "%s: File has invalid permissions (%s)" %
+ (HWBINDER_PATH, permissions))
+ except (ValueError, IOError) as e:
+ asserts.fail("Failed to assert permissions: %s" % str(e))
+
+if __name__ == "__main__":
+ test_runner.main()
diff --git a/api/hwbinder/__init__.py b/api/hwbinder/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/api/hwbinder/__init__.py
diff --git a/api/netd/Android.mk b/api/netd/Android.mk
new file mode 100644
index 0000000..757dffe
--- /dev/null
+++ b/api/netd/Android.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2017 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VtsKernelNetdTest
+include test/vts/tools/build/Android.host_config.mk
diff --git a/api/netd/AndroidTest.xml b/api/netd/AndroidTest.xml
new file mode 100644
index 0000000..fa6ec48
--- /dev/null
+++ b/api/netd/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<configuration description="Config for VTS VtsKernelNetdTest.">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+ <option name="abort-on-push-failure" value="false"/>
+ <option name="push-group" value="HostDrivenTest.push"/>
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer"/>
+ <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+ <option name="test-module-name" value="VtsKernelNetdTest"/>
+ <option name="binary-test-source" value="_32bit::DATA/nativetest/netd_integration_test/netd_integration_test" />
+ <option name="binary-test-source" value="_64bit::DATA/nativetest64/netd_integration_test/netd_integration_test" />
+ <option name="binary-test-type" value="gtest"/>
+ <option name="test-timeout" value="10m"/>
+ </test>
+</configuration>
diff --git a/api/proc/AndroidTest.xml b/api/proc/AndroidTest.xml
index e7fc357..ba6183d 100644
--- a/api/proc/AndroidTest.xml
+++ b/api/proc/AndroidTest.xml
@@ -18,6 +18,7 @@
<option name="push-group" value="HostDrivenTest.push" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer">
+ <option name="dep-module" value="parse" />
<option name="dep-module" value="ply" />
</target_preparer>
<test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
diff --git a/api/proc/KernelProcFileApiTest.py b/api/proc/KernelProcFileApiTest.py
index 660f976..c62cecd 100644
--- a/api/proc/KernelProcFileApiTest.py
+++ b/api/proc/KernelProcFileApiTest.py
@@ -15,68 +15,64 @@
# limitations under the License.
#
-import gzip
import logging
-import os
-import shutil
-import tempfile
from vts.runners.host import asserts
from vts.runners.host import base_test
from vts.runners.host import const
from vts.runners.host import test_runner
-from vts.testcases.kernel.api.proc import required_kernel_configs as configs
-from vts.utils.python.controllers import android_device
-from ProcMemInfoTest import ProcMemInfoTest
-from ProcZoneInfoTest import ProcZoneInfoTest
-from ProcShowUidStatTest import ProcShowUidStatTest
-from ProcCpuInfoTest import ProcCpuInfoTest
-from ProcStatTest import ProcStatTest
-from ProcVmallocInfoTest import ProcVmallocInfoTest
-from ProcRemoveUidRangeTest import ProcRemoveUidRangeTest
-from ProcQtaguidCtrlTest import ProcQtaguidCtrlTest
-from ProcMapsTest import ProcMapsTest
-from ProcSimpleFileTests import ProcKptrRestrictTest
-from ProcSimpleFileTests import ProcMmapMinAddrTest
-from ProcSimpleFileTests import ProcMmapRndBitsTest
-from ProcSimpleFileTests import ProcMmapRndCompatBitsTest
-from ProcSimpleFileTests import ProcOverCommitMemoryTest
-from ProcSimpleFileTests import ProcRandomizeVaSpaceTest
+from vts.testcases.kernel.api.proc import ProcCmdlineTest
+from vts.testcases.kernel.api.proc import ProcCpuInfoTest
+from vts.testcases.kernel.api.proc import ProcKmsgTest
+from vts.testcases.kernel.api.proc import ProcMapsTest
+from vts.testcases.kernel.api.proc import ProcMemInfoTest
+from vts.testcases.kernel.api.proc import ProcModulesTest
+from vts.testcases.kernel.api.proc import ProcMountsTest
+from vts.testcases.kernel.api.proc import ProcQtaguidCtrlTest
+from vts.testcases.kernel.api.proc import ProcRemoveUidRangeTest
+from vts.testcases.kernel.api.proc import ProcSimpleFileTests
+from vts.testcases.kernel.api.proc import ProcShowUidStatTest
+from vts.testcases.kernel.api.proc import ProcStatTest
+from vts.testcases.kernel.api.proc import ProcVersionTest
+from vts.testcases.kernel.api.proc import ProcVmallocInfoTest
+from vts.testcases.kernel.api.proc import ProcZoneInfoTest
+
+from vts.utils.python.controllers import android_device
+from vts.utils.python.file import file_utils
TEST_OBJECTS = {
- ProcMemInfoTest(),
- ProcZoneInfoTest(),
- ProcShowUidStatTest(),
- ProcCpuInfoTest(),
- ProcStatTest(),
- ProcVmallocInfoTest(),
- ProcKptrRestrictTest(),
- ProcRandomizeVaSpaceTest(),
- ProcMmapMinAddrTest(),
- ProcMmapRndBitsTest(),
- ProcMmapRndCompatBitsTest(),
- ProcOverCommitMemoryTest(),
- ProcRemoveUidRangeTest(),
- ProcQtaguidCtrlTest(),
- ProcMapsTest(),
+ ProcCmdlineTest.ProcCmdlineTest(),
+ ProcCpuInfoTest.ProcCpuInfoTest(),
+ ProcKmsgTest.ProcKmsgTest(),
+ ProcSimpleFileTests.ProcKptrRestrictTest(),
+ ProcMapsTest.ProcMapsTest(),
+ ProcMemInfoTest.ProcMemInfoTest(),
+ ProcSimpleFileTests.ProcMmapMinAddrTest(),
+ ProcSimpleFileTests.ProcMmapRndBitsTest(),
+ ProcSimpleFileTests.ProcMmapRndCompatBitsTest(),
+ ProcModulesTest.ProcModulesTest(),
+ ProcMountsTest.ProcMountsTest(),
+ ProcSimpleFileTests.ProcOverCommitMemoryTest(),
+ ProcQtaguidCtrlTest.ProcQtaguidCtrlTest(),
+ ProcSimpleFileTests.ProcRandomizeVaSpaceTest(),
+ ProcRemoveUidRangeTest.ProcRemoveUidRangeTest(),
+ ProcShowUidStatTest.ProcShowUidStatTest(),
+ ProcStatTest.ProcStatTest(),
+ ProcVersionTest.ProcVersionTest(),
+ ProcVmallocInfoTest.ProcVmallocInfoTest(),
+ ProcZoneInfoTest.ProcZoneInfoTest(),
}
+
class KernelProcFileApiTest(base_test.BaseTestClass):
- """Test cases which check content of proc files.
-
- Attributes:
- _temp_dir: The temporary directory to which /proc/config.gz is copied.
- """
-
- PROC_FILE_PATH = "/proc/config.gz"
+ """Test cases which check content of proc files."""
def setUpClass(self):
self.dut = self.registerController(android_device)[0]
self.dut.shell.InvokeTerminal(
"KernelApiTest") # creates a remote shell instance.
self.shell = self.dut.shell.KernelApiTest
- self._temp_dir = tempfile.mkdtemp()
def runProcFileTest(self, test_object):
"""Reads from the file and checks that it parses and the content is valid.
@@ -84,11 +80,19 @@
Args:
test_object: inherits KernelProcFileTestBase, contains the test functions
"""
- logging.info("Testing format of %s" % (test_object.get_path()))
+ filepath = test_object.get_path()
+ file_utils.assertPermissionsAndExistence(
+ self.shell, filepath, test_object.get_permission_checker())
+
+ logging.info("Testing format of %s", filepath)
+
asserts.assertTrue(
test_object.prepare_test(self.shell), "Setup failed!")
- file_content = self.ReadFileContent(test_object.get_path())
+ if not test_object.test_format():
+ return
+
+ file_content = self.ReadFileContent(filepath)
try:
parse_result = test_object.parse_contents(file_content)
except SyntaxError as e:
@@ -98,9 +102,10 @@
def generateProcFileTests(self):
"""Run all proc file tests."""
- self.runGeneratedTests(test_func=self.runProcFileTest,
- settings=TEST_OBJECTS,
- name_func=lambda test_obj: "test" + test_obj.__class__.__name__)
+ self.runGeneratedTests(
+ test_func=self.runProcFileTest,
+ settings=TEST_OBJECTS,
+ name_func=lambda test_obj: "test" + test_obj.__class__.__name__)
def ReadFileContent(self, filepath):
"""Read the content of a file and perform assertions.
@@ -113,8 +118,6 @@
"""
cmd = "cat %s" % filepath
results = self.shell.Execute(cmd)
- logging.info("%s: Shell command '%s' results: %s", filepath, cmd,
- results)
# checks the exit code
asserts.assertEqual(
@@ -123,44 +126,6 @@
return results[const.STDOUT][0]
- def testCheckConfigs(self):
- """Ensures all options from android-base.cfg are enabled."""
- self.dut.adb.pull("%s %s" % (self.PROC_FILE_PATH, self._temp_dir))
- logging.info("Adb pull %s to %s", self.PROC_FILE_PATH, self._temp_dir)
-
- localpath = os.path.join(self._temp_dir, "config.gz")
- with gzip.open(localpath, 'rb') as f:
- device_config_lines = [line.rstrip("\n") for line in f.readlines()]
-
- device_configs = dict()
- for line in device_config_lines:
- if line == "" or line.startswith("#"):
- continue
- config_name, config_state = line.split("=", 1)
- device_configs[config_name] = config_state
-
- should_be_enabled = []
- should_not_be_set = []
- for config_name, config_state in configs.CONFIGS.iteritems():
- if (config_state == "y" and
- (config_name not in device_configs or
- device_configs[config_name] not in ("y", "m"))):
- should_be_enabled.append(config_name)
- elif config_state == "n" and config_name in device_configs:
- should_not_be_set.append(config_name + "=" +
- device_configs[config_name])
-
- asserts.assertTrue(
- len(should_be_enabled) == 0 and len(should_not_be_set) == 0,
- ("The following kernel configs should be enabled: [%s].\n"
- "The following kernel configs should not be set: [%s]") %
- (", ".join(should_be_enabled), ", ".join(should_not_be_set)))
-
- def tearDownClass(self):
- """Deletes the temporary directory."""
- logging.info("Delete %s", self._temp_dir)
- shutil.rmtree(self._temp_dir)
-
if __name__ == "__main__":
test_runner.main()
diff --git a/api/proc/KernelProcFileTestBase.py b/api/proc/KernelProcFileTestBase.py
index ce4fe54..0b0ed02 100644
--- a/api/proc/KernelProcFileTestBase.py
+++ b/api/proc/KernelProcFileTestBase.py
@@ -16,9 +16,14 @@
#
import os
+import parse
import sys
+
+from abc import ABCMeta
+from abc import abstractmethod
from ply import lex
from ply import yacc
+from vts.utils.python.file import file_utils
def repeat_rule(to_repeat, zero_ok=False):
@@ -68,6 +73,8 @@
Child class should also specify a `start` variable to give the starting rule.
"""
+ __metaclass__ = ABCMeta
+
def t_HEX_LITERAL(self, t):
r'0x[a-f0-9]+'
t.value = int(t.value, 0)
@@ -129,29 +136,75 @@
self.parser = yacc.yacc(module=self, write_tables=False, \
errorlog=yacc.PlyLogger(sys.stderr)) #open(os.devnull, 'w')))
- def parse_contents(self, file_contents):
+ def parse_line(self, rule, line, custom={}):
+ """Parse a line of text with the parse library.
+
+ Args:
+ line: string, a line of text
+ rule: string, a format rule. See parse documentation
+ custom: dict, maps to custom type conversion functions
+
+ Returns:
+ list, information parsed from the line
+
+ Raises:
+ SyntaxError: if the line could not be parsed.
"""
- Using the internal parser, parse the contents and return a structure
- constructed according to the parsing rules
+ parsed = parse.parse(rule, line, custom)
+ if parsed is None:
+ raise SyntaxError("Failed to parse line %s according to rule %s" % (line, rule))
+ return list(parsed)
+
+ def parse_contents(self, file_contents):
+ """Using the internal parser, parse the contents.
+
+ Args:
+ file_contents: string, entire contents of a file
+
+ Returns:
+ list, a parsed representation of the file
+
+ Raises:
+ SyntaxError: if the file could not be parsed
"""
return self.parser.parse(file_contents, lexer=self.lexer)
+ @abstractmethod
def get_path(self):
- """
- Return the full path of this proc file.
- """
- return ""
+ """Returns the full path of this proc file (string)."""
+ pass
def prepare_test(self, shell):
- """
- Performs any actions necessary before testing the proc file.
- Return True if successful.
+ """Performs any actions necessary before testing the proc file.
+
+ Args:
+ shell: shell object, for preparation that requires device access
+
+ Returns:
+ boolean, True if successful.
"""
return True
def result_correct(self, parse_result):
- """
- Return True if the parsed result meets the requirements for the
- proc file.
+ """Returns: True if the parsed result meets the requirements (boolean)."""
+ return True
+
+ def test_format(self):
+ """Returns:
+ boolean, True if the file should be read and its format tested.
+ False if only the existence and permission should be tested.
"""
return True
+
+ def get_permission_checker(self):
+ """Gets the function handle to use for validating file permissions.
+
+ Return the function that will check if the permissions are correct.
+ By default, return the IsReadOnly function from file_utils.
+
+ Returns:
+ function which takes one argument (the unix file permission bits
+ in octal format) and returns True if the permissions are correct,
+ False otherwise.
+ """
+ return file_utils.IsReadOnly
diff --git a/api/proc/ProcCmdlineTest.py b/api/proc/ProcCmdlineTest.py
new file mode 100644
index 0000000..8338cfa
--- /dev/null
+++ b/api/proc/ProcCmdlineTest.py
@@ -0,0 +1,29 @@
+#
+# Copyright (C) 2017 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.
+#
+
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+
+
+class ProcCmdlineTest(KernelProcFileTestBase.KernelProcFileTestBase):
+ '''/proc/cmdline contains arguments passed to the kernel.'''
+
+ def parse_contents(self, contents):
+ if len(contents) == 0 or contents[-1] != '\n':
+ raise SyntaxError("missing newline")
+ return contents[:-1].split(' ')
+
+ def get_path(self):
+ return "/proc/cmdline"
diff --git a/api/proc/ProcCpuInfoTest.py b/api/proc/ProcCpuInfoTest.py
index b18d50c..eb3b50b 100644
--- a/api/proc/ProcCpuInfoTest.py
+++ b/api/proc/ProcCpuInfoTest.py
@@ -14,8 +14,8 @@
# limitations under the License.
#
-import KernelProcFileTestBase
-from KernelProcFileTestBase import repeat_rule, literal_token
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+from vts.testcases.kernel.api.proc.KernelProcFileTestBase import repeat_rule, literal_token
class ProcCpuInfoTest(KernelProcFileTestBase.KernelProcFileTestBase):
diff --git a/api/proc/ProcKmsgTest.py b/api/proc/ProcKmsgTest.py
new file mode 100644
index 0000000..b0d6c9e
--- /dev/null
+++ b/api/proc/ProcKmsgTest.py
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2017 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.
+#
+
+from vts.runners.host import const
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+
+
+class ProcKmsgTest(KernelProcFileTestBase.KernelProcFileTestBase):
+ '''/proc/kmsg shows kernel messages in real time.'''
+
+ def test_format(self):
+ return False
+
+ def get_path(self):
+ return '/proc/kmsg'
diff --git a/api/proc/ProcMapsTest.py b/api/proc/ProcMapsTest.py
index 7ccfee4..c981faa 100644
--- a/api/proc/ProcMapsTest.py
+++ b/api/proc/ProcMapsTest.py
@@ -14,45 +14,57 @@
# limitations under the License.
#
-import KernelProcFileTestBase
-from KernelProcFileTestBase import repeat_rule, literal_token
+from parse import with_pattern
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+@with_pattern(r'[0-9a-f]{8,}')
+def token_addr(text):
+ return int(text, 16)
+
+@with_pattern(r'[0-9a-f]{2,5}')
+def token_mm(text):
+ return int(text, 16)
+
+@with_pattern(r'[0-9]+')
+def token_lu(text):
+ return int(text)
+
+@with_pattern(r'[^\n^\0]*')
+def token_path(text):
+ return text.strip()
+
+@with_pattern(r'[r-]')
+def token_rbit(text):
+ return text
+
+@with_pattern(r'[w-]')
+def token_wbit(text):
+ return text
+
+@with_pattern(r'[x-]')
+def token_xbit(text):
+ return text
+
+@with_pattern(r'[sp]')
+def token_spbit(text):
+ return text
+
class ProcMapsTest(KernelProcFileTestBase.KernelProcFileTestBase):
'''/proc/self/maps provides currently mapped memory regions and permissions.'''
- start = 'lines'
-
- t_STRING = literal_token(r'[a-zA-Z\(\)_\-0-9@]+')
- t_PATH = r'/[^\0^\n]*'
- t_BRACKET_ITEM = r'\[[^\0^\n]*\]'
- t_DASH = r'-'
-
- t_ignore = r' '
-
- p_lines = repeat_rule('line')
-
- def p_line(self, p):
- 'line : STRING STRING STRING STRING COLON STRING STRING source NEWLINE'
- rng = p[1].split('-')
- try:
- if len(rng) != 2:
- print 'Invalid address range format!'
- raise SyntaxError
- p[0] = [int(rng[0], 16), int(rng[1], 16), p[2], int(p[3], 16), int(p[4], 16),\
- int(p[6], 16), int(p[7]), p[8]]
- except ValueError:
- print 'Invalid number!'
- raise SyntaxError
-
- def p_source(self, p):
- '''source : PATH
- | BRACKET_ITEM
- | empty'''
- if p[1] is None:
- p[0] = []
- else:
- p[0] = p[1]
+ def parse_contents(self, contents):
+ result = []
+ lines = contents.split('\n')
+ if lines[-1] != '':
+ raise SyntaxError("missing final newline")
+ for line in lines[:-1]:
+ parsed = self.parse_line(
+ "{:addr}-{:addr} {:rbit}{:wbit}{:xbit}{:spbit} {:addr} {:mm}:{:mm} {:lu}{:path}",
+ line, dict(mm=token_mm, addr=token_addr, lu=token_lu, path=token_path,
+ rbit=token_rbit, wbit=token_wbit, xbit=token_xbit, spbit=token_spbit))
+ result.append(parsed)
+ return result
def get_path(self):
return "/proc/self/maps"
diff --git a/api/proc/ProcMemInfoTest.py b/api/proc/ProcMemInfoTest.py
index f0588ad..9182d93 100644
--- a/api/proc/ProcMemInfoTest.py
+++ b/api/proc/ProcMemInfoTest.py
@@ -14,18 +14,27 @@
# limitations under the License.
#
-import KernelProcFileTestBase
-from KernelProcFileTestBase import repeat_rule, literal_token
+import logging
+from parse import with_pattern
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+
+
+@with_pattern(r'[^ ^\t^\n^:^\0]+')
+def token_name(text):
+ return text
+
+@with_pattern(r'[ ]*[0-9]+')
+def token_lu(text):
+ return int(text)
class ProcMemInfoTest(KernelProcFileTestBase.KernelProcFileTestBase):
- """
- /proc/meminfo reports statistics about memory usage on the system.
+ '''/proc/meminfo reports statistics about memory usage on the system.
No new fields should be added to the upstream implementation.
- """
+ '''
- ALLOWED_FIELDS = {
+ REQUIRED_FIELDS = {
"MemTotal",
"MemFree",
"MemAvailable",
@@ -62,20 +71,21 @@
"VmallocChunk",
}
- t_KB = literal_token(r'kB')
-
- start = 'lines'
- p_lines = repeat_rule('line')
-
- def p_line(self, p):
- 'line : STRING COLON SPACEs NUMBER SPACE KB NEWLINE'
- p[0] = [p[1], p[4]]
+ def parse_contents(self, contents):
+ lines = contents.split('\n')
+ if lines[-1] != '':
+ raise SyntaxError("missing final newline")
+ return [self.parse_line("{:name}: {:lu} kB", line, dict(name=token_name, lu=token_lu))
+ for line in lines[:-1]]
def result_correct(self, parse_result):
+ required_fields = self.REQUIRED_FIELDS.copy()
for line in parse_result:
- if line[0] not in self.ALLOWED_FIELDS:
- print "'%s' is an illegal field" % line[0]
- return False
+ if line[0] in required_fields:
+ required_fields.remove(line[0])
+ if len(required_fields) > 0:
+ logging.error("Required fields not present: %s", str(required_fields))
+ return False
return True
def get_path(self):
diff --git a/api/proc/ProcModulesTest.py b/api/proc/ProcModulesTest.py
new file mode 100644
index 0000000..d877ad9
--- /dev/null
+++ b/api/proc/ProcModulesTest.py
@@ -0,0 +1,30 @@
+#
+# Copyright (C) 2017 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.
+#
+
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+
+
+class ProcModulesTest(KernelProcFileTestBase.KernelProcFileTestBase):
+ '''/proc/modules contains information about loaded kernel modules.'''
+
+ def parse_contents(self, contents):
+ return ''
+
+ def result_correct(self, parse_result):
+ return True
+
+ def get_path(self):
+ return "/proc/modules"
diff --git a/api/proc/ProcMountsTest.py b/api/proc/ProcMountsTest.py
new file mode 100644
index 0000000..da0ce0b
--- /dev/null
+++ b/api/proc/ProcMountsTest.py
@@ -0,0 +1,56 @@
+#
+# Copyright (C) 2017 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.
+#
+
+import logging
+from vts.runners.host import const
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+from vts.testcases.kernel.api.proc.KernelProcFileTestBase import repeat_rule, literal_token
+
+
+class ProcMountsTest(KernelProcFileTestBase.KernelProcFileTestBase):
+ '''/proc/self/mounts lists the mounted filesystems.
+
+ /proc/mounts must symlink to this file.'''
+
+ def parse_contents(self, contents):
+ if len(contents) == 0 or contents[-1] != '\n':
+ raise SyntaxError('Missing final newline')
+ result = []
+ for line in contents.split('\n')[:-1]:
+ parsed = line.split(' ')
+ parsed[3] = parsed[3].split(',')
+ result.append(parsed)
+ return result
+
+ def result_correct(self, parse_results):
+ for line in parse_results:
+ if len(line[3]) < 1 or line[3][0] not in {'rw', 'ro'}:
+ logging.error("First attribute must be rw or ro")
+ return False
+ if line[4] != '0' or line[5] != '0':
+ logging.error("Last 2 columns must be 0")
+ return False
+ return True
+
+ def prepare_test(self, shell):
+ # Follow the symlink
+ results = shell.Execute('readlink /proc/mounts')
+ if results[const.EXIT_CODE][0] != 0:
+ return False
+ return results[const.STDOUT][0] == 'self/mounts\n'
+
+ def get_path(self):
+ return "/proc/self/mounts"
diff --git a/api/proc/ProcQtaguidCtrlTest.py b/api/proc/ProcQtaguidCtrlTest.py
index 28f714f..102060b 100644
--- a/api/proc/ProcQtaguidCtrlTest.py
+++ b/api/proc/ProcQtaguidCtrlTest.py
@@ -14,41 +14,42 @@
# limitations under the License.
#
-import KernelProcFileTestBase
-from KernelProcFileTestBase import repeat_rule, literal_token
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+from vts.testcases.kernel.api.proc.KernelProcFileTestBase import repeat_rule, literal_token
+from vts.utils.python.file import file_utils
class ProcQtaguidCtrlTest(KernelProcFileTestBase.KernelProcFileTestBase):
- '''
- /proc/net/xt_qtaguid/ctrl provides information about tagged sockets.
- '''
+ '''/proc/net/xt_qtaguid/ctrl provides information about tagged sockets.
- start = 'content'
+ File content consists of possibly several lines of socket info followed by a
+ single line of events info, followed by a terminating newline.'''
- t_EVENTS = literal_token(r'events')
- t_TAG = literal_token(r'tag')
- t_UID = literal_token(r'uid')
- t_PID = literal_token(r'pid')
- t_FCOUNT = literal_token(r'f_count')
- t_LPAREN = literal_token(r'\(')
- t_RPAREN = literal_token(r'\)')
-
- p_lines = repeat_rule('line', zero_ok=True)
- p_attrs = repeat_rule('attr')
-
- def p_content(self, p):
- 'content : lines EVENTS COLON attrs NEWLINE'
- p[0] = p[1:]
-
- def p_line(self, p):
- 'line : STRING EQUALS NUMBER SPACE TAG EQUALS HEX_LITERAL SPACE \
- LPAREN UID EQUALS NUMBER RPAREN SPACE PID EQUALS NUMBER SPACE \
- FCOUNT EQUALS NUMBER NEWLINE'
- p[0] = p[1:]
-
- def p_attr(self, p):
- 'attr : SPACE STRING EQUALS NUMBER'
- p[0] = [p[2], p[4]]
+ def parse_contents(self, contents):
+ result = []
+ lines = contents.split('\n')
+ if len(lines) == 0 or lines[-1] != '':
+ raise SyntaxError
+ for line in lines[:-2]:
+ parsed = self.parse_line(
+ "sock={:d} tag=0x{:x} (uid={:d}) pid={:d} f_count={:d}", line)
+ if any(map(lambda x: x < 0, parsed)):
+ raise SyntaxError("Negative numbers not allowed!")
+ result.append(parsed)
+ parsed = self.parse_line(
+ "events: sockets_tagged={:d} sockets_untagged={:d} counter_set_changes={:d} "
+ "delete_cmds={:d} iface_events={:d} match_calls={:d} match_calls_prepost={:d} "
+ "match_found_sk={:d} match_found_sk_in_ct={:d} match_found_no_sk_in_ct={:d} "
+ "match_no_sk={:d} match_no_sk_file={:d}", lines[-2])
+ if any(map(lambda x: x < 0, parsed)):
+ raise SyntaxError("Negative numbers not allowed!")
+ result.append(parsed)
+ return result
def get_path(self):
return "/proc/net/xt_qtaguid/ctrl"
+
+ def get_permission_checker(self):
+ """Get r/w file permission checker.
+ """
+ return file_utils.IsReadWrite
diff --git a/api/proc/ProcRemoveUidRangeTest.py b/api/proc/ProcRemoveUidRangeTest.py
index 0cf345e..aeac742 100644
--- a/api/proc/ProcRemoveUidRangeTest.py
+++ b/api/proc/ProcRemoveUidRangeTest.py
@@ -14,41 +14,27 @@
# limitations under the License.
#
-import ProcShowUidStatTest
from vts.runners.host import const
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+from vts.utils.python.file import file_utils
-class ProcRemoveUidRangeTest(ProcShowUidStatTest.ProcShowUidStatTest):
- '''
- /proc/uid_cputime/remove_uid_range can be written in order to remove uids
+class ProcRemoveUidRangeTest(KernelProcFileTestBase.KernelProcFileTestBase):
+ '''/proc/uid_cputime/remove_uid_range can be written in order to remove uids
from being shown when reading show_uid_stat.
Format is '[start uid]-[end uid]'
This is an Android specific file.
-
- Attributes:
- uid_remove: int, the uid that the test attempts to remove from show_uid_range
'''
- def prepare_test(self, shell):
- # Remove the last uid
- results = shell.Execute('cat %s' % self.get_path())
- if results[const.EXIT_CODE][0] != 0:
- return False
- parsed = self.parse_contents(results[const.STDOUT][0])
- self.uid_remove = parsed[-1][0]
+ def test_format(self):
+ return False
- results = shell.Execute('echo "%d-%d" > /proc/uid_cputime/remove_uid_range' % \
- (self.uid_remove, self.uid_remove))
- if results[const.EXIT_CODE][0] != 0:
- print "Failed to remove uid %d" % self.uid_remove
- return False
- return True
+ def get_permission_checker(self):
+ """Get write-only file permission checker.
+ """
+ return file_utils.IsWriteOnly
- def result_correct(self, results):
- for line in results:
- if self.uid_remove == line[0]:
- print line
- return False
- return True
+ def get_path(self):
+ return '/proc/uid_cputime/remove_uid_range'
diff --git a/api/proc/ProcShowUidStatTest.py b/api/proc/ProcShowUidStatTest.py
index d55985e..aa132c9 100644
--- a/api/proc/ProcShowUidStatTest.py
+++ b/api/proc/ProcShowUidStatTest.py
@@ -14,12 +14,11 @@
# limitations under the License.
#
-import KernelProcFileTestBase
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
class ProcShowUidStatTest(KernelProcFileTestBase.KernelProcFileTestBase):
- '''
- /proc/uid_cputime/show_uid_stat provides the time a UID's processes spend
+ '''/proc/uid_cputime/show_uid_stat provides the time a UID's processes spend
in user and kernel space.
This is an Android specific file.
diff --git a/api/proc/ProcSimpleFileTests.py b/api/proc/ProcSimpleFileTests.py
index c3779bf..507f9be 100644
--- a/api/proc/ProcSimpleFileTests.py
+++ b/api/proc/ProcSimpleFileTests.py
@@ -14,19 +14,18 @@
# limitations under the License.
#
-import KernelProcFileTestBase
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+
+from vts.utils.python.file import file_utils
class ProcKptrRestrictTest(KernelProcFileTestBase.KernelProcFileTestBase):
- '''
- /proc/sys/kernel/kptr_restrict determines whether kernel pointers are printed
+ '''/proc/sys/kernel/kptr_restrict determines whether kernel pointers are printed
in proc files.
'''
- start = 'num'
- def p_num(self, p):
- 'num : NUMBER NEWLINE'
- p[0] = p[1]
+ def parse_contents(self, contents):
+ return self.parse_line("{:d}\n", contents)[0]
def result_correct(self, result):
return result >= 0 and result <= 4
@@ -34,17 +33,19 @@
def get_path(self):
return "/proc/sys/kernel/kptr_restrict"
+ def get_permission_checker(self):
+ """Get r/w file permission checker.
+ """
+ return file_utils.IsReadWrite
+
class ProcRandomizeVaSpaceTest(KernelProcFileTestBase.KernelProcFileTestBase):
- '''
- /proc/sys/kernel/randomize_va_space determines the address layout randomization
+ '''/proc/sys/kernel/randomize_va_space determines the address layout randomization
policy for the system.
'''
- start = 'num'
- def p_num(self, p):
- 'num : NUMBER NEWLINE'
- p[0] = p[1]
+ def parse_contents(self, contents):
+ return self.parse_line("{:d}\n", contents)[0]
def result_correct(self, result):
return result >= 0 and result <= 2
@@ -52,16 +53,18 @@
def get_path(self):
return "/proc/sys/kernel/randomize_va_space"
+ def get_permission_checker(self):
+ """Get r/w file permission checker.
+ """
+ return file_utils.IsReadWrite
+
class ProcOverCommitMemoryTest(KernelProcFileTestBase.KernelProcFileTestBase):
+ '''/proc/sys/vm/overcommit_memory determines the kernel virtual memory accounting mode.
'''
- /proc/sys/vm/overcommit_memory determines the kernel virtual memory accounting mode.
- '''
- start = 'num'
- def p_num(self, p):
- 'num : NUMBER NEWLINE'
- p[0] = p[1]
+ def parse_contents(self, contents):
+ return self.parse_line("{:d}\n", contents)[0]
def result_correct(self, result):
return result >= 0 and result <= 2
@@ -69,31 +72,35 @@
def get_path(self):
return "/proc/sys/vm/overcommit_memory"
+ def get_permission_checker(self):
+ """Get r/w file permission checker.
+ """
+ return file_utils.IsReadWrite
+
class ProcMmapMinAddrTest(KernelProcFileTestBase.KernelProcFileTestBase):
+ '''/proc/sys/vm/mmap_min_addr specifies the minimum address that can be mmap'd.
'''
- /proc/sys/vm/mmap_min_addr specifies the minimum address that can be mmap'd.
- '''
- start = 'num'
- def p_num(self, p):
- 'num : NUMBER NEWLINE'
- p[0] = p[1]
+ def parse_contents(self, contents):
+ return self.parse_line("{:d}\n", contents)[0]
def get_path(self):
return "/proc/sys/vm/mmap_min_addr"
+ def get_permission_checker(self):
+ """Get r/w file permission checker.
+ """
+ return file_utils.IsReadWrite
+
class ProcMmapRndBitsTest(KernelProcFileTestBase.KernelProcFileTestBase):
- '''
- /proc/sys/vm/mmap_rnd_(compat_)bits specifies the amount of randomness in mmap'd
+ '''/proc/sys/vm/mmap_rnd_(compat_)bits specifies the amount of randomness in mmap'd
addresses. Must be >= 8.
'''
- start = 'num'
- def p_num(self, p):
- 'num : NUMBER NEWLINE'
- p[0] = p[1]
+ def parse_contents(self, contents):
+ return self.parse_line("{:d}\n", contents)[0]
def result_correct(self, result):
return result >= 8
@@ -101,6 +108,11 @@
def get_path(self):
return "/proc/sys/vm/mmap_rnd_bits"
+ def get_permission_checker(self):
+ """Get r/w file permission checker.
+ """
+ return file_utils.IsReadWrite
+
class ProcMmapRndCompatBitsTest(ProcMmapRndBitsTest):
def get_path(self):
diff --git a/api/proc/ProcStatTest.py b/api/proc/ProcStatTest.py
index b22af0b..9d762b1 100644
--- a/api/proc/ProcStatTest.py
+++ b/api/proc/ProcStatTest.py
@@ -14,24 +14,63 @@
# limitations under the License.
#
-import KernelProcFileTestBase
-from KernelProcFileTestBase import repeat_rule
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+from vts.testcases.kernel.api.proc.KernelProcFileTestBase import repeat_rule, literal_token
class ProcStatTest(KernelProcFileTestBase.KernelProcFileTestBase):
- '''
- /proc/stat provides kernel and system statistics.
- '''
+ '''/proc/stat provides kernel and system statistics.'''
- start = 'lines'
+ start = 'stat'
- p_lines = repeat_rule('line')
+ t_CPU = literal_token(r'cpu[0-9]*')
+ t_INTR = literal_token(r'intr')
+ t_CTXT = literal_token(r'ctxt')
+ t_BTIME = literal_token(r'btime')
+ t_PROCESSES = literal_token(r'processes')
+ t_PROCS_RUNNING = literal_token(r'procs_running')
+ t_PROCS_BLOCKED = literal_token(r'procs_blocked')
+ t_SOFTIRQ = literal_token(r'softirq')
+
+ p_cpus = repeat_rule('cpu')
p_numbers = repeat_rule('NUMBER')
t_ignore = ' '
- def p_line(self, p):
- 'line : STRING NUMBERs NEWLINE'
+ def p_stat(self, p):
+ 'stat : cpus intr ctxt btime processes procs_running procs_blocked softirq'
+ p[0] = p[1:]
+
+ def p_cpu(self, p):
+ 'cpu : CPU NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER NEWLINE'
+ p[0] = p[1:]
+
+ def p_intr(self, p):
+ 'intr : INTR NUMBERs NEWLINE'
+ p[0] = p[1:]
+
+ def p_ctxt(self, p):
+ 'ctxt : CTXT NUMBER NEWLINE'
+ p[0] = p[1:]
+
+ def p_btime(self, p):
+ 'btime : BTIME NUMBER NEWLINE'
+ p[0] = p[1:]
+
+ def p_processes(self, p):
+ 'processes : PROCESSES NUMBER NEWLINE'
+ p[0] = p[1:]
+
+ def p_procs_running(self, p):
+ 'procs_running : PROCS_RUNNING NUMBER NEWLINE'
+ p[0] = p[1:]
+
+ def p_procs_blocked(self, p):
+ 'procs_blocked : PROCS_BLOCKED NUMBER NEWLINE'
+ p[0] = p[1:]
+
+ def p_softirq(self, p):
+ 'softirq : SOFTIRQ NUMBERs NEWLINE'
p[0] = p[1:]
def get_path(self):
diff --git a/api/proc/ProcVersionTest.py b/api/proc/ProcVersionTest.py
new file mode 100644
index 0000000..887235f
--- /dev/null
+++ b/api/proc/ProcVersionTest.py
@@ -0,0 +1,34 @@
+#
+# Copyright (C) 2017 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.
+#
+
+import logging
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+
+
+class ProcVersionTest(KernelProcFileTestBase.KernelProcFileTestBase):
+ '''/proc/version displays the kernel version and build information.'''
+
+ def parse_contents(self, contents):
+ return self.parse_line("{} version {} ({}@{}) ({}) {}\n", contents)
+
+ def result_correct(self, parse_result):
+ if parse_result[0] != 'Linux' or len(parse_result[1].split('.')) != 3:
+ logging.error("Not a valid linux version!")
+ return False
+ return True
+
+ def get_path(self):
+ return "/proc/version"
diff --git a/api/proc/ProcVmallocInfoTest.py b/api/proc/ProcVmallocInfoTest.py
index a88bb45..c60fa93 100644
--- a/api/proc/ProcVmallocInfoTest.py
+++ b/api/proc/ProcVmallocInfoTest.py
@@ -14,37 +14,79 @@
# limitations under the License.
#
-import KernelProcFileTestBase
-from KernelProcFileTestBase import repeat_rule, literal_token
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+from vts.testcases.kernel.api.proc.KernelProcFileTestBase import repeat_rule, literal_token
class ProcVmallocInfoTest(KernelProcFileTestBase.KernelProcFileTestBase):
- '''
- /proc/vmallocinfo provides info on vmalloc'd ranges.
- '''
+ '''/proc/vmallocinfo provides info on vmalloc'd ranges.'''
start = 'lines'
- t_PLUS = literal_token(r'\+')
- t_SLASH = literal_token(r'/')
- t_STRING = r'[a-zA-Z\(\)_0-9\-@\.]+'
+ t_STRING = r'[^ ^\t^\n^-^=]+'
+
+ t_PAGES = literal_token('pages')
+ t_PHYS = literal_token('phys')
+ t_IOREMAP = literal_token('ioremap')
+ t_VMALLOC = literal_token('vmalloc')
+ t_VMAP = literal_token('vmap')
+ t_USER = literal_token('user')
+ t_VPAGES = literal_token('vpages')
+
t_ignore = ' '
p_lines = repeat_rule('line')
def p_line(self, p):
- '''line : addr_range NUMBER STRING NEWLINE
- | addr_range NUMBER STRING PLUS HEX_LITERAL SLASH HEX_LITERAL STRING NEWLINE
- | addr_range NUMBER STRING PLUS HEX_LITERAL SLASH HEX_LITERAL NEWLINE
- | addr_range NUMBER STRING PLUS HEX_LITERAL SLASH HEX_LITERAL \
- STRING EQUALS NUMBER STRING NEWLINE
- | addr_range NUMBER STRING PLUS HEX_LITERAL SLASH HEX_LITERAL \
- STRING EQUALS NUMBER STRING STRING NEWLINE'''
+ 'line : addr_range NUMBER caller pages phys ioremap vmalloc vmap user vpages NEWLINE'
p[0] = p[1:]
def p_addr_range(self, p):
'addr_range : HEX_LITERAL DASH HEX_LITERAL'
p[0] = [p[1], p[3]]
+ def p_caller(self, p):
+ '''caller : STRING
+ | empty'''
+ p[0] = p[1:]
+
+ def p_pages(self, p):
+ '''pages : PAGES EQUALS NUMBER
+ | empty'''
+ if len(p) > 2:
+ p[0] = [p[1], p[3]]
+ else:
+ p[0] = []
+
+ def p_phys(self, p):
+ '''phys : PHYS EQUALS STRING
+ | empty'''
+ p[0] = p[1:]
+
+ def p_ioremap(self, p):
+ '''ioremap : IOREMAP
+ | empty'''
+ p[0] = p[1:]
+
+ def p_vmalloc(self, p):
+ '''vmalloc : VMALLOC
+ | empty'''
+ p[0] = p[1:]
+
+ def p_vmap(self, p):
+ '''vmap : VMAP
+ | empty'''
+ p[0] = p[1:]
+
+ def p_user(self, p):
+ '''user : USER
+ | empty'''
+ p[0] = p[1:]
+
+ def p_vpages(self, p):
+ '''vpages : VPAGES
+ | empty'''
+ p[0] = p[1:]
+
def get_path(self):
return "/proc/vmallocinfo"
diff --git a/api/proc/ProcZoneInfoTest.py b/api/proc/ProcZoneInfoTest.py
index da98a8e..867ad96 100644
--- a/api/proc/ProcZoneInfoTest.py
+++ b/api/proc/ProcZoneInfoTest.py
@@ -14,14 +14,12 @@
# limitations under the License.
#
-import KernelProcFileTestBase
-from KernelProcFileTestBase import repeat_rule, literal_token
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+from vts.testcases.kernel.api.proc.KernelProcFileTestBase import repeat_rule, literal_token
class ProcZoneInfoTest(KernelProcFileTestBase.KernelProcFileTestBase):
- '''
- /proc/zoneinfo displays information about memory zones.
- '''
+ '''/proc/zoneinfo displays information about memory zones.'''
t_APAGES = literal_token(r'pages')
t_PAGESETS = literal_token(r'pagesets')
diff --git a/api/proc/required_kernel_configs.py b/api/proc/required_kernel_configs.py
deleted file mode 100644
index c99e6e7..0000000
--- a/api/proc/required_kernel_configs.py
+++ /dev/null
@@ -1,264 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2017 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.
-#
-"""Required kernel configuration options for Treble.
-
- TODO(jaeshin): Uncomment configs that are temporarily commented out
- (# marlin) to ensure the testCheckConfigs test passes, once the marlin
- kernel is updated.
- TODO(jaeshin): Consolidate new config requirements with android-base.cfg
-
- Kernel configuration requirements are specified in android-base.cfg
-
- Key: config_name
- Value: config_state
- "y": enabled, represents both "y" and "m" options
- "n": should not be set
-"""
-
-CONFIGS = {
- # Loadable Kernel Modules
- # "CONFIG_MODULES": "y", # marlin
- # "CONFIG_MODULE_UNLOAD": "y", # marlin
- # "CONFIG_MODVERSIONS": "y", # marlin
- # "CONFIG_MODULE_SIG": "y", # marlin
- # "CONFIG_MODULE_SIG_FORCE": "y", # marlin
-
- # Device Tree Support
- "CONFIG_OF": "y",
- # "CONFIG_OF_*": "y",
- # "CONFIG_PROC_DEVICETREE": "y", # for kernels prior to 3.15
-
- # procfs
- "CONFIG_PROC_FS": "y",
- "CONFIG_PROC_SYSCTL": "y",
- "CONFIG_PROC_PAGE_MONITOR": "y",
- "CONFIG_PROC_PID_CPUSET": "y",
- "CONFIG_IKCONFIG": "y",
- "CONFIG_IKCONFIG_PROC": "y",
-
- # sysfs
- "CONFIG_SYSFS": "y",
- "CONFIG_SYSFS_DEPRECATED": "n",
-
- # debugfs
- # "CONFIG_DEBUG_FS": "n", # marlin
-
- # selinuxfs
- # "CONFIG_SECURITY_SELINUX": "y", # duplicated below in android-base.cfg
-
- # cgroups
- # "CONFIG_CGROUPS": "y", # duplicated below in android-base.cfg
- "CONFIG_CGROUP_DEBUG": "n",
-
- # memory
- # "CONFIG_MEMCG": "y", # marlin
-
- # cpu
- # "CONFIG_CGROUP_SCHED": "y", # duplicated below in android-base.cfg
- # "CONFIG_RT_GROUP_SCHED": "y", # duplicated below in android-base.cfg
- # "CONFIG_FAIR_GROUP_SCHED": "y", # optional
-
- # cpuacct
- # "CONFIG_CGROUP_CPUACCT": "y", # duplicated below in android-base.cfg
-
- # cpuset
- "CONFIG_CPUSETS": "y",
- # "CONFIG_PROC_PID_CPUSET": "y", # nice to have
-
- # schedtune
- "CONFIG_SCHED_TUNE": "y",
-
- # pstore fs (PENDING confirmation from kernel team)
- # "CONFIG_PSTORE": "y",
- # "CONFIG_PSTORE_*": "y", # differs depending on your hardware, enable the ones present
-
- # functionfs
- # "CONFIG_USB_FUNCTIONFS": "y", # marlin
- # "CONFIG_USB_*": "y", # possibly a few more
-
- # android-base.cfg configs from
- # https://android.googlesource.com/kernel/common/+/android-4.4/android/configs/android-base.cfg
- "CONFIG_DEVKMEM": "n",
- "CONFIG_DEVMEM": "n",
- "CONFIG_INET_LRO": "n",
- "CONFIG_OABI_COMPAT": "n",
- "CONFIG_SYSVIPC": "n",
- "CONFIG_ANDROID": "y",
- "CONFIG_ANDROID_BINDER_IPC": "y",
- "CONFIG_ANDROID_LOW_MEMORY_KILLER": "y",
- "CONFIG_ARMV8_DEPRECATED": "y",
- "CONFIG_ASHMEM": "y",
- "CONFIG_AUDIT": "y",
- "CONFIG_BLK_DEV_DM": "y",
- "CONFIG_BLK_DEV_INITRD": "y",
- "CONFIG_CGROUPS": "y",
- "CONFIG_CGROUP_CPUACCT": "y",
- "CONFIG_CGROUP_FREEZER": "y",
- "CONFIG_CGROUP_SCHED": "y",
- # "CONFIG_CP15_BARRIER_EMULATION": "y", # marlin
- "CONFIG_DM_CRYPT": "y",
- "CONFIG_DM_VERITY": "y",
- "CONFIG_DM_VERITY_FEC": "y",
- "CONFIG_EMBEDDED": "y",
- "CONFIG_FB": "y",
- "CONFIG_HARDENED_USERCOPY": "y",
- "CONFIG_HIGH_RES_TIMERS": "y",
- "CONFIG_INET6_AH": "y",
- "CONFIG_INET6_ESP": "y",
- "CONFIG_INET6_IPCOMP": "y",
- "CONFIG_INET": "y",
- "CONFIG_INET_DIAG_DESTROY": "y",
- "CONFIG_INET_ESP": "y",
- "CONFIG_INET_XFRM_MODE_TUNNEL": "y",
- "CONFIG_IP6_NF_FILTER": "y",
- "CONFIG_IP6_NF_IPTABLES": "y",
- "CONFIG_IP6_NF_MANGLE": "y",
- "CONFIG_IP6_NF_RAW": "y",
- "CONFIG_IP6_NF_TARGET_REJECT": "y",
- "CONFIG_IPV6": "y",
- "CONFIG_IPV6_MIP6": "y",
- "CONFIG_IPV6_MULTIPLE_TABLES": "y",
- "CONFIG_IPV6_OPTIMISTIC_DAD": "y",
- # "CONFIG_IPV6_PRIVACY": "y", # marlin
- "CONFIG_IPV6_ROUTER_PREF": "y",
- "CONFIG_IPV6_ROUTE_INFO": "y",
- "CONFIG_IP_ADVANCED_ROUTER": "y",
- # "CONFIG_IP_MULTICAST": "y", # marlin
- "CONFIG_IP_MULTIPLE_TABLES": "y",
- "CONFIG_IP_NF_ARPFILTER": "y",
- "CONFIG_IP_NF_ARPTABLES": "y",
- "CONFIG_IP_NF_ARP_MANGLE": "y",
- "CONFIG_IP_NF_FILTER": "y",
- "CONFIG_IP_NF_IPTABLES": "y",
- "CONFIG_IP_NF_MANGLE": "y",
- "CONFIG_IP_NF_MATCH_AH": "y",
- "CONFIG_IP_NF_MATCH_ECN": "y",
- "CONFIG_IP_NF_MATCH_TTL": "y",
- "CONFIG_IP_NF_NAT": "y",
- "CONFIG_IP_NF_RAW": "y",
- "CONFIG_IP_NF_SECURITY": "y",
- "CONFIG_IP_NF_TARGET_MASQUERADE": "y",
- "CONFIG_IP_NF_TARGET_NETMAP": "y",
- "CONFIG_IP_NF_TARGET_REDIRECT": "y",
- "CONFIG_IP_NF_TARGET_REJECT": "y",
- "CONFIG_NET": "y",
- "CONFIG_NETDEVICES": "y",
- "CONFIG_NETFILTER": "y",
- # "CONFIG_NETFILTER_TPROXY": "y", # marlin
- "CONFIG_NETFILTER_XT_MATCH_COMMENT": "y",
- "CONFIG_NETFILTER_XT_MATCH_CONNLIMIT": "y",
- "CONFIG_NETFILTER_XT_MATCH_CONNMARK": "y",
- "CONFIG_NETFILTER_XT_MATCH_CONNTRACK": "y",
- "CONFIG_NETFILTER_XT_MATCH_HASHLIMIT": "y",
- "CONFIG_NETFILTER_XT_MATCH_HELPER": "y",
- "CONFIG_NETFILTER_XT_MATCH_IPRANGE": "y",
- "CONFIG_NETFILTER_XT_MATCH_LENGTH": "y",
- "CONFIG_NETFILTER_XT_MATCH_LIMIT": "y",
- "CONFIG_NETFILTER_XT_MATCH_MAC": "y",
- "CONFIG_NETFILTER_XT_MATCH_MARK": "y",
- "CONFIG_NETFILTER_XT_MATCH_PKTTYPE": "y",
- "CONFIG_NETFILTER_XT_MATCH_POLICY": "y",
- "CONFIG_NETFILTER_XT_MATCH_QTAGUID": "y",
- "CONFIG_NETFILTER_XT_MATCH_QUOTA2": "y",
- # "CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG": "y", # marlin
- "CONFIG_NETFILTER_XT_MATCH_QUOTA": "y",
- "CONFIG_NETFILTER_XT_MATCH_SOCKET": "y",
- "CONFIG_NETFILTER_XT_MATCH_STATE": "y",
- "CONFIG_NETFILTER_XT_MATCH_STATISTIC": "y",
- "CONFIG_NETFILTER_XT_MATCH_STRING": "y",
- "CONFIG_NETFILTER_XT_MATCH_TIME": "y",
- "CONFIG_NETFILTER_XT_MATCH_U32": "y",
- "CONFIG_NETFILTER_XT_TARGET_CLASSIFY": "y",
- "CONFIG_NETFILTER_XT_TARGET_CONNMARK": "y",
- "CONFIG_NETFILTER_XT_TARGET_CONNSECMARK": "y",
- "CONFIG_NETFILTER_XT_TARGET_IDLETIMER": "y",
- "CONFIG_NETFILTER_XT_TARGET_MARK": "y",
- "CONFIG_NETFILTER_XT_TARGET_NFLOG": "y",
- "CONFIG_NETFILTER_XT_TARGET_NFQUEUE": "y",
- "CONFIG_NETFILTER_XT_TARGET_SECMARK": "y",
- "CONFIG_NETFILTER_XT_TARGET_TCPMSS": "y",
- "CONFIG_NETFILTER_XT_TARGET_TPROXY": "y",
- "CONFIG_NETFILTER_XT_TARGET_TRACE": "y",
- "CONFIG_NET_CLS_ACT": "y",
- "CONFIG_NET_CLS_U32": "y",
- "CONFIG_NET_EMATCH": "y",
- "CONFIG_NET_EMATCH_U32": "y",
- "CONFIG_NET_KEY": "y",
- "CONFIG_NET_SCHED": "y",
- "CONFIG_NET_SCH_HTB": "y",
- "CONFIG_NF_CONNTRACK": "y",
- "CONFIG_NF_CONNTRACK_AMANDA": "y",
- "CONFIG_NF_CONNTRACK_EVENTS": "y",
- "CONFIG_NF_CONNTRACK_FTP": "y",
- "CONFIG_NF_CONNTRACK_H323": "y",
- "CONFIG_NF_CONNTRACK_IPV4": "y",
- "CONFIG_NF_CONNTRACK_IPV6": "y",
- "CONFIG_NF_CONNTRACK_IRC": "y",
- "CONFIG_NF_CONNTRACK_NETBIOS_NS": "y",
- "CONFIG_NF_CONNTRACK_PPTP": "y",
- "CONFIG_NF_CONNTRACK_SANE": "y",
- "CONFIG_NF_CONNTRACK_SECMARK": "y",
- "CONFIG_NF_CONNTRACK_TFTP": "y",
- "CONFIG_NF_CT_NETLINK": "y",
- "CONFIG_NF_CT_PROTO_DCCP": "y",
- "CONFIG_NF_CT_PROTO_SCTP": "y",
- "CONFIG_NF_CT_PROTO_UDPLITE": "y",
- "CONFIG_NF_NAT": "y",
- "CONFIG_NO_HZ": "y",
- "CONFIG_PACKET": "y",
- "CONFIG_PM_AUTOSLEEP": "y",
- "CONFIG_PM_WAKELOCKS": "y",
- "CONFIG_PPP": "y",
- "CONFIG_PPPOLAC": "y",
- "CONFIG_PPPOPNS": "y",
- "CONFIG_PPP_BSDCOMP": "y",
- "CONFIG_PPP_DEFLATE": "y",
- "CONFIG_PPP_MPPE": "y",
- "CONFIG_PREEMPT": "y",
- "CONFIG_PROFILING": "y",
- "CONFIG_QFMT_V2": "y",
- "CONFIG_QUOTA": "y",
- "CONFIG_QUOTA_NETLINK_INTERFACE": "y",
- "CONFIG_QUOTA_TREE": "y",
- "CONFIG_QUOTACTL": "y",
- # "CONFIG_RANDOMIZE_BASE": "y", # marlin
- "CONFIG_RTC_CLASS": "y",
- "CONFIG_RT_GROUP_SCHED": "y",
- "CONFIG_SECCOMP": "y",
- "CONFIG_SECURITY": "y",
- "CONFIG_SECURITY_NETWORK": "y",
- "CONFIG_SECURITY_PERF_EVENTS_RESTRICT": "y",
- "CONFIG_SECURITY_SELINUX": "y",
- # "CONFIG_SETEND_EMULATION": "y", # marlin
- "CONFIG_STAGING": "y",
- "CONFIG_SWP_EMULATION": "y",
- "CONFIG_SYNC": "y",
- "CONFIG_TUN": "y",
- # "CONFIG_UID_CPUTIME": "y", # marlin
- "CONFIG_UNIX": "y",
- "CONFIG_USB_GADGET": "y",
- # "CONFIG_USB_CONFIGFS": "y", # marlin
- # "CONFIG_USB_CONFIGFS_F_FS": "y", # marlin
- # "CONFIG_USB_CONFIGFS_F_MTP": "y", # marlin
- # "CONFIG_USB_CONFIGFS_F_PTP": "y", # marlin
- # "CONFIG_USB_CONFIGFS_F_ACC": "y", # marlin
- # "CONFIG_USB_CONFIGFS_F_AUDIO_SRC": "y", # marlin
- # "CONFIG_USB_CONFIGFS_UEVENT": "y", # marlin
- # "CONFIG_USB_CONFIGFS_F_MIDI": "y", # marlin
- # "CONFIG_USB_OTG_WAKELOCK": "y", # marlin
- "CONFIG_XFRM_USER": "y",
-}
diff --git a/api/qtaguid/Android.mk b/api/qtaguid/Android.mk
new file mode 100644
index 0000000..e4b56da
--- /dev/null
+++ b/api/qtaguid/Android.mk
@@ -0,0 +1,35 @@
+#
+# Copyright (C) 2017 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE := vts_test_binary_qtaguid_module
+LOCAL_SRC_FILES := SocketTagUserSpace.cpp
+LOCAL_SHARED_LIBRARIES += libcutils libutils liblog libbase
+LOCAL_STATIC_LIBRARIES += libtestUtil
+LOCAL_C_INCLUDES += system/extras/tests/include \
+ test/vts/testcases/system/qtaguid/sample
+LOCAL_CFLAGS += -fno-strict-aliasing
+
+include $(BUILD_NATIVE_TEST)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VtsQtaguidTest
+VTS_CONFIG_SRC_DIR := testcases/kernel/api/qtaguid
+include test/vts/tools/build/Android.host_config.mk
diff --git a/api/qtaguid/AndroidTest.xml b/api/qtaguid/AndroidTest.xml
new file mode 100644
index 0000000..cfc62a1
--- /dev/null
+++ b/api/qtaguid/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<configuration description="Config for VTS VtsQtaguidTest.">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+ <option name="abort-on-push-failure" value="false"/>
+ <option name="push-group" value="HostDrivenTest.push"/>
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer"/>
+ <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+ <option name="test-module-name" value="VtsQtaguidTest"/>
+ <option name="binary-test-source" value="_32bit::DATA/nativetest/vts_test_binary_qtaguid_module/vts_test_binary_qtaguid_module" />
+ <option name="binary-test-source" value="_64bit::DATA/nativetest64/vts_test_binary_qtaguid_module/vts_test_binary_qtaguid_module" />
+ <option name="binary-test-type" value="gtest" />
+ <option name="test-timeout" value="10m" />
+ </test>
+</configuration>
diff --git a/api/qtaguid/SocketTagUserSpace.cpp b/api/qtaguid/SocketTagUserSpace.cpp
new file mode 100644
index 0000000..7c1a53a
--- /dev/null
+++ b/api/qtaguid/SocketTagUserSpace.cpp
@@ -0,0 +1,489 @@
+/*
+ * Copyright (C) 2017 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 requied 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.
+ *
+ */
+
+/*
+ * This socket tagging test is to ensure that the
+ * netfilter/xt_qtaguid kernel module somewhat behaves as expected
+ * with respect to tagging sockets.
+ */
+#define LOG_TAG "SocketTagUsrSpaceTest"
+#include "SocketTagUserSpace.h"
+#include <arpa/inet.h>
+#include <assert.h>
+#include <cutils/qtaguid.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <string>
+
+#include <fstream>
+
+#include <android-base/stringprintf.h>
+#include <gtest/gtest.h>
+#include <utils/Log.h>
+
+static const int kMaxCounterSet = 2;
+
+namespace android {
+
+/* A helper program to generate some traffic between two socket. */
+int server_download(SockInfo sock_server, SockInfo sock_client) {
+ struct sockaddr_in server, client;
+ server.sin_addr.s_addr = inet_addr("127.0.0.1");
+ server.sin_family = AF_INET;
+ server.sin_port = htons(8765);
+ if (bind(sock_server.fd, (struct sockaddr *)&server, sizeof(server)) < 0) {
+ std::cerr << "bind failed" << std::endl;
+ return -1;
+ }
+ std::cout << "socket binded" << std::endl;
+ listen(sock_server.fd, 3);
+ std::cout << "waiting for connection...." << std::endl;
+ int sock_addr_length;
+ sock_addr_length = sizeof(struct sockaddr_in);
+ if (connect(sock_client.fd, (struct sockaddr *)&server, sizeof(server)), 0) {
+ return -1;
+ }
+ int new_socket;
+ new_socket = accept(sock_server.fd, (struct sockaddr *)&client,
+ reinterpret_cast<socklen_t *>(&sock_addr_length));
+ if (new_socket < 0) {
+ return -1;
+ }
+ int packet_Count = 1024;
+ char byte_buffer[1024];
+ snprintf(byte_buffer, sizeof(byte_buffer), "%d", packet_Count);
+ send(sock_client.fd, "start", 5, 0);
+ if (recv(new_socket, byte_buffer, strlen(byte_buffer), 0) < 0) {
+ close(new_socket);
+ return -1;
+ }
+ memset(byte_buffer, 'x', 1023);
+ byte_buffer[1023] = '\0';
+ if (send(new_socket, byte_buffer, strlen(byte_buffer), 0) < 0) {
+ close(new_socket);
+ return -1;
+ }
+ EXPECT_GE(recv(sock_client.fd, byte_buffer, 1024, 0), 0);
+ close(new_socket);
+ return 0;
+}
+
+/* socket setup, initial the socket and try to validate the socket. */
+int SockInfo::setup(int tag) {
+ fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (fd < 0) {
+ std::cout << "socket creation failed: %s" << strerror(errno) << std::endl;
+ return -1;
+ }
+ if (qtaguid_tagSocket(fd, tag, getuid()) < 0) {
+ std::cout << "socket setup: failed to tag" << std::endl;
+ close(fd);
+ return -1;
+ }
+ if (!checkTag(tag, getuid())) {
+ std::cout << "socket setup: Unexpected results: tag not found" << std::endl;
+ close(fd);
+ return -1;
+ }
+ if (qtaguid_untagSocket(fd) < 0) {
+ std::cout << "socket setup: Unexpected results" << std::endl;
+ close(fd);
+ return -1;
+ }
+ return 0;
+}
+
+/* Check if the socket is properly tagged by read through the proc file.*/
+bool SockInfo::checkTag(uint64_t acct_tag, uid_t uid) {
+ int res;
+ uint64_t k_tag;
+ uint32_t k_uid;
+ long dummy_count;
+ pid_t dummy_pid;
+
+ std::ifstream fctrl("/proc/net/xt_qtaguid/ctrl", std::fstream::in);
+ if (!fctrl.is_open()) {
+ std::cout << "qtaguid ctrl open failed!" << std::endl;
+ }
+
+ uint64_t full_tag = (acct_tag << 32) | uid;
+ std::string buff =
+ android::base::StringPrintf(" tag=0x%" PRIx64 " (uid=%u)", full_tag, uid);
+
+ std::cout << "looking for " << buff.c_str() << std::endl;
+ std::string ctrl_data;
+ std::size_t pos = std::string::npos;
+ while (std::getline(fctrl, ctrl_data)) {
+ pos = ctrl_data.find(buff);
+ if (pos != std::string::npos) break;
+ }
+ return pos != std::string::npos;
+}
+
+/*
+ * Check if the socket traffic statistics is properly recorded by reading the
+ * corresponding proc file.
+ */
+bool SockInfo::checkStats(uint64_t acct_tag, uid_t uid, int counterSet,
+ uint32_t *stats_result) {
+ FILE *stats_fd;
+ ssize_t read_size;
+ size_t line_size;
+ uint64_t kTag = (uint64_t)acct_tag << 32;
+ std::ifstream fstats("/proc/net/xt_qtaguid/stats", std::fstream::in);
+ if (!fstats.is_open()) {
+ std::cout << "qtaguid ctrl open failed!" << std::endl;
+ }
+ std::string buff =
+ android::base::StringPrintf("0x%" PRIx64 " %u %d", kTag, uid, counterSet);
+ std::string stats_data;
+ std::size_t pos = std::string::npos;
+ std::cout << "looking for data " << buff << std::endl;
+ while (std::getline(fstats, stats_data)) {
+ pos = stats_data.find(buff);
+ if (pos != std::string::npos) {
+ std::cout << "match_data: " << stats_data << std::endl;
+ std::string match_data = stats_data.substr(pos);
+ sscanf(match_data.c_str(), "0x%" PRIx64 " %u %d %d %d", &kTag, &uid,
+ &counterSet, stats_result, stats_result + 1);
+ return pos != std::string::npos;
+ }
+ }
+ return pos != std::string::npos;
+}
+
+class SocketTagUsrSpaceTest : public ::testing::Test {
+ protected:
+ uint32_t stats_result_[2];
+ SockInfo sock_0;
+ SockInfo sock_1;
+ uid_t fake_uid;
+ uid_t fake_uid2;
+ uid_t inet_uid;
+ uid_t my_uid;
+ pid_t my_pid;
+ int valid_tag1;
+ int valid_tag2;
+ uint64_t max_uint_tag;
+
+ virtual void SetUp() {
+ my_uid = getuid();
+ my_pid = getpid();
+ srand48(my_pid * my_uid);
+ // Adjust fake UIDs and tags so that multiple instances can run
+ // in parallel.
+ fake_uid = rand() & 0x7FFFFFFF;
+ fake_uid2 = rand() & 0x7FFFFFFF;
+ inet_uid = 1024;
+ valid_tag1 = (my_pid << 12) | (rand());
+ valid_tag2 = (my_pid << 12) | (rand());
+ std::cout << "* start: pid=" << my_pid << " uid=" << my_uid
+ << " uid1=0x" << std::hex << fake_uid << " uid2=0x"
+ << fake_uid2 << " inetuid=0x" << inet_uid << "tag1=0x%"
+ << valid_tag1 << " tag2=0x%" << valid_tag2 << std::endl;
+ max_uint_tag = 0xffffffff00000000llu;
+ max_uint_tag = 1llu << 63 | (((uint64_t)my_pid << 48) ^ max_uint_tag);
+ // Check the node /dev/xt_qtaguid exist before start.
+ struct stat nodeStat;
+ EXPECT_GE(stat("/dev/xt_qtaguid", &nodeStat), 0)
+ << "fail to check /dev/xt_qtaguid";
+ // We want to clean up any previous faulty test runs.
+ EXPECT_GE(qtaguid_deleteTagData(0, fake_uid), 0)
+ << "Failed to delete fake_uid";
+ EXPECT_GE(qtaguid_deleteTagData(0, fake_uid2), 0)
+ << "Failed to delete fake_uid2";
+ EXPECT_GE(qtaguid_deleteTagData(0, my_uid), 0) << "Failed to delete my_uid";
+ EXPECT_GE(qtaguid_deleteTagData(0, inet_uid), 0)
+ << "Failed to delete inet_uid";
+ EXPECT_GE(qtaguid_setPacifier(0), 0) << "Turn off pacifier fail";
+ ASSERT_FALSE(sock_0.setup(valid_tag1)) << "socket0 setup failed";
+ ASSERT_FALSE(sock_1.setup(valid_tag1)) << "socket1 setup failed";
+ }
+
+ virtual void TearDown() {
+ if (sock_0.fd >= 0) {
+ close(sock_0.fd);
+ }
+ if (sock_1.fd >= 0) {
+ close(sock_1.fd);
+ }
+ }
+};
+
+/* Tag to a invalid socket fd, should fail */
+TEST_F(SocketTagUsrSpaceTest, invalidSockfdFail) {
+ EXPECT_LT(qtaguid_tagSocket(-1, valid_tag1, my_uid), 0)
+ << "Invalid socketfd case 1, should fail.";
+}
+
+/* Check the stats of a invalid socket, should fail. */
+TEST_F(SocketTagUsrSpaceTest, CheckStatsInvalidSocketFail) {
+ memset(stats_result_, 0, 2);
+ EXPECT_FALSE(sock_0.checkStats(valid_tag1, fake_uid, 0, stats_result_))
+ << "No stats should be here";
+}
+
+/* Untag invalid socket fd, should fail */
+TEST_F(SocketTagUsrSpaceTest, UntagInvalidSocketFail) {
+ EXPECT_LT(qtaguid_untagSocket(-1), 0) << "invalid socket fd, should fail";
+ EXPECT_LT(qtaguid_untagSocket(sock_0.fd), 0)
+ << "no tags on sock0, should fail";
+}
+
+/*
+ * Set the counter to a number larger then max counter avalaible
+ * should fail
+ */
+TEST_F(SocketTagUsrSpaceTest, CounterSetNumExceedFail) {
+ int wrongCounterNum = kMaxCounterSet + 1;
+ EXPECT_LT(qtaguid_setCounterSet(wrongCounterNum, my_uid), 0)
+ << "Invalid counter set number, should fail.";
+}
+
+/* Tag without valid uid, should be tagged with my_uid */
+TEST_F(SocketTagUsrSpaceTest, NoUidTag) {
+ EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag1, 0), 0)
+ << "tag failed without uid";
+ EXPECT_TRUE(sock_0.checkTag(valid_tag1, my_uid)) << "Tag not found";
+}
+
+/*
+ * Tag without tag and uid number, should be tagged with tag 0 and
+ * my_uid
+ */
+TEST_F(SocketTagUsrSpaceTest, NoTagNoUid) {
+ EXPECT_GE(qtaguid_tagSocket(sock_0.fd, 0, 0), 0)
+ << "no tag and uid infomation";
+ ASSERT_TRUE(sock_0.checkTag(0, my_uid)) << "Tag not found";
+}
+
+/* Untag from a tagged socket */
+TEST_F(SocketTagUsrSpaceTest, ValidUntag) {
+ EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag1, my_uid), 0);
+ EXPECT_TRUE(sock_0.checkTag(valid_tag1, my_uid)) << "Tag not found";
+ EXPECT_GE(qtaguid_untagSocket(sock_0.fd), 0);
+ EXPECT_FALSE(sock_0.checkTag(valid_tag1, my_uid)) << "Tag should be removed";
+}
+
+/* Tag a socket for the first time */
+TEST_F(SocketTagUsrSpaceTest, ValidFirsttag) {
+ EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag2, fake_uid), 0);
+ EXPECT_TRUE(sock_0.checkTag(valid_tag2, fake_uid)) << "Tag not found.";
+}
+
+/* ReTag a already tagged socket with the same tag and uid */
+TEST_F(SocketTagUsrSpaceTest, ValidReTag) {
+ EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag2, fake_uid), 0);
+ EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag2, fake_uid), 0);
+ EXPECT_TRUE(sock_0.checkTag(valid_tag2, fake_uid)) << "Tag not found.";
+}
+
+/*
+ * Retag a already tagged socket with the same uid but different tag
+ * Should keep the second one and untag the original one
+ */
+TEST_F(SocketTagUsrSpaceTest, ValidReTagWithAcctTagChange) {
+ EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag2, fake_uid), 0);
+ EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag1, fake_uid), 0);
+ EXPECT_TRUE(sock_0.checkTag(valid_tag1, fake_uid)) << "Tag not found.";
+ EXPECT_FALSE(sock_0.checkTag(valid_tag2, fake_uid))
+ << "Tag should not be here";
+}
+
+/*
+ * Retag a already tagged socket with different uid and different tag.
+ * Should keep both
+ */
+TEST_F(SocketTagUsrSpaceTest, ReTagWithUidChange) {
+ EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag2, fake_uid), 0);
+ EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag1, fake_uid2), 0);
+}
+
+/*
+ * Retag a already tagged socket with different uid but the same tag.
+ * The original one should be replaced by the new one.
+ */
+TEST_F(SocketTagUsrSpaceTest, ReTagWithUidChange2) {
+ EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag2, fake_uid), 0);
+ EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag2, fake_uid2), 0);
+ EXPECT_TRUE(sock_0.checkTag(valid_tag2, fake_uid2)) << "Tag not found.";
+ EXPECT_FALSE(sock_0.checkTag(valid_tag2, fake_uid))
+ << "Tag should not be here";
+}
+
+/* Tag two sockets with two uids and two tags. */
+TEST_F(SocketTagUsrSpaceTest, TagAnotherSocket) {
+ EXPECT_GE(qtaguid_tagSocket(sock_0.fd, max_uint_tag, my_uid), 0);
+ EXPECT_GE(qtaguid_tagSocket(sock_1.fd, valid_tag1, fake_uid2), 0);
+ EXPECT_TRUE(sock_1.checkTag(valid_tag1, fake_uid2)) << "Tag not found.";
+ EXPECT_GE(qtaguid_untagSocket(sock_0.fd), 0);
+ EXPECT_FALSE(sock_0.checkTag(max_uint_tag, fake_uid))
+ << "Tag should not be there";
+ EXPECT_TRUE(sock_1.checkTag(valid_tag1, fake_uid2)) << "Tag not found";
+ EXPECT_GE(qtaguid_untagSocket(sock_1.fd), 0);
+ EXPECT_FALSE(sock_1.checkTag(valid_tag1, fake_uid2))
+ << "Tag should not be there";
+}
+
+/* Tag two sockets with the same uid but different acct_tags. */
+TEST_F(SocketTagUsrSpaceTest, SameUidTwoSocket) {
+ EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag1, my_uid), 0);
+ EXPECT_GE(qtaguid_tagSocket(sock_1.fd, valid_tag2, my_uid), 0);
+ EXPECT_TRUE(sock_1.checkTag(valid_tag2, my_uid)) << "Tag not found.";
+ EXPECT_TRUE(sock_0.checkTag(valid_tag1, my_uid)) << "Tag not found.";
+ EXPECT_GE(qtaguid_untagSocket(sock_0.fd), 0);
+ EXPECT_FALSE(sock_0.checkTag(valid_tag1, my_uid))
+
+ << "Tag should not be there";
+ EXPECT_TRUE(sock_1.checkTag(valid_tag2, my_uid)) << "Tag not found";
+ EXPECT_GE(qtaguid_untagSocket(sock_1.fd), 0);
+ EXPECT_FALSE(sock_1.checkTag(valid_tag2, my_uid))
+ << "Tag should not be there";
+}
+
+/* Tag two sockets with the same acct_tag but different uids */
+TEST_F(SocketTagUsrSpaceTest, SameTagTwoSocket) {
+ EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag1, fake_uid), 0);
+ EXPECT_GE(qtaguid_tagSocket(sock_1.fd, valid_tag1, fake_uid2), 0);
+ EXPECT_TRUE(sock_1.checkTag(valid_tag1, fake_uid)) << "Tag not found.";
+ EXPECT_TRUE(sock_0.checkTag(valid_tag1, fake_uid2)) << "Tag not found.";
+ EXPECT_GE(qtaguid_untagSocket(sock_0.fd), 0);
+ EXPECT_FALSE(sock_0.checkTag(valid_tag1, fake_uid))
+ << "Tag should not be there";
+ EXPECT_TRUE(sock_1.checkTag(valid_tag1, fake_uid2)) << "Tag not found";
+ EXPECT_GE(qtaguid_untagSocket(sock_1.fd), 0);
+ EXPECT_FALSE(sock_1.checkTag(valid_tag1, fake_uid2))
+ << "Tag should not be there";
+}
+
+/* Tag a closed socket, should fail. */
+TEST_F(SocketTagUsrSpaceTest, TagInvalidSocketFail) {
+ close(sock_0.fd);
+ EXPECT_LT(qtaguid_tagSocket(sock_0.fd, valid_tag1, my_uid), 0);
+ EXPECT_FALSE(sock_0.checkTag(valid_tag1, my_uid))
+ << "Tag should not be there";
+}
+
+/* untag from a closed socket, should fail. */
+TEST_F(SocketTagUsrSpaceTest, UntagClosedSocketFail) {
+ EXPECT_GE(qtaguid_tagSocket(sock_1.fd, valid_tag1, my_uid), 0);
+ EXPECT_TRUE(sock_1.checkTag(valid_tag1, my_uid));
+ close(sock_1.fd);
+ EXPECT_LT(qtaguid_untagSocket(sock_1.fd), 0)
+ << "no tag attached, should fail";
+}
+
+/*
+ * set the pacifier ON and try to modify the tags, expect no change to the
+ * ctrl and stats file.
+ */
+TEST_F(SocketTagUsrSpaceTest, PacifierFunctionTest) {
+ EXPECT_GE(qtaguid_tagSocket(sock_0.fd, max_uint_tag, my_uid), 0);
+ EXPECT_GE(qtaguid_setPacifier(1), 0);
+ EXPECT_GE(qtaguid_untagSocket(sock_0.fd), 0);
+ EXPECT_GE(qtaguid_tagSocket(sock_1.fd, valid_tag1, fake_uid2), 0);
+ EXPECT_FALSE(sock_1.checkTag(valid_tag1, fake_uid2))
+ << "Tag should not be there.";
+ EXPECT_GE(qtaguid_setPacifier(0), 0);
+ EXPECT_FALSE(sock_1.checkTag(valid_tag1, fake_uid2))
+ << "Tag should not be there.";
+ EXPECT_TRUE(sock_0.checkTag(max_uint_tag, my_uid)) << "tag not found";
+ EXPECT_GE(qtaguid_untagSocket(sock_0.fd), 0);
+ EXPECT_GE(qtaguid_tagSocket(sock_1.fd, valid_tag1, fake_uid2), 0);
+ EXPECT_FALSE(sock_0.checkTag(max_uint_tag, fake_uid))
+ << "Tag should not be there";
+ EXPECT_TRUE(sock_1.checkTag(valid_tag1, fake_uid2)) << "Tag not found";
+}
+
+/*
+ * try to connect with google.com in order to generate some
+ * tranffic through the socket, the traffic statistics should
+ * be stored in the stats file and will be returned.
+ */
+TEST_F(SocketTagUsrSpaceTest, dataTransmitTest) {
+ memset(stats_result_, 0, 2);
+ EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag1, inet_uid), 0);
+ EXPECT_TRUE(sock_0.checkTag(valid_tag1, inet_uid)) << "tag not found";
+ EXPECT_GE(server_download(sock_0, sock_1), 0);
+ EXPECT_GE(qtaguid_untagSocket(sock_0.fd), 0);
+ close(sock_0.fd);
+ EXPECT_TRUE(sock_0.checkStats(valid_tag1, inet_uid, 0, stats_result_))
+ << "failed to retreive data";
+ std::cout << "the receive packet count is " << stats_result_[1]
+ << ", the byte count is " << stats_result_[0] << std::endl;
+ EXPECT_GT(*stats_result_, (uint32_t)0) << "no stats found for this socket";
+ EXPECT_GT(*(stats_result_ + 1), (uint32_t)0)
+ << "no stats stored for this socket";
+}
+
+/* Generate some traffic first and then delete the
+ * tag and uid from stats. All the stats related should
+ * be deleted. checkStats() should return false.
+ */
+TEST_F(SocketTagUsrSpaceTest, dataStatsDeleteTest) {
+ memset(stats_result_, 0, 2);
+ EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag1, fake_uid), 0);
+ EXPECT_TRUE(sock_0.checkTag(valid_tag1, fake_uid)) << "tag not found";
+ EXPECT_GE(server_download(sock_0, sock_1), 0);
+ EXPECT_GE(qtaguid_untagSocket(sock_0.fd), 0);
+ EXPECT_TRUE(sock_0.checkStats(valid_tag1, fake_uid, 0, stats_result_))
+ << "failed to retreive data";
+ std::cout << "the receive packet count is " << stats_result_[1]
+ << ", the byte count is " << stats_result_[0] << std::endl;
+ EXPECT_GT(*stats_result_, (uint32_t)0) << "no stats found for this socket";
+ EXPECT_GT(*(stats_result_ + 1), (uint32_t)0)
+ << "no stats stored for this socket";
+ EXPECT_GE(qtaguid_deleteTagData(0, fake_uid), 0)
+ << "Failed to delete fake_uid";
+ EXPECT_FALSE(sock_0.checkStats(valid_tag1, fake_uid, 0, stats_result_))
+ << "NO DATA should be stored";
+}
+
+/*
+ * try to store the traffic stats in the secound counter
+ * insdead of the first. All the stats should be stored
+ * in the secound counter.
+ */
+TEST_F(SocketTagUsrSpaceTest, CounterSetTest) {
+ memset(stats_result_, 0, 2);
+ EXPECT_GE(qtaguid_tagSocket(sock_1.fd, valid_tag1, inet_uid), 0);
+ EXPECT_GE(qtaguid_setCounterSet(1, inet_uid), 0);
+ EXPECT_TRUE(sock_1.checkTag(valid_tag1, inet_uid)) << "tag not found";
+ EXPECT_GE(server_download(sock_0, sock_1), 0);
+ EXPECT_GE(qtaguid_untagSocket(sock_1.fd), 0);
+ close(sock_1.fd);
+ EXPECT_TRUE(sock_1.checkStats(valid_tag1, inet_uid, 1, stats_result_))
+ << "failed to retreive data";
+ uint32_t packet_count = 1;
+ uint32_t total_byte = 1024;
+ std::cout << "the receive packet count is " << stats_result_[1]
+ << ", the byte count is " << stats_result_[0] << std::endl;
+ EXPECT_GT(*stats_result_, total_byte) << "no stats found for this socket";
+ EXPECT_GT(*(stats_result_ + 1), packet_count)
+ << "wrong stats stored for this socket";
+ uint32_t stats_foreground[2] = {0, 0};
+ EXPECT_TRUE(sock_0.checkStats(valid_tag1, inet_uid, 0, stats_foreground))
+ << "fail to retrieve data";
+ EXPECT_LE(*stats_foreground, (uint32_t)0) << "stats data is not zero";
+}
+} // namespace android
diff --git a/api/qtaguid/SocketTagUserSpace.h b/api/qtaguid/SocketTagUserSpace.h
new file mode 100644
index 0000000..0bed2f7
--- /dev/null
+++ b/api/qtaguid/SocketTagUserSpace.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2017 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.
+ *
+ */
+
+#ifndef _VTS_SYSTEM_QTAGUID_SOCKET_TAG_USER_SPACE_
+#define _VTS_SYSTEM_QTAGUID_SOCKET_TAG_USER_SPACE_
+
+#include <stdint.h>
+#include <stdlib.h>
+
+namespace android {
+
+// Class created to store socket file description and setup socket
+class SockInfo {
+ public:
+ SockInfo() : fd(-1) {}
+ // set up the socket and verify it by trying to tag it
+ int setup(int tag);
+ // helper function check if the socket is tagged correctly
+ bool checkTag(uint64_t acct_tag, uid_t uid);
+ // helper function check if the socket traffic is properly recorded.
+ bool checkStats(uint64_t acct_tag, uid_t uid, int counterSet,
+ uint32_t *stats_result);
+ // socket file description
+ int fd;
+};
+
+} // namespace android
+
+#endif // _VTS_SYSTEM_QTAGUID_SOCKET_TAG_USER_SPACE_
diff --git a/api/selinux/Android.mk b/api/selinux/Android.mk
new file mode 100644
index 0000000..244af93
--- /dev/null
+++ b/api/selinux/Android.mk
@@ -0,0 +1,25 @@
+#
+# Copyright (C) 2017 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VtsKernelSelinuxFileApi
+VTS_CONFIG_SRC_DIR := testcases/kernel/api/selinux
+include test/vts/tools/build/Android.host_config.mk
diff --git a/api/selinux/AndroidTest.xml b/api/selinux/AndroidTest.xml
new file mode 100644
index 0000000..1e4e018
--- /dev/null
+++ b/api/selinux/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<configuration description="Config for VTS KernelSelinuxFileApiTest test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+ <option name="push-group" value="HostDrivenTest.push" />
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer">
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+ <option name="test-module-name" value="VtsKernelSelinuxFileApi" />
+ <option name="test-case-path" value="vts/testcases/kernel/api/selinux/VtsKernelSelinuxFileApiTest" />
+ </test>
+</configuration>
diff --git a/api/selinux/KernelSelinuxFileTestBase.py b/api/selinux/KernelSelinuxFileTestBase.py
new file mode 100644
index 0000000..d48e007
--- /dev/null
+++ b/api/selinux/KernelSelinuxFileTestBase.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2017 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.
+#
+from abc import ABCMeta
+from abc import abstractmethod
+
+from vts.utils.python.file import file_utils
+
+class KernelSelinuxFileTestBase(object):
+ """Abstract test for the formatting of a selinux file.
+
+ Individual files can inherit from this class and define the correct path,
+ file content, and permissions.
+ """
+ __metaclass__ = ABCMeta
+
+ @abstractmethod
+ def get_path(self):
+ """Return the full path of this selinux file."""
+ pass
+
+ def result_correct(self, file_contents):
+ """Return True if the file contents are correct.
+
+ Subclasses define the requirements for the selinux file and validate
+ that the contents of a file are correct.
+
+ Args:
+ file_contents: String, the contents of an selinux file
+
+ Returns:
+ True if the contents are correct, False otherwise.
+ """
+ return True
+
+ def get_permission_checker(self):
+ """Gets the function handle to use for validating file permissions.
+
+ Return the function that will check if the permissions are correct.
+ By default, return the IsReadOnly function from file_utils.
+
+ Returns:
+ function which takes one argument (the unix file permission bits
+ in octal format) and returns True if the permissions are correct,
+ False otherwise.
+ """
+ return file_utils.IsReadOnly
diff --git a/api/selinux/SelinuxCheckReqProtTest.py b/api/selinux/SelinuxCheckReqProtTest.py
new file mode 100644
index 0000000..5d091a5
--- /dev/null
+++ b/api/selinux/SelinuxCheckReqProtTest.py
@@ -0,0 +1,42 @@
+#
+# Copyright (C) 2017 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.
+#
+from vts.testcases.kernel.api.selinux import KernelSelinuxFileTestBase
+from vts.utils.python.file import file_utils
+
+
+class SelinuxCheckReqProt(KernelSelinuxFileTestBase.KernelSelinuxFileTestBase):
+ """Validate /sys/fs/selinux/checkreqprot content and permissions.
+
+ The contents are binary 0/1 and the file should be read/write.
+ """
+
+ def get_path(self):
+ return "/sys/fs/selinux/checkreqprot"
+
+ def result_correct(self, file_content):
+ """Return True if the file contents are simply 0/1.
+
+ Args:
+ file_contents: String, the contents of the checkreqprot file
+
+ Returns:
+ True if the contents are 0/1, False otherwise.
+ """
+ return file_content == "0" or file_content == "1"
+
+ def get_permission_checker(self):
+ """Gets the function handle to validate r/w file permissions."""
+ return file_utils.IsReadWrite
diff --git a/api/selinux/SelinuxNullTest.py b/api/selinux/SelinuxNullTest.py
new file mode 100644
index 0000000..611e492
--- /dev/null
+++ b/api/selinux/SelinuxNullTest.py
@@ -0,0 +1,31 @@
+#
+# Copyright (C) 2017 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.
+#
+from vts.testcases.kernel.api.selinux import KernelSelinuxFileTestBase
+from vts.utils.python.file import file_utils
+
+
+class SelinuxNull(KernelSelinuxFileTestBase.KernelSelinuxFileTestBase):
+ """Validate /sys/fs/selinux/null permissions.
+
+ The file should be read/write; there are no tests for content format.
+ """
+
+ def get_path(self):
+ return "/sys/fs/selinux/null"
+
+ def get_permission_checker(self):
+ """Gets the function handle to validate r/w file permissions."""
+ return file_utils.IsReadWrite
diff --git a/api/selinux/SelinuxPolicyTest.py b/api/selinux/SelinuxPolicyTest.py
new file mode 100644
index 0000000..9c79336
--- /dev/null
+++ b/api/selinux/SelinuxPolicyTest.py
@@ -0,0 +1,27 @@
+#
+# Copyright (C) 2017 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.
+#
+from vts.testcases.kernel.api.selinux import KernelSelinuxFileTestBase
+from vts.utils.python.file import file_utils
+
+
+class SelinuxPolicy(KernelSelinuxFileTestBase.KernelSelinuxFileTestBase):
+ """Validate /sys/fs/selinux/policy permissions.
+
+ The file permission should be read-only. No content testing at this time.
+ """
+
+ def get_path(self):
+ return "/sys/fs/selinux/policy"
diff --git a/api/selinux/VtsKernelSelinuxFileApiTest.py b/api/selinux/VtsKernelSelinuxFileApiTest.py
new file mode 100644
index 0000000..d35e33b
--- /dev/null
+++ b/api/selinux/VtsKernelSelinuxFileApiTest.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2017 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.
+#
+
+import logging
+
+from vts.runners.host import asserts
+from vts.runners.host import base_test
+from vts.runners.host import const
+from vts.runners.host import test_runner
+from vts.testcases.kernel.api.selinux import SelinuxCheckReqProtTest
+from vts.testcases.kernel.api.selinux import SelinuxPolicyTest
+from vts.testcases.kernel.api.selinux import SelinuxNullTest
+from vts.utils.python.controllers import android_device
+from vts.utils.python.file import file_utils
+
+TEST_OBJECTS = {
+ SelinuxCheckReqProtTest.SelinuxCheckReqProt(),
+ SelinuxPolicyTest.SelinuxPolicy(),
+ SelinuxNullTest.SelinuxNull()
+}
+
+class VtsKernelSelinuxFileApiTest(base_test.BaseTestClass):
+ """Test cases which check content of selinuxfs files.
+ """
+
+ def setUpClass(self):
+ self.dut = self.registerController(android_device)[0]
+ self.dut.shell.InvokeTerminal(
+ "KernelSelinuxFileApiTest") # creates a remote shell instance.
+ self.shell = self.dut.shell.KernelSelinuxFileApiTest
+
+ def runSelinuxFileTest(self, test_object):
+ """Reads the file and checks that its content and permissions are valid.
+
+ Args:
+ test_object: inherits KernelSelinuxFileTestBase, contains the test functions
+ """
+ logging.info("Testing existence of %s" % (test_object.get_path()))
+
+ asserts.assertTrue(
+ file_utils.Exists(test_object.get_path(), self.shell),
+ "%s: File does not exist." % test_object.get_path())
+
+ logging.info("Testing permissions of %s" % (test_object.get_path()))
+ try:
+ permissions = file_utils.GetPermission(
+ test_object.get_path(), self.shell)
+ asserts.assertTrue(test_object.get_permission_checker()(permissions),
+ "%s: File has invalid permissions (%s)" %
+ (test_object.get_path(), permissions))
+ except (ValueError, IOError) as e:
+ asserts.fail("Failed to assert permissions: %s" % str(e))
+
+ logging.info("Testing format of %s" % (test_object.get_path()))
+ file_content = file_utils.ReadFileContent(
+ test_object.get_path(), self.shell)
+ asserts.assertTrue(
+ test_object.result_correct(file_content), "Results not valid!")
+
+ def generateProcFileTests(self):
+ """Run all selinux file tests."""
+ self.runGeneratedTests(test_func=self.runSelinuxFileTest,
+ settings=TEST_OBJECTS,
+ name_func=lambda test_obj: "test" + test_obj.__class__.__name__)
+
+if __name__ == "__main__":
+ test_runner.main()
diff --git a/api/selinux/__init__.py b/api/selinux/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/api/selinux/__init__.py
diff --git a/api/sysfs/Android.mk b/api/sysfs/Android.mk
new file mode 100644
index 0000000..78b6f0c
--- /dev/null
+++ b/api/sysfs/Android.mk
@@ -0,0 +1,23 @@
+#
+# Copyright (C) 2017 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VtsKernelApiSysfsTest
+VTS_CONFIG_SRC_DIR := testcases/kernel/api/sysfs
+include test/vts/tools/build/Android.host_config.mk
diff --git a/api/sysfs/AndroidTest.xml b/api/sysfs/AndroidTest.xml
new file mode 100644
index 0000000..e398c25
--- /dev/null
+++ b/api/sysfs/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<configuration description="Config for VTS KernelApiTest test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+ <option name="push-group" value="HostDrivenTest.push" />
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer">
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+ <option name="test-module-name" value="VtsKernelApiSysfs" />
+ <option name="test-case-path" value="vts/testcases/kernel/api/sysfs/KernelApiSysfsTest" />
+ </test>
+</configuration>
diff --git a/api/sysfs/KernelApiSysfsTest.py b/api/sysfs/KernelApiSysfsTest.py
new file mode 100644
index 0000000..78ed074
--- /dev/null
+++ b/api/sysfs/KernelApiSysfsTest.py
@@ -0,0 +1,120 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2017 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.
+#
+
+import logging
+import re
+
+from vts.runners.host import asserts
+from vts.runners.host import base_test
+from vts.runners.host import test_runner
+from vts.utils.python.controllers import android_device
+from vts.utils.python.file import file_utils
+
+
+class KernelApiSysfsTest(base_test.BaseTestClass):
+ '''Test cases which check sysfs files.'''
+
+ def setUpClass(self):
+ self.dut = self.registerController(android_device)[0]
+ self.dut.shell.InvokeTerminal(
+ 'default') # creates a remote shell instance.
+ self.shell = self.dut.shell.default
+
+ def ConvertToInteger(self, text):
+ '''Check whether a given text is interger.
+
+ Args:
+ text: object, usually a string representing the content of a file
+
+ Returns:
+ bool, True if is integer
+ '''
+ try:
+ return int(text)
+ except ValueError as e:
+ logging.exception(e)
+ asserts.fail('Content "%s" is not integer' % text)
+
+ def MatchRegex(self, regex, string):
+ '''Check whether a string completely matches a given regex.
+
+ Assertions will fail if given string is not a complete match.
+
+ Args:
+ regex: string, regex pattern to match
+ string: string, given string for matching
+ '''
+ pattern = re.compile(regex)
+ match = pattern.match(string)
+ message = 'String "%s" is not a complete match of regex "%s".' % (
+ string, regex)
+ asserts.assertTrue(match is not None, message)
+ asserts.assertEqual(match.start(), 0, message)
+ asserts.assertEqual(match.end(), len(string), message)
+
+ def IsReadOnly(self, path):
+ '''Check whether a given path is read only.
+
+ Assertion will fail if given path does not exist or is not read only.
+ '''
+ permission = ''
+ try:
+ permission = file_utils.GetPermission(path, self.shell)
+ except IOError as e:
+ logging.exception(e)
+ asserts.fail('Path "%s" does not exist or has invalid '
+ 'permission bits' % path)
+
+ try:
+ asserts.assertTrue(
+ file_utils.IsReadOnly(permission),
+ 'path %s is not read only' % path)
+ except IOError as e:
+ logging.exception(e)
+ asserts.fail('Got invalid permission bits "%s" for path "%s"' %
+ (permission, path))
+
+ def testCpuOnlineFormat(self):
+ '''Check the format of cpu online file.
+
+ Confirm /sys/devices/system/cpu/online exists and is read-only.
+ Parse contents to ensure it is a comma-separated series of ranges
+ (%d-%d) and/or integers.
+ '''
+ filepath = '/sys/devices/system/cpu/online'
+ self.IsReadOnly(filepath)
+ content = file_utils.ReadFileContent(filepath, self.shell)
+ regex = '(\d+(-\d+)?)(,\d+(-\d+)?)*'
+ if content.endswith('\n'):
+ content = content[:-1]
+ self.MatchRegex(regex, content)
+
+ def testLastResumeReason(self):
+ '''Check /sys/kernel/wakeup_reasons/last_resume_reason.'''
+ filepath = '/sys/kernel/wakeup_reasons/last_resume_reason'
+ self.IsReadOnly(filepath)
+
+ def testKernelMax(self):
+ '''Check the value of /sys/devices/system/cpu/kernel_max.'''
+ filepath = '/sys/devices/system/cpu/kernel_max'
+ self.IsReadOnly(filepath)
+ content = file_utils.ReadFileContent(filepath, self.shell)
+ self.ConvertToInteger(content)
+
+
+if __name__ == "__main__":
+ test_runner.main()
diff --git a/api/sysfs/__init__.py b/api/sysfs/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/api/sysfs/__init__.py
diff --git a/api/tun/Android.bp b/api/tun/Android.bp
new file mode 100644
index 0000000..f065de2
--- /dev/null
+++ b/api/tun/Android.bp
@@ -0,0 +1,24 @@
+// Copyright (C) 2017 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.
+
+cc_test {
+ name: "vts_kernel_tun_test",
+ srcs: [
+ "vts_kernel_tun_test.cpp",
+ ],
+ shared_libs: [
+ "libbase",
+ ],
+}
+
diff --git a/api/tun/Android.mk b/api/tun/Android.mk
new file mode 100644
index 0000000..09fc0b1
--- /dev/null
+++ b/api/tun/Android.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2017 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VtsKernelTunTest
+include test/vts/tools/build/Android.host_config.mk
diff --git a/api/tun/AndroidTest.xml b/api/tun/AndroidTest.xml
new file mode 100644
index 0000000..87e20c8
--- /dev/null
+++ b/api/tun/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<configuration description="Config for VTS VtsKernelTunTest.">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+ <option name="abort-on-push-failure" value="false"/>
+ <option name="push-group" value="HostDrivenTest.push"/>
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer"/>
+ <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+ <option name="test-module-name" value="VtsKernelTunTest"/>
+ <option name="binary-test-source" value="_32bit::DATA/nativetest/vts_kernel_tun_test/vts_kernel_tun_test" />
+ <option name="binary-test-source" value="_64bit::DATA/nativetest64/vts_kernel_tun_test/vts_kernel_tun_test" />
+ <option name="binary-test-type" value="gtest"/>
+ <option name="test-timeout" value="10m"/>
+ </test>
+</configuration>
diff --git a/api/tun/vts_kernel_tun_test.cpp b/api/tun/vts_kernel_tun_test.cpp
new file mode 100644
index 0000000..701a19d
--- /dev/null
+++ b/api/tun/vts_kernel_tun_test.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include <iostream>
+#include <string>
+
+#include <fcntl.h>
+
+#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
+#include <gtest/gtest.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+
+using std::cout;
+using std::endl;
+using std::string;
+using android::base::StringPrintf;
+using android::base::unique_fd;
+
+static const short kTunModes[] = {
+ IFF_TUN,
+ IFF_TAP,
+};
+
+class VtsKernelTunTest : public ::testing::TestWithParam<short> {
+ public:
+ virtual void SetUp() override {
+ tun_device_ = "/dev/tun";
+ uint32_t num = arc4random_uniform(1000);
+ ifr_name_ = StringPrintf("tun%d", num);
+ }
+
+ // Used to initialize tun device.
+ int TunInit(short flags);
+
+ string tun_device_;
+ string ifr_name_;
+ unique_fd fd_;
+};
+
+int VtsKernelTunTest::TunInit(short mode) {
+ struct ifreq ifr = {
+ .ifr_flags = mode,
+ };
+ strncpy(ifr.ifr_name, ifr_name_.c_str(), IFNAMSIZ);
+ int fd = open(tun_device_.c_str(), O_RDWR | O_NONBLOCK);
+ if (fd < 0) {
+ return -1;
+ }
+ if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) {
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+// Test opening and closing of a tun interface.
+TEST_P(VtsKernelTunTest, OpenAndClose) {
+ fd_ = unique_fd(TunInit(GetParam()));
+ ASSERT_TRUE(fd_ >= 0);
+}
+
+// Test basic read functionality of a tuen interface.
+TEST_P(VtsKernelTunTest, BasicRead) {
+ fd_ = unique_fd(TunInit(GetParam()));
+ ASSERT_TRUE(fd_ >= 0);
+
+ uint8_t test_output;
+ // Expect no packets available on this interface.
+ ASSERT_TRUE(read(fd_, &test_output, 1) < 0);
+}
+
+INSTANTIATE_TEST_CASE_P(Basic, VtsKernelTunTest,
+ ::testing::ValuesIn(kTunModes));
+
+int main(int argc, char **argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/config/Android.mk b/config/Android.mk
new file mode 100644
index 0000000..f9c3bbb
--- /dev/null
+++ b/config/Android.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2017 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VtsKernelConfig
+include test/vts/tools/build/Android.host_config.mk
\ No newline at end of file
diff --git a/config/AndroidTest.xml b/config/AndroidTest.xml
new file mode 100644
index 0000000..29d7c7e
--- /dev/null
+++ b/config/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<configuration description="Config for VTS KernelConfigTest">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+ <option name="push-group" value="HostDrivenTest.push" />
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer">
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+ <option name="test-module-name" value="VtsKernelConfig" />
+ <option name="test-case-path" value="vts/testcases/kernel/config/VtsKernelConfigTest" />
+ </test>
+</configuration>
diff --git a/config/VtsKernelConfigTest.py b/config/VtsKernelConfigTest.py
new file mode 100644
index 0000000..ef70390
--- /dev/null
+++ b/config/VtsKernelConfigTest.py
@@ -0,0 +1,168 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2017 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.
+#
+
+import gzip
+import logging
+import os
+import re
+import shutil
+import tempfile
+
+from vts.runners.host import asserts
+from vts.runners.host import base_test
+from vts.runners.host import const
+from vts.runners.host import keys
+from vts.runners.host import test_runner
+from vts.utils.python.controllers import android_device
+from vts.utils.python.file import file_utils
+
+
+class VtsKernelConfigTest(base_test.BaseTestClass):
+ """Test case which check config options in /proc/config.gz.
+
+ Attributes:
+ _temp_dir: The temporary directory to which /proc/config.gz is copied.
+ """
+
+ PROC_FILE_PATH = "/proc/config.gz"
+ KERNEL_CONFIG_FILE_PATH = "vts/testcases/kernel/config/data"
+ SUPPORTED_KERNEL_VERSIONS = ["3.18", "4.4", "4.9"]
+
+ def setUpClass(self):
+ required_params = [
+ keys.ConfigKeys.IKEY_DATA_FILE_PATH
+ ]
+ self.getUserParams(required_params)
+ self.dut = self.registerController(android_device)[0]
+ self.dut.shell.InvokeTerminal(
+ "KernelConfigTest") # creates a remote shell instance.
+ self.shell = self.dut.shell.KernelConfigTest
+ self._temp_dir = tempfile.mkdtemp()
+
+ def checkKernelVersion(self):
+ """Validate the kernel version of DUT is a valid O kernel version.
+
+ Returns:
+ string, kernel version of device
+ """
+ cmd = "uname -a"
+ results = self.shell.Execute(cmd)
+ logging.info("Shell command '%s' results: %s", cmd, results)
+
+ match = re.search(r"\d+\.\d+", results[const.STDOUT][0])
+ if match is None:
+ asserts.fail("Failed to detect kernel version of device.")
+ else:
+ kernel_version = match.group(0)
+ logging.info("Detected kernel version: %s", kernel_version)
+
+ asserts.assertTrue(kernel_version in self.SUPPORTED_KERNEL_VERSIONS,
+ "Detected kernel version '%s' is not one of %s"
+ % (kernel_version, self.SUPPORTED_KERNEL_VERSIONS))
+
+ return kernel_version
+
+ def parseConfigFileToDict(self, file):
+ """Parse kernel config file to a dictionary.
+
+ Args:
+ file: file object, android-base.cfg or unzipped /proc/config.gz
+
+ Returns:
+ dict: {config_name: config_state}
+ """
+ config_lines = [line.rstrip("\n") for line in file.readlines()]
+ configs = dict()
+
+ for line in config_lines:
+ if line.startswith("#") and line.endswith("is not set"):
+ match = re.search(r"CONFIG_\S+", line)
+ if match is None:
+ asserts.fail("Failed to parse config file")
+ else:
+ config_name = match.group(0)
+ config_state = "n"
+ elif line.startswith("CONFIG_"):
+ config_name, config_state = line.split("=", 1)
+ if config_state.startswith(("'", '"')):
+ config_state = config_state[1:-1]
+ else:
+ continue
+ configs[config_name] = config_state
+
+ return configs
+
+ def testKernelConfigs(self):
+ """Ensures all configs conform to android-base.cfg requirements.
+
+ Detects kernel version of device and validates against appropriate
+ Common Android Kernel android-base.cfg.
+ """
+ logging.info("Testing existence of %s" % self.PROC_FILE_PATH)
+ file_utils.assertPermissionsAndExistence(
+ self.shell, self.PROC_FILE_PATH, file_utils.IsReadOnly)
+
+ logging.info("Validating kernel version of device.")
+ kernel_version = self.checkKernelVersion()
+
+ config_file_path = os.path.join(self.data_file_path,
+ self.KERNEL_CONFIG_FILE_PATH, "android-" + kernel_version,
+ "android-base.cfg")
+ with open(config_file_path, 'r') as config_file:
+ configs = self.parseConfigFileToDict(config_file)
+
+ self.dut.adb.pull("%s %s" % (self.PROC_FILE_PATH, self._temp_dir))
+ logging.info("Adb pull %s to %s", self.PROC_FILE_PATH, self._temp_dir)
+
+ localpath = os.path.join(self._temp_dir, "config.gz")
+ with gzip.open(localpath, "rb") as device_config_file:
+ device_configs = self.parseConfigFileToDict(device_config_file)
+
+ should_be_enabled = []
+ should_not_be_set = []
+ incorrect_config_state = []
+ for config_name, config_state in configs.iteritems():
+ if (config_state == "y" and
+ (config_name not in device_configs or
+ device_configs[config_name] not in ("y", "m"))):
+ should_be_enabled.append(config_name)
+ elif (config_state == "n" and (config_name in device_configs) and
+ device_configs[config_name] != "n"):
+ should_not_be_set.append(config_name + "=" +
+ device_configs[config_name])
+ elif (config_name in device_configs and
+ device_configs[config_name] != config_state):
+ incorrect_config_state.append(config_name + "=" +
+ device_configs[config_name])
+
+ asserts.assertTrue(
+ len(should_be_enabled) == 0 and len(should_not_be_set) == 0 and
+ len(incorrect_config_state) == 0,
+ ("The following kernel configs should be enabled: [%s]\n"
+ "The following kernel configs should not be set: [%s]\n"
+ "THe following kernel configs have incorrect state: [%s]") %
+ (", ".join(should_be_enabled), ", ".join(should_not_be_set),
+ ", ".join(incorrect_config_state)))
+
+ def tearDownClass(self):
+ """Deletes the temporary directory."""
+ logging.info("Delete %s", self._temp_dir)
+ shutil.rmtree(self._temp_dir)
+
+
+if __name__ == "__main__":
+ test_runner.main()
diff --git a/config/__init__.py b/config/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/config/__init__.py
diff --git a/config/data/android-3.18/android-base.cfg b/config/data/android-3.18/android-base.cfg
new file mode 100644
index 0000000..4e305c7
--- /dev/null
+++ b/config/data/android-3.18/android-base.cfg
@@ -0,0 +1,170 @@
+# KEEP ALPHABETICALLY SORTED
+# CONFIG_DEVKMEM is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_FHANDLE is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_MODULES is not set
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_USELIB is not set
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_DEVICES=binder,hwbinder,vndbinder
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ARMV8_DEPRECATED=y
+CONFIG_ASHMEM=y
+CONFIG_AUDIT=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_CP15_BARRIER_EMULATION=y
+CONFIG_DEFAULT_SECURITY_SELINUX=y
+CONFIG_EMBEDDED=y
+CONFIG_FB=y
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_DIAG_DESTROY=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_INET=y
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_INET_ESP=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IPV6=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_NET=y
+CONFIG_NETDEVICES=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_TPROXY=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_CLS_U32=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_KEY=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_NAT=y
+CONFIG_NO_HZ=y
+CONFIG_PACKET=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PPP=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_MPPE=y
+CONFIG_PREEMPT=y
+CONFIG_QFMT_V2=y
+CONFIG_QUOTA=y
+CONFIG_QUOTACTL=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QUOTA_TREE=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_SECCOMP=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SETEND_EMULATION=y
+CONFIG_STAGING=y
+CONFIG_SWITCH=y
+CONFIG_SWP_EMULATION=y
+CONFIG_SYNC=y
+CONFIG_TUN=y
+CONFIG_UID_SYS_STATS=y
+CONFIG_UNIX=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_G_ANDROID=y
+CONFIG_USB_OTG_WAKELOCK=y
+CONFIG_XFRM_USER=y
\ No newline at end of file
diff --git a/config/data/android-4.4/android-base.cfg b/config/data/android-4.4/android-base.cfg
new file mode 100644
index 0000000..2d08ea1
--- /dev/null
+++ b/config/data/android-4.4/android-base.cfg
@@ -0,0 +1,177 @@
+# KEEP ALPHABETICALLY SORTED
+# CONFIG_DEVKMEM is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_FHANDLE is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_MODULES is not set
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_USELIB is not set
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_DEVICES=binder,hwbinder,vndbinder
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ARMV8_DEPRECATED=y
+CONFIG_ASHMEM=y
+CONFIG_AUDIT=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_CP15_BARRIER_EMULATION=y
+CONFIG_DEFAULT_SECURITY_SELINUX=y
+CONFIG_EMBEDDED=y
+CONFIG_FB=y
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_DIAG_DESTROY=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_INET=y
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_INET_ESP=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IPV6=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_NET=y
+CONFIG_NETDEVICES=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_TPROXY=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_CLS_U32=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_KEY=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_NAT=y
+CONFIG_NO_HZ=y
+CONFIG_PACKET=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PPP=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_MPPE=y
+CONFIG_PREEMPT=y
+CONFIG_PROFILING=y
+CONFIG_QFMT_V2=y
+CONFIG_QUOTA=y
+CONFIG_QUOTACTL=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QUOTA_TREE=y
+CONFIG_RANDOMIZE_BASE=y
+CONFIG_RTC_CLASS=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_SECCOMP=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SETEND_EMULATION=y
+CONFIG_STAGING=y
+CONFIG_SWP_EMULATION=y
+CONFIG_SYNC=y
+CONFIG_TUN=y
+CONFIG_UID_SYS_STATS=y
+CONFIG_UNIX=y
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_F_ACC=y
+CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
+CONFIG_USB_CONFIGFS_F_MTP=y
+CONFIG_USB_CONFIGFS_F_PTP=y
+CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_OTG_WAKELOCK=y
+CONFIG_XFRM_USER=y
\ No newline at end of file
diff --git a/config/data/android-4.9/android-base.cfg b/config/data/android-4.9/android-base.cfg
new file mode 100644
index 0000000..2d08ea1
--- /dev/null
+++ b/config/data/android-4.9/android-base.cfg
@@ -0,0 +1,177 @@
+# KEEP ALPHABETICALLY SORTED
+# CONFIG_DEVKMEM is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_FHANDLE is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_MODULES is not set
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_USELIB is not set
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_DEVICES=binder,hwbinder,vndbinder
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ARMV8_DEPRECATED=y
+CONFIG_ASHMEM=y
+CONFIG_AUDIT=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_CP15_BARRIER_EMULATION=y
+CONFIG_DEFAULT_SECURITY_SELINUX=y
+CONFIG_EMBEDDED=y
+CONFIG_FB=y
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_DIAG_DESTROY=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_INET=y
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_INET_ESP=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IPV6=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_NET=y
+CONFIG_NETDEVICES=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_TPROXY=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_CLS_U32=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_KEY=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_NAT=y
+CONFIG_NO_HZ=y
+CONFIG_PACKET=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PPP=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_MPPE=y
+CONFIG_PREEMPT=y
+CONFIG_PROFILING=y
+CONFIG_QFMT_V2=y
+CONFIG_QUOTA=y
+CONFIG_QUOTACTL=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QUOTA_TREE=y
+CONFIG_RANDOMIZE_BASE=y
+CONFIG_RTC_CLASS=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_SECCOMP=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SETEND_EMULATION=y
+CONFIG_STAGING=y
+CONFIG_SWP_EMULATION=y
+CONFIG_SYNC=y
+CONFIG_TUN=y
+CONFIG_UID_SYS_STATS=y
+CONFIG_UNIX=y
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_F_ACC=y
+CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
+CONFIG_USB_CONFIGFS_F_MTP=y
+CONFIG_USB_CONFIGFS_F_PTP=y
+CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_OTG_WAKELOCK=y
+CONFIG_XFRM_USER=y
\ No newline at end of file
diff --git a/ltp/ltp_configs.py b/ltp/ltp_configs.py
index 8413553..29568c7 100644
--- a/ltp/ltp_configs.py
+++ b/ltp/ltp_configs.py
@@ -180,6 +180,8 @@
# Tests disabled
# Based on external/ltp commit 5f01077afe994f4107b147222f3956716d4a8fde
DISABLED_TESTS = [
+ # gunzip newly added on 4/12/17 and test is failing because -r option is not yet implemented.
+ 'commands.gzip01',
# b/32386191 getrusage04 result is flaky
'syscalls.getrusage04',
# b/31154962