github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/pvl/interp_test.go (about) 1 // Copyright 2016 Keybase, Inc. All rights reserved. Use of 2 // this source code is governed by the included BSD license. 3 4 package pvl 5 6 import ( 7 "fmt" 8 "strings" 9 "testing" 10 11 "github.com/PuerkitoBio/goquery" 12 libkb "github.com/keybase/client/go/libkb" 13 keybase1 "github.com/keybase/client/go/protocol/keybase1" 14 jsonw "github.com/keybase/go-jsonw" 15 ) 16 17 type interpUnitTest struct { 18 name string 19 proofinfo ProofInfo 20 // Only one of prepvl or prepvlstr should be specified. 21 prepvl map[keybase1.ProofType]string 22 prepvlstr string 23 service keybase1.ProofType 24 25 // What api call to expect (for non-DNS) 26 restype libkb.XAPIResType 27 resjson string 28 reshtml string 29 restext string 30 resdns map[string]([]string) 31 // (Optional) Expect a different url to be fetched than proofinfo.APIURL 32 urloverride string 33 // (Optional) Don't check that the xapi was hit exactly once. 34 allowmanyfetches bool 35 36 // Whether the proof should validate 37 shouldwork bool 38 // (Optional) error status must equal. Must be specified for INVALID_PVL 39 errstatus keybase1.ProofStatus 40 // (Optional) error string must equal 41 errstr string 42 } 43 44 var interpUnitTests = []interpUnitTest{ 45 // There are a lot of these tests in a line. 46 // They are organized into sections with markdown-style headings. 47 // All tests are run by the single runPvlTest function. If you want to run 48 // just one test, set the `solo` variable there. 49 50 // # Basic tests 51 { 52 name: "basichtml", 53 proofinfo: info1, 54 prepvl: map[keybase1.ProofType]string{ 55 keybase1.ProofType_TWITTER: `[[ 56 {"assert_regex_match": { 57 "pattern": "^https://rooter\\.example\\.com/proofs/%{username_service}/[\\d]+\\.htjsxt$", 58 "from": "hint_url" } }, 59 {"fetch": { 60 "kind": "html", 61 "from": "hint_url" } }, 62 {"selector_css": { 63 "selectors": [".twit", 0], 64 "into": "tmp1" } }, 65 {"whitespace_normalize": { 66 "from": "tmp1", 67 "into": "tmp2" } }, 68 {"assert_regex_match": { 69 "pattern": "^.*goodproof.*$", 70 "from": "tmp2" } } 71 ]]`}, 72 service: keybase1.ProofType_TWITTER, 73 restype: libkb.XAPIResHTML, 74 reshtml: html1, 75 shouldwork: true, 76 }, 77 78 // # Tests for individual valid instructions. 79 // Test match and fail of each instruction. 80 81 // ## AssertRegexMatch 82 { 83 name: "AssertRegexMatch-url-ok", 84 proofinfo: info1, 85 prepvl: map[keybase1.ProofType]string{ 86 keybase1.ProofType_COINBASE: `[[ 87 {"assert_regex_match": { 88 "pattern": "^https://rooter\\.example\\.com/proofs/%{username_service}/[\\d]+\\.htjsxt$", 89 "from": "hint_url" } }, 90 {"fetch": { 91 "kind": "string", 92 "from": "hint_url", 93 "into": "tmp1" } } 94 ]]`}, 95 service: keybase1.ProofType_COINBASE, 96 restype: libkb.XAPIResText, 97 restext: "1234", 98 shouldwork: true, 99 }, { 100 name: "AssertRegexMatch-url-fail", 101 proofinfo: info1, 102 prepvl: map[keybase1.ProofType]string{ 103 keybase1.ProofType_HACKERNEWS: `[[ 104 {"assert_regex_match": { 105 "pattern": "^https://rooter\\.example\\.com/proofs/%{username_service}/+\\.htjsxt$", 106 "from": "hint_url" } }, 107 {"fetch": { 108 "kind": "string", 109 "from": "hint_url", 110 "into": "tmp1" } } 111 ]]`}, 112 service: keybase1.ProofType_HACKERNEWS, 113 restype: libkb.XAPIResText, 114 restext: "1234", 115 shouldwork: false, 116 }, { 117 name: "AssertRegexMatch-content-ok", 118 proofinfo: info1, 119 prepvl: map[keybase1.ProofType]string{ 120 keybase1.ProofType_REDDIT: `[[ 121 {"fetch": { 122 "kind": "html", 123 "from": "hint_url" } }, 124 {"selector_css": { 125 "selectors": [".twit", -1], 126 "into": "tmp1" } }, 127 {"whitespace_normalize": { 128 "from": "tmp1", 129 "into": "tmp2" }}, 130 {"assert_regex_match": { 131 "pattern": "^short %{sig_id_short}$", 132 "from": "tmp2" } } 133 ]]`}, 134 service: keybase1.ProofType_REDDIT, 135 restype: libkb.XAPIResHTML, 136 reshtml: html1, 137 shouldwork: true, 138 }, { 139 name: "AssertRegexMatch-content-fail", 140 proofinfo: info1, 141 prepvl: map[keybase1.ProofType]string{ 142 keybase1.ProofType_TWITTER: `[[ 143 {"fetch": { 144 "kind": "html", 145 "from": "hint_url" } }, 146 {"selector_css": { 147 "selectors": [".twit", -1], 148 "into": "tmp1" } }, 149 {"whitespace_normalize": { 150 "from": "tmp1", 151 "into": "tmp2" } }, 152 {"assert_regex_match": { 153 "pattern": "^wrong %{sig_id_short}$", 154 "from": "tmp2" } } 155 ]]`}, 156 service: keybase1.ProofType_TWITTER, 157 restype: libkb.XAPIResHTML, 158 reshtml: html1, 159 shouldwork: false, 160 }, { 161 name: "AssertRegexMatch-content-fail-case", 162 proofinfo: info1, 163 prepvl: map[keybase1.ProofType]string{ 164 keybase1.ProofType_TWITTER: `[[ 165 {"fetch": { 166 "kind": "html", 167 "from": "hint_url" } }, 168 {"selector_css": { 169 "selectors": [".twit", -1], 170 "into": "tmp1" } }, 171 {"assert_regex_match": { 172 "pattern": "^.*SHORT.*$", 173 "from": "tmp1" } } 174 ]]`}, 175 service: keybase1.ProofType_TWITTER, 176 restype: libkb.XAPIResHTML, 177 reshtml: html1, 178 shouldwork: false, 179 }, { 180 name: "AssertRegexMatch-negate-ok", 181 proofinfo: info1, 182 prepvl: map[keybase1.ProofType]string{ 183 keybase1.ProofType_COINBASE: `[[ 184 {"assert_regex_match": { 185 "pattern": "^.*notacommonstringatall.*$", 186 "from": "hint_url", 187 "negate": true } }, 188 {"fetch": { 189 "kind": "string", 190 "from": "hint_url", 191 "into": "tmp1" } } 192 ]]`}, 193 service: keybase1.ProofType_COINBASE, 194 restype: libkb.XAPIResText, 195 restext: "1234", 196 shouldwork: true, 197 }, { 198 name: "AssertRegexMatch-negate-fail", 199 proofinfo: info1, 200 prepvl: map[keybase1.ProofType]string{ 201 keybase1.ProofType_COINBASE: `[[ 202 {"assert_regex_match": { 203 "pattern": "^.*rooter.*$", 204 "negate": true, 205 "from": "hint_url" } }, 206 {"fetch": { 207 "kind": "string", 208 "from": "hint_url", 209 "into": "tmp1" } } 210 ]]`}, 211 service: keybase1.ProofType_COINBASE, 212 restype: libkb.XAPIResText, 213 restext: "1234", 214 shouldwork: false, 215 }, 216 217 // ## AssertFindBase64 218 { 219 name: "AssertFindBase64-ok", 220 proofinfo: info1, 221 prepvl: map[keybase1.ProofType]string{ 222 keybase1.ProofType_GENERIC_WEB_SITE: `[[ 223 {"fetch": { 224 "kind": "string", 225 "from": "hint_url", 226 "into": "tmp1" } }, 227 {"assert_find_base64": { 228 "needle": "sig", 229 "haystack": "tmp1" } } 230 ]]`}, 231 service: keybase1.ProofType_GENERIC_WEB_SITE, 232 restype: libkb.XAPIResText, 233 // the sig must be on a line with only spacing. 234 restext: fmt.Sprintf(" asdf\n \t\t .\n %v\t\nzad\t.\n", sig1), 235 shouldwork: true, 236 }, { 237 name: "AssertFindBase64-fail", 238 proofinfo: info1, 239 prepvl: map[keybase1.ProofType]string{ 240 keybase1.ProofType_GENERIC_WEB_SITE: `[[ 241 {"fetch": { 242 "kind": "string", 243 "from": "hint_url", 244 "into": "tmp1" } }, 245 {"assert_find_base64": { 246 "needle": "sig", 247 "haystack": "tmp1" } } 248 ]]`}, 249 service: keybase1.ProofType_GENERIC_WEB_SITE, 250 restype: libkb.XAPIResText, 251 restext: sig1[1:], 252 shouldwork: false, 253 }, 254 255 // ## AssertCompare 256 { 257 name: "AssertCompare-cicmp-ok", 258 proofinfo: info1, 259 prepvl: map[keybase1.ProofType]string{ 260 keybase1.ProofType_GENERIC_WEB_SITE: `[[ 261 {"fetch": { 262 "kind": "string", 263 "from": "hint_url", 264 "into": "tmp1" } }, 265 {"assert_compare": { 266 "cmp": "cicmp", 267 "a": "username_keybase", 268 "b": "tmp1" } } 269 ]]`}, 270 service: keybase1.ProofType_GENERIC_WEB_SITE, 271 restype: libkb.XAPIResText, 272 restext: "krONK", 273 shouldwork: true, 274 }, { 275 name: "AssertCompare-cicmp-fail", 276 proofinfo: info1, 277 prepvl: map[keybase1.ProofType]string{ 278 keybase1.ProofType_GENERIC_WEB_SITE: `[[ 279 {"fetch": { 280 "kind": "string", 281 "from": "hint_url", 282 "into": "tmp1" } }, 283 {"assert_compare": { 284 "cmp": "cicmp", 285 "a": "username_keybase", 286 "b": "tmp1" } } 287 ]]`}, 288 service: keybase1.ProofType_GENERIC_WEB_SITE, 289 restype: libkb.XAPIResText, 290 restext: "kr0nk", 291 shouldwork: false, 292 }, { 293 name: "AssertCompare-stripdots-then-cicmp-ok", 294 proofinfo: info1, 295 prepvl: map[keybase1.ProofType]string{ 296 keybase1.ProofType_GENERIC_WEB_SITE: `[[ 297 {"fetch": { 298 "kind": "string", 299 "from": "hint_url", 300 "into": "tmp1" } }, 301 {"assert_compare": { 302 "cmp": "stripdots-then-cicmp", 303 "a": "username_keybase", 304 "b": "tmp1" } } 305 ]]`}, 306 service: keybase1.ProofType_GENERIC_WEB_SITE, 307 restype: libkb.XAPIResText, 308 restext: "kr.O..NK", 309 shouldwork: true, 310 }, 311 { 312 name: "AssertCompare-stripdots-then-cicmp-fail", 313 proofinfo: info1, 314 prepvl: map[keybase1.ProofType]string{ 315 keybase1.ProofType_GENERIC_WEB_SITE: `[[ 316 {"fetch": { 317 "kind": "string", 318 "from": "hint_url", 319 "into": "tmp1" } }, 320 {"assert_compare": { 321 "cmp": "stripdots-then-cicmp", 322 "a": "username_keybase", 323 "b": "tmp1" } } 324 ]]`}, 325 service: keybase1.ProofType_GENERIC_WEB_SITE, 326 restype: libkb.XAPIResText, 327 restext: "kr0nk", 328 shouldwork: false, 329 }, { 330 name: "AssertCompare-exact-ok", 331 proofinfo: info1, 332 prepvl: map[keybase1.ProofType]string{ 333 keybase1.ProofType_GENERIC_WEB_SITE: `[[ 334 {"fetch": { 335 "kind": "string", 336 "from": "hint_url", 337 "into": "tmp1" } }, 338 {"assert_compare": { 339 "cmp": "exact", 340 "a": "username_keybase", 341 "b": "tmp1" } } 342 ]]`}, 343 service: keybase1.ProofType_GENERIC_WEB_SITE, 344 restype: libkb.XAPIResText, 345 restext: "kronk", 346 shouldwork: true, 347 }, { 348 name: "AssertCompare-exact-fail", 349 proofinfo: info1, 350 prepvl: map[keybase1.ProofType]string{ 351 keybase1.ProofType_GENERIC_WEB_SITE: `[[ 352 {"fetch": { 353 "kind": "string", 354 "from": "hint_url", 355 "into": "tmp1" } }, 356 {"assert_compare": { 357 "cmp": "exact", 358 "a": "username_keybase", 359 "b": "tmp1" } } 360 ]]`}, 361 service: keybase1.ProofType_GENERIC_WEB_SITE, 362 restype: libkb.XAPIResText, 363 restext: "kroNk", 364 shouldwork: false, 365 }, 366 367 // ## RegexCapture and WhitespaceNormalize tested together 368 { 369 name: "RegexCapture-ok-ignoregroup", 370 proofinfo: info1, 371 prepvl: map[keybase1.ProofType]string{ 372 keybase1.ProofType_GENERIC_WEB_SITE: `[[ 373 {"fetch": { 374 "kind": "html", 375 "from": "hint_url" } }, 376 {"selector_css": { 377 "selectors": ["div.twit", -1], 378 "into": "tmp1" } }, 379 {"whitespace_normalize": { 380 "from": "tmp1", 381 "into": "tmp2" } }, 382 {"regex_capture": { 383 "pattern": "^(?:sHoRt) ([A-Za-z0-9+/=]+)$", 384 "case_insensitive": true, 385 "from": "tmp2", 386 "into": ["tmp3"] } }, 387 {"assert_regex_match": { 388 "pattern": "^%{sig_id_short}$", 389 "from": "tmp3" } } 390 ]]`}, 391 service: keybase1.ProofType_GENERIC_WEB_SITE, 392 restype: libkb.XAPIResHTML, 393 reshtml: html1, 394 shouldwork: true, 395 }, { 396 // A repeated capture group returns its last match. 397 name: "RegexCapture-ok-multimatch", 398 proofinfo: info1, 399 prepvl: map[keybase1.ProofType]string{ 400 keybase1.ProofType_GENERIC_WEB_SITE: `[[ 401 {"fetch": { 402 "kind": "html", 403 "from": "hint_url" } }, 404 {"selector_css": { 405 "selectors": ["div.twit", -1], 406 "into": "tmp1" } }, 407 {"whitespace_normalize": { 408 "from": "tmp1", 409 "into": "tmp2" } }, 410 {"regex_capture": { 411 "pattern": "^(short).*$", 412 "from": "tmp2", 413 "into": ["tmp3"] } }, 414 {"regex_capture": { 415 "pattern": "^(\\w)+$", 416 "from": "tmp3", 417 "into": ["tmp4"] } }, 418 {"assert_regex_match": { 419 "pattern": "^t$", 420 "from": "tmp4" } } 421 ]]`}, 422 service: keybase1.ProofType_GENERIC_WEB_SITE, 423 restype: libkb.XAPIResHTML, 424 reshtml: html1, 425 shouldwork: true, 426 }, { 427 // Capturing into multiple variables 428 // also more capture groups than 'into' variables 429 name: "RegexCapture-ok-multi-capture", 430 proofinfo: info1, 431 prepvl: map[keybase1.ProofType]string{ 432 keybase1.ProofType_GENERIC_WEB_SITE: `[[ 433 {"fetch": { 434 "kind": "string", 435 "from": "hint_url", 436 "into": "tmp1" } }, 437 {"regex_capture": { 438 "pattern": "^(\\w) (\\w) (\\w) (\\w) (\\w).*$", 439 "from": "tmp1", 440 "into": ["a", "b", "c"] } }, 441 {"assert_regex_match": { 442 "pattern": "^%{a} %{b} %{c} d e f$", 443 "from": "tmp1" } } 444 ]]`}, 445 service: keybase1.ProofType_GENERIC_WEB_SITE, 446 restype: libkb.XAPIResText, 447 restext: "a b c d e f", 448 shouldwork: true, 449 }, { 450 // Less capture groups than `into` variables 451 name: "RegexCapture-ok-multi-capture", 452 proofinfo: info1, 453 prepvl: map[keybase1.ProofType]string{ 454 keybase1.ProofType_GENERIC_WEB_SITE: `[[ 455 {"fetch": { 456 "kind": "string", 457 "from": "hint_url", 458 "into": "tmp1" } }, 459 {"regex_capture": { 460 "pattern": "^(\\w) (\\w) .*$", 461 "from": "tmp1", 462 "into": ["a", "b", "c"] } } 463 ]]`}, 464 service: keybase1.ProofType_GENERIC_WEB_SITE, 465 restype: libkb.XAPIResText, 466 restext: "a b c d e f", 467 shouldwork: false, 468 }, { 469 name: "RegexCapture-fail-nomatch", 470 proofinfo: info1, 471 prepvl: map[keybase1.ProofType]string{ 472 keybase1.ProofType_GENERIC_WEB_SITE: `[[ 473 {"fetch": { 474 "kind": "html", 475 "from": "hint_url" } }, 476 {"selector_css": { 477 "selectors": ["div.twit", -1], 478 "into": "tmp1" } }, 479 {"regex_capture": { 480 "pattern": "^(nowhere)$", 481 "case_insensitive": true, 482 "from": "tmp1", 483 "into": ["tmp2"] } } 484 ]]`}, 485 service: keybase1.ProofType_GENERIC_WEB_SITE, 486 restype: libkb.XAPIResHTML, 487 reshtml: html1, 488 shouldwork: false, 489 }, { 490 name: "RegexCapture-fail-nogroup", 491 proofinfo: info1, 492 prepvl: map[keybase1.ProofType]string{ 493 keybase1.ProofType_GENERIC_WEB_SITE: `[[ 494 {"fetch": { 495 "kind": "html", 496 "from": "hint_url" } }, 497 {"selector_css": { 498 "selectors": ["div.twit", -1], 499 "into": "tmp1" } }, 500 {"whitespace_normalize": { 501 "from": "tmp1", 502 "into": "tmp2" } }, 503 {"regex_capture": { 504 "pattern": "^sHoRt.*$", 505 "case_insensitive": true, 506 "from": "tmp2", 507 "into": ["tmp3"] } }, 508 {"assert_regex_match": { 509 "pattern": "^%{sig_id_short}$/s", 510 "from": "tmp3" } } 511 ]]`}, 512 service: keybase1.ProofType_GENERIC_WEB_SITE, 513 restype: libkb.XAPIResHTML, 514 reshtml: html1, 515 shouldwork: false, 516 }, 517 518 // ## ReplaceAll 519 { 520 name: "ReplaceAll-ok", 521 proofinfo: info1, 522 prepvl: map[keybase1.ProofType]string{ 523 keybase1.ProofType_GENERIC_WEB_SITE: `[[ 524 {"fetch": { 525 "kind": "string", 526 "from": "hint_url", 527 "into": "a" } }, 528 {"replace_all": { 529 "old": "foo", 530 "new": "pow", 531 "from": "a", 532 "into": "b" } }, 533 {"assert_regex_match": { 534 "pattern": "^pow bar powz barz$", 535 "from": "b" } } 536 ]]`}, 537 service: keybase1.ProofType_GENERIC_WEB_SITE, 538 restype: libkb.XAPIResText, 539 restext: "foo bar fooz barz", 540 shouldwork: true, 541 }, { 542 name: "ReplaceAll-ok-no-matches", 543 proofinfo: info1, 544 prepvl: map[keybase1.ProofType]string{ 545 keybase1.ProofType_GENERIC_WEB_SITE: `[[ 546 {"fetch": { 547 "kind": "string", 548 "from": "hint_url", 549 "into": "a" } }, 550 {"replace_all": { 551 "old": "foo", 552 "new": "pow", 553 "from": "a", 554 "into": "b" } }, 555 {"assert_regex_match": { 556 "pattern": "^%{a}$", 557 "from": "b" } } 558 ]]`}, 559 service: keybase1.ProofType_GENERIC_WEB_SITE, 560 restype: libkb.XAPIResText, 561 restext: "glue bar gluez barz", 562 shouldwork: true, 563 }, { 564 // Test unescaping the weird escaping that facebook comments use. 565 name: "ReplaceAll-ok-facebook", 566 proofinfo: info1, 567 prepvl: map[keybase1.ProofType]string{ 568 keybase1.ProofType_GENERIC_WEB_SITE: `[[ 569 {"fetch": { 570 "kind": "string", 571 "from": "hint_url", 572 "into": "tmp1" } }, 573 {"replace_all": { 574 "old": "-\\-\\", 575 "new": "--", 576 "from": "tmp1", 577 "into": "tmp2" } }, 578 {"replace_all": { 579 "old": "\\\\", 580 "new": "\\", 581 "from": "tmp2", 582 "into": "tmp3" } }, 583 {"assert_regex_match": { 584 "pattern": "^double -- back \\\\$", 585 "from": "tmp3" } }, 586 {"fill": { 587 "with": "double -- back \\", 588 "into": "ref" } }, 589 {"assert_compare": { 590 "cmp": "exact", 591 "a": "tmp3", 592 "b": "ref" } } 593 ]]`}, 594 service: keybase1.ProofType_GENERIC_WEB_SITE, 595 restype: libkb.XAPIResText, 596 restext: "double -\\-\\ back \\\\", 597 shouldwork: true, 598 }, 599 600 // ## ParseURL 601 { 602 name: "ParseURL-ok", 603 proofinfo: info1, 604 prepvl: map[keybase1.ProofType]string{ 605 keybase1.ProofType_GITHUB: `[[ 606 {"fetch": { 607 "kind": "string", 608 "from": "hint_url", 609 "into": "tmp1" } }, 610 {"parse_url": { 611 "from": "tmp1", 612 "path": "path", 613 "host": "host", 614 "scheme": "scheme" } }, 615 {"assert_regex_match": { 616 "pattern": "^/noodle$", 617 "from": "path" } }, 618 {"assert_regex_match": { 619 "pattern": "^digg.example.com$", 620 "from": "host" } }, 621 {"assert_regex_match": { 622 "pattern": "^http$", 623 "from": "scheme" } } 624 ]]`}, 625 service: keybase1.ProofType_GITHUB, 626 restype: libkb.XAPIResText, 627 restext: "http://digg.example.com/noodle", 628 shouldwork: true, 629 }, { 630 name: "ParseURL-fail", 631 proofinfo: info1, 632 prepvl: map[keybase1.ProofType]string{ 633 keybase1.ProofType_GITHUB: `[[ 634 {"fetch": { 635 "kind": "string", 636 "from": "hint_url", 637 "into": "tmp1" } }, 638 {"parse_url": { 639 "from": "tmp1", 640 "path": "path" } } 641 ]]`}, 642 service: keybase1.ProofType_GITHUB, 643 restype: libkb.XAPIResText, 644 restext: "htj0*#)%*J)*H^dle", 645 shouldwork: false, 646 }, 647 648 // ## Fetch 649 { 650 name: "Fetch-string", 651 proofinfo: info1, 652 prepvl: map[keybase1.ProofType]string{ 653 keybase1.ProofType_GITHUB: `[[ 654 {"fetch": { 655 "kind": "string", 656 "from": "hint_url", 657 "into": "tmp1" } }, 658 {"assert_regex_match": { 659 "pattern": "^str9\n$", 660 "from": "tmp1" } } 661 ]]`}, 662 service: keybase1.ProofType_GITHUB, 663 restype: libkb.XAPIResText, 664 restext: "str9\n", 665 shouldwork: true, 666 }, { 667 name: "Fetch-html", 668 proofinfo: info1, 669 prepvl: map[keybase1.ProofType]string{ 670 keybase1.ProofType_GITHUB: `[[ 671 {"fetch": { 672 "kind": "html", 673 "from": "hint_url" } }, 674 {"selector_css": { 675 "selectors": ["head title"], 676 "into": "tmp1" } }, 677 {"assert_regex_match": { 678 "pattern": "^proofer$", 679 "from": "tmp1" } } 680 ]]`}, 681 service: keybase1.ProofType_GITHUB, 682 restype: libkb.XAPIResHTML, 683 reshtml: html1, 684 shouldwork: true, 685 }, { 686 name: "Fetch-json", 687 proofinfo: info1, 688 prepvl: map[keybase1.ProofType]string{ 689 keybase1.ProofType_GITHUB: `[[ 690 {"fetch": { 691 "kind": "json", 692 "from": "hint_url" } }, 693 {"selector_json": { 694 "selectors": ["data", 2, "type"], 695 "into": "tmp1" } }, 696 {"assert_regex_match": { 697 "pattern": "^useful$", 698 "from": "tmp1" } } 699 ]]`}, 700 service: keybase1.ProofType_GITHUB, 701 restype: libkb.XAPIResJSON, 702 resjson: json1, 703 shouldwork: true, 704 }, 705 706 // ## ParseHTML 707 { 708 name: "ParseHTML-ok", 709 proofinfo: info1, 710 prepvl: map[keybase1.ProofType]string{ 711 keybase1.ProofType_GITHUB: `[[ 712 {"fetch": { 713 "kind": "string", 714 "from": "hint_url", 715 "into": "tmp1" } }, 716 {"parse_html": { 717 "from": "tmp1" } }, 718 {"selector_css": { 719 "selectors": ["p", 2], 720 "into": "tmp2" } }, 721 {"assert_regex_match": { 722 "pattern": "^c$", 723 "from": "tmp2" } } 724 ]]`}, 725 service: keybase1.ProofType_GITHUB, 726 restype: libkb.XAPIResText, 727 restext: "<p>a</p><p>b</p><p>c</p>", 728 shouldwork: true, 729 }, 730 731 // ## SelectorJSON 732 { 733 name: "SelectorJSON-simple", 734 proofinfo: info1, 735 prepvl: map[keybase1.ProofType]string{ 736 keybase1.ProofType_GITHUB: `[[ 737 {"fetch": { 738 "kind": "json", 739 "from": "hint_url" } }, 740 {"selector_json": { 741 "selectors": ["data", 2, "type"], 742 "into": "tmp1" } }, 743 {"assert_regex_match": { 744 "pattern": "^useful$", 745 "from": "tmp1" } } 746 ]]`}, 747 service: keybase1.ProofType_GITHUB, 748 restype: libkb.XAPIResJSON, 749 resjson: json1, 750 shouldwork: true, 751 }, { 752 name: "SelectorJSON-index-dne", 753 proofinfo: info1, 754 prepvl: map[keybase1.ProofType]string{ 755 keybase1.ProofType_GITHUB: `[[ 756 {"fetch": { 757 "kind": "json", 758 "from": "hint_url" } }, 759 {"selector_json": { 760 "selectors": ["data", 500], 761 "into": "tmp1" } } 762 ]]`}, 763 service: keybase1.ProofType_GITHUB, 764 restype: libkb.XAPIResJSON, 765 resjson: json1, 766 shouldwork: false, 767 }, { 768 name: "SelectorJSON-key-dne", 769 proofinfo: info1, 770 prepvl: map[keybase1.ProofType]string{ 771 keybase1.ProofType_GITHUB: `[[ 772 {"fetch": { 773 "kind": "json", 774 "from": "hint_url" } }, 775 {"selector_json": { 776 "selectors": ["data", "a500"], 777 "into": "tmp1" } } 778 ]]`}, 779 service: keybase1.ProofType_GITHUB, 780 restype: libkb.XAPIResJSON, 781 resjson: json1, 782 shouldwork: false, 783 }, { 784 name: "SelectorJSON-index-neg", 785 proofinfo: info1, 786 prepvl: map[keybase1.ProofType]string{ 787 keybase1.ProofType_GITHUB: `[[ 788 {"fetch": { 789 "kind": "json", 790 "from": "hint_url" } }, 791 {"selector_json": { 792 "selectors": ["data", -1, "poster"], 793 "into": "tmp1" } }, 794 {"assert_regex_match": { 795 "pattern": "^eve$", 796 "from": "tmp1" } } 797 ]]`}, 798 service: keybase1.ProofType_GITHUB, 799 restype: libkb.XAPIResJSON, 800 resjson: json1, 801 shouldwork: true, 802 }, { 803 name: "SelectorJSON-index-all", 804 proofinfo: info1, 805 prepvl: map[keybase1.ProofType]string{ 806 keybase1.ProofType_GITHUB: `[[ 807 {"fetch": { 808 "kind": "json", 809 "from": "hint_url" } }, 810 {"selector_json": { 811 "selectors": ["data", {"all": true }, "poster"], 812 "into": "tmp1" } }, 813 {"assert_regex_match": { 814 "pattern": "^kronk eve$", 815 "from": "tmp1" } } 816 ]]`}, 817 service: keybase1.ProofType_GITHUB, 818 restype: libkb.XAPIResJSON, 819 resjson: json1, 820 shouldwork: true, 821 }, { 822 // Index into a non-array 823 name: "SelectorJSON-index-nonarray", 824 proofinfo: info1, 825 prepvl: map[keybase1.ProofType]string{ 826 keybase1.ProofType_GITHUB: `[[ 827 {"fetch": { 828 "kind": "json", 829 "from": "hint_url" } }, 830 {"selector_json": { 831 "selectors": ["data", {"all": true }, "extra", 0, 0], 832 "into": "tmp1" } }, 833 {"assert_regex_match": { 834 "pattern": "^4$", 835 "from": "tmp1" } } 836 ]]`}, 837 service: keybase1.ProofType_GITHUB, 838 restype: libkb.XAPIResJSON, 839 resjson: json1, 840 shouldwork: true, 841 }, 842 843 // ## SelectorCSS 844 { 845 name: "SelectorCSS-ok", 846 proofinfo: info1, 847 prepvl: map[keybase1.ProofType]string{ 848 keybase1.ProofType_GITHUB: `[[ 849 {"fetch": { 850 "kind": "html", 851 "from": "hint_url" } }, 852 {"selector_css": { 853 "selectors": ["body .twit", -1], 854 "into": "tmp1" } }, 855 {"whitespace_normalize": { 856 "from": "tmp1", 857 "into": "tmp2" } }, 858 {"assert_regex_match": { 859 "pattern": "^short %{sig_id_short}$", 860 "from": "tmp2" } } 861 ]]`}, 862 service: keybase1.ProofType_GITHUB, 863 restype: libkb.XAPIResHTML, 864 reshtml: html1, 865 shouldwork: true, 866 }, { 867 name: "SelectorCSS-fail-dontcrash", 868 proofinfo: info1, 869 prepvl: map[keybase1.ProofType]string{ 870 keybase1.ProofType_GITHUB: `[[ 871 {"fetch": { 872 "kind": "html", 873 "from": "hint_url" } }, 874 {"selector_css": { 875 "selectors": ["body .twit:eq(0)"], 876 "into": "tmp1" } }, 877 {"assert_regex_match": { 878 "pattern": "^$", 879 "from": "tmp1" } } 880 ]]`}, 881 service: keybase1.ProofType_GITHUB, 882 restype: libkb.XAPIResHTML, 883 reshtml: html1, 884 shouldwork: false, 885 }, { 886 name: "SelectorCSS-ok-multi", 887 proofinfo: info1, 888 prepvl: map[keybase1.ProofType]string{ 889 keybase1.ProofType_GITHUB: `[[ 890 {"fetch": { 891 "kind": "html", 892 "from": "hint_url" } }, 893 {"selector_css": { 894 "selectors": ["body .twit"], 895 "multi": true, 896 "into": "tmp1" } }, 897 {"assert_regex_match": { 898 "pattern": "^[\\s\\S]*goodproof[\\s\\S]*evil\\.com[\\s\\S]*short[\\s\\S]*$", 899 "from": "tmp1" } } 900 ]]`}, 901 service: keybase1.ProofType_GITHUB, 902 restype: libkb.XAPIResHTML, 903 reshtml: html1, 904 shouldwork: true, 905 }, { 906 name: "SelectorCSS-fail-nonmulti", 907 proofinfo: info1, 908 prepvl: map[keybase1.ProofType]string{ 909 keybase1.ProofType_GITHUB: `[[ 910 {"fetch": { 911 "kind": "html", 912 "from": "hint_url" } }, 913 {"selector_css": { 914 "selectors": ["body .twit"], 915 "into": "tmp1" } }, 916 {"whitespace_normalize": { 917 "from": "tmp1", 918 "into": "tmp2" } }, 919 {"assert_regex_match": { 920 "pattern": "^short %{sig_id_short}$", 921 "from": "tmp2" } } 922 ]]`}, 923 service: keybase1.ProofType_GITHUB, 924 restype: libkb.XAPIResHTML, 925 reshtml: html1, 926 shouldwork: false, 927 }, { 928 name: "SelectorCSS-ok-attr", 929 proofinfo: info1, 930 prepvl: map[keybase1.ProofType]string{ 931 keybase1.ProofType_GITHUB: `[[ 932 {"fetch": { 933 "kind": "html", 934 "from": "hint_url" } }, 935 {"selector_css": { 936 "selectors": ["body .twit[data-x]"], 937 "attr": "data-x", 938 "into": "tmp1" } }, 939 {"assert_regex_match": { 940 "pattern": "^y$", 941 "from": "tmp1" } } 942 ]]`}, 943 service: keybase1.ProofType_GITHUB, 944 restype: libkb.XAPIResHTML, 945 reshtml: html1, 946 shouldwork: true, 947 }, { 948 name: "SelectorCSS-ok-attr-dne", 949 proofinfo: info1, 950 prepvl: map[keybase1.ProofType]string{ 951 keybase1.ProofType_GITHUB: `[[ 952 {"fetch": { 953 "kind": "html", 954 "from": "hint_url" } }, 955 {"selector_css": { 956 "selectors": ["body .twit"], 957 "multi": true, 958 "attr": "dne", 959 "into": "tmp1" } }, 960 {"assert_regex_match": { 961 "pattern": "^$", 962 "from": "tmp1" } } 963 ]]`}, 964 service: keybase1.ProofType_GITHUB, 965 restype: libkb.XAPIResHTML, 966 reshtml: html1, 967 shouldwork: true, 968 }, { 969 name: "SelectorCSS-ok-contents", 970 proofinfo: info1, 971 prepvl: map[keybase1.ProofType]string{ 972 keybase1.ProofType_GITHUB: `[[ 973 {"fetch": { 974 "kind": "html", 975 "from": "hint_url" } }, 976 {"selector_css": { 977 "selectors": [".a .b", {"contents": true}], 978 "multi": true, 979 "data": true, 980 "into": "tmp1" } }, 981 {"whitespace_normalize": { 982 "from": "tmp1", 983 "into": "tmp2" } }, 984 {"replace_all": { 985 "old": " ", 986 "new": "", 987 "from": "tmp2", 988 "into": "tmp3" } }, 989 {"assert_regex_match": { 990 "pattern": "^cowabunga$", 991 "from": "tmp3" } } 992 ]]`}, 993 service: keybase1.ProofType_GITHUB, 994 restype: libkb.XAPIResHTML, 995 reshtml: html2, 996 shouldwork: true, 997 }, 998 999 // ## Fill 1000 { 1001 name: "Fill-ok", 1002 proofinfo: info1, 1003 prepvl: map[keybase1.ProofType]string{ 1004 keybase1.ProofType_GITHUB: `[[ 1005 {"fetch": { 1006 "kind": "string", 1007 "from": "hint_url", 1008 "into": "tmp1" } }, 1009 {"fill": { 1010 "with": "%{tmp1}-%{username_keybase}", 1011 "into": "tmp2" } }, 1012 {"assert_regex_match": { 1013 "pattern": "^foozle-kronk$", 1014 "from": "tmp2" } } 1015 ]]`}, 1016 service: keybase1.ProofType_GITHUB, 1017 restype: libkb.XAPIResText, 1018 restext: "foozle", 1019 shouldwork: true, 1020 }, { 1021 name: "Fill-ok-noregexesc", 1022 proofinfo: info1, 1023 prepvl: map[keybase1.ProofType]string{ 1024 keybase1.ProofType_GITHUB: `[[ 1025 {"fetch": { 1026 "kind": "string", 1027 "from": "hint_url", 1028 "into": "tmp1" } }, 1029 {"fill": { 1030 "with": "%{tmp1}-%{username_keybase}", 1031 "into": "tmp2" } }, 1032 {"assert_regex_match": { 1033 "pattern": "^\\(x\\)-kronk$", 1034 "from": "tmp2" } } 1035 ]]`}, 1036 service: keybase1.ProofType_GITHUB, 1037 restype: libkb.XAPIResText, 1038 restext: "(x)", 1039 shouldwork: true, 1040 }, 1041 1042 // # Tests for invalid PVL at the top level 1043 { 1044 name: "omitted-service", 1045 proofinfo: info1, 1046 // Empty service entries should fail. 1047 prepvl: map[keybase1.ProofType]string{ 1048 keybase1.ProofType_TWITTER: `[[ 1049 {"fetch": { 1050 "kind": "html", 1051 "from": "hint_url" } } 1052 ]]`, 1053 }, 1054 // GITHUB here isn't TWITTER 1055 service: keybase1.ProofType_GITHUB, 1056 restype: libkb.XAPIResHTML, 1057 reshtml: html1, 1058 shouldwork: false, 1059 errstatus: keybase1.ProofStatus_INVALID_PVL, 1060 }, { 1061 name: "omitted-version", 1062 proofinfo: info1, 1063 prepvlstr: `{"revision": 1, "services": {}}`, 1064 service: keybase1.ProofType_GITHUB, 1065 restype: libkb.XAPIResHTML, 1066 reshtml: html1, 1067 shouldwork: false, 1068 errstatus: keybase1.ProofStatus_INVALID_PVL, 1069 }, { 1070 name: "omitted-revision", 1071 proofinfo: info1, 1072 prepvlstr: `{"pvl_version": 1, "services": {}}`, 1073 service: keybase1.ProofType_GITHUB, 1074 restype: libkb.XAPIResHTML, 1075 reshtml: html1, 1076 shouldwork: false, 1077 errstatus: keybase1.ProofStatus_INVALID_PVL, 1078 }, { 1079 name: "bad-services", 1080 proofinfo: info1, 1081 prepvlstr: `{"pvl_version": 1, "revision": 2, "services": []}`, 1082 service: keybase1.ProofType_GITHUB, 1083 restype: libkb.XAPIResHTML, 1084 reshtml: html1, 1085 shouldwork: false, 1086 errstatus: keybase1.ProofStatus_INVALID_PVL, 1087 }, { 1088 name: "non-array-script", 1089 proofinfo: info1, 1090 prepvlstr: `{"pvl_version": 1, "revision": 2, "services": {"github": "bad"}}`, 1091 service: keybase1.ProofType_GITHUB, 1092 restype: libkb.XAPIResHTML, 1093 reshtml: html1, 1094 shouldwork: false, 1095 errstatus: keybase1.ProofStatus_INVALID_PVL, 1096 }, { 1097 name: "empty-script", 1098 proofinfo: info1, 1099 prepvlstr: `{"pvl_version": 1, "revision": 2, "services": {"github": [[]]}}`, 1100 service: keybase1.ProofType_GITHUB, 1101 restype: libkb.XAPIResHTML, 1102 reshtml: html1, 1103 shouldwork: false, 1104 errstatus: keybase1.ProofStatus_INVALID_PVL, 1105 }, { 1106 name: "empty-script-multi", 1107 proofinfo: info1, 1108 prepvlstr: `{"pvl_version": 1, "revision": 2, "services": {"github": [[], []]}}`, 1109 service: keybase1.ProofType_GITHUB, 1110 restype: libkb.XAPIResHTML, 1111 reshtml: html1, 1112 shouldwork: false, 1113 errstatus: keybase1.ProofStatus_INVALID_PVL, 1114 }, { 1115 name: "no-scripts", 1116 proofinfo: info1, 1117 prepvlstr: `{"pvl_version": 1, "revision": 2, "services": {"github": []}}`, 1118 service: keybase1.ProofType_GITHUB, 1119 restype: libkb.XAPIResHTML, 1120 reshtml: html1, 1121 shouldwork: false, 1122 errstatus: keybase1.ProofStatus_INVALID_PVL, 1123 }, 1124 1125 // ## Tests for bad proofinfo 1126 { 1127 name: "bad-sig-path-in-domain-web", 1128 proofinfo: infoBadDomain, 1129 prepvl: map[keybase1.ProofType]string{ 1130 keybase1.ProofType_GENERIC_WEB_SITE: `[[ 1131 {"fetch": { 1132 "kind": "string", 1133 "from": "hint_url", 1134 "into": "tmp1" } } 1135 ]]`}, 1136 service: keybase1.ProofType_GENERIC_WEB_SITE, 1137 restype: libkb.XAPIResText, 1138 restext: "fuzztroo", 1139 shouldwork: false, 1140 errstatus: keybase1.ProofStatus_BAD_SIGNATURE, 1141 }, { 1142 name: "bad-sig-path-in-domain-dns", 1143 proofinfo: infoBadDomain, 1144 prepvl: map[keybase1.ProofType]string{ 1145 keybase1.ProofType_DNS: `[[ 1146 {"assert_regex_match": { 1147 "pattern": "^foo$", 1148 "from": "hint_url" } } 1149 ]]`}, 1150 service: keybase1.ProofType_DNS, 1151 resdns: map[string][]string{ 1152 info1.Hostname: {"NO", "ok"}, 1153 }, 1154 shouldwork: false, 1155 errstatus: keybase1.ProofStatus_BAD_SIGNATURE, 1156 }, { 1157 name: "bad-sig-proto", 1158 proofinfo: infoBadProto, 1159 prepvl: map[keybase1.ProofType]string{ 1160 keybase1.ProofType_GENERIC_WEB_SITE: `[[ 1161 {"fetch": { 1162 "kind": "string", 1163 "from": "hint_url", 1164 "into": "tmp1" } } 1165 ]]`}, 1166 service: keybase1.ProofType_GENERIC_WEB_SITE, 1167 restype: libkb.XAPIResText, 1168 restext: "fuzztroo", 1169 shouldwork: false, 1170 errstatus: keybase1.ProofStatus_BAD_SIGNATURE, 1171 }, { 1172 name: "bad-sig-sig", 1173 proofinfo: infoBadSig, 1174 prepvl: map[keybase1.ProofType]string{ 1175 keybase1.ProofType_GENERIC_WEB_SITE: `[[ 1176 {"fetch": { 1177 "kind": "string", 1178 "from": "hint_url", 1179 "into": "tmp1" } } 1180 ]]`}, 1181 service: keybase1.ProofType_GENERIC_WEB_SITE, 1182 restype: libkb.XAPIResText, 1183 restext: "fuzztroo", 1184 shouldwork: false, 1185 errstatus: keybase1.ProofStatus_BAD_SIGNATURE, 1186 }, 1187 1188 // ## (Invalid) AssertRegexMatch 1189 { 1190 name: "AssertRegexMatch-invalid-missing^", 1191 proofinfo: info1, 1192 prepvl: map[keybase1.ProofType]string{ 1193 keybase1.ProofType_GITHUB: `[[ 1194 {"fetch": { 1195 "kind": "string", 1196 "from": "hint_url", 1197 "into": "tmp1" } }, 1198 {"assert_regex_match": { 1199 "pattern": "foobar$", 1200 "from": "tmp1" } } 1201 ]]`}, 1202 service: keybase1.ProofType_GITHUB, 1203 restype: libkb.XAPIResText, 1204 restext: "fuzztroo", 1205 shouldwork: false, 1206 errstatus: keybase1.ProofStatus_INVALID_PVL, 1207 }, { 1208 name: "AssertRegexMatch-invalid-missing$", 1209 proofinfo: info1, 1210 prepvl: map[keybase1.ProofType]string{ 1211 keybase1.ProofType_GITHUB: `[[ 1212 {"fetch": { 1213 "kind": "string", 1214 "from": "hint_url", 1215 "into": "tmp1" } }, 1216 {"assert_regex_match": { 1217 "pattern": "^foobar", 1218 "from": "tmp1" } } 1219 ]]`}, 1220 service: keybase1.ProofType_GITHUB, 1221 restype: libkb.XAPIResText, 1222 restext: "fuzztroo", 1223 shouldwork: false, 1224 errstatus: keybase1.ProofStatus_INVALID_PVL, 1225 }, { 1226 name: "AssertRegexMatch-invalid-badvar", 1227 proofinfo: info1, 1228 prepvl: map[keybase1.ProofType]string{ 1229 keybase1.ProofType_GITHUB: `[[ 1230 {"fetch": { 1231 "kind": "string", 1232 "from": "hint_url", 1233 "into": "tmp1" } }, 1234 {"assert_regex_match": { 1235 "pattern": "^%{hostname}$", 1236 "from": "tmp1" } } 1237 ]]`}, 1238 service: keybase1.ProofType_GITHUB, 1239 restype: libkb.XAPIResText, 1240 restext: "fuzztroo", 1241 shouldwork: false, 1242 errstatus: keybase1.ProofStatus_INVALID_PVL, 1243 }, { 1244 name: "AssertRegexMatch-invalid-redesc", 1245 proofinfo: info1, 1246 prepvl: map[keybase1.ProofType]string{ 1247 keybase1.ProofType_GITHUB: `[[ 1248 {"fetch": { 1249 "kind": "string", 1250 "from": "hint_url", 1251 "into": "tmp1" } }, 1252 {"assert_regex_match": { 1253 "pattern": ["^foobar$"], 1254 "from": "tmp1" } } 1255 ]]`}, 1256 service: keybase1.ProofType_GITHUB, 1257 restype: libkb.XAPIResText, 1258 restext: "fuzztroo", 1259 shouldwork: false, 1260 errstatus: keybase1.ProofStatus_INVALID_PVL, 1261 }, { 1262 name: "AssertRegexMatch-invalid-badre", 1263 proofinfo: info1, 1264 prepvl: map[keybase1.ProofType]string{ 1265 keybase1.ProofType_GITHUB: `[[ 1266 {"fetch": { 1267 "kind": "string", 1268 "from": "hint_url", 1269 "into": "tmp1" } }, 1270 {"assert_regex_match": { 1271 "pattern": "^foo)(bar$", 1272 "from": "tmp1" } } 1273 ]]`}, 1274 service: keybase1.ProofType_GITHUB, 1275 restype: libkb.XAPIResText, 1276 restext: "fuzztroo", 1277 shouldwork: false, 1278 errstatus: keybase1.ProofStatus_INVALID_PVL, 1279 }, 1280 1281 // ## (Invalid) AssertFindBase64 1282 { 1283 name: "AssertFindBase64-invalid-badtarget", 1284 proofinfo: info1, 1285 prepvl: map[keybase1.ProofType]string{ 1286 keybase1.ProofType_GITHUB: `[[ 1287 {"fetch": { 1288 "kind": "string", 1289 "from": "hint_url", 1290 "into": "tmp1" } }, 1291 {"assert_find_base64": { 1292 "needle": "username_keybase", 1293 "haystack": "tmp1" } } 1294 ]]`}, 1295 service: keybase1.ProofType_GITHUB, 1296 restype: libkb.XAPIResText, 1297 restext: "foobar", 1298 shouldwork: false, 1299 errstatus: keybase1.ProofStatus_INVALID_PVL, 1300 }, 1301 1302 // ## (Invalid) AssertCompare 1303 { 1304 name: "AssertCompare-invalid-strategy", 1305 proofinfo: info1, 1306 prepvl: map[keybase1.ProofType]string{ 1307 keybase1.ProofType_GENERIC_WEB_SITE: `[[ 1308 {"fetch": { 1309 "kind": "string", 1310 "from": "hint_url", 1311 "into": "tmp1" } }, 1312 {"assert_compare": { 1313 "cmp": "", 1314 "a": "username_keybase", 1315 "b": "tmp1" } } 1316 ]]`}, 1317 service: keybase1.ProofType_GENERIC_WEB_SITE, 1318 restype: libkb.XAPIResText, 1319 restext: "krONK", 1320 shouldwork: false, 1321 errstatus: keybase1.ProofStatus_INVALID_PVL, 1322 }, { 1323 name: "AssertCompare-invalid-noa", 1324 proofinfo: info1, 1325 prepvl: map[keybase1.ProofType]string{ 1326 keybase1.ProofType_GENERIC_WEB_SITE: `[[ 1327 {"fetch": { 1328 "kind": "string", 1329 "from": "hint_url", 1330 "into": "tmp1" } }, 1331 {"assert_compare": { 1332 "cmp": "", 1333 "a": "", 1334 "b": "tmp1" } } 1335 ]]`}, 1336 service: keybase1.ProofType_GENERIC_WEB_SITE, 1337 restype: libkb.XAPIResText, 1338 restext: "krONK", 1339 shouldwork: false, 1340 errstatus: keybase1.ProofStatus_INVALID_PVL, 1341 }, 1342 1343 // ## (Invalid) WhitespaceNormalize 1344 // No tests 1345 1346 // ## (Invalid) RegexCapture 1347 // Mostly the same as AssertRegexMatch 1348 { 1349 name: "RegexCapture-invalid-missing^", 1350 proofinfo: info1, 1351 prepvl: map[keybase1.ProofType]string{ 1352 keybase1.ProofType_GITHUB: `[[ 1353 {"fetch": { 1354 "kind": "string", 1355 "from": "hint_url", 1356 "into": "tmp1" } }, 1357 {"regex_capture": { 1358 "pattern": "(f)oobar$", 1359 "from": "tmp1", 1360 "into": ["tmp2"] } } 1361 ]]`}, 1362 service: keybase1.ProofType_GITHUB, 1363 restype: libkb.XAPIResText, 1364 restext: "fuzztroo", 1365 shouldwork: false, 1366 errstatus: keybase1.ProofStatus_INVALID_PVL, 1367 }, { 1368 name: "RegexCapture-invalid-missing$", 1369 proofinfo: info1, 1370 prepvl: map[keybase1.ProofType]string{ 1371 keybase1.ProofType_GITHUB: `[[ 1372 {"fetch": { 1373 "kind": "string", 1374 "from": "hint_url", 1375 "into": "tmp1" } }, 1376 {"regex_capture": { 1377 "pattern": "^(f)oobar", 1378 "from": "tmp1", 1379 "into": ["tmp2"] } } 1380 ]]`}, 1381 service: keybase1.ProofType_GITHUB, 1382 restype: libkb.XAPIResText, 1383 restext: "fuzztroo", 1384 shouldwork: false, 1385 errstatus: keybase1.ProofStatus_INVALID_PVL, 1386 }, { 1387 name: "RegexCapture-invalid-badvar", 1388 proofinfo: info1, 1389 prepvl: map[keybase1.ProofType]string{ 1390 keybase1.ProofType_GITHUB: `[[ 1391 {"fetch": { 1392 "kind": "string", 1393 "from": "hint_url", 1394 "into": "tmp1" } }, 1395 {"regex_capture": { 1396 "pattern": "^(%{hostname})$", 1397 "from": "tmp1", 1398 "into": ["tmp2"] } } 1399 ]]`}, 1400 service: keybase1.ProofType_GITHUB, 1401 restype: libkb.XAPIResText, 1402 restext: "fuzztroo", 1403 shouldwork: false, 1404 errstatus: keybase1.ProofStatus_INVALID_PVL, 1405 }, { 1406 name: "RegexCapture-invalid-redesc", 1407 proofinfo: info1, 1408 prepvl: map[keybase1.ProofType]string{ 1409 keybase1.ProofType_GITHUB: `[[ 1410 {"fetch": { 1411 "kind": "string", 1412 "from": "hint_url", 1413 "into": "tmp1" } }, 1414 {"regex_capture": { 1415 "pattern": ["^(f)oobar$"], 1416 "from": "tmp1", 1417 "into": ["tmp2"] } } 1418 ]]`}, 1419 service: keybase1.ProofType_GITHUB, 1420 restype: libkb.XAPIResText, 1421 restext: "fuzztroo", 1422 shouldwork: false, 1423 errstatus: keybase1.ProofStatus_INVALID_PVL, 1424 }, 1425 1426 // ## (Invalid) ParseURL 1427 { 1428 name: "ParseURL-invalid-missing-from", 1429 proofinfo: info1, 1430 prepvl: map[keybase1.ProofType]string{ 1431 keybase1.ProofType_GITHUB: `[[ 1432 {"fetch": { 1433 "kind": "string", 1434 "from": "hint_url", 1435 "into": "tmp1" } }, 1436 {"parse_url": { 1437 "path": "path" } } 1438 ]]`}, 1439 service: keybase1.ProofType_GITHUB, 1440 restype: libkb.XAPIResText, 1441 restext: "http://example.com/", 1442 shouldwork: false, 1443 errstatus: keybase1.ProofStatus_INVALID_PVL, 1444 }, 1445 1446 // ## (Invalid) ReplaceAll 1447 // No tests 1448 1449 // ## (Invalid) Fetch 1450 { 1451 name: "Fetch-invalid-type", 1452 proofinfo: info1, 1453 prepvl: map[keybase1.ProofType]string{ 1454 keybase1.ProofType_GITHUB: `[[ 1455 {"fetch": { 1456 "kind": "whatsthis", 1457 "from": "hint_url" } } 1458 ]]`}, 1459 service: keybase1.ProofType_GITHUB, 1460 restype: libkb.XAPIResText, 1461 restext: "foobar", 1462 shouldwork: false, 1463 errstatus: keybase1.ProofStatus_INVALID_PVL, 1464 }, { 1465 name: "Fetch-invalid-indns", 1466 proofinfo: info1, 1467 prepvl: map[keybase1.ProofType]string{ 1468 keybase1.ProofType_DNS: `[[ 1469 {"fetch": { 1470 "kind": "whatsthis", 1471 "from": "hint_url" } } 1472 ]]`}, 1473 service: keybase1.ProofType_DNS, 1474 restype: libkb.XAPIResText, 1475 restext: "foobar", 1476 shouldwork: false, 1477 errstatus: keybase1.ProofStatus_INVALID_PVL, 1478 }, 1479 { 1480 name: "Fetch-invalid-multiple", 1481 proofinfo: info1, 1482 prepvl: map[keybase1.ProofType]string{ 1483 keybase1.ProofType_GITHUB: `[[ 1484 {"fetch": { 1485 "kind": "string", 1486 "from": "hint_url", 1487 "into": "tmp2" } }, 1488 {"fetch": { 1489 "kind": "string", 1490 "from": "hint_url", 1491 "into": "tmp2" } } 1492 ]]`}, 1493 service: keybase1.ProofType_GITHUB, 1494 restype: libkb.XAPIResText, 1495 restext: "foobar", 1496 shouldwork: false, 1497 errstatus: keybase1.ProofStatus_INVALID_PVL, 1498 }, 1499 1500 // ## (Invalid) ParseHTML 1501 // No tests 1502 1503 // ## (Invalid) SelectorJSON 1504 { 1505 name: "SelectorJSON-invalid-scripttype", 1506 proofinfo: info1, 1507 prepvl: map[keybase1.ProofType]string{ 1508 keybase1.ProofType_GITHUB: `[[ 1509 {"fetch": { 1510 "kind": "string", 1511 "from": "hint_url", 1512 "into": "tmp1" } }, 1513 {"selector_json": { 1514 "selectors": [0], 1515 "into": "tmp1" } } 1516 ]]`}, 1517 service: keybase1.ProofType_GITHUB, 1518 restype: libkb.XAPIResText, 1519 restext: "foobar", 1520 shouldwork: false, 1521 errstatus: keybase1.ProofStatus_INVALID_PVL, 1522 }, { 1523 name: "SelectorJSON-invalid-selectorlist", 1524 proofinfo: info1, 1525 prepvl: map[keybase1.ProofType]string{ 1526 keybase1.ProofType_GITHUB: `[[ 1527 {"fetch": { 1528 "kind": "json", 1529 "from": "hint_url" } }, 1530 {"selector_json": { 1531 "selectors": 0 } } 1532 ]]`}, 1533 service: keybase1.ProofType_GITHUB, 1534 restype: libkb.XAPIResJSON, 1535 resjson: json1, 1536 shouldwork: false, 1537 errstatus: keybase1.ProofStatus_INVALID_PVL, 1538 }, { 1539 name: "SelectorJSON-invalid-empty", 1540 proofinfo: info1, 1541 prepvl: map[keybase1.ProofType]string{ 1542 keybase1.ProofType_GITHUB: `[[ 1543 {"fetch": { 1544 "kind": "json", 1545 "from": "hint_url" } }, 1546 {"selector_json": { 1547 "selectors": [], 1548 "into": "tmp1" } } 1549 ]]`}, 1550 service: keybase1.ProofType_GITHUB, 1551 restype: libkb.XAPIResJSON, 1552 resjson: json1, 1553 shouldwork: false, 1554 errstatus: keybase1.ProofStatus_INVALID_PVL, 1555 }, { 1556 name: "SelectorJSON-invalid-contents", 1557 proofinfo: info1, 1558 prepvl: map[keybase1.ProofType]string{ 1559 keybase1.ProofType_GITHUB: `[[ 1560 {"fetch": { 1561 "kind": "json", 1562 "from": "hint_url" } }, 1563 {"selector_json": { 1564 "selectors": [{"contents": true}], 1565 "into": "tmp1" } } 1566 ]]`}, 1567 service: keybase1.ProofType_GITHUB, 1568 restype: libkb.XAPIResJSON, 1569 resjson: json1, 1570 shouldwork: false, 1571 errstatus: keybase1.ProofStatus_INVALID_PVL, 1572 }, { 1573 name: "SelectorJSON-invalid-spec", 1574 proofinfo: info1, 1575 prepvl: map[keybase1.ProofType]string{ 1576 keybase1.ProofType_GITHUB: `[[ 1577 {"fetch": { 1578 "kind": "json", 1579 "from": "hint_url" } }, 1580 {"selector_json": { 1581 "selectors": [{"foo": "bar" }], 1582 "into": "tmp1" } } 1583 ]]`}, 1584 service: keybase1.ProofType_GITHUB, 1585 restype: libkb.XAPIResJSON, 1586 resjson: json1, 1587 shouldwork: false, 1588 errstatus: keybase1.ProofStatus_INVALID_PVL, 1589 }, 1590 1591 // ## (Invalid) SelectorCSS 1592 { 1593 name: "SelectorCSS-invalid-scripttype", 1594 proofinfo: info1, 1595 prepvl: map[keybase1.ProofType]string{ 1596 keybase1.ProofType_GITHUB: `[[ 1597 {"fetch": { 1598 "kind": "json", 1599 "from": "hint_url" } }, 1600 {"selector_css": { 1601 "selectors": [0], 1602 "into": "tmp1" } } 1603 ]]`}, 1604 service: keybase1.ProofType_GITHUB, 1605 restype: libkb.XAPIResJSON, 1606 resjson: json1, 1607 shouldwork: false, 1608 errstatus: keybase1.ProofStatus_INVALID_PVL, 1609 }, { 1610 name: "SelectorCSS-invalid-selectorlist", 1611 proofinfo: info1, 1612 prepvl: map[keybase1.ProofType]string{ 1613 keybase1.ProofType_GITHUB: `[[ 1614 {"fetch": { 1615 "kind": "html", 1616 "from": "hint_url" } }, 1617 {"selector_css": { 1618 "selectors": 0 }, 1619 "into": "tmp1" } 1620 ]]`}, 1621 service: keybase1.ProofType_GITHUB, 1622 restype: libkb.XAPIResHTML, 1623 reshtml: html1, 1624 shouldwork: false, 1625 errstatus: keybase1.ProofStatus_INVALID_PVL, 1626 }, { 1627 name: "SelectorCSS-invalid-empty", 1628 proofinfo: info1, 1629 prepvl: map[keybase1.ProofType]string{ 1630 keybase1.ProofType_GITHUB: `[[ 1631 {"fetch": { 1632 "kind": "html", 1633 "from": "hint_url" } }, 1634 {"selector_css": { 1635 "selectors": [], 1636 "into": "tmp1" } } 1637 ]]`}, 1638 service: keybase1.ProofType_GITHUB, 1639 restype: libkb.XAPIResHTML, 1640 reshtml: html1, 1641 shouldwork: false, 1642 errstatus: keybase1.ProofStatus_INVALID_PVL, 1643 }, { 1644 name: "SelectorCSS-invalid-spec", 1645 proofinfo: info1, 1646 prepvl: map[keybase1.ProofType]string{ 1647 keybase1.ProofType_GITHUB: `[[ 1648 {"fetch": { 1649 "kind": "html" } }, 1650 {"selector_css": { 1651 "selectors": [{"foo": "bar" }], 1652 "into": "tmp1" } } 1653 ]]`}, 1654 service: keybase1.ProofType_GITHUB, 1655 restype: libkb.XAPIResHTML, 1656 reshtml: html1, 1657 shouldwork: false, 1658 errstatus: keybase1.ProofStatus_INVALID_PVL, 1659 }, 1660 1661 // ## (Invalid) Fill 1662 { 1663 name: "Fill-invalid-badreg", 1664 proofinfo: info1, 1665 prepvl: map[keybase1.ProofType]string{ 1666 keybase1.ProofType_GITHUB: `[[ 1667 {"fetch": { 1668 "kind": "string", 1669 "from": "hint_url", 1670 "into": "tmp1" } }, 1671 {"fill": { 1672 "with": "%{hostname}", 1673 "into": "tmp2" } } 1674 ]]`}, 1675 service: keybase1.ProofType_GITHUB, 1676 restype: libkb.XAPIResText, 1677 restext: "foozle", 1678 shouldwork: false, 1679 errstatus: keybase1.ProofStatus_INVALID_PVL, 1680 }, { 1681 name: "Fill-invalid-overwrite", 1682 proofinfo: info1, 1683 prepvl: map[keybase1.ProofType]string{ 1684 keybase1.ProofType_GITHUB: `[[ 1685 {"fetch": { 1686 "kind": "string", 1687 "from": "hint_url", 1688 "into": "tmp1" } }, 1689 {"fill": { 1690 "with": "yeck", 1691 "into": "tmp1" } } 1692 ]]`}, 1693 service: keybase1.ProofType_GITHUB, 1694 restype: libkb.XAPIResText, 1695 restext: "foozle", 1696 shouldwork: false, 1697 errstatus: keybase1.ProofStatus_INVALID_PVL, 1698 }, 1699 1700 // # Multiple Scripts 1701 { 1702 name: "MultipleScripts-first-ok", 1703 proofinfo: info1, 1704 prepvl: map[keybase1.ProofType]string{ 1705 keybase1.ProofType_FACEBOOK: `[[ 1706 {"fetch": { 1707 "kind": "string", 1708 "from": "hint_url", 1709 "into": "tmp1" } }, 1710 {"assert_regex_match": { 1711 "pattern": "^ok$", 1712 "from": "tmp1" } } 1713 ], [ 1714 {"fetch": { 1715 "kind": "string", 1716 "from": "hint_url", 1717 "into": "tmp1" } }, 1718 {"assert_regex_match": { 1719 "pattern": "^NO$", 1720 "from": "tmp1" } } 1721 ]]`}, 1722 service: keybase1.ProofType_FACEBOOK, 1723 restype: libkb.XAPIResText, 1724 restext: "ok", 1725 shouldwork: true, 1726 }, { 1727 name: "MultipleScripts-second-ok", 1728 proofinfo: info1, 1729 prepvl: map[keybase1.ProofType]string{ 1730 keybase1.ProofType_FACEBOOK: `[[ 1731 {"fetch": { 1732 "kind": "string", 1733 "from": "hint_url", 1734 "into": "tmp1" } }, 1735 {"assert_regex_match": { 1736 "pattern": "^NO$", 1737 "from": "tmp1" } } 1738 ], [ 1739 {"fetch": { 1740 "kind": "string", 1741 "from": "hint_url", 1742 "into": "tmp1" } }, 1743 {"assert_regex_match": { 1744 "pattern": "^ok$", 1745 "from": "tmp1" } } 1746 ]]`}, 1747 service: keybase1.ProofType_FACEBOOK, 1748 restype: libkb.XAPIResText, 1749 restext: "ok", 1750 allowmanyfetches: true, 1751 shouldwork: true, 1752 }, { 1753 name: "MultipleScripts-both-ok", 1754 proofinfo: info1, 1755 prepvl: map[keybase1.ProofType]string{ 1756 keybase1.ProofType_FACEBOOK: `[[ 1757 {"fetch": { 1758 "kind": "string", 1759 "from": "hint_url", 1760 "into": "tmp1" } }, 1761 {"assert_regex_match": { 1762 "pattern": "^ok$", 1763 "from": "tmp1" } } 1764 ], [ 1765 {"fetch": { 1766 "kind": "string", 1767 "from": "hint_url", 1768 "into": "tmp1" } }, 1769 {"assert_regex_match": { 1770 "pattern": "^ok", 1771 "from": "tmp1" } } 1772 ]]`}, 1773 service: keybase1.ProofType_FACEBOOK, 1774 restype: libkb.XAPIResText, 1775 restext: "ok", 1776 shouldwork: true, 1777 }, { 1778 name: "MultipleScripts-both-fail", 1779 proofinfo: info1, 1780 prepvl: map[keybase1.ProofType]string{ 1781 keybase1.ProofType_FACEBOOK: `[[ 1782 {"fetch": { 1783 "kind": "string", 1784 "from": "hint_url", 1785 "into": "tmp1" } }, 1786 {"assert_regex_match": { 1787 "pattern": "^NO$", 1788 "error": ["HOST_UNREACHABLE", "x"], 1789 "from": "tmp1" } } 1790 ], [ 1791 {"fetch": { 1792 "kind": "string", 1793 "from": "hint_url", 1794 "into": "tmp1" } }, 1795 {"assert_regex_match": { 1796 "pattern": "^NO$", 1797 "error": ["HOST_UNREACHABLE", "x"], 1798 "from": "tmp1" } } 1799 ]]`}, 1800 service: keybase1.ProofType_FACEBOOK, 1801 restype: libkb.XAPIResText, 1802 restext: "ok", 1803 shouldwork: false, 1804 errstatus: keybase1.ProofStatus_HOST_UNREACHABLE, 1805 }, 1806 1807 // # DNS tests 1808 // Checking a DNS proof is different from checking other proofs. 1809 // It runs each script against each TXT record of 2 domains. 1810 // That mechanism is tested here. 1811 { 1812 name: "DNS-second-record-ok", 1813 proofinfo: info1, 1814 prepvl: map[keybase1.ProofType]string{ 1815 keybase1.ProofType_DNS: `[[ 1816 {"assert_regex_match": { 1817 "pattern": "^ok$", 1818 "from": "txt" } } 1819 ]]`}, 1820 service: keybase1.ProofType_DNS, 1821 resdns: map[string][]string{ 1822 info1.Hostname: {"NO", "ok"}, 1823 }, 1824 shouldwork: true, 1825 }, { 1826 name: "DNS-_keybase-ok", 1827 proofinfo: info1, 1828 prepvl: map[keybase1.ProofType]string{ 1829 keybase1.ProofType_DNS: `[[ 1830 {"assert_regex_match": { 1831 "pattern": "^ok$", 1832 "from": "txt" } } 1833 ]]`}, 1834 service: keybase1.ProofType_DNS, 1835 resdns: map[string][]string{ 1836 info1.Hostname: {"NO_1", "NO_2"}, 1837 "_keybase." + info1.Hostname: {"NO_3", "ok"}, 1838 }, 1839 shouldwork: true, 1840 }, { 1841 name: "DNS-no-records", 1842 proofinfo: info1, 1843 prepvl: map[keybase1.ProofType]string{ 1844 keybase1.ProofType_DNS: `[[ 1845 {"assert_regex_match": { 1846 "pattern": "^ok$", 1847 "from": "txt" } } 1848 ]]`}, 1849 service: keybase1.ProofType_DNS, 1850 resdns: map[string][]string{ 1851 info1.Hostname: {}, 1852 "_keybase." + info1.Hostname: {}, 1853 }, 1854 shouldwork: false, 1855 }, { 1856 name: "DNS-no-matching-records", 1857 proofinfo: info1, 1858 prepvl: map[keybase1.ProofType]string{ 1859 keybase1.ProofType_DNS: `[[ 1860 {"assert_regex_match": { 1861 "pattern": "^ok$", 1862 "from": "txt" } } 1863 ]]`}, 1864 service: keybase1.ProofType_DNS, 1865 resdns: map[string][]string{ 1866 info1.Hostname: {"NO_1"}, 1867 "_keybase." + info1.Hostname: {"NO_2", "NO_3"}, 1868 }, 1869 shouldwork: false, 1870 }, { 1871 name: "DNS-error-then-succeed", 1872 proofinfo: info1, 1873 prepvl: map[keybase1.ProofType]string{ 1874 keybase1.ProofType_DNS: `[[ 1875 {"assert_regex_match": { 1876 "pattern": "^ok$", 1877 "from": "txt" } } 1878 ]]`}, 1879 service: keybase1.ProofType_DNS, 1880 resdns: map[string][]string{ 1881 info1.Hostname: {"ERROR"}, 1882 "_keybase." + info1.Hostname: {"ok"}, 1883 }, 1884 shouldwork: true, 1885 }, { 1886 name: "DNS-error-then-succeed-2", 1887 proofinfo: info1, 1888 prepvl: map[keybase1.ProofType]string{ 1889 keybase1.ProofType_DNS: `[[ 1890 {"assert_regex_match": { 1891 "pattern": "^ok1$", 1892 "from": "txt" } } 1893 ], [ 1894 {"assert_regex_match": { 1895 "pattern": "^ok2$", 1896 "from": "txt" } } 1897 ]]`}, 1898 service: keybase1.ProofType_DNS, 1899 resdns: map[string][]string{ 1900 info1.Hostname: {"NO_1", "ok2"}, 1901 }, 1902 shouldwork: true, 1903 }, 1904 1905 // # Custom Errors 1906 { 1907 name: "CustomError-ok", 1908 proofinfo: info1, 1909 prepvl: map[keybase1.ProofType]string{ 1910 keybase1.ProofType_GITHUB: `[[ 1911 { "fetch": { 1912 "kind": "string", 1913 "from": "hint_url", 1914 "into": "tmp1" } }, 1915 { "assert_regex_match": { 1916 "pattern": "^foo$", 1917 "error": ["PERMISSION_DENIED", "whoops!"], 1918 "from": "tmp1" } } 1919 ]]`}, 1920 service: keybase1.ProofType_GITHUB, 1921 restype: libkb.XAPIResText, 1922 restext: "bar", 1923 shouldwork: false, 1924 errstatus: keybase1.ProofStatus_PERMISSION_DENIED, 1925 errstr: "whoops!", 1926 }, { 1927 name: "CustomError-wrong-short-array", 1928 proofinfo: info1, 1929 prepvl: map[keybase1.ProofType]string{ 1930 keybase1.ProofType_GITHUB: `[[ 1931 { "fetch": { 1932 "kind": "string", 1933 "from": "hint_url", 1934 "into": "tmp1" } }, 1935 { "assert_regex_match": { 1936 "pattern": "^foo$", 1937 "error": ["PERMISSION_DENIED"], 1938 "from": "tmp1" } } 1939 ]]`}, 1940 service: keybase1.ProofType_GITHUB, 1941 restype: libkb.XAPIResText, 1942 restext: "bar", 1943 shouldwork: false, 1944 errstatus: keybase1.ProofStatus_INVALID_PVL, 1945 }, { 1946 name: "CustomError-wrong-type1", 1947 proofinfo: info1, 1948 prepvl: map[keybase1.ProofType]string{ 1949 keybase1.ProofType_GITHUB: `[[ 1950 { "fetch": { 1951 "kind": "string", 1952 "from": "hint_url", 1953 "into": "tmp1" } }, 1954 { "assert_regex_match": { 1955 "pattern": "^foo$", 1956 "error": 108, 1957 "from": "tmp1" } } 1958 ]]`}, 1959 service: keybase1.ProofType_GITHUB, 1960 restype: libkb.XAPIResText, 1961 restext: "bar", 1962 shouldwork: false, 1963 errstatus: keybase1.ProofStatus_INVALID_PVL, 1964 }, { 1965 name: "CustomError-wrong-type2", 1966 proofinfo: info1, 1967 prepvl: map[keybase1.ProofType]string{ 1968 keybase1.ProofType_GITHUB: `[[ 1969 { "fetch": { 1970 "kind": "string", 1971 "from": "hint_url", 1972 "into": "tmp1" } }, 1973 { "assert_regex_match": { 1974 "pattern": "^foo$", 1975 "error": ["TIMEOUT", []], 1976 "from": "tmp1" } } 1977 ]]`}, 1978 service: keybase1.ProofType_GITHUB, 1979 restype: libkb.XAPIResText, 1980 restext: "bar", 1981 shouldwork: false, 1982 errstatus: keybase1.ProofStatus_INVALID_PVL, 1983 }, { 1984 // A custom error should not affect invalidity. 1985 // Here the regex contains invalid var name. 1986 name: "CustomError-and-invalid", 1987 proofinfo: info1, 1988 prepvl: map[keybase1.ProofType]string{ 1989 keybase1.ProofType_GITHUB: `[[ 1990 { "fetch": { 1991 "kind": "string", 1992 "from": "hint_url", 1993 "into": "tmp1" } }, 1994 { "assert_regex_match": { 1995 "pattern": "^%{invalid}$", 1996 "error": ["PERMISSION_DENIED", "whoops"], 1997 "from": "tmp1" } } 1998 ]]`}, 1999 service: keybase1.ProofType_GITHUB, 2000 restype: libkb.XAPIResText, 2001 restext: "bar", 2002 shouldwork: false, 2003 errstatus: keybase1.ProofStatus_INVALID_PVL, 2004 }, { 2005 // Without a custom error, a default will appear. 2006 name: "CustomError-none", 2007 proofinfo: info1, 2008 prepvl: map[keybase1.ProofType]string{ 2009 keybase1.ProofType_GITHUB: `[[ 2010 { "fetch": { 2011 "kind": "string", 2012 "from": "hint_url", 2013 "into": "tmp1" } }, 2014 { "assert_regex_match": { 2015 "pattern": "^foo$", 2016 "from": "tmp1" } } 2017 ]]`}, 2018 service: keybase1.ProofType_GITHUB, 2019 restype: libkb.XAPIResText, 2020 restext: "bar", 2021 shouldwork: false, 2022 errstatus: keybase1.ProofStatus_CONTENT_FAILURE, 2023 errstr: "Regex did not match (^foo$)", 2024 }, 2025 } 2026 2027 func TestUnits(t *testing.T) { 2028 solo := "" 2029 for _, unit := range interpUnitTests { 2030 if len(solo) == 0 || unit.name == solo { 2031 t.Logf("Testing: %v", unit.name) 2032 runPvlTest(t, &unit) 2033 } 2034 } 2035 if len(solo) > 0 { 2036 // Soloing a test shall never be checked in. 2037 t.Fatalf("soloed a test that passed\n\n\n*\n*\n*\n*\n*\n*\n*") 2038 } 2039 } 2040 2041 type failer func(string, ...interface{}) 2042 2043 func runPvlTest(t *testing.T, unit *interpUnitTest) { 2044 tc := libkb.SetupTest(t, unit.name, 1) 2045 defer tc.Cleanup() 2046 2047 fail := func(f string, arg ...interface{}) { 2048 f2 := fmt.Sprintf("[%v] ", unit.name) + f 2049 t.Fatalf(f2, arg...) 2050 } 2051 2052 g := tc.G 2053 xapi := newStubAPIEngine() 2054 g.XAPI = xapi 2055 2056 var pvl string 2057 var err error 2058 switch { 2059 case (unit.prepvl == nil) == (unit.prepvlstr == ""): 2060 fail("one of prepvl or prepvlstr must be specified") 2061 case unit.prepvlstr == "": 2062 pvl, err = makeTestPvl(unit.prepvl) 2063 if err != nil { 2064 fail("Error in prepvl: %v", err) 2065 } 2066 default: 2067 pvl = unit.prepvlstr 2068 } 2069 2070 var url = unit.proofinfo.APIURL 2071 if unit.urloverride != "" { 2072 url = unit.urloverride 2073 } 2074 2075 isdns := unit.service == keybase1.ProofType_DNS 2076 2077 if isdns { 2078 unit.proofinfo.stubDNS = newStubDNSEngine(unit.resdns) 2079 } else { 2080 switch unit.restype { 2081 case libkb.XAPIResJSON: 2082 xapi.Set(url, newExternalJSONRes(unit.resjson, fail)) 2083 case libkb.XAPIResHTML: 2084 xapi.SetHTML(url, newExternalHTMLRes(unit.reshtml, fail)) 2085 case libkb.XAPIResText: 2086 xapi.SetText(url, newExternalTextRes(unit.restext, fail)) 2087 default: 2088 fail("unsupported restype: %v", unit.restype) 2089 } 2090 } 2091 2092 m := libkb.NewMetaContextForTest(tc) 2093 perr := CheckProof(m, pvl, unit.service, unit.proofinfo) 2094 if perr == nil { 2095 if !unit.shouldwork { 2096 fail("proof should have failed") 2097 } 2098 2099 // err is definitely nil here. 2100 if isdns { 2101 if !unit.proofinfo.stubDNS.IsOk() { 2102 fail("DNS stub ran out of bounds") 2103 } 2104 } else { 2105 if unit.allowmanyfetches { 2106 err = xapi.AssertCalledWith(unit.restype, url) 2107 } else { 2108 err = xapi.AssertCalledOnceWith(unit.restype, url) 2109 } 2110 if err != nil { 2111 fail("%v", err) 2112 } 2113 } 2114 } else { 2115 if unit.shouldwork { 2116 fail("proof failed: %v", perr) 2117 } 2118 none := keybase1.ProofStatus_NONE 2119 if unit.errstatus != none && perr.GetProofStatus() != unit.errstatus { 2120 fail("status mismatch:\n expected: %v\n got: %v", unit.errstatus, perr.GetProofStatus()) 2121 } 2122 if len(unit.errstr) > 0 && unit.errstr != perr.GetDesc() { 2123 fail("status mismatch:\n expected: %v\n got: %v", unit.errstr, perr.GetDesc()) 2124 } 2125 if unit.errstatus == none && perr.GetProofStatus() == keybase1.ProofStatus_INVALID_PVL { 2126 fail("unexpected INVALID_PVL:\n expected: %v\n got: %v", unit.errstatus, perr.Error()) 2127 } 2128 } 2129 } 2130 2131 func makeTestPvl(rules map[keybase1.ProofType]string) (string, error) { 2132 var pvl string 2133 services := jsonw.NewDictionary() 2134 for ptype, v1 := range rules { 2135 var err error 2136 ptypestr, err := serviceToString(ptype) 2137 if err != nil { 2138 return pvl, err 2139 } 2140 v2, err := jsonw.Unmarshal([]byte(v1)) 2141 if err != nil { 2142 return pvl, err 2143 } 2144 err = services.SetKey(ptypestr, v2) 2145 if err != nil { 2146 return pvl, err 2147 } 2148 } 2149 pvlStr := jsonw.NewDictionary() 2150 err := pvlStr.SetKey("pvl_version", jsonw.NewInt(SupportedVersion)) 2151 if err != nil { 2152 return pvl, err 2153 } 2154 err = pvlStr.SetKey("revision", jsonw.NewInt(1)) 2155 if err != nil { 2156 return pvl, err 2157 } 2158 err = pvlStr.SetKey("services", services) 2159 if err != nil { 2160 return pvl, err 2161 } 2162 pvlB, err := pvlStr.Marshal() 2163 if err != nil { 2164 return pvl, err 2165 } 2166 pvl = string(pvlB) 2167 return pvl, nil 2168 } 2169 2170 func newExternalJSONRes(json string, fail failer) *libkb.ExternalAPIRes { 2171 if json == "" { 2172 fail("empty json string") 2173 } 2174 w, err := jsonw.Unmarshal([]byte(json)) 2175 if err != nil { 2176 fail("invalid json: %v", err) 2177 } 2178 return &libkb.ExternalAPIRes{HTTPStatus: 200, Body: w} 2179 } 2180 2181 func newExternalHTMLRes(html string, fail failer) *libkb.ExternalHTMLRes { 2182 if html == "" { 2183 fail("empty html string") 2184 } 2185 reader := strings.NewReader(html) 2186 doc, err := goquery.NewDocumentFromReader(reader) 2187 if err != nil { 2188 fail("invalid html: %v", err) 2189 } 2190 return &libkb.ExternalHTMLRes{HTTPStatus: 200, GoQuery: doc} 2191 } 2192 2193 func newExternalTextRes(text string, fail failer) *libkb.ExternalTextRes { 2194 if text == "" { 2195 fail("empty text response") 2196 } 2197 return &libkb.ExternalTextRes{HTTPStatus: 200, Body: text} 2198 }