github.com/attic-labs/noms@v0.0.0-20210827224422-e5fa29d95e8b/samples/go/nomdex/parser_test.go (about) 1 // Copyright 2016 Attic Labs, Inc. All rights reserved. 2 // Licensed under the Apache License, version 2.0: 3 // http://www.apache.org/licenses/LICENSE-2.0 4 5 package main 6 7 import ( 8 "testing" 9 "text/scanner" 10 11 "github.com/attic-labs/noms/go/chunks" 12 "github.com/attic-labs/noms/go/datas" 13 "github.com/attic-labs/noms/go/types" 14 "github.com/stretchr/testify/assert" 15 ) 16 17 type scannerResult struct { 18 tok int 19 text string 20 } 21 22 type parseResult struct { 23 query string 24 ex expr 25 } 26 27 func TestQueryScanner(t *testing.T) { 28 assert := assert.New(t) 29 30 s := NewQueryScanner(`9 (99.9) -9 0x7F "99.9" and or http://localhost:8000/cli-tour::yo <= >= < > = _ !=`) 31 32 scannerResults := []scannerResult{ 33 {tok: scanner.Int, text: "9"}, 34 {tok: int('('), text: "("}, 35 {tok: scanner.Float, text: "99.9"}, 36 {tok: int(')'), text: ")"}, 37 {tok: '-', text: "-"}, 38 {tok: scanner.Int, text: "9"}, 39 {tok: scanner.Int, text: "0x7F"}, 40 {tok: scanner.String, text: `"99.9"`}, 41 {tok: scanner.Ident, text: "and"}, 42 {tok: scanner.Ident, text: "or"}, 43 {tok: scanner.Ident, text: "http://localhost:8000/cli-tour::yo"}, 44 {tok: scanner.Ident, text: "<="}, 45 {tok: scanner.Ident, text: ">="}, 46 {tok: scanner.Ident, text: "<"}, 47 {tok: scanner.Ident, text: ">"}, 48 {tok: int('='), text: "="}, 49 {tok: int('_'), text: "_"}, 50 {tok: scanner.Ident, text: "!="}, 51 } 52 53 for _, sr := range scannerResults { 54 tok := s.Scan() 55 assert.Equal(sr.tok, int(tok), "expected text: %s, found: %s, pos: %s", sr.text, s.TokenText(), s.Pos()) 56 assert.Equal(sr.text, s.TokenText()) 57 } 58 tok := s.Scan() 59 assert.Equal(scanner.EOF, int(tok)) 60 } 61 62 func TestPeek(t *testing.T) { 63 assert := assert.New(t) 64 65 s := NewQueryScanner(`_ < "one"`) 66 scannerResults := []scannerResult{ 67 {tok: int('_'), text: "_"}, 68 {tok: scanner.Ident, text: "<"}, 69 {tok: scanner.String, text: `"one"`}, 70 {tok: scanner.EOF, text: ""}, 71 } 72 73 for _, sr := range scannerResults { 74 assert.Equal(sr.tok, int(s.Peek())) 75 assert.Equal(sr.text, s.TokenText()) 76 assert.Equal(sr.tok, int(s.Scan())) 77 assert.Equal(sr.text, s.TokenText()) 78 } 79 } 80 81 func TestParsing(t *testing.T) { 82 assert := assert.New(t) 83 84 re1 := compExpr{"index1", equals, types.Number(2015)} 85 re2 := compExpr{"index1", gte, types.Number(2020)} 86 re3 := compExpr{"index1", lte, types.Number(2022)} 87 re4 := compExpr{"index1", lt, types.Number(-2030)} 88 re5 := compExpr{"index1", ne, types.Number(3.5)} 89 re6 := compExpr{"index1", ne, types.Number(-3500.4536632)} 90 re7 := compExpr{"index1", ne, types.String("whassup")} 91 92 queries := []parseResult{ 93 {`index1 = 2015`, re1}, 94 {`(index1 = 2015 )`, re1}, 95 {`(((index1 = 2015 ) ))`, re1}, 96 {`index1 = 2015 or index1 >= 2020`, logExpr{or, re1, re2, "index1"}}, 97 {`(index1 = 2015) or index1 >= 2020`, logExpr{or, re1, re2, "index1"}}, 98 {`index1 = 2015 or (index1 >= 2020)`, logExpr{or, re1, re2, "index1"}}, 99 {`(index1 = 2015 or index1 >= 2020)`, logExpr{or, re1, re2, "index1"}}, 100 {`(index1 = 2015 or index1 >= 2020) and index1 <= 2022`, logExpr{and, logExpr{or, re1, re2, "index1"}, re3, "index1"}}, 101 {`index1 = 2015 or index1 >= 2020 and index1 <= 2022`, logExpr{or, re1, logExpr{and, re2, re3, "index1"}, "index1"}}, 102 {`index1 = 2015 or index1 >= 2020 and index1 <= 2022 or index1 < -2030`, logExpr{or, re1, logExpr{and, re2, logExpr{or, re3, re4, "index1"}, "index1"}, "index1"}}, 103 {`(index1 = 2015 or index1 >= 2020) and (index1 <= 2022 or index1 < -2030)`, logExpr{and, logExpr{or, re1, re2, "index1"}, logExpr{or, re3, re4, "index1"}, "index1"}}, 104 {`index1 != 3.5`, re5}, 105 {`index1 != -3500.4536632`, re6}, 106 {`index1 != "whassup"`, re7}, 107 } 108 109 storage := &chunks.MemoryStorage{} 110 db := datas.NewDatabase(storage.NewView()) 111 _, err := db.CommitValue(db.GetDataset("index1"), types.NewMap(db, types.String("one"), types.NewSet(db, types.String("two")))) 112 assert.NoError(err) 113 114 im := &indexManager{db: db, indexes: map[string]types.Map{}} 115 for _, pr := range queries { 116 expr, err := parseQuery(pr.query, im) 117 assert.NoError(err) 118 assert.Equal(pr.ex, expr, "bad query: %s", pr.query) 119 } 120 121 badQueries := []string{ 122 `sdfsd = 2015`, 123 `index1 = "unfinished string`, 124 `index1 and 2015`, 125 `index1 < `, 126 `index1 < 2015 and ()`, 127 `index1 < 2015 an index1 > 2016`, 128 `(index1 < 2015) what`, 129 `(index1< 2015`, 130 `(badIndexName < 2015)`, 131 } 132 133 im1 := &indexManager{db: db, indexes: map[string]types.Map{}} 134 for _, q := range badQueries { 135 expr, err := parseQuery(q, im1) 136 assert.Error(err) 137 assert.Nil(expr) 138 } 139 }