#! /usr/bin/python ### -*-python-*- ### ### Generate input script and expected output for dynamic array testing. import sys as SYS import random as R if SYS.version_info >= (3,): xrange = range ###-------------------------------------------------------------------------- ### 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 --------------------------------------------------