Ejemplo n.º 1
0
 def tuple(self):
     if self._tuple is None:
         clsname = self.get_classname()
         if clsname == 'com.android.commands.monkey.ape.naming.EmptyNamer$1':
             self._tuple = tuple()
         elif clsname == 'com.android.commands.monkey.ape.naming.ActionPatchNamer$ActionPatchName':
             self._tuple = ('ActionPatch', Name.init(self.baseName),
                            self.patch, enumToString(self.scrollType))
         elif clsname == 'com.android.commands.monkey.ape.naming.TypeNamer$TypeName':
             if self.resourceId is None or len(self.resourceId) == 0:
                 self._tuple = ('Type', self.klass)
             else:
                 self._tuple = ('Type', self.klass, self.resourceId)
         elif clsname == 'com.android.commands.monkey.ape.naming.CompoundNamer$CompoundName':
             self._tuple = ('Compound',
                            tuple(classReadJavaList(self.names, Name)))
         elif clsname == 'com.android.commands.monkey.ape.naming.IndexNamer$IndexName':
             self._tuple = ('Index', self.index)
         elif clsname == 'com.android.commands.monkey.ape.naming.ParentNamer$ParentName':
             self._tuple = ('Parent', Name.init(self.parentName),
                            Name.init(self.localName))
         elif clsname == 'com.android.commands.monkey.ape.naming.TextNamer$TextName':
             if self.contentDesc is None or self.contentDesc == "":
                 self._tuple = ('Text', self.text)
             else:
                 self._tuple = ('Text', self.text, self.contentDesc)
         elif clsname == 'com.android.commands.monkey.ape.naming.AncestorNamer$AncestorName':
             self._tuple = ('Ancestor',
                            tuple(classReadJavaList(self.names, Name)))
         else:
             raise NotImplementedError(clsname)
     return self._tuple
Ejemplo n.º 2
0
 def __eq__(self, other):
     other = StateKey.init(other)
     if other is None:
         return False
     if self.activity != other.activity:
         return False
     if namingModule.Naming.init(self.naming) != namingModule.Naming.init(
             other.naming):
         return False
     return classReadJavaList(self.widgets,
                              namingModule.Name) == classReadJavaList(
                                  other.widgets, namingModule.Name)
Ejemplo n.º 3
0
 def select_Document(self, document):
     assert isinstance(document, etree._Element)
     ret = dict()
     for namelet in classReadJavaList(self.namelets, Namelet):
         nodes = namelet.filter_Object(document)
         for node in nodes:
             try:
                 ret[node].append(namelet)
             except KeyError:
                 ret[node] = [namelet]
     return ret
Ejemplo n.º 4
0
 def select_LNamelet(self, namelets):
     namelets = classReadJavaList(namelets, Namelet)
     if len(namelets) == 1:
         return namelets[0]
     namelets.sort()
     for i in range(len(namelets)):
         namelet = Namelet.init(namelets[i].parent)
         while namelet is not None:
             if namelet < namelets[0]:
                 break
             namelet = Namelet.init(namelet.parent)
         if namelet is None:
             return namelets[i]
     return None
Ejemplo n.º 5
0
 def naming(self, node):
     node = treeModule.GUITreeNode.init(node)
     clsname = self.get_classname()
     if clsname == 'com.android.commands.monkey.ape.naming.EmptyNamer':
         return Name(tuple())
     elif clsname == 'com.android.commands.monkey.ape.naming.ActionPatchNamer':
         interactiveProperties = [
             "isEnabled", "isClickable", "isScrollable", "isLongClickable",
             "isScrollable"
         ]
         patch = 0
         for prop in interactiveProperties:
             patch <<= 1
             if getattr(node, prop)():
                 patch |= 1
         scrollType = node.getScrollType()
         return Name(
             ('ActionPatch', Namer.init(self.baseNamer).naming(node), patch,
              enumToString(scrollType)))
     elif clsname == 'com.android.commands.monkey.ape.naming.TypeNamer':
         return Name(('Type', node.getClassName(), node.getResourceID()))
     elif clsname == 'com.android.commands.monkey.ape.naming.CompoundNamer':
         names = []
         for namer in classReadJavaList(self.namers, Namer):
             names.append(namer.naming(node))
         return Name(('Compound', names))
     elif clsname == 'com.android.commands.monkey.ape.naming.IndexNamer':
         return Name(('Index', node.getIndex()))
     elif clsname == 'com.android.commands.monkey.ape.naming.ParentNamer':
         parentNode = node.getParent()
         localName = Namer.init(self.namer).naming(node)
         if parentNode is not None:
             parentName = parentNode.getTempXPathName()
             if parentName is None:
                 parentName = parentNode.getXPathName()
             assert parentName is not None, "Parent name should not be null"
             return Name(('Parent', parentName, localName))
         return Name(('Parent', tuple(), localName))
     elif clsname == 'com.android.commands.monkey.ape.naming.TextNamer':
         return Name(('Text', node.getText(), node.getContentDesc()))
     elif clsname == 'com.android.commands.monkey.ape.naming.AncestorNamer':
         parentNode = node.getParent()
         namerTypes = self.getNamerTypes()
         localNamer = NamerFactory.getLocalNamer(self)
         if parentNode is not None:
             useParent = 'PARENT' in namerTypes
             names = [localNamer.naming(node)]
             if useParent:
                 while parentNode is not None:
                     tempName = parentNode.getTempXPathName()
                     if tempName is None:
                         tempName = parentNode.getXPathName()
                     assert tempName is not None, "Temp name of a parent node should be set."
                     tempNamer = tempName.getNamer()
                     parentNamer = NamerFactory.getLocalNamer(tempNamer)
                     names.append(parentNamer.naming(parentNode))
                     parentNode = parentNode.getParent()
             else:
                 while parentNode is not None:
                     names.append(localNamer.naming(parentNode))
                     parentNode = parentNode.getParent()
             return Name(('Ancestor', reversed(names)))
         return Name(('Ancestor', localNamer.naming(node)))
     else:
         raise NotImplementedError(clsname)
Ejemplo n.º 6
0
def makeUnit(expname, exptype, directory, printSubsequence, detail, allcrash):
    apelog_fname = os.path.join(directory, 'ape_stdout_stderr.txt')
    logcat_fname = os.path.join(directory, 'logcat.txt')
    mtdata_directories = glob.glob(os.path.join(directory, 'mt_data', '*'))

    assert os.path.isfile(apelog_fname), apelog_fname
    assert os.path.isfile(logcat_fname), logcat_fname

    modelobjects = glob.glob(os.path.join(directory, 'ape', '*', 'sataModel.obj'))
    if len(modelobjects) < 1:
        print("There is no model object in {}".format(directory))
        with open(apelog_fname, 'rt') as f:
            num_lines = int(run_cmd('wc -l {}'.format(apelog_fname)).split()[0])

            for i, line in enumerate(f):
                if i >= num_lines - 10:
                    print(' {}: {}'.format(i, line.rstrip()))

        return None

    assert len(modelobjects) == 1, modelobjects
    modelobject_fname = modelobjects[0]

    warningCounter = Counter()
    waitCounter = Counter()
    crashLongMessagesCounter = Counter()
    time_elapsed = -1
    strategy_cnt = {}
    first_timestamp = -1
    strategy_changed_timestamp = -1
    first_met_timestamp = -1
    timestamp = -1
    with open(apelog_fname, 'rt') as f:
        it = iter(f)
        for line in it:
            line = line.rstrip()
            if line.startswith('[APE_MT_WARNING]'):
                warningCounter.append(line)

            gp = re.match(r'\[APE\] ([a-zA-Z]+) Strategy: buffer size \(([0-9]+)\)', line)
            if gp:
                nums = [re.match(r'\[APE\] *([0-9]+)  (.*)', next(it).rstrip()) for strategy in strategies[gp.group(1)]]
                strategy_cnt = dict(map(lambda gp:(gp.group(2), int(gp.group(1))), nums))
                continue

            elif line.startswith('## Network stats: elapsed time='):
                gp = re.match(r'## Network stats: elapsed time=([0-9]+)ms \(([0-9]+)ms mobile, ([0-9]+)ms wifi, ([0-9]+)ms not connected\)', line)
                assert gp, line
                total, mob, wifi, total2 = gp.groups()
                assert total == total2 and mob == wifi, line
                time_elapsed = int(total)

            elif line == "[APE] *** INFO *** We are still waiting for activity loading. Let's wait for another 100ms...":
                waitCounter.append(line)

            elif line.startswith("[APE] // Long Msg: "):
                crashLongMessagesCounter.append(line[len("[APE] // Long Msg: "):])

                if allcrash:
                    print(line)
                    while line.startswith("[APE] //"):
                        line = next(it).rstrip()
                        print(line)
                    assert line.startswith('[APE] *** INFO *** Appending crash [')
                    current_timestamp = int(line.split('@')[1])
                    print('*** Time elapsed {}'.format(current_timestamp - first_timestamp))
                    print()

            elif line == "[APE] *** INFO *** Half time/counter consumed":
                strategy_changed_timestamp = timestamp

            elif line.startswith("[MonkeyServer] idle fetch"):
                gp = re.match(r'\[MonkeyServer\] idle fetch ([-]{0,1}[0-9]+)', line)
                assert gp, line
                timestamp = int(gp.group(1))
                if first_timestamp == -1 and timestamp not in [0, -1]:
                    first_timestamp = timestamp
            elif line == '[APE_MT] Lastlast transition met target':
                if first_met_timestamp == -1:
                    first_met_timestamp = timestamp
            elif 'MET TARGET' in line: # for old version
                if first_met_timestamp == -1:
                    first_met_timestamp = timestamp


    if time_elapsed == -1:
        print("Time elapsed not found")
        with open(apelog_fname, 'rt') as f:
            num_lines = int(run_cmd('wc -l {}'.format(apelog_fname)).split()[0])

            for i, line in enumerate(f):
                if i >= num_lines - 10:
                    print(' {}: {}'.format(i, line.rstrip()))
        return None
    targetMethods = []
    lazy_counter = Counter()
    registered_counter = Counter()
    registered_lazily_counter = Counter()
    with open(logcat_fname, 'rt') as f:
        for line in f:
            if 'MiniTrace' not in line:
                continue

            line = line.rstrip()
            line = line[line.index('MiniTrace'):]

            gp = re.match(r'MiniTrace: TargetMethod (.*):(.*)\[(.*)\] ([a-z ]+)', line)
            if gp:
                clsname, mtdname, signature, status = gp.groups()
                if status == 'lazy':
                    clsname = 'L{};'.format(clsname)
                    if (clsname, mtdname, signature) not in targetMethods:
                        targetMethods.append((clsname, mtdname, signature))
                    lazy_counter.append((clsname, mtdname, signature))
                elif status == 'registered':
                    clsname = 'L{};'.format(clsname)
                    if (clsname, mtdname, signature) not in targetMethods:
                        targetMethods.append((clsname, mtdname, signature))
                    lazy_counter.append((clsname, mtdname, signature))
                else:
                    assert status == 'registered lazily', status
                    assert clsname[0] == 'L' and clsname[-1] == ';', clsname
                    registered_lazily_counter.append((clsname, mtdname, signature))
    method_register_status = {}
    for method in targetMethods:
        if registered_counter[method] == 0:
            data =  '{}/{}'.format(registered_lazily_counter[method], lazy_counter[method])
        else:
            assert registered_lazily_counter[method] == 0, registered_lazily_counter[method]
            assert lazy_counter[method] == 0, lazy_counter[method]
            data = '{}/{}'.format(registered_counter[method], registered_counter[method])
        method_register_status[method] = data

    # self.exptype = exptype
    # self.expname = expname
    # self.directory = directory

    # marked call
    class MtdCounter(object):
        def __init__(self):
            self.cnt = 0
            self.main_tid = -1
            self.main_cnt = 0
        def setTid(self, main_tid):
            self.main_tid = main_tid
        def inc(self, value):
            self.main_cnt += 1
        def tidInc(self, tid, value):
            assert self.main_tid != -1
            if tid == self.main_tid:
                self.main_cnt += 1
            self.cnt += 1

    class ExecutionData:
        def __init__(self, string):
            assert all(c in ['0', '1'] for c in string), string
            self.string = string

        def union(self, new_string):
            assert len(self.string) == len(new_string)
            new_string = ''.join(['1' if a == '1' or b == '1' else '0' \
                for a, b in zip(self.string, new_string)])
            self.string = new_string

        def __or__(self, other):
            assert len(self.string) == len(other.string)
            new_string = ''.join(['1' if a == '1' or b == '1' else '0' \
                for a, b in zip(self.string, other.string)])
            return ExecutionData(new_string)

        def __repr__(self):
            return '<ExecutionData string={}>'.format(self.string)

        def ratio(self):
            return self.string.count('1') / len(self.string)

    sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '../crashgen'))
    from consumer import parse_data, Threads, Methods

    execution_data = {}
    mtdCounter = MtdCounter()
    for mtdata_directory in mtdata_directories:
        binary_fname = os.path.join(mtdata_directory, 'data_0.bin')
        thread_fname = os.path.join(mtdata_directory, 'info_t.log')
        method_fname = os.path.join(mtdata_directory, 'info_m.log')

        if any(not os.path.isfile(fname) for fname in [binary_fname, thread_fname, method_fname]):
            continue
        mtdCounter.setTid(Threads(thread_fname).get_main_tid())
        parse_data(binary_fname, {10: mtdCounter.inc, 11: mtdCounter.inc, 12: mtdCounter.inc,
            13: mtdCounter.tidInc, 14: mtdCounter.tidInc, 15: mtdCounter.tidInc}, verbose=False)

        methods = Methods(method_fname)
        execf = os.path.join(mtdata_directory, 'exec.txt')
        with open(execf, 'rt') as f:
            for line in f:
                line = line.rstrip()
                if line.startswith('\0'):
                    line = line[1:]
                if line == '':
                    break
                if not line.startswith('Timestamp'):
                    mtdptr, execdata = line.split()
                    mtdptr = int(mtdptr, 16)
                    clsname, mtdname, signature, defclass = methods[mtdptr]
                    try:
                        execution_data[(clsname, mtdname, signature)].union(execdata)
                    except KeyError:
                        execution_data[(clsname, mtdname, signature)] = ExecutionData(execdata)


    string = '{},{}'.format(expname, exptype)
    string += ',{},{},{},'.format(time_elapsed, warningCounter.total(), waitCounter.total())

    assert all(method in targetMethods for method in execution_data)
    method_data = []
    for method in targetMethods:
        if method not in execution_data:
            data = 0.0
        else:
            data = execution_data[method].ratio()
        method_data.append('%s:%.3f' % (method_register_status[method], data))
    string += '/'.join(method_data)
    string += ',{},{}'.format(strategy_cnt.get('TARGET', 0) + strategy_cnt.get('MCMC', 0), sum(strategy_cnt.values()))
    string += ',{},{}'.format(mtdCounter.main_cnt, mtdCounter.cnt)

    # strategy changed timestamp
    if strategy_changed_timestamp == -1:
        string += ',NaN'
    else:
        string += ',{}'.format(strategy_changed_timestamp - first_timestamp)
    # first met transition timestmap
    if first_met_timestamp == -1:
        string += ',NaN'
    else:
        string += ',{}'.format(first_met_timestamp - first_timestamp)

    warningCounter.pretty()
    if not detail:
        string += ',{}'.format(crashLongMessagesCounter.total())
        string += ',{}'.format('/'.join(map(lambda tup:'{} {} [{}]'.format(*tup), targetMethods)))
        return string

    # analysis for sataModel.obj
    # crashes with targets
    # GUITreeTransition marked/total
    # State marked/total
    # StateTransition marked/total
    # unique subsequences (>=3 times / at least once)
    # @TODO State score
    # @TODO StateTransition score
    data = []
    import javaobj
    from common import classReadJavaList, readJavaList
    from tree import GUITree
    from model import Model, Graph, StateTransition
    try:
        with open(modelobject_fname, 'rb') as f:
            model = Model(javaobj.loads(f.read()))
    except Exception:
        return string + ',javaobjError'

    graph = Graph.init(model.graph)

    # crashes
    crashWithTargetMethodsCounter = Counter("crashes with target")
    crashWithoutTargetMethodsCounter = Counter("crashes without target")
    firstMoment = -1
    firstMomentTargetMethods = -1
    records = model.actionHistory
    for record in readJavaList(records):
        if firstMoment == -1:
            firstMoment = record.clockTimestamp
        if not record.guiAction:
            action = record.modelAction
            constant = action.type.constant
            if constant == 'PHANTOM_CRASH':
                # check stackTrace
                stackTrace = action.crash.stackTrace
                metTarget = False
                for line in stackTrace.split('\n'):
                    if metTarget:
                        break
                    for (clsname, mtdname, signature) in targetMethods:
                        if mtdname in line and clsname[1:-1].split('/')[-1] in line:
                            metTarget = True
                            break
                if metTarget:
                    crashWithTargetMethodsCounter.append(action.crash.stackTrace)
                    if firstMomentTargetMethods == -1:
                        firstMomentTargetMethods = record.clockTimestamp
                else:
                    crashWithoutTargetMethodsCounter.append(action.crash.longMsg)

    crashWithTargetMethodsCounter.pretty()
    crashWithoutTargetMethodsCounter.pretty()
    if firstMomentTargetMethods == -1:
        data.append('NaN')
    else:
        data.append(firstMomentTargetMethods - firstMoment)
    data.append(crashWithTargetMethodsCounter.total())
    data.append(crashLongMessagesCounter.total())

    treeHistory = graph.treeTransitionHistory
    marked_gtransitions = []
    marked_transitions = set()
    for gtransition in treeHistory:
        if gtransition.hasMetTargetMethod:
            marked_gtransitions.append(gtransition)
            marked_transitions.add(gtransition.stateTransition)

    data.append(len(marked_gtransitions))
    data.append(len(treeHistory))

    targetGUITrees = classReadJavaList(graph.metTargetMethodGUITrees, GUITree)
    targetStates = set(map(lambda t:t.getCurrentState(), targetGUITrees))
    targetStateIds = set(map(lambda t:id(t.currentState), targetGUITrees))
    assert len(targetStates) == len(targetStateIds), (len(targetStates), len(targetStateIds))

    data.append(len(targetStates))
    data.append(graph.size())

    # Split with marked State (old) -> Split with marked StateTransition
    from parseobj import getSubsequences, TargetSubsequence
    subsequences = getSubsequences(model, graph)
    subseqCounter = Counter()
    targetSubsequences = []
    for seq in subsequences:
        targetSubsequence = TargetSubsequence(seq[0], seq.getTimestampDelta(0))
        for i in range(1, len(seq)):
            tr = seq[i]
            timestamp = seq.getTimestampDelta(i)
            if tr.hasMetTargetMethod == True:
            # if id(tr.source.currentState) in targetStateIds:
                subseqCounter.append(targetSubsequence)
                targetSubsequences.append(targetSubsequence)
                targetSubsequence = TargetSubsequence(tr, timestamp)
            else:
                targetSubsequence.append(tr, timestamp)
        # subseqCounter.append(targetSubsequence)
        targetSubsequence.setActionRecords(seq.actionRecordsAtEnd)
        targetSubsequences.append(targetSubsequence)

    data.append(len([s for s in subseqCounter.values() if s >= 3]))
    data.append(len(subseqCounter))
    if printSubsequence:
        currentRunningSubsequences = []
        for subsequence in targetSubsequences:
            currentRunningSubsequences.append(subsequence)
            # if subsequence.containsTarget():
            crash = subsequence.getCrash()
            if crash:
                print('Subsequence newly emrged# {}'.format(subsequence.timestamps[0]))
                print(crash['stackTrace'])
                for subsequence in currentRunningSubsequences:
                    print(subsequence.seqdetail())
                print()
                currentRunningSubsequences = []
            # print('{}: {}'.format(subsequence.timestamps[0], subsequence.seqdetail()))

    string += ',' + ','.join(map(str, data))
    if len(subseqCounter) == 0:
        string += ',NaN,NaN,NaN,NaN,NaN,NaN'
    else:
        # #subseq with len <=1, <=2, <=3, <=4, <=5
        keys = subseqCounter.keys()
        cnts = []
        for sz in [1, 2, 3, 4, 5]:
            cnts.append(len([s for s in keys if len(s) <= sz]))
        cnts = tuple(cnts)
        string += ',%.2f,%d,%d,%d,%d,%d' % ((subseqCounter.total() / len(subseqCounter),) + cnts)

    # statistics for state / transition
    state_scores = []
    for state in targetStates:
        state_scores.append(graph.metTargetScore(state))
    if state_scores != []:
        state_scores = np.array(state_scores)
        string += ',%d,%.3f,%.3f,%.3f,%.3f' % (
            len(state_scores),
            np.min(state_scores),
            np.max(state_scores),
            np.average(state_scores),
            np.std(state_scores))
    else:
        string += ',0,NaN,NaN,NaN,NaN'

    transition_scores = []
    for transition in marked_transitions:
        transition_scores.append(StateTransition.init(transition).metTargetRatio())
    if transition_scores != []:
        transition_scores = np.array(transition_scores)
        string += ',%d,%.3f,%.3f,%.3f,%.3f' % (
            len(transition_scores),
            np.min(transition_scores),
            np.max(transition_scores),
            np.average(transition_scores),
            np.std(transition_scores))
    else:
        string += ',0,NaN,NaN,NaN,NaN'
    string += ',{}'.format('/'.join(map(lambda tup:'{} {} [{}]'.format(*tup), targetMethods)))

    return string
Ejemplo n.º 7
0
 def getGUITreeTransitions(self):
     return classReadJavaList(self.treeTransitions,
                              treeModule.GUITreeTransition)
Ejemplo n.º 8
0
 def buildStateKey(naming, componentName, currentNames):
     naming = namingModule.Naming.init(naming)
     widgets = classReadJavaList(currentNames, namingModule.Name)
     return StateKey(componentName, naming, widgets)
Ejemplo n.º 9
0
 def __hash__(self):
     return hash((self.activity, namingModule.Naming.init(self.naming), \
         tuple(classReadJavaList(self.widgets, namingModule.Name))))