""" ./QA/common.py - common code for QA """ import contextlib import json import os import shutil import socket import subprocess def execute(args): """ Execute a specified command """ subprocess.run(args) def execute_jafar_and_miniooni(ooni_exe, outfile, experiment, tag, args): """ Executes jafar and miniooni. Returns the test keys. """ tmpoutfile = "/tmp/{}".format(outfile) with contextlib.suppress(FileNotFoundError): os.remove(tmpoutfile) # just in case execute( [ "./jafar", "-main-command", "./QA/minioonilike.py {} -n -o '{}' --home /tmp {}".format( ooni_exe, tmpoutfile, experiment ), "-main-user", "nobody", # should be present on Unix "-tag", tag, ] + args ) shutil.copy(tmpoutfile, outfile) result = read_result(outfile) assert isinstance(result, dict) assert isinstance(result["test_keys"], dict) return result["test_keys"] def read_result(outfile): """ Reads the result of an experiment """ return json.load(open(outfile, "rb")) def test_keys(result): """ Returns just the test keys of a specific result """ return result["test_keys"] def check_maybe_binary_value(value): """ Make sure a maybe binary value is correct """ assert isinstance(value, str) or ( isinstance(value, dict) and value["format"] == "base64" and isinstance(value["data"], str) ) def with_free_port(func): """ This function executes |func| passing it a port number on localhost which is bound but not listening for new connections """ # See with contextlib.closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock: sock.bind(("127.0.0.1", 0)) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) func(sock.getsockname()[1])