# # Copyright (C) 2018 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 os import time import environment_variables as env class SyzkallerTestCase(object): """Represents syzkaller test case. Attributes: _env: dict, inverted map of environment varialbes for this test. _device_target: string, OS of the target device. _device_code: string, serial number of the target device. _device_type: string, type of the target device. _reproduce: boolean, whether or not to reproduce if a crash is found. _http: integer, path to localhost where the test information will be shown. _procs: integer, number of processes this test case will use if available. _test_name: string, the unique name for this test case. _work_dir_path: string, path to the work directory for this test case. _config_file_path: string, path to the config file for this test case. """ def __init__(self, env, device_target, device_code, device_type, reproduce, procs): self._env = env self._device_target = device_target self._device_code = device_code self._device_type = device_type self._reproduce = reproduce self._http = 'localhost:50000' self._procs = procs self._test_name = self.GenerateTestName() self._work_dir_path = self.GenerateCorpusDir() self._config_file_path = self.GenerateConfigFile() def GenerateTestName(self): """Uses device code and time to create unique name Returns: test_name, string, the unique test name for this test case. """ test_name = '%s_%s_%d' % (time.strftime('%Y-%m-%d'), self._device_code, int(time.time())) return str(test_name) def GenerateCorpusDir(self): """Creates working directory for this test case. Returns: work_dir_path, string, path to the working directory for this test case. """ work_dir_path = os.path.join(self._env['syzkaller_work_dir'], self._test_name) if not os.path.exists(work_dir_path): os.makedirs(work_dir_path) return work_dir_path def GenerateConfigFile(self): """Creates configuration file for this test case. Returns: config_file_path, string, path to the configuration file for this test case. """ # read template config with open(self._env['template_cfg'], 'r') as temp: template_cfg = str(temp.read()) # fill out template template_cfg = template_cfg.replace('{device_target}', self._device_target) template_cfg = template_cfg.replace('{reproduce}', self._reproduce) template_cfg = template_cfg.replace('{work_dir_path}', self._work_dir_path) template_cfg = template_cfg.replace('{http}', self._http) template_cfg = template_cfg.replace('{syzkaller_dir_path}', self._env['syzkaller_dir']) template_cfg = template_cfg.replace('{device_code}', self._device_code) template_cfg = template_cfg.replace('{device_type}', self._device_type) template_cfg = template_cfg.replace('{procs}', str(self._procs)) # save config file config_file_path = self._work_dir_path + str('.cfg') with open(config_file_path, 'w') as config_file: config_file.write(template_cfg) return config_file_path def GetRunCommand(self): """Creates test run command for this case. Returns: test_command, string, test run command for this test case. """ syz_manager_path = os.path.join(self._env['syzkaller_bin_dir'], 'syz-manager') test_command = '%s -config=%s' % (syz_manager_path, self._config_file_path) return test_command