You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

695 lines
13 KiB

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