Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/README-testing b/README-testing
new file mode 100644
index 0000000..3c50858
--- /dev/null
+++ b/README-testing
@@ -0,0 +1,22 @@
+
+=== Simple tests (commandline, config file)
+
+
+Run
+
+ # make check-TESTS
+
+to run the tests written in python.
+
+
+
+
+=== Unit tests
+
+These use gdb and pexpect to set boothd state to some configured value,
+injecting some input and looking at the output.
+
+ # python script/unit-test.py src/boothd unit-tests/
+
+
+
diff --git a/script/unit-test.py b/script/unit-test.py
new file mode 100644
index 0000000..0c15a39
--- /dev/null
+++ b/script/unit-test.py
@@ -0,0 +1,139 @@
+#!/usr/bin/python
+
+import os
+import re
+import shutil
+import sys
+import time
+import pexpect
+
+binary = sys.argv[1]
+test_base = sys.argv[2] + "/"
+
+
+class Common():
+ gdb = None
+ booth = None
+ prompt = "CUSTOM-GDB-PROMPT-%d-%d" % (os.getpid(), time.time())
+
+ def sync(timeout=-1):
+ gdb.expect(prompt, timeout)
+
+ def __init__(self):
+ booth = pexpect.spawn(binary, args=["daemon", "-D", "-c", test_base + "/booth.conf"])
+ booth.expect("o") # TODO
+
+ gdb = pexpect.spawn("gdb",
+ args=["-quiet", "-p", booth.pid],
+ timeout=30,
+ maxread=32768)
+ gdb.expect("(gdb)")
+ gdb.sendline("set pagination off\n")
+ gdb.sendline("set prompt " + prompt + "\n");
+ self.sync(2000)
+
+ def send_cmd(stg):
+ gdb.sendline(stg + "\n")
+ gdb.sync()
+
+ def set_val(name, value, numeric_conv=None):
+ # string value?
+ if re.match('^"', value):
+ send_cmd("print strcpy(" + name + ", " + value + ")")
+ # numeric
+ elif numeric_conv:
+ send_cmd("set variable " + name + " = " + numeric_conv + "(" + value + ")")
+ else:
+ send_cmd("set variable " + name + " = " + value)
+
+
+class Message(Common):
+ def set_break():
+ "message_recv"
+
+ def send_vals(data):
+ for (n, v) in data:
+ set_val("msg->" + n, v, "htonl")
+
+class Ticket(Common):
+ def send_vals(data):
+ for (n, v) in data:
+ set_val(n, v)
+
+def read_test_input(file, state=None):
+ fo = open(file, "r")
+ m = { "ticket": {}, "message" : {} }
+ for line in fo.readlines():
+ # comment?
+ if re.match("^\\s*#", line):
+ continue
+
+ # message resp. ticket
+ res = re.match("^\\s*(\\w+)\\s*:\\s*$", line)
+ if res:
+ state = res.group(1)
+ continue
+
+ res = re.match("^\\s*(\\S+)\\s*(.*)\\s*$", line)
+ if res:
+ assert(state)
+ if not m[state]:
+ m[state] = {}
+ m[state][ res.group(1) ] = res.group(2)
+ return m
+
+if __name__ == '__main__':
+ if os.geteuid() == 0:
+ sys.stderr.write("Must be run non-root; aborting.\n")
+ sys.exit(1)
+
+ defaults = read_test_input(test_base + "_defaults.txt", state="ticket")
+ print defaults
+ sys.exit(0)
+
+
+##
+##name value
+##
+##value.match
+##
+##function void():
+## tmp_path = '/tmp/booth-tests'
+## if not os.path.exists(tmp_path):
+## os.makedirs(tmp_path)
+## test_run_path = tempfile.mkdtemp(prefix='%d.' % time.time(), dir=tmp_path)
+##
+## suite = unittest.TestSuite()
+## testclasses = [
+## SiteConfigTests,
+## #ArbitratorConfigTests,
+## ClientConfigTests,
+## ]
+## for testclass in testclasses:
+## testclass.test_run_path = test_run_path
+## suite.addTests(unittest.TestLoader().loadTestsFromTestCase(testclass))
+##
+## runner_args = {
+## 'verbosity' : 4,
+## }
+## major, minor, micro, releaselevel, serial = sys.version_info
+## if major > 2 or (major == 2 and minor >= 7):
+## # New in 2.7
+## runner_args['buffer'] = True
+## runner_args['failfast'] = True
+## pass
+##
+## # not root anymore, so safe
+## # needed because old instances might still use the UDP port.
+## os.system("killall boothd")
+##
+## runner = unittest.TextTestRunner(**runner_args)
+## result = runner.run(suite)
+##
+## if result.wasSuccessful():
+## shutil.rmtree(test_run_path)
+## sys.exit(0)
+## else:
+## print "Left %s for debugging" % test_run_path
+## s
+##
diff --git a/unit-tests/_defaults.txt b/unit-tests/_defaults.txt
new file mode 100644
index 0000000..e96e4f0
--- /dev/null
+++ b/unit-tests/_defaults.txt
@@ -0,0 +1,42 @@
+# vim: ft=sh et :
+
+
+# ticket defaults, mostly set via config file.
+ticket:
+
+ name "ticket"
+
+ ## these would matter if testing via GDB had high latencies
+ #expiry 60
+ #timeout 10
+ #acquire_after 30
+
+
+
+ # defaults for all tests
+ state ST_INIT
+ next_cron time(0)+500
+ # local is site[0] per convention
+
+ owner booth_conf->site[1]
+ expires time(0)+600
+ last_ack_ballot 242
+
+ proposer 0
+ proposed_owner 0
+ new_ballot 0
+ proposal_acknowledges 0
+ retry_number 0
+
+
+
+# defaults for input message.
+# sender is a peer, and it wants something.
+message:
+
+ header.id "ticket"
+ owner -1
+ ballot 0
+ prev_ballot 0
+ expiry 0
+
diff --git a/unit-tests/booth.conf b/unit-tests/booth.conf
new file mode 100644
index 0000000..2988387
--- /dev/null
+++ b/unit-tests/booth.conf
@@ -0,0 +1,16 @@
+# "local"
+site=127.0.0.1
+
+# these should not exist, although it shouldn't matter much
+# because no packets should be sent anyway
+arbitrator="127.0.0.243"
+site="127.0.0.244"
+
+# The ticket name, which corresponds to a set of resources which can be
+# fail-overed among different sites.
+ticket="ticketA"
+ticket="ticketB"
+ expire = 60
+ timeout = 10
+ acquire-after = 30
+ weights = 1,2,3
diff --git a/unit-tests/init-catchup.txt b/unit-tests/init-catchup.txt
new file mode 100644
index 0000000..621c209
--- /dev/null
+++ b/unit-tests/init-catchup.txt
@@ -0,0 +1,6 @@
+
+
+
+input:
+ :
+

File Metadata

Mime Type
text/x-diff
Expires
Wed, Jun 25, 6:27 AM (10 h, 54 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1952434
Default Alt Text
(6 KB)

Event Timeline