Coverage for kea/start.py: 98%
102 statements
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-22 16:05 +0800
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-22 16:05 +0800
1import argparse
2import warnings
3from dataclasses import dataclass
5from hypothesis.errors import NonInteractiveExampleWarning
6warnings.filterwarnings("ignore", category=NonInteractiveExampleWarning)
7import coloredlogs
8coloredlogs.install()
10from .input_manager import DEFAULT_POLICY, DEFAULT_TIMEOUT
11from .kea import Kea
12from .utils import get_yml_config, sanitize_args
13from .droidbot import DroidBot
14from .utils import DEFAULT_POLICY, DEFAULT_EVENT_INTERVAL, DEFAULT_TIMEOUT, DEFAULT_EVENT_COUNT
16@dataclass
17class Setting:
18 """`Setting` is a Python DataClass
20 TODO: it seems the Setting class is redudant? why not just using options?
21 """
22 apk_path: str
23 device_serial: str = None
24 output_dir:str ="output"
25 is_emulator: bool =True #True for emulators, False for real devices.
26 policy_name: str = DEFAULT_POLICY
27 random_input: bool =True
28 event_interval: int= DEFAULT_EVENT_INTERVAL
29 timeout: int = DEFAULT_TIMEOUT
30 event_count: int= DEFAULT_EVENT_COUNT
31 cv_mode=None
32 debug_mode: bool=False
33 keep_app:bool=None
34 keep_env=None
35 profiling_method=None
36 grant_perm: bool=True
37 send_document: bool=True
38 enable_accessibility_hard=None
39 master=None
40 humanoid=None
41 ignore_ad=None
42 replay_output=None
43 number_of_events_that_restart_app:int =100
44 run_initial_rules_after_every_mutation=True
45 is_harmonyos:bool=False
46 generate_utg:bool=False
47 is_package:bool=False
49def parse_args():
50 """Parse, load and sanitize the args from the command line and the config file `config.yml`.
52 The args are either specified via the command line or the config file `config.yml`.
53 The design purpose of config.yml is to ease specifying the args via a config file.
54 """
55 parser = argparse.ArgumentParser(description="Start kea to test app.",
56 formatter_class=argparse.RawTextHelpFormatter)
57 parser.add_argument("-f", nargs="+", action="store",dest="property_files", help="The app properties to be tested.")
58 parser.add_argument("-d", "--device_serial", action="store", dest="device_serial", default=None,
59 help="The serial number of target device (use `adb devices` to find)")
60 parser.add_argument("-a","--apk", action="store", dest="apk_path",
61 help="The file path to target APK")
62 parser.add_argument("-o","--output", action="store", dest="output_dir", default="output",
63 help="directory of output")
64 parser.add_argument("-p","--policy", action="store", dest="policy",choices=["random", "guided", "llm"], default=DEFAULT_POLICY, # tingsu: can we change "mutate" to "guided"?
65 help='Policy used for input event generation. ')
66 parser.add_argument("-t", "--timeout", action="store", dest="timeout", default=DEFAULT_TIMEOUT, type=int,
67 help="Timeout in seconds. Default: %d" % DEFAULT_TIMEOUT)
68 parser.add_argument("-n","--number_of_events_that_restart_app", action="store", dest="number_of_events_that_restart_app", default=100, type=int,
69 help="Restart the app when this number of events has been executed. Default: 100")
70 parser.add_argument("-debug", action="store_true", dest="debug_mode",
71 help="Run in debug mode (dump debug messages).")
72 parser.add_argument("-keep_app", action="store_true", dest="keep_app",
73 help="Keep the app on the device after testing.")
74 parser.add_argument("-grant_perm", action="store_true", dest="grant_perm",
75 help="Grant all permissions while installing. Useful for Android 6.0+.")
76 parser.add_argument("-is_emulator", action="store_true", dest="is_emulator",default=True,
77 help="Declare the target device to be an emulator, which would be treated specially.")
78 parser.add_argument("-is_harmonyos", action="store_true", dest="is_harmonyos", default=False,
79 help="use harmonyos devices")
80 parser.add_argument("-load_config", action="store_true", dest="load_config", default=False,
81 help="load the args from config.yml, and the args in the command line will be ignored.")
82 parser.add_argument("-utg", action="store_true", dest="generate_utg", default=False,
83 help="Generate UI transition graph")
84 options = parser.parse_args()
86 # load the args from the config file `config.yml`
87 if options.load_config:
88 options = load_ymal_args(options)
90 # sanitize these args
91 sanitize_args(options)
93 return options
95def load_ymal_args(opts):
96 """Load the args from the config file `config.yml`.
98 The design purpose of config.yml is to ease specifying the args via a config file.
99 Note that the values of the args in config.yml would overwrite those args specified via the command line.
100 """
101 config_dict = get_yml_config()
102 for key, value in config_dict.items():
103 if key.lower() == "system" and value:
104 opts.is_harmonyos = value.lower() == "harmonyos"
105 elif key.lower() in ["app_path", "package", "package_name"] and value:
106 opts.apk_path = value
107 elif key.lower() == "policy" and value:
108 opts.policy = value
109 elif key.lower() == "output_dir" and value:
110 opts.output_dir = value
111 elif key.lower() == "count" and value:
112 opts.count = value
113 elif key.lower() in ["target", "device", "device_serial"] and value:
114 opts.device_serial = value
115 elif key.lower() in ["property", "properties", "file", "files"] and value:
116 opts.property_files = value
117 elif key.lower() == "keep_app" and value:
118 opts.keep_app = value
120 return opts
122def load_pdl_driver(settings: "Setting"):
123 """Load the pdl (property description language) driver according to the target mobile platform
124 (e.g., Android, HarmonyOS).
125 """
126 if settings.is_harmonyos:
127 from kea.harmonyos_pdl_driver import HarmonyOS_PDL_Driver
128 return HarmonyOS_PDL_Driver(serial=settings.device_serial)
129 else:
130 from kea.android_pdl_driver import Android_PDL_Driver
131 return Android_PDL_Driver(serial=settings.device_serial)
133def start_kea(kea:"Kea", settings:"Setting" = None):
135 # droidbot is used as the data generator of Kea
136 droidbot = DroidBot(
137 app_path=settings.apk_path,
138 device_serial=settings.device_serial,
139 is_emulator=settings.is_emulator,
140 output_dir=settings.output_dir,
141 env_policy = None,
142 policy_name=settings.policy_name,
143 random_input=settings.random_input,
144 event_interval=settings.event_interval,
145 timeout=settings.timeout,
146 event_count=settings.event_count,
147 cv_mode=settings.cv_mode,
148 debug_mode=settings.debug_mode,
149 keep_app=settings.keep_app,
150 keep_env=settings.keep_env,
151 profiling_method=settings.profiling_method,
152 grant_perm=settings.grant_perm,
153 send_document=settings.send_document,
154 enable_accessibility_hard=settings.enable_accessibility_hard,
155 master=settings.master,
156 humanoid=settings.humanoid,
157 ignore_ad=settings.ignore_ad,
158 replay_output=settings.replay_output,
159 kea=kea,
160 number_of_events_that_restart_app=settings.number_of_events_that_restart_app,
161 run_initial_rules_after_every_mutation=settings.run_initial_rules_after_every_mutation,
162 is_harmonyos=settings.is_harmonyos,
163 is_package=settings.is_package,
164 settings=settings,
165 generate_utg=settings.generate_utg
166 )
168 kea._pdl_driver.set_droidbot(droidbot)
169 droidbot.start()
172def main():
173 """the main entry of Kea.
174 """
175 # parse the args
176 options = parse_args()
178 # setup the setting
179 settings = Setting(apk_path=options.apk_path,
180 device_serial=options.device_serial,
181 output_dir=options.output_dir,
182 timeout=options.timeout,
183 policy_name=options.policy,
184 number_of_events_that_restart_app=options.number_of_events_that_restart_app, # tingsu: do we need a better name?
185 debug_mode=options.debug_mode,
186 keep_app=options.keep_app,
187 is_harmonyos=options.is_harmonyos,
188 grant_perm=options.grant_perm,
189 is_emulator=options.is_emulator,
190 generate_utg=options.generate_utg,
191 is_package=options.is_package
192 )
194 # load the pdl driver for Android/HarmonyOS
195 driver = load_pdl_driver(settings)
196 Kea.set_pdl_driver(driver)
197 # load the app properties to be tested
198 Kea.load_app_properties(options.property_files)
200 # create Kea
201 kea = Kea()
202 print(f"INFO: All Test cases: {kea._KeaTest_DB}")
203 # start Kea
204 start_kea(kea, settings)
206if __name__ == "__main__":
207 main()