"""Install the release and run embedded-component instrumentation on one explicit device.""" import argparse,hashlib,json,pathlib,subprocess,time APP=pathlib.Path(__file__).resolve().parents[1] def main(): parser=argparse.ArgumentParser(description=__doc__);parser.add_argument('--serial',required=True);parser.add_argument('--output',type=pathlib.Path,required=True) args=parser.parse_args();args.output.mkdir(parents=True,exist_ok=True) def adb(*command,binary=False,timeout=30,retries=3): last=None for attempt in range(retries): result=subprocess.run(['adb','-s',args.serial,*command],stdout=subprocess.PIPE,stderr=subprocess.PIPE,timeout=timeout) if result.returncode==0:return result.stdout if binary else result.stdout.decode('utf-8',errors='replace').strip() last=(result.stdout+result.stderr).decode('utf-8',errors='replace').strip() if command[0]!='install'and'device' not in last.lower()and'closed' not in last.lower():break print('Device connection interrupted; retrying this command.',flush=True);time.sleep(1) raise RuntimeError(last) apk=APP/'app/build/outputs/apk/release/app-release.apk';test=APP/'app/build/outputs/apk/androidTest/release/app-release-androidTest.apk' assert apk.is_file()and test.is_file() model=adb('shell','getprop','ro.product.model');sdk=adb('shell','getprop','ro.build.version.sdk') original=args.output/'original-ime.txt' if not original.exists():original.write_text(adb('shell','settings','get','secure','default_input_method')+'\n',encoding='utf-8') host=APP/'host/build/outputs/apk/debug/host-debug.apk' for path in [apk,test,host]:print(adb('install','-r',str(path),timeout=90),flush=True) before=adb('shell','settings','get','secure','default_input_method') print('Default system IME retained; testing the embedded keyboard only.',flush=True) adb('shell','input','keyevent','224');adb('shell','wm','dismiss-keyguard') # The instrumentation is bounded short acceptance, not a stress/soak run. command=['adb','-s',args.serial,'shell','am','instrument','-w','-r','com.sydxky.crabinput.test/androidx.test.runner.AndroidJUnitRunner'] result=subprocess.run(command,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,timeout=240) output=result.stdout.decode('utf-8',errors='replace');(args.output/'instrumentation.txt').write_text(output,encoding='utf-8');print(output,flush=True) passed=result.returncode==0 and 'OK (8 tests)'in output and 'FAILURES!!!'not in output report={'model':model,'sdk':sdk,'version':'1.2.0','apk_sha256':hashlib.sha256(apk.read_bytes()).hexdigest(),'instrumentation_tests':8,'embedded_component':True,'system_ime_unchanged':adb('shell','settings','get','secure','default_input_method')==before,'passed':passed} (args.output/'device-validation.json').write_text(json.dumps(report,indent=2)+'\n',encoding='utf-8') assert passed and report['system_ime_unchanged'],'See instrumentation.txt; failed/unfinished cases are not accepted' adb('shell','am','start','-n','com.sydxky.crabinput/.MainActivity');time.sleep(.5) (args.output/'home.png').write_bytes(adb('exec-out','screencap','-p',binary=True)) print(json.dumps(report),flush=True) if __name__=='__main__':main()