diff options
Diffstat (limited to 'src/test/test_cmdline_args.py')
-rwxr-xr-x | src/test/test_cmdline_args.py | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/src/test/test_cmdline_args.py b/src/test/test_cmdline_args.py new file mode 100755 index 000000000..6d9cf44db --- /dev/null +++ b/src/test/test_cmdline_args.py @@ -0,0 +1,273 @@ +#!/usr/bin/python + +import binascii +import hashlib +import os +import re +import shutil +import subprocess +import sys +import tempfile +import unittest + +TOR = "./src/or/tor" +TOP_SRCDIR = "." + +if len(sys.argv) > 1: + TOR = sys.argv[1] + del sys.argv[1] + +if len(sys.argv) > 1: + TOP_SRCDIR = sys.argv[1] + del sys.argv[1] + +class UnexpectedSuccess(Exception): + pass + +class UnexpectedFailure(Exception): + pass + +def contents(fn): + f = open(fn) + try: + return f.read() + finally: + f.close() + +def run_tor(args, failure=False): + p = subprocess.Popen([TOR] + args, stdout=subprocess.PIPE) + output, _ = p.communicate() + result = p.poll() + if result and not failure: + raise UnexpectedFailure() + elif not result and failure: + raise UnexpectedSuccess() + return output + +def spaceify_fp(fp): + for i in xrange(0, len(fp), 4): + yield fp[i:i+4] + +def lines(s): + out = s.split("\n") + if out and out[-1] == '': + del out[-1] + return out + +def strip_log_junk(line): + m = re.match(r'([^\[]+\[[a-z]*\] *)(.*)', line) + if not m: + return ""+line + return m.group(2).strip() + +def randstring(entropy_bytes): + s = os.urandom(entropy_bytes) + return binascii.b2a_hex(s) + +def findLineContaining(lines, s): + for ln in lines: + if s in ln: + return True + return False + +class CmdlineTests(unittest.TestCase): + + def test_version(self): + out = run_tor(["--version"]) + self.failUnless(out.startswith("Tor version ")) + self.assertEquals(len(lines(out)), 1) + + def test_quiet(self): + out = run_tor(["--quiet", "--quumblebluffin", "1"], failure=True) + self.assertEquals(out, "") + + def test_help(self): + out = run_tor(["--help"], failure=False) + out2 = run_tor(["-h"], failure=False) + self.assert_(out.startswith("Copyright (c) 2001")) + self.assert_(out.endswith( + "tor -f <torrc> [args]\n" + "See man page for options, or https://www.torproject.org/ for documentation.\n")) + self.assert_(out == out2) + + def test_hush(self): + torrc = tempfile.NamedTemporaryFile(delete=False) + torrc.close() + try: + out = run_tor(["--hush", "-f", torrc.name, + "--quumblebluffin", "1"], failure=True) + finally: + os.unlink(torrc.name) + self.assertEquals(len(lines(out)), 2) + ln = [ strip_log_junk(l) for l in lines(out) ] + self.assertEquals(ln[0], "Failed to parse/validate config: Unknown option 'quumblebluffin'. Failing.") + self.assertEquals(ln[1], "Reading config failed--see warnings above.") + + def test_missing_argument(self): + out = run_tor(["--hush", "--hash-password"], failure=True) + self.assertEquals(len(lines(out)), 2) + ln = [ strip_log_junk(l) for l in lines(out) ] + self.assertEquals(ln[0], "Command-line option '--hash-password' with no value. Failing.") + + def test_hash_password(self): + out = run_tor(["--hash-password", "woodwose"]) + result = lines(out)[-1] + self.assertEquals(result[:3], "16:") + self.assertEquals(len(result), 61) + r = binascii.a2b_hex(result[3:]) + self.assertEquals(len(r), 29) + + salt, how, hashed = r[:8], r[8], r[9:] + self.assertEquals(len(hashed), 20) + + count = (16 + (ord(how) & 15)) << ((ord(how) >> 4) + 6) + stuff = salt + "woodwose" + repetitions = count // len(stuff) + 1 + inp = stuff * repetitions + inp = inp[:count] + + self.assertEquals(hashlib.sha1(inp).digest(), hashed) + + def test_digests(self): + main_c = os.path.join(TOP_SRCDIR, "src", "or", "main.c") + + if os.stat(TOR).st_mtime < os.stat(main_c).st_mtime: + self.skipTest(TOR+" not up to date") + out = run_tor(["--digests"]) + main_line = [ l for l in lines(out) if l.endswith("/main.c") ] + digest, name = main_line[0].split() + actual = hashlib.sha1(open(main_c).read()).hexdigest() + self.assertEquals(digest, actual) + + def test_dump_options(self): + default_torrc = tempfile.NamedTemporaryFile(delete=False) + torrc = tempfile.NamedTemporaryFile(delete=False) + torrc.write("SocksPort 9999") + torrc.close() + default_torrc.write("SafeLogging 0") + default_torrc.close() + out_sh = out_nb = out_fl = None + opts = [ "-f", torrc.name, + "--defaults-torrc", default_torrc.name ] + try: + out_sh = run_tor(["--dump-config", "short"]+opts) + out_nb = run_tor(["--dump-config", "non-builtin"]+opts) + out_fl = run_tor(["--dump-config", "full"]+opts) + out_nr = run_tor(["--dump-config", "bliznert"]+opts, + failure=True) + + out_verif = run_tor(["--verify-config"]+opts) + finally: + os.unlink(torrc.name) + os.unlink(default_torrc.name) + + self.assertEquals(len(lines(out_sh)), 2) + self.assert_(lines(out_sh)[0].startswith("DataDirectory ")) + self.assertEquals(lines(out_sh)[1:], + [ "SocksPort 9999" ]) + + self.assertEquals(len(lines(out_nb)), 2) + self.assertEquals(lines(out_nb), + [ "SafeLogging 0", + "SocksPort 9999" ]) + + out_fl = lines(out_fl) + self.assert_(len(out_fl) > 100) + self.assert_("SocksPort 9999" in out_fl) + self.assert_("SafeLogging 0" in out_fl) + self.assert_("ClientOnly 0" in out_fl) + + self.assert_(out_verif.endswith("Configuration was valid\n")) + + def test_list_fingerprint(self): + tmpdir = tempfile.mkdtemp(prefix='ttca_') + torrc = tempfile.NamedTemporaryFile(delete=False) + torrc.write("ORPort 9999\n") + torrc.write("DataDirectory %s\n"%tmpdir) + torrc.write("Nickname tippi") + torrc.close() + opts = ["-f", torrc.name] + try: + out = run_tor(["--list-fingerprint"]+opts) + fp = contents(os.path.join(tmpdir, "fingerprint")) + finally: + os.unlink(torrc.name) + shutil.rmtree(tmpdir) + + out = lines(out) + lastlog = strip_log_junk(out[-2]) + lastline = out[-1] + fp = fp.strip() + nn_fp = fp.split()[0] + space_fp = " ".join(spaceify_fp(fp.split()[1])) + self.assertEquals(lastlog, + "Your Tor server's identity key fingerprint is '%s'"%fp) + self.assertEquals(lastline, "tippi %s"%space_fp) + self.assertEquals(nn_fp, "tippi") + + def test_list_options(self): + out = lines(run_tor(["--list-torrc-options"])) + self.assert_(len(out)>100) + self.assert_(out[0] <= 'AccountingMax') + self.assert_("UseBridges" in out) + self.assert_("SocksPort" in out) + + def test_cmdline_args(self): + default_torrc = tempfile.NamedTemporaryFile(delete=False) + torrc = tempfile.NamedTemporaryFile(delete=False) + torrc.write("SocksPort 9999\n") + torrc.write("SocksPort 9998\n") + torrc.write("ORPort 9000\n") + torrc.write("ORPort 9001\n") + torrc.write("Nickname eleventeen\n") + torrc.write("ControlPort 9500\n") + torrc.close() + default_torrc.write("") + default_torrc.close() + out_sh = out_nb = out_fl = None + opts = [ "-f", torrc.name, + "--defaults-torrc", default_torrc.name, + "--dump-config", "short" ] + try: + out_1 = run_tor(opts) + out_2 = run_tor(opts+["+ORPort", "9003", + "SocksPort", "9090", + "/ControlPort", + "/TransPort", + "+ExtORPort", "9005"]) + finally: + os.unlink(torrc.name) + os.unlink(default_torrc.name) + + out_1 = [ l for l in lines(out_1) if not l.startswith("DataDir") ] + out_2 = [ l for l in lines(out_2) if not l.startswith("DataDir") ] + + self.assertEquals(out_1, + ["ControlPort 9500", + "Nickname eleventeen", + "ORPort 9000", + "ORPort 9001", + "SocksPort 9999", + "SocksPort 9998"]) + self.assertEquals(out_2, + ["ExtORPort 9005", + "Nickname eleventeen", + "ORPort 9000", + "ORPort 9001", + "ORPort 9003", + "SocksPort 9090"]) + + def test_missing_torrc(self): + fname = "nonexistent_file_"+randstring(8) + out = run_tor(["-f", fname, "--verify-config"], failure=True) + ln = [ strip_log_junk(l) for l in lines(out) ] + self.assert_("Unable to open configuration file" in ln[-2]) + self.assert_("Reading config failed" in ln[-1]) + + out = run_tor(["-f", fname, "--verify-config", "--ignore-missing-torrc"]) + ln = [ strip_log_junk(l) for l in lines(out) ] + self.assert_(findLineContaining(ln, ", using reasonable defaults")) + self.assert_("Configuration was valid" in ln[-1]) + +if __name__ == '__main__': + unittest.main() |