go-vise

Constrained Size Output Virtual Machine
Info | Log | Files | Refs | README | LICENSE

testutil.go (7828B)


      1 package dbtest
      2 
      3 import (
      4 	"bytes"
      5 	"context"
      6 	"encoding/hex"
      7 	"errors"
      8 	"fmt"
      9 	"path"
     10 	"testing"
     11 
     12 	"git.defalsify.org/vise.git/lang"
     13 	"git.defalsify.org/vise.git/db"
     14 )
     15 
     16 
     17 type testCase struct {
     18 	typ uint8
     19 	s string
     20 	k []byte
     21 	v []byte
     22 	x []byte
     23 	l *lang.Language
     24 	t string
     25 }
     26 
     27 type testVector struct {
     28 	c map[string]*testCase
     29 	v []string
     30 	i int
     31 	s string
     32 }
     33 
     34 type testFunc func() testVector
     35 
     36 var (
     37 	tests = []testFunc{
     38 		generateSessionTestVectors,
     39 		generateMultiSessionTestVectors,
     40 		generateLanguageTestVectors,
     41 		generateMultiLanguageTestVectors,
     42 		generateSessionLanguageTestVectors,
     43 	}
     44 	dataTypeDebug = map[uint8]string{
     45 		db.DATATYPE_BIN: "bytecode",
     46 		db.DATATYPE_TEMPLATE: "template",
     47 		db.DATATYPE_MENU: "menu",
     48 		db.DATATYPE_STATICLOAD: "staticload",
     49 		db.DATATYPE_STATE: "state",
     50 		db.DATATYPE_USERDATA: "udata",
     51 	}
     52 )
     53 
     54 func(tc *testCase) Key() []byte {
     55 	return tc.k
     56 }
     57 
     58 func(tc *testCase) Val() []byte {
     59 	return tc.v
     60 }
     61 
     62 func(tc *testCase) Typ() uint8 {
     63 	return tc.typ
     64 }
     65 
     66 func(tc *testCase) Session() string {
     67 	return tc.s
     68 }
     69 
     70 func(tc *testCase) Lang() string {
     71 	if tc.l == nil {
     72 		return ""
     73 	}
     74 	return tc.l.Code
     75 }
     76 
     77 func(tc *testCase) Expect() []byte {
     78 	return tc.x
     79 }
     80 
     81 func(tc *testCase) Label() string {
     82 	return tc.t
     83 }
     84 
     85 func(tv *testVector) add(typ uint8, k string, v string, session string, expect string, language string)  {
     86 	var b []byte
     87 	var x []byte
     88 	var err error
     89 	var ln *lang.Language
     90 
     91 	if typ == db.DATATYPE_BIN {
     92 		b, err = hex.DecodeString(v)
     93 		if err != nil {
     94 			panic(err)
     95 		}
     96 		x, err = hex.DecodeString(expect)
     97 		if err != nil {
     98 			panic(err)
     99 		}
    100 	} else {
    101 		b = []byte(v)
    102 		x = []byte(expect)
    103 	}
    104 	
    105 	if language != "" {
    106 		lo, err := lang.LanguageFromCode(language)
    107 		if err != nil {
    108 			panic(err)
    109 		}
    110 		ln = &lo
    111 	}
    112 	s := dataTypeDebug[typ]
    113 	s = path.Join(s, session)
    114 	s = path.Join(s, k)
    115 	if ln != nil {
    116 		s = path.Join(s, language)
    117 	}
    118 	o := &testCase {
    119 		typ: typ,
    120 		k: []byte(k),
    121 		v: b,
    122 		s: session,
    123 		x: x,
    124 		l: ln,
    125 		t: s,
    126 	}
    127 	tv.c[s] = o
    128 	i := len(tv.v)
    129 	tv.v = append(tv.v, s)
    130 	logg.Tracef("add testcase", "i", i, "s", s, "k", o.k)
    131 }
    132 
    133 func(tv *testVector) next() (int, *testCase) {
    134 	i := tv.i
    135 	if i == len(tv.v) {
    136 		return -1, nil
    137 	}
    138 	tv.i++
    139 	return i, tv.c[tv.v[i]]
    140 }
    141 
    142 func(tv *testVector) rewind() {
    143 	tv.i = 0
    144 }
    145 
    146 func(tv *testVector) put(ctx context.Context, db db.Db) error {
    147 	var i int
    148 	var tc *testCase
    149 	defer tv.rewind()
    150 
    151 	for true {
    152 		i, tc = tv.next()
    153 		if i == -1 {
    154 			break
    155 		}
    156 		logg.TraceCtxf(ctx, "running put for test", "vector", tv.label(), "case", tc.Label())
    157 		db.SetPrefix(tc.Typ())
    158 		db.SetSession(tc.Session())
    159 		db.SetLock(tc.Typ(), false)
    160 		db.SetLanguage(nil)
    161 		if tc.Lang() != "" {
    162 			ln, err := lang.LanguageFromCode(tc.Lang())
    163 			if err != nil {
    164 				return err
    165 			}
    166 			db.SetLanguage(&ln)
    167 		}
    168 		err := db.Put(ctx, tc.Key(), tc.Val())
    169 		if err != nil {
    170 			return err
    171 		}
    172 		db.SetLock(tc.Typ(), true)
    173 	}
    174 	return nil
    175 }
    176 
    177 func(tv *testVector) label() string {
    178 	return tv.s
    179 }
    180 
    181 func generateSessionTestVectors() testVector {
    182 	tv := testVector{c: make(map[string]*testCase), s: "session"}
    183 	tv.add(db.DATATYPE_BIN, "foo", "deadbeef", "", "beeffeed", "")
    184 	tv.add(db.DATATYPE_BIN, "foo", "beeffeed", "inky", "beeffeed", "")
    185 	tv.add(db.DATATYPE_TEMPLATE, "foo", "tinkywinky", "", "dipsy", "")
    186 	tv.add(db.DATATYPE_TEMPLATE, "foo", "dipsy", "pinky", "dipsy", "")
    187 	tv.add(db.DATATYPE_MENU, "foo", "lala", "", "pu", "")
    188 	tv.add(db.DATATYPE_MENU, "foo", "pu", "blinky", "pu", "")
    189 	tv.add(db.DATATYPE_STATICLOAD, "foo", "bar", "", "baz", "")
    190 	tv.add(db.DATATYPE_STATICLOAD, "foo", "baz", "clyde", "baz", "")
    191 	tv.add(db.DATATYPE_STATE, "foo", "xyzzy", "", "xyzzy", "")
    192 	tv.add(db.DATATYPE_STATE, "foo", "plugh", "sue", "plugh", "")
    193 	tv.add(db.DATATYPE_USERDATA, "foo", "itchy", "", "itchy", "")
    194 	tv.add(db.DATATYPE_USERDATA, "foo", "scratchy", "poochie", "scratchy", "")
    195 	return tv
    196 }
    197 
    198 func generateLanguageTestVectors() testVector {
    199 	tv := testVector{c: make(map[string]*testCase), s: "language"}
    200 	tv.add(db.DATATYPE_BIN, "foo", "deadbeef", "", "beeffeed", "")
    201 	tv.add(db.DATATYPE_BIN, "foo", "beeffeed", "", "beeffeed", "nor")
    202 	tv.add(db.DATATYPE_TEMPLATE, "foo", "tinkywinky", "", "tinkywinky", "")
    203 	tv.add(db.DATATYPE_TEMPLATE, "foo", "dipsy", "", "dipsy", "nor")
    204 	tv.add(db.DATATYPE_MENU, "foo", "lala", "", "lala", "")
    205 	tv.add(db.DATATYPE_MENU, "foo", "pu", "", "pu", "nor")
    206 	tv.add(db.DATATYPE_STATICLOAD, "foo", "bar", "", "bar", "")
    207 	tv.add(db.DATATYPE_STATICLOAD, "foo", "baz", "", "baz", "nor")
    208 	tv.add(db.DATATYPE_STATE, "foo", "xyzzy", "", "plugh", "")
    209 	tv.add(db.DATATYPE_STATE, "foo", "plugh", "", "plugh", "nor")
    210 	tv.add(db.DATATYPE_USERDATA, "foo", "itchy", "", "scratchy", "")
    211 	tv.add(db.DATATYPE_USERDATA, "foo", "scratchy", "", "scratchy", "nor")
    212 	return tv
    213 }
    214 
    215 func generateMultiLanguageTestVectors() testVector {
    216 	tv := testVector{c: make(map[string]*testCase), s: "multilanguage"}
    217 	tv.add(db.DATATYPE_TEMPLATE, "foo", "tinkywinky", "", "pu", "")
    218 	tv.add(db.DATATYPE_TEMPLATE, "foo", "dipsy", "", "dipsy", "nor")
    219 	tv.add(db.DATATYPE_TEMPLATE, "foo", "lala", "", "lala", "swa")
    220 	tv.add(db.DATATYPE_TEMPLATE, "foo", "pu", "", "pu", "")
    221 	return tv
    222 }
    223 
    224 func generateSessionLanguageTestVectors() testVector {
    225 	tv := testVector{c: make(map[string]*testCase), s: "sessionlanguage"}
    226 	tv.add(db.DATATYPE_TEMPLATE, "foo", "tinkywinky", "", "pu", "")
    227 	tv.add(db.DATATYPE_TEMPLATE, "foo", "dipsy", "", "lala", "nor")
    228 	tv.add(db.DATATYPE_TEMPLATE, "foo", "lala", "bar", "lala", "nor")
    229 	tv.add(db.DATATYPE_TEMPLATE, "foo", "pu", "bar", "pu", "")
    230 	tv.add(db.DATATYPE_STATE, "foo", "inky", "", "pinky", "")
    231 	tv.add(db.DATATYPE_STATE, "foo", "pinky", "", "pinky", "nor")
    232 	tv.add(db.DATATYPE_STATE, "foo", "blinky", "bar", "clyde", "nor")
    233 	tv.add(db.DATATYPE_STATE, "foo", "clyde", "bar", "clyde", "")
    234 	tv.add(db.DATATYPE_BIN, "foo", "deadbeef", "", "feebdaed", "")
    235 	tv.add(db.DATATYPE_BIN, "foo", "beeffeed", "", "feebdaed", "nor")
    236 	tv.add(db.DATATYPE_BIN, "foo", "deeffeeb", "baz", "feebdaed", "nor")
    237 	tv.add(db.DATATYPE_BIN, "foo", "feebdaed", "baz", "feebdaed", "")
    238 	return tv
    239 }
    240 
    241 func generateMultiSessionTestVectors() testVector {
    242 	tv := testVector{c: make(map[string]*testCase), s: "multisession"}
    243 	tv.add(db.DATATYPE_TEMPLATE, "foo", "red", "", "blue", "")
    244 	tv.add(db.DATATYPE_TEMPLATE, "foo", "green", "bar", "blue", "")
    245 	tv.add(db.DATATYPE_TEMPLATE, "foo", "blue", "baz", "blue", "")
    246 	tv.add(db.DATATYPE_STATE, "foo", "inky", "", "inky", "")
    247 	tv.add(db.DATATYPE_STATE, "foo", "pinky", "clyde", "pinky", "")
    248 	tv.add(db.DATATYPE_STATE, "foo", "blinky", "sue", "blinky", "")
    249 	tv.add(db.DATATYPE_BIN, "foo", "deadbeef", "", "feebdeef", "")
    250 	tv.add(db.DATATYPE_BIN, "foo", "feedbeef", "bar", "feebdeef", "")
    251 	tv.add(db.DATATYPE_BIN, "foo", "feebdeef", "baz", "feebdeef", "")
    252 	return tv
    253 }
    254 
    255 func runTest(t *testing.T, ctx context.Context, db db.Db, vs testVector) error {
    256 	err := vs.put(ctx, db)
    257 	if err != nil {
    258 		return err
    259 	}
    260 	for true {
    261 		i, tc := vs.next()
    262 		if i == -1 {
    263 			break
    264 		}
    265 		s := fmt.Sprintf("Test%s[%d]%s", vs.label(), i, tc.Label())
    266 		r := t.Run(s, func(t *testing.T) {
    267 			db.SetPrefix(tc.Typ())
    268 			db.SetSession(tc.Session())
    269 			if tc.Lang() != "" {
    270 				ln, err := lang.LanguageFromCode(tc.Lang())
    271 				if err != nil {
    272 					t.Fatal(err)
    273 				}
    274 				db.SetLanguage(&ln)
    275 			} else {
    276 				db.SetLanguage(nil)
    277 			}
    278 			db.SetSession(tc.Session())
    279 			v, err := db.Get(ctx, tc.Key())
    280 			if err != nil {
    281 				t.Fatal(err)
    282 			}
    283 			if !bytes.Equal(tc.Expect(), v) {
    284 				t.Fatalf("expected %s, got %s", tc.Expect(), v)
    285 			}
    286 		})
    287 		if !r {
    288 			return errors.New("subtest fail")
    289 		}
    290 	}
    291 	return nil
    292 
    293 }
    294 
    295 
    296 func runTests(t *testing.T, ctx context.Context, db db.Db) error {
    297 	for _, fn := range tests {
    298 		err := runTest(t, ctx, db, fn())
    299 		if err != nil {
    300 			return err
    301 		}
    302 	}
    303 	
    304 	return nil
    305 }
    306 
    307 func RunTests(t *testing.T, ctx context.Context, db db.Db) error {
    308 	return runTests(t, ctx, db)
    309 }