Coverage for kea/start.py: 98%

102 statements  

« prev     ^ index     » next       coverage.py v7.6.9, created at 2024-12-22 16:05 +0800

1import argparse 

2import warnings 

3from dataclasses import dataclass 

4 

5from hypothesis.errors import NonInteractiveExampleWarning 

6warnings.filterwarnings("ignore", category=NonInteractiveExampleWarning) 

7import coloredlogs 

8coloredlogs.install() 

9 

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 

15 

16@dataclass 

17class Setting: 

18 """`Setting` is a Python DataClass 

19 

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 

48 

49def parse_args(): 

50 """Parse, load and sanitize the args from the command line and the config file `config.yml`. 

51 

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() 

85 

86 # load the args from the config file `config.yml` 

87 if options.load_config: 

88 options = load_ymal_args(options) 

89 

90 # sanitize these args 

91 sanitize_args(options) 

92 

93 return options 

94 

95def load_ymal_args(opts): 

96 """Load the args from the config file `config.yml`.  

97 

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 

119 

120 return opts 

121 

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) 

132 

133def start_kea(kea:"Kea", settings:"Setting" = None): 

134 

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 ) 

167 

168 kea._pdl_driver.set_droidbot(droidbot) 

169 droidbot.start() 

170 

171 

172def main(): 

173 """the main entry of Kea. 

174 """ 

175 # parse the args 

176 options = parse_args() 

177 

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 ) 

193 

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) 

199 

200 # create Kea 

201 kea = Kea() 

202 print(f"INFO: All Test cases: {kea._KeaTest_DB}") 

203 # start Kea 

204 start_kea(kea, settings) 

205 

206if __name__ == "__main__": 

207 main()