Infrastructure: Switch testing over to Autotest.
[mLib] / struct / t / da-gtest.py
diff --git a/struct/t/da-gtest.py b/struct/t/da-gtest.py
new file mode 100644 (file)
index 0000000..14bc0cc
--- /dev/null
@@ -0,0 +1,180 @@
+#! /usr/bin/python
+### -*-python-*-
+###
+### Generate input script and expected output for dynamic array testing.
+
+import sys as SYS
+import random as R
+
+###--------------------------------------------------------------------------
+### Command-line parsing.
+
+SYS.argv[0:1] = []
+def arg(default = None):
+  if len(SYS.argv):
+    r = SYS.argv[0]
+    SYS.argv[0:1] = []
+    return r
+  else:
+    return default
+
+R.seed(None)
+SEED = int(arg(str(R.randrange(0, 1 << 32))), 0)
+R.seed(SEED)
+
+LINES = int(arg(1000))
+
+###--------------------------------------------------------------------------
+### Initialization.
+
+SERIAL = 1
+ARRAY = []
+
+SCRIPT = open('da.script', 'w')
+WIN = open('expout', 'w')
+
+###--------------------------------------------------------------------------
+### Utility functions.
+
+OPS = []
+def op(weight):
+  """
+  Operation decorator.  Add the following function to the operations table,
+  with the given probability WEIGHT.  This works as follows: if TOTAL is the
+  total of all the WEIGHTs, then this operation has a probability of
+  WEIGHT/TOTAL of being selected.
+  """
+  def _(cls):
+    OPS.append((weight, cls))
+    return cls
+  return _
+
+def serial():
+  """Return the next number in a simple sequence."""
+  global SERIAL
+  SERIAL += 1
+  return SERIAL - 1
+
+def mkseq():
+  """Return a short list of stuff to be added to the array."""
+  seq = [serial()]
+  while R.randrange(0, 4) < 3: seq.append(serial())
+  return seq
+
+def mkseqlen():
+  """Return a length of stuff to be removed from the array."""
+  n = 1
+  while R.randrange(0, 4) < 3: n += 1
+  return n
+
+###--------------------------------------------------------------------------
+### The actual operations.
+
+@op(20)
+def op_push():
+  n = serial()
+  SCRIPT.write('push %d\n' % n)
+  ARRAY.append(n)
+@op(20)
+def op_pop():
+  SCRIPT.write('pop\n')
+  if not ARRAY:
+    WIN.write('*UFLOW*\n')
+  else:
+    n, = ARRAY[-1:]
+    ARRAY[-1:] = []
+    WIN.write('%d\n' % n)
+@op(20)
+def op_unshift():
+  n = serial()
+  SCRIPT.write('unshift %d\n' % n)
+  ARRAY[0:0] = [n]
+@op(20)
+def op_shift():
+  SCRIPT.write('shift\n')
+  if not ARRAY:
+    WIN.write('*UFLOW*\n')
+  else:
+    n = ARRAY[0]
+    ARRAY[0:1] = []
+    WIN.write('%d\n' % n)
+
+@op(10)
+def op_insert():
+  stuff = mkseq()
+  SCRIPT.write('insert ' + ' '.join(['%d' % i for i in stuff]) + '\n')
+  ARRAY[0:0] = stuff
+@op(10)
+def op_append():
+  global ARRAY                          # += is a binding occurrence
+  stuff = mkseq()
+  SCRIPT.write('append ' + ' '.join(['%d' % i for i in stuff]) + '\n')
+  ARRAY += stuff
+
+@op(20)
+def op_delete():
+  if len(ARRAY) < LINES/10: return
+  n = mkseqlen()
+  SCRIPT.write('delete %d\n' % n)
+  if n > len(ARRAY): WIN.write('*UFLOW*\n')
+  else: ARRAY[0:n] = []
+@op(20)
+def op_reduce():
+  if len(ARRAY) < LINES/10: return
+  n = mkseqlen()
+  SCRIPT.write('reduce %d\n' % n)
+  if n > len(ARRAY): WIN.write('*UFLOW*\n')
+  else: ARRAY[-n:] = []
+
+def mkindex():
+  if not ARRAY: ix = 0
+  else: ix = R.randrange(0, len(ARRAY))
+  while R.randrange(0, 2) < 1: ix += 1
+  return ix
+
+@op(20)
+def op_set():
+  global ARRAY                          # += is a binding occurrence
+  ix, x = mkindex(), serial()
+  SCRIPT.write('set %d %d\n' % (ix, x))
+  if ix >= len(ARRAY): ARRAY += [-1] * (ix - len(ARRAY) + 1)
+  ARRAY[ix] = x
+@op(20)
+def op_get():
+  ix = mkindex()
+  SCRIPT.write('get %d\n' % ix)
+  if ix >= len(ARRAY): WIN.write('*RANGE*\n')
+  else: WIN.write('%d\n' % ARRAY[ix])
+
+@op(10)
+def op_first():
+  SCRIPT.write('first\n')
+  if len(ARRAY): WIN.write('%d\n' % ARRAY[0])
+  else: WIN.write('*RANGE*\n')
+@op(10)
+def op_last():
+  SCRIPT.write('last\n')
+  if len(ARRAY): WIN.write('%d\n' % ARRAY[-1])
+  else: WIN.write('*RANGE*\n')
+
+@op(1)
+def op_show():
+  SCRIPT.write('show\n')
+  if not ARRAY: WIN.write('*EMPTY*\n')
+  else: WIN.write(' '.join(['%d' % i for i in ARRAY]) + '\n')
+
+###--------------------------------------------------------------------------
+### Generate the output.
+
+OPTAB = []
+for p, func in OPS:
+  OPTAB += [func] * p
+for i in xrange(LINES):
+  OPTAB[R.randrange(0, len(OPTAB))]()
+op_show()
+
+SCRIPT.close()
+WIN.close()
+open('da.seed', 'w').write('da-gtest seed = %08x\n' % SEED)
+
+###----- That's all, folks --------------------------------------------------