177be4309SSarath Lakshman#!/usr/bin/env python
277be4309SSarath Lakshman# Description: Wrapper script for running CouchDB unit tests
377be4309SSarath Lakshman
477be4309SSarath Lakshmanimport sys
577be4309SSarath Lakshmanimport getopt
677be4309SSarath Lakshmanimport os
777be4309SSarath Lakshmanimport subprocess
877be4309SSarath Lakshmanimport re
9aae1433bSAman Achpalimport platform
10aae1433bSAman Achpalimport shlex
1177be4309SSarath Lakshman
1277be4309SSarath LakshmanTEST_COUNT_RE = r"^1\.\.(\d+)"
1377be4309SSarath LakshmanTEST_OK_RE = r"(^ok)\b"
1477be4309SSarath LakshmanTEST_NOT_OK_RE = r"(^not ok)\b"
15efc2e928SVolker Mische
16efc2e928SVolker MischeMODULES = ["../test/etap"]
1777be4309SSarath Lakshman
1877be4309SSarath Lakshmandef usage():
19efc2e928SVolker Mische    print "Usage: %s -p builddir -l erl_libs_dir -m module_dir_paths" \
2028974078SVolker Mische    " -f erl_flags -t testfile [ -v ] [ -c couchstore_install_path ]" \
216edbd3a3SVolker Mische    " [-e escript_path]" \
2228974078SVolker Mische    % sys.argv[0]
2377be4309SSarath Lakshman    print
2477be4309SSarath Lakshman
25aae1433bSAman Achpaldef setup():
26aae1433bSAman Achpal    """Configure LD_LIBRARY_PATH"""
27aae1433bSAman Achpal    if platform.system() == "Linux":
28aae1433bSAman Achpal        dname, fname = os.path.split(os.path.abspath(__file__))
29f59f9fe1SAman Achpal        cpath = dname.rsplit('couchdb')[0]
30aae1433bSAman Achpal        nspath = os.path.join(cpath, 'ns_server')
31aae1433bSAman Achpal
32aae1433bSAman Achpal        def read_configuration():
33aae1433bSAman Achpal            cfig = os.path.join(nspath, 'build', 'cluster_run.configuration')
34aae1433bSAman Achpal            with open(cfig) as f:
35aae1433bSAman Achpal                def fn(line):
36aae1433bSAman Achpal                    k, v = line.strip().split('=')
37aae1433bSAman Achpal                    return k, shlex.split(v)[0]
38aae1433bSAman Achpal                return dict(fn(line) for line in f.readlines())
39aae1433bSAman Achpal
40aae1433bSAman Achpal        config = read_configuration()
41aae1433bSAman Achpal        PREFIX = config['prefix']
42aae1433bSAman Achpal
43aae1433bSAman Achpal        LIBS = os.path.join(PREFIX, 'lib')
44aae1433bSAman Achpal        MEMCACHED = os.path.join(LIBS, 'memcached')
45aae1433bSAman Achpal        LD_LIBRARY_PATH = LIBS + os.pathsep + MEMCACHED
46aae1433bSAman Achpal        env = os.environ.copy()
47aae1433bSAman Achpal        if 'LD_LIBRARY_PATH' in env:
48aae1433bSAman Achpal            LD_LIBRARY_PATH += os.pathsep + env['LD_LIBRARY_PATH']
49aae1433bSAman Achpal        os.environ['LD_LIBRARY_PATH'] = LD_LIBRARY_PATH
50aae1433bSAman Achpal
51aae1433bSAman Achpaldef run_test(testfile,eescript_path, verbose = False):
5277be4309SSarath Lakshman    test_total = -1
5377be4309SSarath Lakshman    test_passed = 0
5477be4309SSarath Lakshman    exit_status = 0
5577be4309SSarath Lakshman    count_re = re.compile(TEST_COUNT_RE)
5677be4309SSarath Lakshman    ok_re = re.compile(TEST_OK_RE)
5777be4309SSarath Lakshman    not_ok_re = re.compile(TEST_NOT_OK_RE)
586edbd3a3SVolker Mische    s = subprocess.Popen([escript_path, testfile], stdout=subprocess.PIPE,
5977be4309SSarath Lakshman            stderr=subprocess.PIPE)
6077be4309SSarath Lakshman    while True:
6177be4309SSarath Lakshman        line = s.stdout.readline()
6277be4309SSarath Lakshman        if line:
6377be4309SSarath Lakshman            if ok_re.match(line):
6477be4309SSarath Lakshman                test_passed += 1
6577be4309SSarath Lakshman                print line,
6677be4309SSarath Lakshman            elif not_ok_re.match(line):
6777be4309SSarath Lakshman                print line,
6877be4309SSarath Lakshman            else:
694a0fd1a2SSarath Lakshman                if verbose:
704a0fd1a2SSarath Lakshman                    print line,
714a0fd1a2SSarath Lakshman
7277be4309SSarath Lakshman                count = count_re.match(line)
7377be4309SSarath Lakshman                if count:
7477be4309SSarath Lakshman                    test_total = int(count.group(1))
7577be4309SSarath Lakshman        else:
7677be4309SSarath Lakshman            break
7777be4309SSarath Lakshman
7877be4309SSarath Lakshman    if test_total == test_passed:
7977be4309SSarath Lakshman        exit_status = 0
8077be4309SSarath Lakshman    else:
8177be4309SSarath Lakshman        exit_status = 1
8277be4309SSarath Lakshman        err = s.stderr.read()
8377be4309SSarath Lakshman        if err:
8477be4309SSarath Lakshman            print err
8577be4309SSarath Lakshman
8677be4309SSarath Lakshman    if test_total > 0:
8777be4309SSarath Lakshman        print "%d/%d tests passed" %(test_passed, test_total)
8877be4309SSarath Lakshman
8977be4309SSarath Lakshman    return exit_status
9077be4309SSarath Lakshman
9177be4309SSarath Lakshmanif __name__ == '__main__':
9277be4309SSarath Lakshman    try:
936edbd3a3SVolker Mische        opts, args = getopt.getopt(sys.argv[1:], "p:l:m:f:t:hvc:e:", \
9428974078SVolker Mische                    ["path=", "libsdir=", "modules=", "flags=", "test=",
956edbd3a3SVolker Mische                     "help", "verbose", "couchstore-installdir=", "escript="])
9677be4309SSarath Lakshman    except getopt.GetoptError, err:
9777be4309SSarath Lakshman        print err
9877be4309SSarath Lakshman        usage()
9977be4309SSarath Lakshman        sys.exit(2)
10077be4309SSarath Lakshman
10177be4309SSarath Lakshman    if not opts:
10277be4309SSarath Lakshman        usage()
10377be4309SSarath Lakshman        sys.exit(2)
10477be4309SSarath Lakshman
10577be4309SSarath Lakshman    path = None
106efc2e928SVolker Mische    libsdir = None
10777be4309SSarath Lakshman    test = None
10877be4309SSarath Lakshman    modules = None
10928974078SVolker Mische    flags = None
1104a0fd1a2SSarath Lakshman    verbose = False
1114a0fd1a2SSarath Lakshman    couchstore_path = None
1126edbd3a3SVolker Mische    escript_path = 'escript'
11377be4309SSarath Lakshman
11477be4309SSarath Lakshman    for opt, arg in opts:
11577be4309SSarath Lakshman        if opt in ("-p", "--path"):
11677be4309SSarath Lakshman            path = arg
11728974078SVolker Mische        elif opt in ("-l", "--libsdir"):
118efc2e928SVolker Mische            libsdir = arg
11928974078SVolker Mische        elif opt in ("-m", "--modules"):
12077be4309SSarath Lakshman            modules = arg
12128974078SVolker Mische        elif opt in ("-f", "--flags"):
12228974078SVolker Mische            flags = arg
12377be4309SSarath Lakshman        elif opt in ("-t", "--test"):
12477be4309SSarath Lakshman            test = arg
1254a0fd1a2SSarath Lakshman        elif opt in ("-v", "--verbose"):
1264a0fd1a2SSarath Lakshman            verbose = True
1274a0fd1a2SSarath Lakshman        elif opt in ("-c", "--couchstore-installdir"):
1284a0fd1a2SSarath Lakshman            couchstore_path = arg
1296edbd3a3SVolker Mische        elif opt in ("-e", "--escript"):
1306edbd3a3SVolker Mische            escript_path = arg
13177be4309SSarath Lakshman        elif opt in ("-h", "--help"):
13277be4309SSarath Lakshman            usage()
13377be4309SSarath Lakshman            sys.exit(0)
13477be4309SSarath Lakshman
13577be4309SSarath Lakshman    if modules:
13677be4309SSarath Lakshman        MODULES += modules.split(",")
13777be4309SSarath Lakshman
138efc2e928SVolker Mische    erl_libs = []
139efc2e928SVolker Mische    env = os.getenv("ERL_LIBS")
140efc2e928SVolker Mische    if env:
141efc2e928SVolker Mische        erl_libs.append(env)
142efc2e928SVolker Mische    if libsdir:
143efc2e928SVolker Mische        erl_libs.append(libsdir)
144efc2e928SVolker Mische
14528974078SVolker Mische    erl_flags = []
146efc2e928SVolker Mische    env = os.getenv("ERL_FLAGS")
147efc2e928SVolker Mische    if env:
14828974078SVolker Mische        erl_flags.append(env)
14928974078SVolker Mische    if flags:
15028974078SVolker Mische        erl_flags.append(flags)
151efc2e928SVolker Mische
15277be4309SSarath Lakshman    if path:
153efc2e928SVolker Mische        erl_libs.append(path)
154efc2e928SVolker Mische
155efc2e928SVolker Mische        # As some modules are not proper OTP apps, just add all dirs as
156efc2e928SVolker Mische        # ERL_FLAGS paths as well
157efc2e928SVolker Mische        MODULES += [d for d in os.listdir(path)
158efc2e928SVolker Mische                   if os.path.isdir(os.path.join(path, d))]
159efc2e928SVolker Mische
16028974078SVolker Mische        paths = map(lambda x: " %s" %os.path.join(path, x), MODULES)
16128974078SVolker Mische        erl_flags.append("-pa" + " ".join(paths))
16228974078SVolker Mische
16328974078SVolker Mische
16428974078SVolker Mische    # Erlang modules expect posix path format
16528974078SVolker Mische    # which is respected by all platforms
16628974078SVolker Mische    # including Windows. So replace '\' by '/'
16728974078SVolker Mische    # Ensure spaces escaped by '\' are intact,
16828974078SVolker Mische    # since directory names might contain space
16928974078SVolker Mische    pattern = re.compile(r'\\(\S)')
17028974078SVolker Mische
17128974078SVolker Mische    erl_flags = " ".join(erl_flags)
17228974078SVolker Mische    erl_flags = pattern.sub(r'/\1', erl_flags)
17328974078SVolker Mische    os.putenv("ERL_FLAGS", erl_flags)
1746e93e510Sharsha
175efc2e928SVolker Mische    erl_libs = os.pathsep.join(erl_libs)
176efc2e928SVolker Mische    erl_libs = pattern.sub(r'/\1', erl_libs)
177efc2e928SVolker Mische    os.putenv("ERL_LIBS", erl_libs)
178efc2e928SVolker Mische
179efc2e928SVolker Mische    if verbose:
180efc2e928SVolker Mische        print('ERL_LIBS="{}"'.format(erl_libs))
181efc2e928SVolker Mische        print('ERL_FLAGS="{}"'.format(erl_flags))
18277be4309SSarath Lakshman
1834a0fd1a2SSarath Lakshman    if couchstore_path:
1844a0fd1a2SSarath Lakshman        env = os.getenv("PATH")
1854a0fd1a2SSarath Lakshman        if env:
1864a0fd1a2SSarath Lakshman            env += ":"
1874a0fd1a2SSarath Lakshman        else:
1884a0fd1a2SSarath Lakshman            env = ""
1894a0fd1a2SSarath Lakshman
1904a0fd1a2SSarath Lakshman        env += couchstore_path
1914a0fd1a2SSarath Lakshman        os.putenv("PATH", env)
1924a0fd1a2SSarath Lakshman
19377be4309SSarath Lakshman    if test:
194f59f9fe1SAman Achpal        """
195f59f9fe1SAman Achpal        Uncomment to fix mapreduce_nif_not_loaded
196f59f9fe1SAman Achpal        setup()
197f59f9fe1SAman Achpal        """
1986edbd3a3SVolker Mische        sys.exit(run_test(test, escript_path, verbose))
19977be4309SSarath Lakshman    else:
20077be4309SSarath Lakshman        sys.exit("ERROR: No test specified")
201