github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/libkb/assertion_parser_test.go (about) 1 // Copyright 2015 Keybase, Inc. All rights reserved. Use of 2 // this source code is governed by the included BSD license. 3 4 package libkb 5 6 import ( 7 "strings" 8 "testing" 9 10 "github.com/stretchr/testify/require" 11 ) 12 13 func testLexer(t *testing.T, name string, s string, expected []Token) { 14 lexer := NewLexer(s) 15 i := 0 16 for { 17 tok := lexer.Get() 18 if i >= len(expected) { 19 t.Errorf("%s, unexpected token %d [T%v: '%v']", name, i, tok.Typ, string(tok.value)) 20 break 21 } 22 if !tok.Eq(expected[i]) { 23 t.Errorf("%s, token %d: [T%v: '%v'] != [T%v: '%v']", 24 name, i, tok.Typ, string(tok.value), expected[i].Typ, string(expected[i].value)) 25 } 26 if tok.Typ == EOF { 27 break 28 } 29 i++ 30 } 31 } 32 33 func TestLexer1(t *testing.T) { 34 s := "http://foo.com && http://bar.com" 35 expected := []Token{ 36 {URL, []byte("http://foo.com")}, 37 {AND, []byte("&&")}, 38 {URL, []byte("http://bar.com")}, 39 {EOF, []byte{}}, 40 } 41 testLexer(t, "test1", s, expected) 42 } 43 44 func TestLexer2(t *testing.T) { 45 s := " ( a && b ) || ( c && d && e ) " 46 expected := []Token{ 47 {LPAREN, []byte("(")}, 48 {URL, []byte("a")}, 49 {AND, []byte("&&")}, 50 {URL, []byte("b")}, 51 {RPAREN, []byte(")")}, 52 {OR, []byte("||")}, 53 {LPAREN, []byte("(")}, 54 {URL, []byte("c")}, 55 {AND, []byte("&&")}, 56 {URL, []byte("d")}, 57 {AND, []byte("&&")}, 58 {URL, []byte("e")}, 59 {RPAREN, []byte(")")}, 60 {EOF, []byte{}}, 61 } 62 testLexer(t, "test2", s, expected) 63 } 64 65 func TestLexer3(t *testing.T) { 66 s := "aa && |bb" 67 expected := []Token{ 68 {URL, []byte("aa")}, 69 {AND, []byte("&&")}, 70 {ERROR, []byte("|bb")}, 71 {EOF, []byte{}}, 72 } 73 testLexer(t, "test3", s, expected) 74 } 75 76 func TestLexerSquareBrackets(t *testing.T) { 77 s := "michal,[michal@zapu.net]@email" 78 expected := []Token{ 79 {URL, []byte("michal")}, 80 {OR, []byte(",")}, 81 {URL, []byte("[michal@zapu.net]@email")}, 82 {EOF, []byte{}}, 83 } 84 testLexer(t, "square brackets", s, expected) 85 } 86 87 func TestLexerEmailInvalidParentheses(t *testing.T) { 88 // Rejected proposal for round brackets, but make sure 89 // there is expected way in which it is parsed. 90 91 s := "michal,(michal@zapu.net)@email" 92 expected := []Token{ 93 {URL, []byte("michal")}, 94 {OR, []byte(",")}, 95 {LPAREN, []byte("(")}, 96 {URL, []byte("michal@zapu.net")}, 97 {RPAREN, []byte(")")}, 98 {URL, []byte("@email")}, 99 {EOF, []byte{}}, 100 } 101 testLexer(t, "round brackets", s, expected) 102 103 s = "twitter://alice&&(alice@keybasers.de)@email" 104 expected = []Token{ 105 {URL, []byte("twitter://alice")}, 106 {AND, []byte("&&")}, 107 {LPAREN, []byte("(")}, 108 {URL, []byte("alice@keybasers.de")}, 109 {RPAREN, []byte(")")}, 110 {URL, []byte("@email")}, 111 {EOF, []byte{}}, 112 } 113 testLexer(t, "round brackets", s, expected) 114 } 115 116 func TestLexerEmailPlusSign(t *testing.T) { 117 s := "twitter://alice&&[a.li.c+e@keybasers.de]@email" 118 expected := []Token{ 119 {URL, []byte("twitter://alice")}, 120 {AND, []byte("&&")}, 121 {URL, []byte("[a.li.c+e@keybasers.de]@email")}, 122 {EOF, []byte{}}, 123 } 124 testLexer(t, "square brackets 1", s, expected) 125 126 s = "alice@twitter||email:[a.li.c+e@keybasers.de]" 127 expected = []Token{ 128 {URL, []byte("alice@twitter")}, 129 {OR, []byte("||")}, 130 {URL, []byte("email:[a.li.c+e@keybasers.de]")}, 131 {EOF, []byte{}}, 132 } 133 testLexer(t, "square brackets 2", s, expected) 134 135 s = "alice@twitter||email://[a.li.c+e@keybasers.de]" 136 expected = []Token{ 137 {URL, []byte("alice@twitter")}, 138 {OR, []byte("||")}, 139 {URL, []byte("email://[a.li.c+e@keybasers.de]")}, 140 {EOF, []byte{}}, 141 } 142 testLexer(t, "square brackets 3", s, expected) 143 144 // This is not a valid email, but not caught at the lexer stage, 145 // it's still supposed to generate URL token. 146 s = "twitter:ae,email:[a,e@keybasers.de]" 147 expected = []Token{ 148 {URL, []byte("twitter:ae")}, 149 {OR, []byte(",")}, 150 {URL, []byte("email:[a,e@keybasers.de]")}, 151 {EOF, []byte{}}, 152 } 153 testLexer(t, "square brackets 4", s, expected) 154 155 // Same here: 156 s = "email:[],email://[]" 157 expected = []Token{ 158 {URL, []byte("email:[]")}, 159 {OR, []byte(",")}, 160 {URL, []byte("email://[]")}, 161 {EOF, []byte{}}, 162 } 163 testLexer(t, "square brackets 5", s, expected) 164 165 // Weirdness 166 s = "[michal]@[keybase]" 167 expected = []Token{ 168 {URL, []byte("[michal]@")}, 169 {ERROR, []byte("[keybase]")}, 170 {EOF, []byte{}}, 171 } 172 testLexer(t, "square brackets 6", s, expected) 173 } 174 175 func TestParser1(t *testing.T) { 176 inp := " aa || bb && cc ||\n dd ||\n ee && ff || gg && (hh ||\nii)" 177 outp := "aa,bb+cc,dd,ee+ff,gg+(hh,ii)" 178 expr, err := AssertionParse(testAssertionContext{}, inp) 179 if err != nil { 180 t.Error(err) 181 } else if expr.String() != outp { 182 t.Errorf("Wrong parse result: %s v %s", expr.String(), outp) 183 } 184 } 185 186 func TestParser2(t *testing.T) { 187 inp := " web://a.aa || http://b.bb && dns://c.cc ||\n dd ||\n pgp:ee && reddit:foo || twitter:goo && (https:h.in ||\ndns:i.co)" 188 outp := "a.aa@web,b.bb@http+c.cc@dns,dd,ee@pgp+foo@reddit,goo@twitter+(h.in@https,i.co@dns)" 189 expr, err := AssertionParse(testAssertionContext{}, inp) 190 if err != nil { 191 t.Error(err) 192 } else if expr.String() != outp { 193 t.Errorf("Wrong parse result: %s v %s", expr.String(), outp) 194 } 195 } 196 197 func TestNormalization(t *testing.T) { 198 // Test moved to externals/ since it requires knowledge of social networks 199 } 200 201 type Pair struct { 202 k, v string 203 } 204 205 func TestParserFail1(t *testing.T) { 206 bads := []Pair{ 207 {"aa ||", "Unexpected EOF parsing assertion"}, 208 {"aa &&", "Unexpected EOF parsing assertion"}, 209 {"(aa", "Unbalanced parentheses"}, 210 {"aa && dns:", "Bad assertion, no value given (key=dns)"}, 211 {"&& aa", "Unexpected token: &&"}, 212 {"|| aa", "Unexpected token: ||"}, 213 {"aa)", "Found junk at end of input: )"}, 214 {"()", "Illegal parenthetical expression"}, 215 {"a@pgp", "bad hex string: 'a'"}, 216 {"aBCP@pgp", "bad hex string: 'abcp'"}, 217 {"jj@pgp", "bad hex string: 'jj'"}, 218 {"aa && |bb", "Syntax error when parsing: |bb"}, 219 } 220 221 for _, bad := range bads { 222 expr, err := AssertionParse(testAssertionContext{}, bad.k) 223 if err == nil { 224 t.Errorf("Expected a parse error in %s (got %v)", bad, expr) 225 } else if err.Error() != bad.v { 226 t.Errorf("Got wrong error; wanted '%s', but got '%s'", bad.v, err) 227 } 228 } 229 } 230 231 func TestParseAssertionsWithReaders(t *testing.T) { 232 units := []struct { 233 input string 234 writers string // expected writers (reserialized and comma-sep) 235 readers string // expected readers 236 error string // expected error regex 237 }{ 238 { 239 input: "alice,bob&&bob@twitter", 240 writers: "alice,bob+bob@twitter", 241 }, 242 { 243 input: "alice,bob&&bob@twitter#char", 244 writers: "alice,bob+bob@twitter", 245 readers: "char", 246 }, 247 { 248 input: "alice#char,liz", 249 writers: "alice", 250 readers: "char,liz", 251 }, 252 { 253 input: "alice", 254 writers: "alice", 255 }, 256 { 257 // doesn't dedup at the moment 258 input: "alice#alice", 259 writers: "alice", 260 readers: "alice", 261 }, 262 { 263 input: "alice+github:alice", 264 writers: "alice+alice@github", 265 }, 266 { 267 input: "1f5DE74F4D4E8884775F2BF1514FC07220D4A61A@pgp,milessteele.com@https", 268 writers: "1f5de74f4d4e8884775f2bf1514fc07220d4a61a@pgp,milessteele.com@https", 269 }, 270 { 271 input: "", 272 error: `^empty assertion$`, 273 }, 274 { 275 input: "#char,liz", 276 error: `.*`, 277 }, 278 { 279 input: "char||liz", 280 error: `disallowed.*OR`, 281 }, 282 } 283 284 ser := func(exprs []AssertionExpression) string { 285 var strs []string 286 for _, expr := range exprs { 287 strs = append(strs, expr.String()) 288 } 289 return strings.Join(strs, ",") 290 } 291 292 for i, unit := range units { 293 t.Logf("%v: %v", i, unit.input) 294 writers, readers, err := ParseAssertionsWithReaders(testAssertionContext{}, unit.input) 295 if len(unit.error) == 0 { 296 require.NoError(t, err) 297 require.Equal(t, unit.writers, ser(writers)) 298 require.Equal(t, unit.readers, ser(readers)) 299 } else { 300 require.Error(t, err) 301 require.Regexp(t, unit.error, err.Error()) 302 } 303 } 304 }