1*795d594fSAndroid Build Coastguard Worker#!/usr/bin/python3 2*795d594fSAndroid Build Coastguard Worker# 3*795d594fSAndroid Build Coastguard Worker# Copyright (C) 2015 The Android Open Source Project 4*795d594fSAndroid Build Coastguard Worker# 5*795d594fSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*795d594fSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*795d594fSAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*795d594fSAndroid Build Coastguard Worker# 9*795d594fSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*795d594fSAndroid Build Coastguard Worker# 11*795d594fSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*795d594fSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*795d594fSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*795d594fSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*795d594fSAndroid Build Coastguard Worker# limitations under the License. 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker""" 18*795d594fSAndroid Build Coastguard WorkerGenerate Smali test files for test 967. 19*795d594fSAndroid Build Coastguard Worker""" 20*795d594fSAndroid Build Coastguard Worker 21*795d594fSAndroid Build Coastguard Workerimport os 22*795d594fSAndroid Build Coastguard Workerimport sys 23*795d594fSAndroid Build Coastguard Workerfrom pathlib import Path 24*795d594fSAndroid Build Coastguard Worker 25*795d594fSAndroid Build Coastguard WorkerBUILD_TOP = os.getenv("ANDROID_BUILD_TOP") 26*795d594fSAndroid Build Coastguard Workerif BUILD_TOP is None: 27*795d594fSAndroid Build Coastguard Worker print("ANDROID_BUILD_TOP not set. Please run build/envsetup.sh", file=sys.stderr) 28*795d594fSAndroid Build Coastguard Worker sys.exit(1) 29*795d594fSAndroid Build Coastguard Worker 30*795d594fSAndroid Build Coastguard Worker# Allow us to import utils and mixins. 31*795d594fSAndroid Build Coastguard Workersys.path.append(str(Path(BUILD_TOP)/"art"/"test"/"utils"/"python")) 32*795d594fSAndroid Build Coastguard Worker 33*795d594fSAndroid Build Coastguard Workerfrom testgen.utils import get_copyright, subtree_sizes, gensym, filter_blanks 34*795d594fSAndroid Build Coastguard Workerimport testgen.mixins as mixins 35*795d594fSAndroid Build Coastguard Worker 36*795d594fSAndroid Build Coastguard Workerfrom enum import Enum 37*795d594fSAndroid Build Coastguard Workerfrom functools import total_ordering 38*795d594fSAndroid Build Coastguard Workerimport itertools 39*795d594fSAndroid Build Coastguard Workerimport string 40*795d594fSAndroid Build Coastguard Worker 41*795d594fSAndroid Build Coastguard Worker# The max depth the type tree can have. 42*795d594fSAndroid Build Coastguard WorkerMAX_IFACE_DEPTH = 2 43*795d594fSAndroid Build Coastguard Worker 44*795d594fSAndroid Build Coastguard Workerclass MainClass(mixins.DumpMixin, mixins.Named, mixins.SmaliFileMixin): 45*795d594fSAndroid Build Coastguard Worker """ 46*795d594fSAndroid Build Coastguard Worker A Main.smali file containing the Main class and the main function. It will run 47*795d594fSAndroid Build Coastguard Worker all the test functions we have. 48*795d594fSAndroid Build Coastguard Worker """ 49*795d594fSAndroid Build Coastguard Worker 50*795d594fSAndroid Build Coastguard Worker MAIN_CLASS_TEMPLATE = """{copyright} 51*795d594fSAndroid Build Coastguard Worker 52*795d594fSAndroid Build Coastguard Worker.class public LMain; 53*795d594fSAndroid Build Coastguard Worker.super Ljava/lang/Object; 54*795d594fSAndroid Build Coastguard Worker 55*795d594fSAndroid Build Coastguard Worker# class Main {{ 56*795d594fSAndroid Build Coastguard Worker 57*795d594fSAndroid Build Coastguard Worker.method public constructor <init>()V 58*795d594fSAndroid Build Coastguard Worker .registers 1 59*795d594fSAndroid Build Coastguard Worker invoke-direct {{p0}}, Ljava/lang/Object;-><init>()V 60*795d594fSAndroid Build Coastguard Worker return-void 61*795d594fSAndroid Build Coastguard Worker.end method 62*795d594fSAndroid Build Coastguard Worker 63*795d594fSAndroid Build Coastguard Worker{test_funcs} 64*795d594fSAndroid Build Coastguard Worker 65*795d594fSAndroid Build Coastguard Worker{main_func} 66*795d594fSAndroid Build Coastguard Worker 67*795d594fSAndroid Build Coastguard Worker# }} 68*795d594fSAndroid Build Coastguard Worker""" 69*795d594fSAndroid Build Coastguard Worker 70*795d594fSAndroid Build Coastguard Worker MAIN_FUNCTION_TEMPLATE = """ 71*795d594fSAndroid Build Coastguard Worker# public static void main(String[] args) {{ 72*795d594fSAndroid Build Coastguard Worker.method public static main([Ljava/lang/String;)V 73*795d594fSAndroid Build Coastguard Worker .locals 0 74*795d594fSAndroid Build Coastguard Worker 75*795d594fSAndroid Build Coastguard Worker {test_group_invoke} 76*795d594fSAndroid Build Coastguard Worker 77*795d594fSAndroid Build Coastguard Worker return-void 78*795d594fSAndroid Build Coastguard Worker.end method 79*795d594fSAndroid Build Coastguard Worker# }} 80*795d594fSAndroid Build Coastguard Worker""" 81*795d594fSAndroid Build Coastguard Worker 82*795d594fSAndroid Build Coastguard Worker TEST_GROUP_INVOKE_TEMPLATE = """ 83*795d594fSAndroid Build Coastguard Worker# {test_name}(); 84*795d594fSAndroid Build Coastguard Worker invoke-static {{}}, {test_name}()V 85*795d594fSAndroid Build Coastguard Worker""" 86*795d594fSAndroid Build Coastguard Worker 87*795d594fSAndroid Build Coastguard Worker def __init__(self): 88*795d594fSAndroid Build Coastguard Worker """ 89*795d594fSAndroid Build Coastguard Worker Initialize this MainClass. We start out with no tests. 90*795d594fSAndroid Build Coastguard Worker """ 91*795d594fSAndroid Build Coastguard Worker self.tests = set() 92*795d594fSAndroid Build Coastguard Worker 93*795d594fSAndroid Build Coastguard Worker def get_expected(self): 94*795d594fSAndroid Build Coastguard Worker """ 95*795d594fSAndroid Build Coastguard Worker Get the expected output of this test. 96*795d594fSAndroid Build Coastguard Worker """ 97*795d594fSAndroid Build Coastguard Worker all_tests = sorted(self.tests) 98*795d594fSAndroid Build Coastguard Worker return filter_blanks("\n".join(a.get_expected() for a in all_tests)) 99*795d594fSAndroid Build Coastguard Worker 100*795d594fSAndroid Build Coastguard Worker def add_test(self, ty): 101*795d594fSAndroid Build Coastguard Worker """ 102*795d594fSAndroid Build Coastguard Worker Add a test for the concrete type 'ty' 103*795d594fSAndroid Build Coastguard Worker """ 104*795d594fSAndroid Build Coastguard Worker self.tests.add(Func(ty)) 105*795d594fSAndroid Build Coastguard Worker 106*795d594fSAndroid Build Coastguard Worker def get_name(self): 107*795d594fSAndroid Build Coastguard Worker """ 108*795d594fSAndroid Build Coastguard Worker Get the name of this class 109*795d594fSAndroid Build Coastguard Worker """ 110*795d594fSAndroid Build Coastguard Worker return "Main" 111*795d594fSAndroid Build Coastguard Worker 112*795d594fSAndroid Build Coastguard Worker def __str__(self): 113*795d594fSAndroid Build Coastguard Worker """ 114*795d594fSAndroid Build Coastguard Worker Print the MainClass smali code. 115*795d594fSAndroid Build Coastguard Worker """ 116*795d594fSAndroid Build Coastguard Worker all_tests = sorted(self.tests) 117*795d594fSAndroid Build Coastguard Worker test_invoke = "" 118*795d594fSAndroid Build Coastguard Worker test_funcs = "" 119*795d594fSAndroid Build Coastguard Worker for t in all_tests: 120*795d594fSAndroid Build Coastguard Worker test_funcs += str(t) 121*795d594fSAndroid Build Coastguard Worker for t in all_tests: 122*795d594fSAndroid Build Coastguard Worker test_invoke += self.TEST_GROUP_INVOKE_TEMPLATE.format(test_name=t.get_name()) 123*795d594fSAndroid Build Coastguard Worker main_func = self.MAIN_FUNCTION_TEMPLATE.format(test_group_invoke=test_invoke) 124*795d594fSAndroid Build Coastguard Worker 125*795d594fSAndroid Build Coastguard Worker return self.MAIN_CLASS_TEMPLATE.format(copyright = get_copyright("smali"), 126*795d594fSAndroid Build Coastguard Worker test_funcs = test_funcs, 127*795d594fSAndroid Build Coastguard Worker main_func = main_func) 128*795d594fSAndroid Build Coastguard Worker 129*795d594fSAndroid Build Coastguard Workerclass Func(mixins.Named, mixins.NameComparableMixin): 130*795d594fSAndroid Build Coastguard Worker """ 131*795d594fSAndroid Build Coastguard Worker A function that tests the functionality of a concrete type. Should only be 132*795d594fSAndroid Build Coastguard Worker constructed by MainClass.add_test. 133*795d594fSAndroid Build Coastguard Worker """ 134*795d594fSAndroid Build Coastguard Worker 135*795d594fSAndroid Build Coastguard Worker TEST_FUNCTION_TEMPLATE = """ 136*795d594fSAndroid Build Coastguard Worker# public static void {fname}() {{ 137*795d594fSAndroid Build Coastguard Worker# {farg} v = null; 138*795d594fSAndroid Build Coastguard Worker# try {{ 139*795d594fSAndroid Build Coastguard Worker# v = new {farg}(); 140*795d594fSAndroid Build Coastguard Worker# }} catch (Throwable e) {{ 141*795d594fSAndroid Build Coastguard Worker# System.out.println("Unexpected error occurred which creating {farg} instance"); 142*795d594fSAndroid Build Coastguard Worker# e.printStackTrace(System.out); 143*795d594fSAndroid Build Coastguard Worker# return; 144*795d594fSAndroid Build Coastguard Worker# }} 145*795d594fSAndroid Build Coastguard Worker# try {{ 146*795d594fSAndroid Build Coastguard Worker# v.callSupers(); 147*795d594fSAndroid Build Coastguard Worker# return; 148*795d594fSAndroid Build Coastguard Worker# }} catch (Throwable e) {{ 149*795d594fSAndroid Build Coastguard Worker# e.printStackTrace(System.out); 150*795d594fSAndroid Build Coastguard Worker# return; 151*795d594fSAndroid Build Coastguard Worker# }} 152*795d594fSAndroid Build Coastguard Worker# }} 153*795d594fSAndroid Build Coastguard Worker.method public static {fname}()V 154*795d594fSAndroid Build Coastguard Worker .locals 7 155*795d594fSAndroid Build Coastguard Worker sget-object v4, Ljava/lang/System;->out:Ljava/io/PrintStream; 156*795d594fSAndroid Build Coastguard Worker 157*795d594fSAndroid Build Coastguard Worker :new_{fname}_try_start 158*795d594fSAndroid Build Coastguard Worker new-instance v0, L{farg}; 159*795d594fSAndroid Build Coastguard Worker invoke-direct {{v0}}, L{farg};-><init>()V 160*795d594fSAndroid Build Coastguard Worker goto :call_{fname}_try_start 161*795d594fSAndroid Build Coastguard Worker :new_{fname}_try_end 162*795d594fSAndroid Build Coastguard Worker .catch Ljava/lang/Throwable; {{:new_{fname}_try_start .. :new_{fname}_try_end}} :new_error_{fname}_start 163*795d594fSAndroid Build Coastguard Worker :new_error_{fname}_start 164*795d594fSAndroid Build Coastguard Worker move-exception v6 165*795d594fSAndroid Build Coastguard Worker const-string v5, "Unexpected error occurred which creating {farg} instance" 166*795d594fSAndroid Build Coastguard Worker invoke-virtual {{v4,v5}}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V 167*795d594fSAndroid Build Coastguard Worker invoke-virtual {{v6,v4}}, Ljava/lang/Throwable;->printStackTrace(Ljava/io/PrintStream;)V 168*795d594fSAndroid Build Coastguard Worker return-void 169*795d594fSAndroid Build Coastguard Worker :call_{fname}_try_start 170*795d594fSAndroid Build Coastguard Worker invoke-virtual {{v0}}, L{farg};->callSupers()V 171*795d594fSAndroid Build Coastguard Worker return-void 172*795d594fSAndroid Build Coastguard Worker :call_{fname}_try_end 173*795d594fSAndroid Build Coastguard Worker .catch Ljava/lang/Throwable; {{:call_{fname}_try_start .. :call_{fname}_try_end}} :error_{fname}_start 174*795d594fSAndroid Build Coastguard Worker :error_{fname}_start 175*795d594fSAndroid Build Coastguard Worker move-exception v6 176*795d594fSAndroid Build Coastguard Worker invoke-virtual {{v6,v4}}, Ljava/lang/Throwable;->printStackTrace(Ljava/io/PrintStream;)V 177*795d594fSAndroid Build Coastguard Worker return-void 178*795d594fSAndroid Build Coastguard Worker.end method 179*795d594fSAndroid Build Coastguard Worker""" 180*795d594fSAndroid Build Coastguard Worker 181*795d594fSAndroid Build Coastguard Worker def __init__(self, farg): 182*795d594fSAndroid Build Coastguard Worker """ 183*795d594fSAndroid Build Coastguard Worker Initialize a test function for the given argument 184*795d594fSAndroid Build Coastguard Worker """ 185*795d594fSAndroid Build Coastguard Worker self.farg = farg 186*795d594fSAndroid Build Coastguard Worker 187*795d594fSAndroid Build Coastguard Worker def get_expected(self): 188*795d594fSAndroid Build Coastguard Worker """ 189*795d594fSAndroid Build Coastguard Worker Get the expected output calling this function. 190*795d594fSAndroid Build Coastguard Worker """ 191*795d594fSAndroid Build Coastguard Worker return "\n".join(self.farg.get_expected()) 192*795d594fSAndroid Build Coastguard Worker 193*795d594fSAndroid Build Coastguard Worker def get_name(self): 194*795d594fSAndroid Build Coastguard Worker """ 195*795d594fSAndroid Build Coastguard Worker Get the name of this function 196*795d594fSAndroid Build Coastguard Worker """ 197*795d594fSAndroid Build Coastguard Worker return "TEST_FUNC_{}".format(self.farg.get_name()) 198*795d594fSAndroid Build Coastguard Worker 199*795d594fSAndroid Build Coastguard Worker def __str__(self): 200*795d594fSAndroid Build Coastguard Worker """ 201*795d594fSAndroid Build Coastguard Worker Print the smali code of this function. 202*795d594fSAndroid Build Coastguard Worker """ 203*795d594fSAndroid Build Coastguard Worker return self.TEST_FUNCTION_TEMPLATE.format(fname = self.get_name(), 204*795d594fSAndroid Build Coastguard Worker farg = self.farg.get_name()) 205*795d594fSAndroid Build Coastguard Worker 206*795d594fSAndroid Build Coastguard Workerclass InterfaceCallResponse(Enum): 207*795d594fSAndroid Build Coastguard Worker """ 208*795d594fSAndroid Build Coastguard Worker An enumeration of all the different types of responses to an interface call we can have 209*795d594fSAndroid Build Coastguard Worker """ 210*795d594fSAndroid Build Coastguard Worker NoError = 0 211*795d594fSAndroid Build Coastguard Worker NoSuchMethodError = 1 212*795d594fSAndroid Build Coastguard Worker AbstractMethodError = 2 213*795d594fSAndroid Build Coastguard Worker IncompatibleClassChangeError = 3 214*795d594fSAndroid Build Coastguard Worker 215*795d594fSAndroid Build Coastguard Worker def get_output_format(self): 216*795d594fSAndroid Build Coastguard Worker if self == InterfaceCallResponse.NoError: 217*795d594fSAndroid Build Coastguard Worker return "No exception thrown for {iface_name}.super.call() on {tree}\n" 218*795d594fSAndroid Build Coastguard Worker elif self == InterfaceCallResponse.AbstractMethodError: 219*795d594fSAndroid Build Coastguard Worker return "AbstractMethodError thrown for {iface_name}.super.call() on {tree}\n" 220*795d594fSAndroid Build Coastguard Worker elif self == InterfaceCallResponse.NoSuchMethodError: 221*795d594fSAndroid Build Coastguard Worker return "NoSuchMethodError thrown for {iface_name}.super.call() on {tree}\n" 222*795d594fSAndroid Build Coastguard Worker else: 223*795d594fSAndroid Build Coastguard Worker return "IncompatibleClassChangeError thrown for {iface_name}.super.call() on {tree}\n" 224*795d594fSAndroid Build Coastguard Worker 225*795d594fSAndroid Build Coastguard Workerclass TestClass(mixins.DumpMixin, mixins.Named, mixins.NameComparableMixin, mixins.SmaliFileMixin): 226*795d594fSAndroid Build Coastguard Worker """ 227*795d594fSAndroid Build Coastguard Worker A class that will be instantiated to test interface super behavior. 228*795d594fSAndroid Build Coastguard Worker """ 229*795d594fSAndroid Build Coastguard Worker 230*795d594fSAndroid Build Coastguard Worker TEST_CLASS_TEMPLATE = """{copyright} 231*795d594fSAndroid Build Coastguard Worker 232*795d594fSAndroid Build Coastguard Worker.class public L{class_name}; 233*795d594fSAndroid Build Coastguard Worker.super Ljava/lang/Object; 234*795d594fSAndroid Build Coastguard Worker{implements_spec} 235*795d594fSAndroid Build Coastguard Worker 236*795d594fSAndroid Build Coastguard Worker# public class {class_name} implements {ifaces} {{ 237*795d594fSAndroid Build Coastguard Worker 238*795d594fSAndroid Build Coastguard Worker.method public constructor <init>()V 239*795d594fSAndroid Build Coastguard Worker .registers 1 240*795d594fSAndroid Build Coastguard Worker invoke-direct {{p0}}, Ljava/lang/Object;-><init>()V 241*795d594fSAndroid Build Coastguard Worker return-void 242*795d594fSAndroid Build Coastguard Worker.end method 243*795d594fSAndroid Build Coastguard Worker 244*795d594fSAndroid Build Coastguard Worker# public void call() {{ 245*795d594fSAndroid Build Coastguard Worker# throw new Error("{class_name}.call(v) should never get called!"); 246*795d594fSAndroid Build Coastguard Worker# }} 247*795d594fSAndroid Build Coastguard Worker.method public call()V 248*795d594fSAndroid Build Coastguard Worker .locals 2 249*795d594fSAndroid Build Coastguard Worker new-instance v0, Ljava/lang/Error; 250*795d594fSAndroid Build Coastguard Worker const-string v1, "{class_name}.call(v) should never get called!" 251*795d594fSAndroid Build Coastguard Worker invoke-direct {{v0, v1}}, Ljava/lang/Error;-><init>(Ljava/lang/String;)V 252*795d594fSAndroid Build Coastguard Worker throw v0 253*795d594fSAndroid Build Coastguard Worker.end method 254*795d594fSAndroid Build Coastguard Worker 255*795d594fSAndroid Build Coastguard Worker# public void callSupers() {{ 256*795d594fSAndroid Build Coastguard Worker.method public callSupers()V 257*795d594fSAndroid Build Coastguard Worker .locals 4 258*795d594fSAndroid Build Coastguard Worker sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream; 259*795d594fSAndroid Build Coastguard Worker 260*795d594fSAndroid Build Coastguard Worker {super_calls} 261*795d594fSAndroid Build Coastguard Worker 262*795d594fSAndroid Build Coastguard Worker return-void 263*795d594fSAndroid Build Coastguard Worker.end method 264*795d594fSAndroid Build Coastguard Worker# }} 265*795d594fSAndroid Build Coastguard Worker 266*795d594fSAndroid Build Coastguard Worker# }} 267*795d594fSAndroid Build Coastguard Worker""" 268*795d594fSAndroid Build Coastguard Worker SUPER_CALL_TEMPLATE = """ 269*795d594fSAndroid Build Coastguard Worker# try {{ 270*795d594fSAndroid Build Coastguard Worker# System.out.println("Calling {iface_name}.super.call() on {tree}"); 271*795d594fSAndroid Build Coastguard Worker# {iface_name}.super.call(); 272*795d594fSAndroid Build Coastguard Worker# System.out.println("No exception thrown for {iface_name}.super.call() on {tree}"); 273*795d594fSAndroid Build Coastguard Worker# }} catch (AbstractMethodError ame) {{ 274*795d594fSAndroid Build Coastguard Worker# System.out.println("AbstractMethodError thrown for {iface_name}.super.call() on {tree}"); 275*795d594fSAndroid Build Coastguard Worker# }} catch (NoSuchMethodError nsme) {{ 276*795d594fSAndroid Build Coastguard Worker# System.out.println("NoSuchMethodError thrown for {iface_name}.super.call() on {tree}"); 277*795d594fSAndroid Build Coastguard Worker# }} catch (IncompatibleClassChangeError icce) {{ 278*795d594fSAndroid Build Coastguard Worker# System.out.println("IncompatibleClassChangeError thrown for {iface_name}.super.call() on {tree}"); 279*795d594fSAndroid Build Coastguard Worker# }} catch (Throwable t) {{ 280*795d594fSAndroid Build Coastguard Worker# System.out.println("Unknown error thrown for {iface_name}.super.call() on {tree}"); 281*795d594fSAndroid Build Coastguard Worker# throw t; 282*795d594fSAndroid Build Coastguard Worker# }} 283*795d594fSAndroid Build Coastguard Worker :call_{class_name}_{iface_name}_try_start 284*795d594fSAndroid Build Coastguard Worker const-string v1, "Calling {iface_name}.super.call() on {tree}" 285*795d594fSAndroid Build Coastguard Worker invoke-virtual {{v0, v1}}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V 286*795d594fSAndroid Build Coastguard Worker invoke-super {{p0}}, L{iface_name};->call()V 287*795d594fSAndroid Build Coastguard Worker const-string v1, "No exception thrown for {iface_name}.super.call() on {tree}" 288*795d594fSAndroid Build Coastguard Worker invoke-virtual {{v0, v1}}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V 289*795d594fSAndroid Build Coastguard Worker goto :call_{class_name}_{iface_name}_end 290*795d594fSAndroid Build Coastguard Worker :call_{class_name}_{iface_name}_try_end 291*795d594fSAndroid Build Coastguard Worker .catch Ljava/lang/AbstractMethodError; {{:call_{class_name}_{iface_name}_try_start .. :call_{class_name}_{iface_name}_try_end}} :AME_{class_name}_{iface_name}_start 292*795d594fSAndroid Build Coastguard Worker .catch Ljava/lang/NoSuchMethodError; {{:call_{class_name}_{iface_name}_try_start .. :call_{class_name}_{iface_name}_try_end}} :NSME_{class_name}_{iface_name}_start 293*795d594fSAndroid Build Coastguard Worker .catch Ljava/lang/IncompatibleClassChangeError; {{:call_{class_name}_{iface_name}_try_start .. :call_{class_name}_{iface_name}_try_end}} :ICCE_{class_name}_{iface_name}_start 294*795d594fSAndroid Build Coastguard Worker .catch Ljava/lang/Throwable; {{:call_{class_name}_{iface_name}_try_start .. :call_{class_name}_{iface_name}_try_end}} :error_{class_name}_{iface_name}_start 295*795d594fSAndroid Build Coastguard Worker :AME_{class_name}_{iface_name}_start 296*795d594fSAndroid Build Coastguard Worker const-string v1, "AbstractMethodError thrown for {iface_name}.super.call() on {tree}" 297*795d594fSAndroid Build Coastguard Worker invoke-virtual {{v0, v1}}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V 298*795d594fSAndroid Build Coastguard Worker goto :call_{class_name}_{iface_name}_end 299*795d594fSAndroid Build Coastguard Worker :NSME_{class_name}_{iface_name}_start 300*795d594fSAndroid Build Coastguard Worker const-string v1, "NoSuchMethodError thrown for {iface_name}.super.call() on {tree}" 301*795d594fSAndroid Build Coastguard Worker invoke-virtual {{v0, v1}}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V 302*795d594fSAndroid Build Coastguard Worker goto :call_{class_name}_{iface_name}_end 303*795d594fSAndroid Build Coastguard Worker :ICCE_{class_name}_{iface_name}_start 304*795d594fSAndroid Build Coastguard Worker const-string v1, "IncompatibleClassChangeError thrown for {iface_name}.super.call() on {tree}" 305*795d594fSAndroid Build Coastguard Worker invoke-virtual {{v0, v1}}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V 306*795d594fSAndroid Build Coastguard Worker goto :call_{class_name}_{iface_name}_end 307*795d594fSAndroid Build Coastguard Worker :error_{class_name}_{iface_name}_start 308*795d594fSAndroid Build Coastguard Worker move-exception v2 309*795d594fSAndroid Build Coastguard Worker const-string v1, "Unknown error thrown for {iface_name}.super.call() on {tree}" 310*795d594fSAndroid Build Coastguard Worker invoke-virtual {{v0, v1}}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V 311*795d594fSAndroid Build Coastguard Worker throw v2 312*795d594fSAndroid Build Coastguard Worker :call_{class_name}_{iface_name}_end 313*795d594fSAndroid Build Coastguard Worker""" 314*795d594fSAndroid Build Coastguard Worker 315*795d594fSAndroid Build Coastguard Worker IMPLEMENTS_TEMPLATE = """ 316*795d594fSAndroid Build Coastguard Worker.implements L{iface_name}; 317*795d594fSAndroid Build Coastguard Worker""" 318*795d594fSAndroid Build Coastguard Worker 319*795d594fSAndroid Build Coastguard Worker OUTPUT_PREFIX = "Calling {iface_name}.super.call() on {tree}\n" 320*795d594fSAndroid Build Coastguard Worker 321*795d594fSAndroid Build Coastguard Worker def __init__(self, ifaces): 322*795d594fSAndroid Build Coastguard Worker """ 323*795d594fSAndroid Build Coastguard Worker Initialize this test class which implements the given interfaces 324*795d594fSAndroid Build Coastguard Worker """ 325*795d594fSAndroid Build Coastguard Worker self.ifaces = ifaces 326*795d594fSAndroid Build Coastguard Worker self.class_name = "CLASS_"+gensym() 327*795d594fSAndroid Build Coastguard Worker 328*795d594fSAndroid Build Coastguard Worker def get_name(self): 329*795d594fSAndroid Build Coastguard Worker """ 330*795d594fSAndroid Build Coastguard Worker Get the name of this class 331*795d594fSAndroid Build Coastguard Worker """ 332*795d594fSAndroid Build Coastguard Worker return self.class_name 333*795d594fSAndroid Build Coastguard Worker 334*795d594fSAndroid Build Coastguard Worker def get_tree(self): 335*795d594fSAndroid Build Coastguard Worker """ 336*795d594fSAndroid Build Coastguard Worker Print out a representation of the type tree of this class 337*795d594fSAndroid Build Coastguard Worker """ 338*795d594fSAndroid Build Coastguard Worker return "[{class_name} {iface_tree}]".format(class_name = self.class_name, 339*795d594fSAndroid Build Coastguard Worker iface_tree = print_tree(self.ifaces)) 340*795d594fSAndroid Build Coastguard Worker 341*795d594fSAndroid Build Coastguard Worker def __iter__(self): 342*795d594fSAndroid Build Coastguard Worker """ 343*795d594fSAndroid Build Coastguard Worker Step through all interfaces implemented transitively by this class 344*795d594fSAndroid Build Coastguard Worker """ 345*795d594fSAndroid Build Coastguard Worker for i in self.ifaces: 346*795d594fSAndroid Build Coastguard Worker yield i 347*795d594fSAndroid Build Coastguard Worker yield from i 348*795d594fSAndroid Build Coastguard Worker 349*795d594fSAndroid Build Coastguard Worker def get_expected(self): 350*795d594fSAndroid Build Coastguard Worker for iface in self.ifaces: 351*795d594fSAndroid Build Coastguard Worker yield self.OUTPUT_PREFIX.format(iface_name = iface.get_name(), tree = self.get_tree()) 352*795d594fSAndroid Build Coastguard Worker yield from iface.get_expected() 353*795d594fSAndroid Build Coastguard Worker yield iface.get_response().get_output_format().format(iface_name = iface.get_name(), 354*795d594fSAndroid Build Coastguard Worker tree = self.get_tree()) 355*795d594fSAndroid Build Coastguard Worker 356*795d594fSAndroid Build Coastguard Worker def __str__(self): 357*795d594fSAndroid Build Coastguard Worker """ 358*795d594fSAndroid Build Coastguard Worker Print the smali code of this class. 359*795d594fSAndroid Build Coastguard Worker """ 360*795d594fSAndroid Build Coastguard Worker s_ifaces = '\n'.join(map(lambda a: self.IMPLEMENTS_TEMPLATE.format(iface_name = a.get_name()), 361*795d594fSAndroid Build Coastguard Worker self.ifaces)) 362*795d594fSAndroid Build Coastguard Worker j_ifaces = ', '.join(map(lambda a: a.get_name(), self.ifaces)) 363*795d594fSAndroid Build Coastguard Worker super_template = self.SUPER_CALL_TEMPLATE 364*795d594fSAndroid Build Coastguard Worker super_calls = "\n".join(super_template.format(iface_name = iface.get_name(), 365*795d594fSAndroid Build Coastguard Worker class_name = self.get_name(), 366*795d594fSAndroid Build Coastguard Worker tree = self.get_tree()) for iface in self.ifaces) 367*795d594fSAndroid Build Coastguard Worker return self.TEST_CLASS_TEMPLATE.format(copyright = get_copyright('smali'), 368*795d594fSAndroid Build Coastguard Worker ifaces = j_ifaces, 369*795d594fSAndroid Build Coastguard Worker implements_spec = s_ifaces, 370*795d594fSAndroid Build Coastguard Worker tree = self.get_tree(), 371*795d594fSAndroid Build Coastguard Worker class_name = self.class_name, 372*795d594fSAndroid Build Coastguard Worker super_calls = super_calls) 373*795d594fSAndroid Build Coastguard Worker 374*795d594fSAndroid Build Coastguard Workerclass InterfaceType(Enum): 375*795d594fSAndroid Build Coastguard Worker """ 376*795d594fSAndroid Build Coastguard Worker An enumeration of all the different types of interfaces we can have. 377*795d594fSAndroid Build Coastguard Worker 378*795d594fSAndroid Build Coastguard Worker default: It has a default method 379*795d594fSAndroid Build Coastguard Worker abstract: It has a method declared but not defined 380*795d594fSAndroid Build Coastguard Worker empty: It does not have the method 381*795d594fSAndroid Build Coastguard Worker """ 382*795d594fSAndroid Build Coastguard Worker default = 0 383*795d594fSAndroid Build Coastguard Worker abstract = 1 384*795d594fSAndroid Build Coastguard Worker empty = 2 385*795d594fSAndroid Build Coastguard Worker 386*795d594fSAndroid Build Coastguard Worker def get_suffix(self): 387*795d594fSAndroid Build Coastguard Worker if self == InterfaceType.default: 388*795d594fSAndroid Build Coastguard Worker return "_DEFAULT" 389*795d594fSAndroid Build Coastguard Worker elif self == InterfaceType.abstract: 390*795d594fSAndroid Build Coastguard Worker return "_ABSTRACT" 391*795d594fSAndroid Build Coastguard Worker elif self == InterfaceType.empty: 392*795d594fSAndroid Build Coastguard Worker return "_EMPTY" 393*795d594fSAndroid Build Coastguard Worker else: 394*795d594fSAndroid Build Coastguard Worker raise TypeError("Interface type had illegal value.") 395*795d594fSAndroid Build Coastguard Worker 396*795d594fSAndroid Build Coastguard Workerclass ConflictInterface: 397*795d594fSAndroid Build Coastguard Worker """ 398*795d594fSAndroid Build Coastguard Worker A singleton representing a conflict of default methods. 399*795d594fSAndroid Build Coastguard Worker """ 400*795d594fSAndroid Build Coastguard Worker 401*795d594fSAndroid Build Coastguard Worker def is_conflict(self): 402*795d594fSAndroid Build Coastguard Worker """ 403*795d594fSAndroid Build Coastguard Worker Returns true if this is a conflict interface and calling the method on this interface will 404*795d594fSAndroid Build Coastguard Worker result in an IncompatibleClassChangeError. 405*795d594fSAndroid Build Coastguard Worker """ 406*795d594fSAndroid Build Coastguard Worker return True 407*795d594fSAndroid Build Coastguard Worker 408*795d594fSAndroid Build Coastguard Worker def is_abstract(self): 409*795d594fSAndroid Build Coastguard Worker """ 410*795d594fSAndroid Build Coastguard Worker Returns true if this is an abstract interface and calling the method on this interface will 411*795d594fSAndroid Build Coastguard Worker result in an AbstractMethodError. 412*795d594fSAndroid Build Coastguard Worker """ 413*795d594fSAndroid Build Coastguard Worker return False 414*795d594fSAndroid Build Coastguard Worker 415*795d594fSAndroid Build Coastguard Worker def is_empty(self): 416*795d594fSAndroid Build Coastguard Worker """ 417*795d594fSAndroid Build Coastguard Worker Returns true if this is an abstract interface and calling the method on this interface will 418*795d594fSAndroid Build Coastguard Worker result in a NoSuchMethodError. 419*795d594fSAndroid Build Coastguard Worker """ 420*795d594fSAndroid Build Coastguard Worker return False 421*795d594fSAndroid Build Coastguard Worker 422*795d594fSAndroid Build Coastguard Worker def is_default(self): 423*795d594fSAndroid Build Coastguard Worker """ 424*795d594fSAndroid Build Coastguard Worker Returns true if this is a default interface and calling the method on this interface will 425*795d594fSAndroid Build Coastguard Worker result in a method actually being called. 426*795d594fSAndroid Build Coastguard Worker """ 427*795d594fSAndroid Build Coastguard Worker return False 428*795d594fSAndroid Build Coastguard Worker 429*795d594fSAndroid Build Coastguard Worker def get_response(self): 430*795d594fSAndroid Build Coastguard Worker return InterfaceCallResponse.IncompatibleClassChangeError 431*795d594fSAndroid Build Coastguard Worker 432*795d594fSAndroid Build Coastguard WorkerCONFLICT_TYPE = ConflictInterface() 433*795d594fSAndroid Build Coastguard Worker 434*795d594fSAndroid Build Coastguard Workerclass TestInterface(mixins.DumpMixin, mixins.Named, mixins.NameComparableMixin, mixins.SmaliFileMixin): 435*795d594fSAndroid Build Coastguard Worker """ 436*795d594fSAndroid Build Coastguard Worker An interface that will be used to test default method resolution order. 437*795d594fSAndroid Build Coastguard Worker """ 438*795d594fSAndroid Build Coastguard Worker 439*795d594fSAndroid Build Coastguard Worker TEST_INTERFACE_TEMPLATE = """{copyright} 440*795d594fSAndroid Build Coastguard Worker.class public abstract interface L{class_name}; 441*795d594fSAndroid Build Coastguard Worker.super Ljava/lang/Object; 442*795d594fSAndroid Build Coastguard Worker{implements_spec} 443*795d594fSAndroid Build Coastguard Worker 444*795d594fSAndroid Build Coastguard Worker# public interface {class_name} {extends} {ifaces} {{ 445*795d594fSAndroid Build Coastguard Worker 446*795d594fSAndroid Build Coastguard Worker{func} 447*795d594fSAndroid Build Coastguard Worker 448*795d594fSAndroid Build Coastguard Worker# }} 449*795d594fSAndroid Build Coastguard Worker""" 450*795d594fSAndroid Build Coastguard Worker 451*795d594fSAndroid Build Coastguard Worker SUPER_CALL_TEMPLATE = TestClass.SUPER_CALL_TEMPLATE 452*795d594fSAndroid Build Coastguard Worker OUTPUT_PREFIX = TestClass.OUTPUT_PREFIX 453*795d594fSAndroid Build Coastguard Worker 454*795d594fSAndroid Build Coastguard Worker DEFAULT_FUNC_TEMPLATE = """ 455*795d594fSAndroid Build Coastguard Worker# public default void call() {{ 456*795d594fSAndroid Build Coastguard Worker.method public call()V 457*795d594fSAndroid Build Coastguard Worker .locals 4 458*795d594fSAndroid Build Coastguard Worker sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream; 459*795d594fSAndroid Build Coastguard Worker 460*795d594fSAndroid Build Coastguard Worker {super_calls} 461*795d594fSAndroid Build Coastguard Worker 462*795d594fSAndroid Build Coastguard Worker return-void 463*795d594fSAndroid Build Coastguard Worker.end method 464*795d594fSAndroid Build Coastguard Worker# }} 465*795d594fSAndroid Build Coastguard Worker""" 466*795d594fSAndroid Build Coastguard Worker 467*795d594fSAndroid Build Coastguard Worker ABSTRACT_FUNC_TEMPLATE = """ 468*795d594fSAndroid Build Coastguard Worker# public void call(); 469*795d594fSAndroid Build Coastguard Worker.method public abstract call()V 470*795d594fSAndroid Build Coastguard Worker.end method 471*795d594fSAndroid Build Coastguard Worker""" 472*795d594fSAndroid Build Coastguard Worker 473*795d594fSAndroid Build Coastguard Worker EMPTY_FUNC_TEMPLATE = """""" 474*795d594fSAndroid Build Coastguard Worker 475*795d594fSAndroid Build Coastguard Worker IMPLEMENTS_TEMPLATE = """ 476*795d594fSAndroid Build Coastguard Worker.implements L{iface_name}; 477*795d594fSAndroid Build Coastguard Worker""" 478*795d594fSAndroid Build Coastguard Worker 479*795d594fSAndroid Build Coastguard Worker def __init__(self, ifaces, iface_type, full_name = None): 480*795d594fSAndroid Build Coastguard Worker """ 481*795d594fSAndroid Build Coastguard Worker Initialize interface with the given super-interfaces 482*795d594fSAndroid Build Coastguard Worker """ 483*795d594fSAndroid Build Coastguard Worker self.ifaces = sorted(ifaces) 484*795d594fSAndroid Build Coastguard Worker self.iface_type = iface_type 485*795d594fSAndroid Build Coastguard Worker if full_name is None: 486*795d594fSAndroid Build Coastguard Worker end = self.iface_type.get_suffix() 487*795d594fSAndroid Build Coastguard Worker self.class_name = "INTERFACE_"+gensym()+end 488*795d594fSAndroid Build Coastguard Worker else: 489*795d594fSAndroid Build Coastguard Worker self.class_name = full_name 490*795d594fSAndroid Build Coastguard Worker 491*795d594fSAndroid Build Coastguard Worker def get_specific_version(self, v): 492*795d594fSAndroid Build Coastguard Worker """ 493*795d594fSAndroid Build Coastguard Worker Returns a copy of this interface of the given type for use in partial compilation. 494*795d594fSAndroid Build Coastguard Worker """ 495*795d594fSAndroid Build Coastguard Worker return TestInterface(self.ifaces, v, full_name = self.class_name) 496*795d594fSAndroid Build Coastguard Worker 497*795d594fSAndroid Build Coastguard Worker def get_super_types(self): 498*795d594fSAndroid Build Coastguard Worker """ 499*795d594fSAndroid Build Coastguard Worker Returns a set of all the supertypes of this interface 500*795d594fSAndroid Build Coastguard Worker """ 501*795d594fSAndroid Build Coastguard Worker return set(i2 for i2 in self) 502*795d594fSAndroid Build Coastguard Worker 503*795d594fSAndroid Build Coastguard Worker def is_conflict(self): 504*795d594fSAndroid Build Coastguard Worker """ 505*795d594fSAndroid Build Coastguard Worker Returns true if this is a conflict interface and calling the method on this interface will 506*795d594fSAndroid Build Coastguard Worker result in an IncompatibleClassChangeError. 507*795d594fSAndroid Build Coastguard Worker """ 508*795d594fSAndroid Build Coastguard Worker return False 509*795d594fSAndroid Build Coastguard Worker 510*795d594fSAndroid Build Coastguard Worker def is_abstract(self): 511*795d594fSAndroid Build Coastguard Worker """ 512*795d594fSAndroid Build Coastguard Worker Returns true if this is an abstract interface and calling the method on this interface will 513*795d594fSAndroid Build Coastguard Worker result in an AbstractMethodError. 514*795d594fSAndroid Build Coastguard Worker """ 515*795d594fSAndroid Build Coastguard Worker return self.iface_type == InterfaceType.abstract 516*795d594fSAndroid Build Coastguard Worker 517*795d594fSAndroid Build Coastguard Worker def is_empty(self): 518*795d594fSAndroid Build Coastguard Worker """ 519*795d594fSAndroid Build Coastguard Worker Returns true if this is an abstract interface and calling the method on this interface will 520*795d594fSAndroid Build Coastguard Worker result in a NoSuchMethodError. 521*795d594fSAndroid Build Coastguard Worker """ 522*795d594fSAndroid Build Coastguard Worker return self.iface_type == InterfaceType.empty 523*795d594fSAndroid Build Coastguard Worker 524*795d594fSAndroid Build Coastguard Worker def is_default(self): 525*795d594fSAndroid Build Coastguard Worker """ 526*795d594fSAndroid Build Coastguard Worker Returns true if this is a default interface and calling the method on this interface will 527*795d594fSAndroid Build Coastguard Worker result in a method actually being called. 528*795d594fSAndroid Build Coastguard Worker """ 529*795d594fSAndroid Build Coastguard Worker return self.iface_type == InterfaceType.default 530*795d594fSAndroid Build Coastguard Worker 531*795d594fSAndroid Build Coastguard Worker def get_expected(self): 532*795d594fSAndroid Build Coastguard Worker response = self.get_response() 533*795d594fSAndroid Build Coastguard Worker if response == InterfaceCallResponse.NoError: 534*795d594fSAndroid Build Coastguard Worker for iface in self.ifaces: 535*795d594fSAndroid Build Coastguard Worker if self.is_default(): 536*795d594fSAndroid Build Coastguard Worker yield self.OUTPUT_PREFIX.format(iface_name = iface.get_name(), tree = self.get_tree()) 537*795d594fSAndroid Build Coastguard Worker yield from iface.get_expected() 538*795d594fSAndroid Build Coastguard Worker if self.is_default(): 539*795d594fSAndroid Build Coastguard Worker yield iface.get_response().get_output_format().format(iface_name = iface.get_name(), 540*795d594fSAndroid Build Coastguard Worker tree = self.get_tree()) 541*795d594fSAndroid Build Coastguard Worker 542*795d594fSAndroid Build Coastguard Worker def get_response(self): 543*795d594fSAndroid Build Coastguard Worker if self.is_default(): 544*795d594fSAndroid Build Coastguard Worker return InterfaceCallResponse.NoError 545*795d594fSAndroid Build Coastguard Worker elif self.is_abstract(): 546*795d594fSAndroid Build Coastguard Worker return InterfaceCallResponse.AbstractMethodError 547*795d594fSAndroid Build Coastguard Worker elif len(self.ifaces) == 0: 548*795d594fSAndroid Build Coastguard Worker return InterfaceCallResponse.NoSuchMethodError 549*795d594fSAndroid Build Coastguard Worker else: 550*795d594fSAndroid Build Coastguard Worker return self.get_called().get_response() 551*795d594fSAndroid Build Coastguard Worker 552*795d594fSAndroid Build Coastguard Worker def get_called(self): 553*795d594fSAndroid Build Coastguard Worker """ 554*795d594fSAndroid Build Coastguard Worker Returns the interface that will be called when the method on this class is invoked or 555*795d594fSAndroid Build Coastguard Worker CONFLICT_TYPE if there is no interface that will be called. 556*795d594fSAndroid Build Coastguard Worker """ 557*795d594fSAndroid Build Coastguard Worker if not self.is_empty() or len(self.ifaces) == 0: 558*795d594fSAndroid Build Coastguard Worker return self 559*795d594fSAndroid Build Coastguard Worker else: 560*795d594fSAndroid Build Coastguard Worker best = self 561*795d594fSAndroid Build Coastguard Worker for super_iface in self.ifaces: 562*795d594fSAndroid Build Coastguard Worker super_best = super_iface.get_called() 563*795d594fSAndroid Build Coastguard Worker if super_best.is_conflict(): 564*795d594fSAndroid Build Coastguard Worker return CONFLICT_TYPE 565*795d594fSAndroid Build Coastguard Worker elif best.is_default(): 566*795d594fSAndroid Build Coastguard Worker if super_best.is_default(): 567*795d594fSAndroid Build Coastguard Worker return CONFLICT_TYPE 568*795d594fSAndroid Build Coastguard Worker elif best.is_abstract(): 569*795d594fSAndroid Build Coastguard Worker if super_best.is_default(): 570*795d594fSAndroid Build Coastguard Worker best = super_best 571*795d594fSAndroid Build Coastguard Worker else: 572*795d594fSAndroid Build Coastguard Worker assert best.is_empty() 573*795d594fSAndroid Build Coastguard Worker best = super_best 574*795d594fSAndroid Build Coastguard Worker return best 575*795d594fSAndroid Build Coastguard Worker 576*795d594fSAndroid Build Coastguard Worker def get_name(self): 577*795d594fSAndroid Build Coastguard Worker """ 578*795d594fSAndroid Build Coastguard Worker Get the name of this class 579*795d594fSAndroid Build Coastguard Worker """ 580*795d594fSAndroid Build Coastguard Worker return self.class_name 581*795d594fSAndroid Build Coastguard Worker 582*795d594fSAndroid Build Coastguard Worker def get_tree(self): 583*795d594fSAndroid Build Coastguard Worker """ 584*795d594fSAndroid Build Coastguard Worker Print out a representation of the type tree of this class 585*795d594fSAndroid Build Coastguard Worker """ 586*795d594fSAndroid Build Coastguard Worker return "[{class_name} {iftree}]".format(class_name = self.get_name(), 587*795d594fSAndroid Build Coastguard Worker iftree = print_tree(self.ifaces)) 588*795d594fSAndroid Build Coastguard Worker 589*795d594fSAndroid Build Coastguard Worker def __iter__(self): 590*795d594fSAndroid Build Coastguard Worker """ 591*795d594fSAndroid Build Coastguard Worker Performs depth-first traversal of the interface tree this interface is the 592*795d594fSAndroid Build Coastguard Worker root of. Does not filter out repeats. 593*795d594fSAndroid Build Coastguard Worker """ 594*795d594fSAndroid Build Coastguard Worker for i in self.ifaces: 595*795d594fSAndroid Build Coastguard Worker yield i 596*795d594fSAndroid Build Coastguard Worker yield from i 597*795d594fSAndroid Build Coastguard Worker 598*795d594fSAndroid Build Coastguard Worker def __str__(self): 599*795d594fSAndroid Build Coastguard Worker """ 600*795d594fSAndroid Build Coastguard Worker Print the smali code of this interface. 601*795d594fSAndroid Build Coastguard Worker """ 602*795d594fSAndroid Build Coastguard Worker s_ifaces = '\n'.join(map(lambda a: self.IMPLEMENTS_TEMPLATE.format(iface_name = a.get_name()), 603*795d594fSAndroid Build Coastguard Worker self.ifaces)) 604*795d594fSAndroid Build Coastguard Worker j_ifaces = ', '.join(map(lambda a: a.get_name(), self.ifaces)) 605*795d594fSAndroid Build Coastguard Worker if self.is_default(): 606*795d594fSAndroid Build Coastguard Worker super_template = self.SUPER_CALL_TEMPLATE 607*795d594fSAndroid Build Coastguard Worker super_calls ="\n".join(super_template.format(iface_name = iface.get_name(), 608*795d594fSAndroid Build Coastguard Worker class_name = self.get_name(), 609*795d594fSAndroid Build Coastguard Worker tree = self.get_tree()) for iface in self.ifaces) 610*795d594fSAndroid Build Coastguard Worker funcs = self.DEFAULT_FUNC_TEMPLATE.format(super_calls = super_calls) 611*795d594fSAndroid Build Coastguard Worker elif self.is_abstract(): 612*795d594fSAndroid Build Coastguard Worker funcs = self.ABSTRACT_FUNC_TEMPLATE.format() 613*795d594fSAndroid Build Coastguard Worker else: 614*795d594fSAndroid Build Coastguard Worker funcs = "" 615*795d594fSAndroid Build Coastguard Worker return self.TEST_INTERFACE_TEMPLATE.format(copyright = get_copyright('smali'), 616*795d594fSAndroid Build Coastguard Worker implements_spec = s_ifaces, 617*795d594fSAndroid Build Coastguard Worker extends = "extends" if len(self.ifaces) else "", 618*795d594fSAndroid Build Coastguard Worker ifaces = j_ifaces, 619*795d594fSAndroid Build Coastguard Worker func = funcs, 620*795d594fSAndroid Build Coastguard Worker tree = self.get_tree(), 621*795d594fSAndroid Build Coastguard Worker class_name = self.class_name) 622*795d594fSAndroid Build Coastguard Worker 623*795d594fSAndroid Build Coastguard Workerdef print_tree(ifaces): 624*795d594fSAndroid Build Coastguard Worker """ 625*795d594fSAndroid Build Coastguard Worker Prints a list of iface trees 626*795d594fSAndroid Build Coastguard Worker """ 627*795d594fSAndroid Build Coastguard Worker return " ".join(i.get_tree() for i in ifaces) 628*795d594fSAndroid Build Coastguard Worker 629*795d594fSAndroid Build Coastguard Worker# The deduplicated output of subtree_sizes for each size up to 630*795d594fSAndroid Build Coastguard Worker# MAX_LEAF_IFACE_PER_OBJECT. 631*795d594fSAndroid Build Coastguard WorkerSUBTREES = [set(tuple(sorted(l)) for l in subtree_sizes(i)) 632*795d594fSAndroid Build Coastguard Worker for i in range(MAX_IFACE_DEPTH + 1)] 633*795d594fSAndroid Build Coastguard Worker 634*795d594fSAndroid Build Coastguard Workerdef create_test_classes(): 635*795d594fSAndroid Build Coastguard Worker """ 636*795d594fSAndroid Build Coastguard Worker Yield all the test classes with the different interface trees 637*795d594fSAndroid Build Coastguard Worker """ 638*795d594fSAndroid Build Coastguard Worker for num in range(1, MAX_IFACE_DEPTH + 1): 639*795d594fSAndroid Build Coastguard Worker for split in SUBTREES[num]: 640*795d594fSAndroid Build Coastguard Worker ifaces = [] 641*795d594fSAndroid Build Coastguard Worker for sub in split: 642*795d594fSAndroid Build Coastguard Worker ifaces.append(list(create_interface_trees(sub))) 643*795d594fSAndroid Build Coastguard Worker for supers in itertools.product(*ifaces): 644*795d594fSAndroid Build Coastguard Worker yield TestClass(supers) 645*795d594fSAndroid Build Coastguard Worker 646*795d594fSAndroid Build Coastguard Workerdef create_interface_trees(num): 647*795d594fSAndroid Build Coastguard Worker """ 648*795d594fSAndroid Build Coastguard Worker Yield all the interface trees up to 'num' depth. 649*795d594fSAndroid Build Coastguard Worker """ 650*795d594fSAndroid Build Coastguard Worker if num == 0: 651*795d594fSAndroid Build Coastguard Worker for iftype in InterfaceType: 652*795d594fSAndroid Build Coastguard Worker yield TestInterface(tuple(), iftype) 653*795d594fSAndroid Build Coastguard Worker return 654*795d594fSAndroid Build Coastguard Worker for split in SUBTREES[num]: 655*795d594fSAndroid Build Coastguard Worker ifaces = [] 656*795d594fSAndroid Build Coastguard Worker for sub in split: 657*795d594fSAndroid Build Coastguard Worker ifaces.append(list(create_interface_trees(sub))) 658*795d594fSAndroid Build Coastguard Worker for supers in itertools.product(*ifaces): 659*795d594fSAndroid Build Coastguard Worker for iftype in InterfaceType: 660*795d594fSAndroid Build Coastguard Worker yield TestInterface(supers, iftype) 661*795d594fSAndroid Build Coastguard Worker 662*795d594fSAndroid Build Coastguard Workerdef create_all_test_files(): 663*795d594fSAndroid Build Coastguard Worker """ 664*795d594fSAndroid Build Coastguard Worker Creates all the objects representing the files in this test. They just need to 665*795d594fSAndroid Build Coastguard Worker be dumped. 666*795d594fSAndroid Build Coastguard Worker """ 667*795d594fSAndroid Build Coastguard Worker mc = MainClass() 668*795d594fSAndroid Build Coastguard Worker classes = {mc} 669*795d594fSAndroid Build Coastguard Worker for clazz in create_test_classes(): 670*795d594fSAndroid Build Coastguard Worker classes.add(clazz) 671*795d594fSAndroid Build Coastguard Worker for i in clazz: 672*795d594fSAndroid Build Coastguard Worker classes.add(i) 673*795d594fSAndroid Build Coastguard Worker mc.add_test(clazz) 674*795d594fSAndroid Build Coastguard Worker return mc, classes 675*795d594fSAndroid Build Coastguard Worker 676*795d594fSAndroid Build Coastguard Workerdef main(argv): 677*795d594fSAndroid Build Coastguard Worker smali_dir = Path(argv[1]) 678*795d594fSAndroid Build Coastguard Worker if not smali_dir.exists() or not smali_dir.is_dir(): 679*795d594fSAndroid Build Coastguard Worker print("{} is not a valid smali dir".format(smali_dir), file=sys.stderr) 680*795d594fSAndroid Build Coastguard Worker sys.exit(1) 681*795d594fSAndroid Build Coastguard Worker expected_txt = Path(argv[2]) 682*795d594fSAndroid Build Coastguard Worker mainclass, all_files = create_all_test_files() 683*795d594fSAndroid Build Coastguard Worker with expected_txt.open('w') as out: 684*795d594fSAndroid Build Coastguard Worker print(mainclass.get_expected(), file=out) 685*795d594fSAndroid Build Coastguard Worker for f in all_files: 686*795d594fSAndroid Build Coastguard Worker f.dump(smali_dir) 687*795d594fSAndroid Build Coastguard Worker 688*795d594fSAndroid Build Coastguard Workerif __name__ == '__main__': 689*795d594fSAndroid Build Coastguard Worker main(sys.argv) 690