1// Copyright 2016 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5//go:build !go1.10 6// +build !go1.10 7 8package bidirule 9 10import ( 11 "golang.org/x/text/transform" 12 "golang.org/x/text/unicode/bidi" 13) 14 15var testCases = [][]ruleTest{ 16 // Go-specific rules. 17 // Invalid UTF-8 is invalid. 18 0: []ruleTest{{ 19 in: "", 20 dir: bidi.LeftToRight, 21 }, { 22 in: "\x80", 23 dir: bidi.LeftToRight, 24 err: ErrInvalid, 25 n: 0, 26 }, { 27 in: "\xcc", 28 dir: bidi.LeftToRight, 29 err: ErrInvalid, 30 n: 0, 31 }, { 32 in: "abc\x80", 33 dir: bidi.LeftToRight, 34 err: ErrInvalid, 35 n: 3, 36 }, { 37 in: "abc\xcc", 38 dir: bidi.LeftToRight, 39 err: ErrInvalid, 40 n: 3, 41 }, { 42 in: "abc\xccdef", 43 dir: bidi.LeftToRight, 44 err: ErrInvalid, 45 n: 3, 46 }, { 47 in: "\xccdef", 48 dir: bidi.LeftToRight, 49 err: ErrInvalid, 50 n: 0, 51 }, { 52 in: strR + "\x80", 53 dir: bidi.RightToLeft, 54 err: ErrInvalid, 55 n: len(strR), 56 }, { 57 in: strR + "\xcc", 58 dir: bidi.RightToLeft, 59 err: ErrInvalid, 60 n: len(strR), 61 }, { 62 in: strAL + "\xcc" + strR, 63 dir: bidi.RightToLeft, 64 err: ErrInvalid, 65 n: len(strAL), 66 }, { 67 in: "\xcc" + strR, 68 dir: bidi.RightToLeft, 69 err: ErrInvalid, 70 n: 0, 71 }}, 72 73 // Rule 2.1: The first character must be a character with Bidi property L, 74 // R, or AL. If it has the R or AL property, it is an RTL label; if it has 75 // the L property, it is an LTR label. 76 1: []ruleTest{{ 77 in: strL, 78 dir: bidi.LeftToRight, 79 }, { 80 in: strR, 81 dir: bidi.RightToLeft, 82 }, { 83 in: strAL, 84 dir: bidi.RightToLeft, 85 }, { 86 in: strAN, 87 dir: bidi.RightToLeft, 88 err: ErrInvalid, 89 }, { 90 in: strEN, 91 dir: bidi.LeftToRight, 92 err: nil, // not an RTL string 93 }, { 94 in: strES, 95 dir: bidi.LeftToRight, 96 err: nil, // not an RTL string 97 }, { 98 in: strET, 99 dir: bidi.LeftToRight, 100 err: nil, // not an RTL string 101 }, { 102 in: strCS, 103 dir: bidi.LeftToRight, 104 err: nil, // not an RTL string 105 }, { 106 in: strNSM, 107 dir: bidi.LeftToRight, 108 err: nil, // not an RTL string 109 }, { 110 in: strBN, 111 dir: bidi.LeftToRight, 112 err: nil, // not an RTL string 113 }, { 114 in: strB, 115 dir: bidi.LeftToRight, 116 err: nil, // not an RTL string 117 }, { 118 in: strS, 119 dir: bidi.LeftToRight, 120 err: nil, // not an RTL string 121 }, { 122 in: strWS, 123 dir: bidi.LeftToRight, 124 err: nil, // not an RTL string 125 }, { 126 in: strON, 127 dir: bidi.LeftToRight, 128 err: nil, // not an RTL string 129 }, { 130 in: strEN + strR, 131 dir: bidi.RightToLeft, 132 err: ErrInvalid, 133 n: 3, 134 }, { 135 in: strES + strR, 136 dir: bidi.RightToLeft, 137 err: ErrInvalid, 138 n: 2, 139 }, { 140 in: strET + strR, 141 dir: bidi.RightToLeft, 142 err: ErrInvalid, 143 n: 1, 144 }, { 145 in: strCS + strR, 146 dir: bidi.RightToLeft, 147 err: ErrInvalid, 148 n: 1, 149 }, { 150 in: strNSM + strR, 151 dir: bidi.RightToLeft, 152 err: ErrInvalid, 153 n: 2, 154 }, { 155 in: strBN + strR, 156 dir: bidi.RightToLeft, 157 err: ErrInvalid, 158 n: 3, 159 }, { 160 in: strB + strR, 161 dir: bidi.RightToLeft, 162 err: ErrInvalid, 163 n: 3, 164 }, { 165 in: strS + strR, 166 dir: bidi.RightToLeft, 167 err: ErrInvalid, 168 n: 1, 169 }, { 170 in: strWS + strR, 171 dir: bidi.RightToLeft, 172 err: ErrInvalid, 173 n: 1, 174 }, { 175 in: strON + strR, 176 dir: bidi.RightToLeft, 177 err: ErrInvalid, 178 n: 1, 179 }}, 180 181 // Rule 2.2: In an RTL label, only characters with the Bidi properties R, 182 // AL, AN, EN, ES, CS, ET, ON, BN, or NSM are allowed. 183 2: []ruleTest{{ 184 in: strR + strR + strAL, 185 dir: bidi.RightToLeft, 186 }, { 187 in: strR + strAL + strR, 188 dir: bidi.RightToLeft, 189 }, { 190 in: strR + strAN + strAL, 191 dir: bidi.RightToLeft, 192 }, { 193 in: strR + strEN + strR, 194 dir: bidi.RightToLeft, 195 }, { 196 in: strR + strES + strR, 197 dir: bidi.RightToLeft, 198 }, { 199 in: strR + strCS + strR, 200 dir: bidi.RightToLeft, 201 }, { 202 in: strR + strET + strAL, 203 dir: bidi.RightToLeft, 204 }, { 205 in: strR + strON + strR, 206 dir: bidi.RightToLeft, 207 }, { 208 in: strR + strBN + strR, 209 dir: bidi.RightToLeft, 210 }, { 211 in: strR + strNSM + strAL, 212 dir: bidi.RightToLeft, 213 }, { 214 in: strR + strL + strR, 215 dir: bidi.RightToLeft, 216 n: len(strR), 217 err: ErrInvalid, 218 }, { 219 in: strR + strB + strR, 220 dir: bidi.RightToLeft, 221 n: len(strR), 222 err: ErrInvalid, 223 }, { 224 in: strR + strS + strAL, 225 dir: bidi.RightToLeft, 226 n: len(strR), 227 err: ErrInvalid, 228 }, { 229 in: strR + strWS + strAL, 230 dir: bidi.RightToLeft, 231 n: len(strR), 232 err: ErrInvalid, 233 }, { 234 in: strAL + strR + strAL, 235 dir: bidi.RightToLeft, 236 }, { 237 in: strAL + strAL + strR, 238 dir: bidi.RightToLeft, 239 }, { 240 in: strAL + strAN + strAL, 241 dir: bidi.RightToLeft, 242 }, { 243 in: strAL + strEN + strR, 244 dir: bidi.RightToLeft, 245 }, { 246 in: strAL + strES + strR, 247 dir: bidi.RightToLeft, 248 }, { 249 in: strAL + strCS + strR, 250 dir: bidi.RightToLeft, 251 }, { 252 in: strAL + strET + strAL, 253 dir: bidi.RightToLeft, 254 }, { 255 in: strAL + strON + strR, 256 dir: bidi.RightToLeft, 257 }, { 258 in: strAL + strBN + strR, 259 dir: bidi.RightToLeft, 260 }, { 261 in: strAL + strNSM + strAL, 262 dir: bidi.RightToLeft, 263 }, { 264 in: strAL + strL + strR, 265 dir: bidi.RightToLeft, 266 n: len(strAL), 267 err: ErrInvalid, 268 }, { 269 in: strAL + strB + strR, 270 dir: bidi.RightToLeft, 271 n: len(strAL), 272 err: ErrInvalid, 273 }, { 274 in: strAL + strS + strAL, 275 dir: bidi.RightToLeft, 276 n: len(strAL), 277 err: ErrInvalid, 278 }, { 279 in: strAL + strWS + strAL, 280 dir: bidi.RightToLeft, 281 n: len(strAL), 282 err: ErrInvalid, 283 }}, 284 285 // Rule 2.3: In an RTL label, the end of the label must be a character with 286 // Bidi property R, AL, EN, or AN, followed by zero or more characters with 287 // Bidi property NSM. 288 3: []ruleTest{{ 289 in: strR + strNSM, 290 dir: bidi.RightToLeft, 291 }, { 292 in: strR + strR, 293 dir: bidi.RightToLeft, 294 }, { 295 in: strR + strAL + strNSM, 296 dir: bidi.RightToLeft, 297 }, { 298 in: strR + strEN + strNSM + strNSM, 299 dir: bidi.RightToLeft, 300 }, { 301 in: strR + strAN, 302 dir: bidi.RightToLeft, 303 }, { 304 in: strR + strES + strNSM, 305 dir: bidi.RightToLeft, 306 n: len(strR + strES + strNSM), 307 err: ErrInvalid, 308 }, { 309 in: strR + strCS + strNSM + strNSM, 310 dir: bidi.RightToLeft, 311 n: len(strR + strCS + strNSM + strNSM), 312 err: ErrInvalid, 313 }, { 314 in: strR + strET, 315 dir: bidi.RightToLeft, 316 n: len(strR + strET), 317 err: ErrInvalid, 318 }, { 319 in: strR + strON + strNSM, 320 dir: bidi.RightToLeft, 321 n: len(strR + strON + strNSM), 322 err: ErrInvalid, 323 }, { 324 in: strR + strBN + strNSM + strNSM, 325 dir: bidi.RightToLeft, 326 n: len(strR + strBN + strNSM + strNSM), 327 err: ErrInvalid, 328 }, { 329 in: strR + strL + strNSM, 330 dir: bidi.RightToLeft, 331 n: len(strR), 332 err: ErrInvalid, 333 }, { 334 in: strR + strB + strNSM + strNSM, 335 dir: bidi.RightToLeft, 336 n: len(strR), 337 err: ErrInvalid, 338 }, { 339 in: strR + strS, 340 dir: bidi.RightToLeft, 341 n: len(strR), 342 err: ErrInvalid, 343 }, { 344 in: strR + strWS, 345 dir: bidi.RightToLeft, 346 n: len(strR), 347 err: ErrInvalid, 348 }, { 349 in: strAL + strNSM, 350 dir: bidi.RightToLeft, 351 }, { 352 in: strAL + strR, 353 dir: bidi.RightToLeft, 354 }, { 355 in: strAL + strAL + strNSM, 356 dir: bidi.RightToLeft, 357 }, { 358 in: strAL + strEN + strNSM + strNSM, 359 dir: bidi.RightToLeft, 360 }, { 361 in: strAL + strAN, 362 dir: bidi.RightToLeft, 363 }, { 364 in: strAL + strES + strNSM, 365 dir: bidi.RightToLeft, 366 n: len(strAL + strES + strNSM), 367 err: ErrInvalid, 368 }, { 369 in: strAL + strCS + strNSM + strNSM, 370 dir: bidi.RightToLeft, 371 n: len(strAL + strCS + strNSM + strNSM), 372 err: ErrInvalid, 373 }, { 374 in: strAL + strET, 375 dir: bidi.RightToLeft, 376 n: len(strAL + strET), 377 err: ErrInvalid, 378 }, { 379 in: strAL + strON + strNSM, 380 dir: bidi.RightToLeft, 381 n: len(strAL + strON + strNSM), 382 err: ErrInvalid, 383 }, { 384 in: strAL + strBN + strNSM + strNSM, 385 dir: bidi.RightToLeft, 386 n: len(strAL + strBN + strNSM + strNSM), 387 err: ErrInvalid, 388 }, { 389 in: strAL + strL + strNSM, 390 dir: bidi.RightToLeft, 391 n: len(strAL), 392 err: ErrInvalid, 393 }, { 394 in: strAL + strB + strNSM + strNSM, 395 dir: bidi.RightToLeft, 396 n: len(strAL), 397 err: ErrInvalid, 398 }, { 399 in: strAL + strS, 400 dir: bidi.RightToLeft, 401 n: len(strAL), 402 err: ErrInvalid, 403 }, { 404 in: strAL + strWS, 405 dir: bidi.RightToLeft, 406 n: len(strAL), 407 err: ErrInvalid, 408 }}, 409 410 // Rule 2.4: In an RTL label, if an EN is present, no AN may be present, 411 // and vice versa. 412 4: []ruleTest{{ 413 in: strR + strEN + strAN, 414 dir: bidi.RightToLeft, 415 n: len(strR + strEN), 416 err: ErrInvalid, 417 }, { 418 in: strR + strAN + strEN + strNSM, 419 dir: bidi.RightToLeft, 420 n: len(strR + strAN), 421 err: ErrInvalid, 422 }, { 423 in: strAL + strEN + strAN, 424 dir: bidi.RightToLeft, 425 n: len(strAL + strEN), 426 err: ErrInvalid, 427 }, { 428 in: strAL + strAN + strEN + strNSM, 429 dir: bidi.RightToLeft, 430 n: len(strAL + strAN), 431 err: ErrInvalid, 432 }}, 433 434 // Rule 2.5: In an LTR label, only characters with the Bidi properties L, 435 // EN, ES, CS, ET, ON, BN, or NSM are allowed. 436 5: []ruleTest{{ 437 in: strL + strL + strL, 438 dir: bidi.LeftToRight, 439 }, { 440 in: strL + strEN + strL, 441 dir: bidi.LeftToRight, 442 }, { 443 in: strL + strES + strL, 444 dir: bidi.LeftToRight, 445 }, { 446 in: strL + strCS + strL, 447 dir: bidi.LeftToRight, 448 }, { 449 in: strL + strET + strL, 450 dir: bidi.LeftToRight, 451 }, { 452 in: strL + strON + strL, 453 dir: bidi.LeftToRight, 454 }, { 455 in: strL + strBN + strL, 456 dir: bidi.LeftToRight, 457 }, { 458 in: strL + strNSM + strL, 459 dir: bidi.LeftToRight, 460 }, { 461 in: strL + strR + strL, 462 dir: bidi.RightToLeft, 463 n: len(strL), 464 err: ErrInvalid, 465 }, { 466 in: strL + strAL + strL, 467 dir: bidi.RightToLeft, 468 n: len(strL), 469 err: ErrInvalid, 470 }, { 471 in: strL + strAN + strL, 472 dir: bidi.RightToLeft, 473 n: len(strL), 474 err: ErrInvalid, 475 }, { 476 in: strL + strB + strL, 477 dir: bidi.LeftToRight, 478 n: len(strL + strAN + strL), 479 err: nil, 480 }, { 481 in: strL + strB + strL + strR, 482 dir: bidi.RightToLeft, 483 n: len(strL + strB + strL), 484 err: ErrInvalid, 485 }, { 486 in: strL + strS + strL, 487 dir: bidi.LeftToRight, 488 n: len(strL + strS + strL), 489 err: nil, 490 }, { 491 in: strL + strS + strL + strR, 492 dir: bidi.RightToLeft, 493 n: len(strL + strS + strL), 494 err: ErrInvalid, 495 }, { 496 in: strL + strWS + strL, 497 dir: bidi.LeftToRight, 498 n: len(strL + strWS + strL), 499 err: nil, 500 }, { 501 in: strL + strWS + strL + strR, 502 dir: bidi.RightToLeft, 503 n: len(strL + strWS + strL), 504 err: ErrInvalid, 505 }}, 506 507 // Rule 2.6: In an LTR label, the end of the label must be a character with 508 // Bidi property L or EN, followed by zero or more characters with Bidi 509 // property NSM. 510 6: []ruleTest{{ 511 in: strL, 512 dir: bidi.LeftToRight, 513 }, { 514 in: strL + strNSM, 515 dir: bidi.LeftToRight, 516 }, { 517 in: strL + strNSM + strNSM, 518 dir: bidi.LeftToRight, 519 }, { 520 in: strL + strEN, 521 dir: bidi.LeftToRight, 522 }, { 523 in: strL + strEN + strNSM, 524 dir: bidi.LeftToRight, 525 }, { 526 in: strL + strEN + strNSM + strNSM, 527 dir: bidi.LeftToRight, 528 }, { 529 in: strL + strES, 530 dir: bidi.LeftToRight, 531 n: len(strL + strES), 532 err: nil, 533 }, { 534 in: strL + strES + strR, 535 dir: bidi.RightToLeft, 536 n: len(strL + strES), 537 err: ErrInvalid, 538 }, { 539 in: strL + strCS, 540 dir: bidi.LeftToRight, 541 n: len(strL + strCS), 542 err: nil, 543 }, { 544 in: strL + strCS + strR, 545 dir: bidi.RightToLeft, 546 n: len(strL + strCS), 547 err: ErrInvalid, 548 }, { 549 in: strL + strET, 550 dir: bidi.LeftToRight, 551 n: len(strL + strET), 552 err: nil, 553 }, { 554 in: strL + strET + strR, 555 dir: bidi.RightToLeft, 556 n: len(strL + strET), 557 err: ErrInvalid, 558 }, { 559 in: strL + strON, 560 dir: bidi.LeftToRight, 561 n: len(strL + strON), 562 err: nil, 563 }, { 564 in: strL + strON + strR, 565 dir: bidi.RightToLeft, 566 n: len(strL + strON), 567 err: ErrInvalid, 568 }, { 569 in: strL + strBN, 570 dir: bidi.LeftToRight, 571 n: len(strL + strBN), 572 err: nil, 573 }, { 574 in: strL + strBN + strR, 575 dir: bidi.RightToLeft, 576 n: len(strL + strBN), 577 err: ErrInvalid, 578 }, { 579 in: strL + strR, 580 dir: bidi.RightToLeft, 581 n: len(strL), 582 err: ErrInvalid, 583 }, { 584 in: strL + strAL, 585 dir: bidi.RightToLeft, 586 n: len(strL), 587 err: ErrInvalid, 588 }, { 589 in: strL + strAN, 590 dir: bidi.RightToLeft, 591 n: len(strL), 592 err: ErrInvalid, 593 }, { 594 in: strL + strB, 595 dir: bidi.LeftToRight, 596 n: len(strL + strB), 597 err: nil, 598 }, { 599 in: strL + strB + strR, 600 dir: bidi.RightToLeft, 601 n: len(strL + strB), 602 err: ErrInvalid, 603 }, { 604 in: strL + strB, 605 dir: bidi.LeftToRight, 606 n: len(strL + strB), 607 err: nil, 608 }, { 609 in: strL + strB + strR, 610 dir: bidi.RightToLeft, 611 n: len(strL + strB), 612 err: ErrInvalid, 613 }, { 614 in: strL + strB, 615 dir: bidi.LeftToRight, 616 n: len(strL + strB), 617 err: nil, 618 }, { 619 in: strL + strB + strR, 620 dir: bidi.RightToLeft, 621 n: len(strL + strB), 622 err: ErrInvalid, 623 }}, 624 625 // Incremental processing. 626 9: []ruleTest{{ 627 in: "e\u0301", // é 628 dir: bidi.LeftToRight, 629 630 pSrc: 2, 631 nSrc: 1, 632 err0: transform.ErrShortSrc, 633 }, { 634 in: "e\u1000f", // é 635 dir: bidi.LeftToRight, 636 637 pSrc: 3, 638 nSrc: 1, 639 err0: transform.ErrShortSrc, 640 }, { 641 // Remain invalid once invalid. 642 in: strR + "ab", 643 dir: bidi.RightToLeft, 644 n: len(strR), 645 err: ErrInvalid, 646 647 pSrc: len(strR) + 1, 648 nSrc: len(strR), 649 err0: ErrInvalid, 650 }, { 651 // Short destination 652 in: "abcdefghij", 653 dir: bidi.LeftToRight, 654 655 pSrc: 10, 656 szDst: 5, 657 nSrc: 5, 658 err0: transform.ErrShortDst, 659 }, { 660 // Short destination splitting input rune 661 in: "e\u0301", 662 dir: bidi.LeftToRight, 663 664 pSrc: 3, 665 szDst: 2, 666 nSrc: 1, 667 err0: transform.ErrShortDst, 668 }}, 669} 670