Validation scripts for our SEMERU project.
Last active
August 29, 2015 13:56
-
-
Save nejstastnejsistene/9241456 to your computer and use it in GitHub Desktop.
partition_events.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Byte-compiled / optimized / DLL files | |
__pycache__/ | |
*.py[cod] | |
# C extensions | |
*.so | |
# Distribution / packaging | |
.Python | |
env/ | |
bin/ | |
build/ | |
develop-eggs/ | |
dist/ | |
eggs/ | |
lib/ | |
lib64/ | |
parts/ | |
sdist/ | |
var/ | |
*.egg-info/ | |
.installed.cfg | |
*.egg | |
# Installer logs | |
pip-log.txt | |
pip-delete-this-directory.txt | |
# Unit test / coverage reports | |
htmlcov/ | |
.tox/ | |
.coverage | |
.cache | |
nosetests.xml | |
coverage.xml | |
# Translations | |
*.mo | |
# Mr Developer | |
.mr.developer.cfg | |
.project | |
.pydevproject | |
# Rope | |
.ropeproject | |
# Django stuff: | |
*.log | |
*.pot | |
# Sphinx documentation | |
docs/_build/ | |
*.txt | |
*.log | |
test | |
*.log2 | |
*.zip | |
reran |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
partition_events () { | |
export input_file=$1 | |
python << EOF | |
#!/usr/bin/env python | |
import re | |
import sys | |
#from evdev.ecodes import * | |
EV_SYN = 0 | |
EV_KEY = 1 | |
EV_ABS = 3 | |
ABS_X = 0 | |
ABS_Y = 1 | |
ABS_MT_POSITION_X = 53 | |
ABS_MT_POSITION_Y = 54 | |
ABS_MT_TRACKING_ID = 57 | |
SYN_REPORT = 0 | |
BTN_TOUCH = 330 | |
pattern = re.compile( | |
r'\[\s*(\d*\.\d*)\] /dev/input/event(\d): ' \ | |
r'([0-9a-f]{4}) ([0-9a-f]{4}) ([0-9a-f]{8})') | |
input_file = open('$input_file') | |
x, y = 0, 0 | |
was_finger_down = False | |
finger_down = False | |
events = [] | |
coords = [] | |
for line in input_file: | |
if line[0] != '[': | |
continue | |
time, device, type, code, value = re.match(pattern, line).groups() | |
time = float(time) | |
device = int(device) | |
type = int(type, 16) | |
code = int(code, 16) | |
value = int(value, 16) | |
event = device, type, code, value | |
events.append(event) | |
# Button down. | |
if type == EV_KEY: | |
# If the touch screen has been toggled, let sync events | |
# handle the logic. | |
if code == BTN_TOUCH: | |
finger_down = value | |
# For any other button, print the action after the button has | |
# been released. | |
elif value == 0: | |
duration = time - start_time | |
fmt = 'button press: duration={}, device={}, code={}' | |
print fmt.format(duration, device, keys[code]) | |
events = [] | |
elif value == 1: | |
start_time = time | |
# Absolute coordinates from a touchscreen. | |
elif type == EV_ABS: | |
if code in (ABS_X, ABS_MT_POSITION_X): | |
x = value | |
elif code in (ABS_Y, ABS_MT_POSITION_Y): | |
y = value | |
elif code == ABS_MT_TRACKING_ID: | |
finger_down = value != 0xffffffff | |
# Sync. | |
elif type == EV_SYN and code == SYN_REPORT: | |
# If the finger has changed: | |
if finger_down != was_finger_down: | |
# Restart the coordinate list. | |
if finger_down: | |
start_time = time | |
coords = [(x, y)] | |
# If the finger is removed from the touchscreen, end the | |
# action and print the events. | |
else: | |
duration = time - start_time | |
fmt = 'touch action: duration={:f}, num_coords={}, coords={}' | |
print fmt.format(duration, len(coords), coords) | |
events = [] | |
coords = [] | |
was_finger_down = finger_down | |
# Append the current coordinates to the list. | |
else: | |
coords.append((x, y)) | |
else: | |
raise Exception, 'unrecognized event: {}'.format(event) | |
EOF | |
} | |
expand_description () { | |
export description=$1 | |
python << EOF | |
import os, sys, re | |
with open(os.environ['description']) as f: | |
for line in f.read().split('\n'): | |
if 'typed' in line.lower(): | |
try: | |
for ch in re.search(r'"(.*)"', line).group(1): | |
print 'I touched the "{}" button on the keyboard.'.format(ch) | |
except: | |
print >> sys.stderr, '\nError: unable to find delimited string. Don\'t forget to add double quotes for typed events' | |
sys.exit(1) | |
elif line: | |
print line | |
EOF | |
} | |
app=$1 | |
if [ -z $app ]; then | |
echo usage: $0 \<app name\> | |
exit 1 | |
fi | |
for lastname in `ls`; do | |
# Skip non-directories. | |
if [ ! -d $lastname ]; then | |
continue | |
fi | |
# Make sure the app exists. | |
if [ ! -d "$lastname/$app" ]; then | |
echo \"$lastname/$app\" does not exist | |
continue | |
fi | |
# Clear any old data before writing the new data. | |
rm -f "$app-records.txt" "$app-description.txt" | |
# Iterate through each scenario. | |
for scenario in `ls "$lastname/$app"`; do | |
# For each record, concatentate its events and descriptions. | |
for record in `ls "$lastname/$app/$scenario"/record*.log`; do | |
partition_events $record >> "$app-records.txt" | |
expand_description "$lastname/$app/$scenario/description.txt" >> "$app-description.txt" | |
done | |
done | |
done | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import sys | |
import re | |
from commands import getoutput | |
if len(sys.argv) != 3: | |
print >> sys.stderr, 'usage: {} <scenario> <events>'.format(__file__) | |
with open(sys.argv[1]) as f: | |
scenario = filter(None, f) | |
events = getoutput('./partition_events.py {}'.format(sys.argv[2])) | |
events = filter(None, events.split('\n')) | |
max_len = max(map(len, scenario)) + 2 | |
s = iter(scenario) | |
e = iter(events) | |
while True: | |
try: | |
line = next(s).strip() | |
except StopIteration: | |
# Break when we run out of lines in the scenario. | |
break | |
try: | |
if 'typed' in line.lower(): | |
print line | |
try: | |
in_quotes = re.search(r'"(.*)"', line).group(1) | |
for i in in_quotes: | |
print (' '*4 + i).ljust(max_len, '.'), next(e) | |
except: | |
print >> sys.stderr, '\nError: unable to find delimited string. Don\'t forget to add double quotes for typed events' | |
sys.exit(1) | |
else: | |
print line.ljust(max_len, '.'), next(e) | |
except StopIteration: | |
print >> sys.stderr, '\nError: Too few events!' | |
sys.exit(1) | |
# Make sure we are also out of events. | |
# This means there are the same number of scenarios and events. | |
try: | |
next(e) | |
print >> sys.stderr, '\nError: Too many events!' | |
sys.exit(1) | |
except StopIteration: | |
print '\nSuccess: It looks like they match up!' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import re | |
import sys | |
#from evdev.ecodes import * | |
EV_SYN = 0 | |
EV_KEY = 1 | |
EV_ABS = 3 | |
ABS_X = 0 | |
ABS_Y = 1 | |
ABS_MT_POSITION_X = 53 | |
ABS_MT_POSITION_Y = 54 | |
ABS_MT_TRACKING_ID = 57 | |
SYN_REPORT = 0 | |
BTN_TOUCH = 330 | |
pattern = re.compile( | |
r'\[\s*(\d*\.\d*)\] /dev/input/event(\d): ' \ | |
r'([0-9a-f]{4}) ([0-9a-f]{4}) ([0-9a-f]{8})') | |
input_file = open(sys.argv[1]) | |
x, y = 0, 0 | |
was_finger_down = False | |
finger_down = False | |
events = [] | |
coords = [] | |
def translate_event(time, device, type, code, value): | |
if code == ABS_MT_POSITION_X: | |
return time, device, type, ABS_X, int(value / (1343.0/1200.0)) | |
elif code == ABS_MT_POSITION_Y: | |
return time, device, type, ABS_Y, int(value / (2239.0/1920.0)) | |
elif code == ABS_MT_TRACKING_ID: | |
if value == 0xffffffff: | |
return time, device, EV_KEY, BTN_TOUCH, 0 | |
else: | |
return time, device, EV_KEY, BTN_TOUCH, 1 | |
elif code == SYN_REPORT: | |
return time, device, type, code, value | |
# Skip events that don't have a corresponding event, | |
# such as ABS_MT_PRESSURE. | |
def print_event(event): | |
if event is not None: | |
time, device, type, code, value = event | |
print '[{:15.6f}] /dev/input/event{}:'.format(time, device), | |
print '{:04x} {:04x} {:08x}'.format(type, code, value) | |
for line in input_file: | |
if line[0] != '[': | |
continue | |
time, device, type, code, value = re.match(pattern, line).groups() | |
time = float(time) | |
device = int(device) | |
type = int(type, 16) | |
code = int(code, 16) | |
value = int(value, 16) | |
event = time, device, type, code, value | |
events.append(event) | |
# Button down. | |
if type == EV_KEY: | |
# If the touch screen has been toggled, let sync events | |
# handle the logic. | |
if code == BTN_TOUCH: | |
finger_down = value | |
# For any other button, print the action after the button has | |
# been released. | |
elif value == 0: | |
duration = time - start_time | |
fmt = 'button press: duration={}, device={}, code={}' | |
print fmt.format(duration, device, code) | |
events = [] | |
elif value == 1: | |
start_time = time | |
# Absolute coordinates from a touchscreen. | |
elif type == EV_ABS: | |
if code in (ABS_X, ABS_MT_POSITION_X): | |
x = value | |
elif code in (ABS_Y, ABS_MT_POSITION_Y): | |
y = value | |
elif code == ABS_MT_TRACKING_ID: | |
finger_down = value != 0xffffffff | |
# Sync. | |
elif type == EV_SYN and code == SYN_REPORT: | |
# If the finger has changed: | |
if finger_down != was_finger_down: | |
# Restart the coordinate list. | |
if finger_down: | |
start_time = time | |
coords = [(x, y)] | |
# If the finger is removed from the touchscreen, end the | |
# action and print the events. | |
else: | |
i = 0 | |
while i < len(events): | |
e = events[i] | |
if e[3] == ABS_MT_TRACKING_ID and e[4] != 0xffffffff: | |
e1 = events[i+1] | |
e2 = events[i+2] | |
if e1[3] in (ABS_MT_POSITION_X, ABS_MT_POSITION_Y): | |
print_event(translate_event(*((e[0],)+e1[1:]))) | |
if e2[3] in (ABS_MT_POSITION_X, ABS_MT_POSITION_Y): | |
print_event(translate_event(*((e[0],)+e2[1:]))) | |
print_event(translate_event(*e)) | |
i += 1 | |
events = [] | |
coords = [] | |
was_finger_down = finger_down | |
# Append the current coordinates to the list. | |
else: | |
coords.append((x, y)) | |
else: | |
raise Exception, 'unrecognized event: {}'.format(event) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import re | |
import sys | |
#from evdev.ecodes import * | |
EV_SYN = 0 | |
EV_KEY = 1 | |
EV_ABS = 3 | |
ABS_X = 0 | |
ABS_Y = 1 | |
ABS_MT_POSITION_X = 53 | |
ABS_MT_POSITION_Y = 54 | |
ABS_MT_TRACKING_ID = 57 | |
SYN_REPORT = 0 | |
BTN_TOUCH = 330 | |
pattern = re.compile( | |
r'\[\s*(\d*\.\d*)\] /dev/input/event(\d): ' \ | |
r'([0-9a-f]{4}) ([0-9a-f]{4}) ([0-9a-f]{8})') | |
input_file = open(sys.argv[1]) | |
x, y = 0, 0 | |
was_finger_down = False | |
finger_down = False | |
events = [] | |
coords = [] | |
for line in input_file: | |
if line[0] != '[': | |
continue | |
time, device, type, code, value = re.match(pattern, line).groups() | |
time = float(time) | |
device = int(device) | |
type = int(type, 16) | |
code = int(code, 16) | |
value = int(value, 16) | |
event = device, type, code, value | |
events.append(event) | |
# Button down. | |
if type == EV_KEY: | |
# If the touch screen has been toggled, let sync events | |
# handle the logic. | |
if code == BTN_TOUCH: | |
finger_down = value | |
# For any other button, print the action after the button has | |
# been released. | |
elif value == 0: | |
duration = time - start_time | |
fmt = 'button press: duration={}, device={}, code={}' | |
print fmt.format(duration, device, keys[code]) | |
events = [] | |
elif value == 1: | |
start_time = time | |
# Absolute coordinates from a touchscreen. | |
elif type == EV_ABS: | |
if code in (ABS_X, ABS_MT_POSITION_X): | |
x = value | |
elif code in (ABS_Y, ABS_MT_POSITION_Y): | |
y = value | |
elif code == ABS_MT_TRACKING_ID: | |
finger_down = value != 0xffffffff | |
# Sync. | |
elif type == EV_SYN and code == SYN_REPORT: | |
# If the finger has changed: | |
if finger_down != was_finger_down: | |
# Restart the coordinate list. | |
if finger_down: | |
start_time = time | |
coords = [(x, y)] | |
# If the finger is removed from the touchscreen, end the | |
# action and print the events. | |
else: | |
duration = time - start_time | |
fmt = 'touch action: duration={:f}, num_coords={}, coords={}' | |
print fmt.format(duration, len(coords), coords) | |
events = [] | |
coords = [] | |
was_finger_down = finger_down | |
# Append the current coordinates to the list. | |
else: | |
coords.append((x, y)) | |
else: | |
raise Exception, 'unrecognized event: {}'.format(event) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import sys | |
import os | |
import glob | |
import fnmatch | |
def lcs(a, b): | |
lengths = [[0 for j in range(len(b)+1)] for i in range(len(a)+1)] | |
# row 0 and column 0 are initialized to 0 already | |
for i, x in enumerate(a): | |
for j, y in enumerate(b): | |
if x == y: | |
lengths[i+1][j+1] = lengths[i][j] + 1 | |
else: | |
lengths[i+1][j+1] = \ | |
max(lengths[i+1][j], lengths[i][j+1]) | |
# read the substring out from the matrix | |
result = [] | |
x, y = len(a), len(b) | |
while x != 0 and y != 0: | |
if lengths[x][y] == lengths[x-1][y]: | |
x -= 1 | |
elif lengths[x][y] == lengths[x][y-1]: | |
y -= 1 | |
else: | |
assert a[x-1] == b[y-1] | |
result.insert(0, a[x-1]) | |
x -= 1 | |
y -= 1 | |
return result | |
def method_to_logcat_fmt(method): | |
if '(' in method: | |
method = method[:method.index('(')] | |
return method.strip().replace('/', '.') | |
def sanitize_scenario(filename): | |
with open(filename) as f: | |
for line in f: | |
_, _, method = line.strip().split(',', 2) | |
if '#' in method: | |
for meth in reversed(method.split('#')): | |
yield method_to_logcat_fmt(meth) | |
else: | |
yield method_to_logcat_fmt(method) | |
def read_logcat(filename): | |
with open(filename) as f: | |
return f.read().split() | |
def compare_trace(scenario_filename, logcat_filename): | |
scenario = list(sanitize_scenario(scenario_filename)) | |
logcat = read_logcat(logcat_filename) | |
seq = lcs(scenario, logcat) | |
if seq: | |
first_index = last_index = scenario.index(seq[0]) | |
for item in seq[1:]: | |
last_index = scenario.index(item, last_index) | |
if len(seq) == 1: | |
norm = 1.0 | |
else: | |
norm = len(seq) / float(last_index - first_index) | |
else: | |
norm = 0.0 | |
return logcat_filename, get_description(scenario_filename), \ | |
scenario_filename, len(seq), norm, 'produce-bug?' | |
def logcats(app): | |
return sorted(glob.glob('reran/results/logcats/' + app + '/*_final.txt')) | |
def scenarios(app): | |
for root, dirnames, filenames in os.walk('reran/results/' + app): | |
for filename in fnmatch.filter(filenames, '*.at2'): | |
yield os.path.join(root, filename) | |
def split_directories(path): | |
folders = [] | |
while True: | |
path,folder = os.path.split(path) | |
if folder != "": | |
folders.append(folder) | |
else: | |
if path != "": | |
folders.append(path) | |
break | |
return list(reversed(folders)) | |
def get_description(scenario): | |
path = app, name, scenario = split_directories(scenario)[2:-1] | |
desc_path = os.path.join('reran', 'repository', name, | |
app, scenario, 'description.txt') | |
assert os.path.exists(desc_path) | |
return desc_path | |
def compare_all(app): | |
for logcat in logcats(app): | |
for scenario in scenarios(app): | |
yield compare_trace(scenario, logcat) | |
if __name__ == '__main__': | |
tuples = compare_all(sys.argv[1]) | |
for x in sorted(tuples, key=lambda x: (x[0], 1-x[-2])): | |
print ', '.join(map(str, x)) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def lcs(a, b): | |
lengths = [[0 for j in range(len(b)+1)] for i in range(len(a)+1)] | |
# row 0 and column 0 are initialized to 0 already | |
for i, x in enumerate(a): | |
for j, y in enumerate(b): | |
if x == y: | |
lengths[i+1][j+1] = lengths[i][j] + 1 | |
else: | |
lengths[i+1][j+1] = \ | |
max(lengths[i+1][j], lengths[i][j+1]) | |
# read the substring out from the matrix | |
result = [] | |
x, y = len(a), len(b) | |
while x != 0 and y != 0: | |
if lengths[x][y] == lengths[x-1][y]: | |
x -= 1 | |
elif lengths[x][y] == lengths[x][y-1]: | |
y -= 1 | |
else: | |
assert a[x-1] == b[y-1] | |
result.insert(0, a[x-1]) | |
x -= 1 | |
y -= 1 | |
return result | |
import sys | |
from commands import getoutput | |
scenario = getoutput('python sanitize-traces.py "{0}" | uniq'.format(sys.argv[1])).split() | |
stack_trace = open(sys.argv[2]).read().split() | |
seq = lcs(scenario, stack_trace) | |
if seq: | |
first_index = last_index = scenario.index(seq[0]) | |
for item in seq[1:]: | |
last_index = scenario.index(item, last_index) | |
if len(seq) == 1: | |
norm = 1.0 | |
else: | |
norm = len(seq) / float(last_index - first_index) | |
else: | |
norm = 0.0 | |
print '<{0}, {1}, {2}, {3}>'.format(sys.argv[1], sys.argv[2], len(seq), norm) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment