| package bidi |
| |
| import ( |
| "log" |
| "testing" |
| ) |
| |
| type runInformation struct { |
| str string |
| dir Direction |
| start int |
| end int |
| } |
| |
| func TestSimple(t *testing.T) { |
| str := "Hellö" |
| p := Paragraph{} |
| p.SetString(str) |
| order, err := p.Order() |
| if err != nil { |
| log.Fatal(err) |
| } |
| expectedRuns := []runInformation{ |
| {"Hellö", LeftToRight, 0, 4}, |
| } |
| |
| if !p.IsLeftToRight() { |
| t.Error("p.IsLeftToRight() == false; want true") |
| } |
| if nr, want := order.NumRuns(), len(expectedRuns); nr != want { |
| t.Errorf("order.NumRuns() = %d; want %d", nr, want) |
| } |
| for i, want := range expectedRuns { |
| r := order.Run(i) |
| if got := r.String(); got != want.str { |
| t.Errorf("Run(%d) = %q; want %q", i, got, want.str) |
| } |
| if s, e := r.Pos(); s != want.start || e != want.end { |
| t.Errorf("Run(%d).start = %d, .end = %d; want start %d, end %d", i, s, e, want.start, want.end) |
| } |
| if d := r.Direction(); d != want.dir { |
| t.Errorf("Run(%d).Direction = %d; want %d", i, d, want.dir) |
| } |
| } |
| } |
| |
| func TestMixed(t *testing.T) { |
| str := `العاشر ليونيكود (Unicode Conference)، الذي سيعقد في 10-12 آذار 1997 مبدينة` |
| p := Paragraph{} |
| p.SetString(str) |
| order, err := p.Order() |
| if err != nil { |
| log.Fatal(err) |
| } |
| if p.IsLeftToRight() { |
| t.Error("p.IsLeftToRight() == true; want false") |
| } |
| |
| expectedRuns := []runInformation{ |
| {"العاشر ليونيكود (", RightToLeft, 0, 16}, |
| {"Unicode Conference", LeftToRight, 17, 34}, |
| {")، الذي سيعقد في ", RightToLeft, 35, 51}, |
| {"10", LeftToRight, 52, 53}, |
| {"-", RightToLeft, 54, 54}, |
| {"12", LeftToRight, 55, 56}, |
| {" آذار ", RightToLeft, 57, 62}, |
| {"1997", LeftToRight, 63, 66}, |
| {" مبدينة", RightToLeft, 67, 73}, |
| } |
| |
| if nr, want := order.NumRuns(), len(expectedRuns); nr != want { |
| t.Errorf("order.NumRuns() = %d; want %d", nr, want) |
| } |
| |
| for i, want := range expectedRuns { |
| r := order.Run(i) |
| if got := r.String(); got != want.str { |
| t.Errorf("Run(%d) = %q; want %q", i, got, want.str) |
| } |
| if s, e := r.Pos(); s != want.start || e != want.end { |
| t.Errorf("Run(%d).start = %d, .end = %d; want start = %d, end = %d", i, s, e, want.start, want.end) |
| } |
| if d := r.Direction(); d != want.dir { |
| t.Errorf("Run(%d).Direction = %d; want %d", i, d, want.dir) |
| } |
| } |
| } |
| |
| func TestExplicitIsolate(t *testing.T) { |
| // https://www.w3.org/International/articles/inline-bidi-markup/uba-basics.en#beyond |
| str := "The names of these states in Arabic are \u2067مصر\u2069, \u2067البحرين\u2069 and \u2067الكويت\u2069 respectively." |
| p := Paragraph{} |
| p.SetString(str) |
| order, err := p.Order() |
| if err != nil { |
| log.Fatal(err) |
| } |
| if !p.IsLeftToRight() { |
| t.Error("p.IsLeftToRight() == false; want true") |
| } |
| |
| expectedRuns := []runInformation{ |
| {"The names of these states in Arabic are \u2067", LeftToRight, 0, 40}, |
| {"مصر", RightToLeft, 41, 43}, |
| {"\u2069, \u2067", LeftToRight, 44, 47}, |
| {"البحرين", RightToLeft, 48, 54}, |
| {"\u2069 and \u2067", LeftToRight, 55, 61}, |
| {"الكويت", RightToLeft, 62, 67}, |
| {"\u2069 respectively.", LeftToRight, 68, 82}, |
| } |
| |
| if nr, want := order.NumRuns(), len(expectedRuns); nr != want { |
| t.Errorf("order.NumRuns() = %d; want %d", nr, want) |
| } |
| |
| for i, want := range expectedRuns { |
| r := order.Run(i) |
| if got := r.String(); got != want.str { |
| t.Errorf("Run(%d) = %q; want %q", i, got, want.str) |
| } |
| if s, e := r.Pos(); s != want.start || e != want.end { |
| t.Errorf("Run(%d).start = %d, .end = %d; want start = %d, end = %d", i, s, e, want.start, want.end) |
| } |
| if d := r.Direction(); d != want.dir { |
| t.Errorf("Run(%d).Direction = %d; want %d", i, d, want.dir) |
| } |
| } |
| } |
| |
| func TestWithoutExplicitIsolate(t *testing.T) { |
| str := "The names of these states in Arabic are مصر, البحرين and الكويت respectively." |
| p := Paragraph{} |
| p.SetString(str) |
| order, err := p.Order() |
| if err != nil { |
| log.Fatal(err) |
| } |
| if !p.IsLeftToRight() { |
| t.Error("p.IsLeftToRight() == false; want true") |
| } |
| |
| expectedRuns := []runInformation{ |
| {"The names of these states in Arabic are ", LeftToRight, 0, 39}, |
| {"مصر, البحرين", RightToLeft, 40, 51}, |
| {" and ", LeftToRight, 52, 56}, |
| {"الكويت", RightToLeft, 57, 62}, |
| {" respectively.", LeftToRight, 63, 76}, |
| } |
| |
| if nr, want := order.NumRuns(), len(expectedRuns); nr != want { |
| t.Errorf("order.NumRuns() = %d; want %d", nr, want) |
| } |
| |
| for i, want := range expectedRuns { |
| r := order.Run(i) |
| if got := r.String(); got != want.str { |
| t.Errorf("Run(%d) = %q; want %q", i, got, want.str) |
| } |
| if s, e := r.Pos(); s != want.start || e != want.end { |
| t.Errorf("Run(%d).start = %d, .end = %d; want start = %d, end = %d", i, s, e, want.start, want.end) |
| } |
| if d := r.Direction(); d != want.dir { |
| t.Errorf("Run(%d).Direction = %d; want %d", i, d, want.dir) |
| } |
| } |
| } |
| |
| func TestLongUTF8(t *testing.T) { |
| str := `𠀀` |
| p := Paragraph{} |
| p.SetString(str) |
| order, err := p.Order() |
| if err != nil { |
| log.Fatal(err) |
| } |
| if !p.IsLeftToRight() { |
| t.Error("p.IsLeftToRight() == false; want true") |
| } |
| |
| expectedRuns := []runInformation{ |
| {"𠀀", LeftToRight, 0, 0}, |
| } |
| |
| if nr, want := order.NumRuns(), len(expectedRuns); nr != want { |
| t.Errorf("order.NumRuns() = %d; want %d", nr, want) |
| } |
| |
| for i, want := range expectedRuns { |
| r := order.Run(i) |
| if got := r.String(); got != want.str { |
| t.Errorf("Run(%d) = %q; want %q", i, got, want.str) |
| } |
| if s, e := r.Pos(); s != want.start || e != want.end { |
| t.Errorf("Run(%d).start = %d, .end = %d; want start = %d, end = %d", i, s, e, want.start, want.end) |
| } |
| if d := r.Direction(); d != want.dir { |
| t.Errorf("Run(%d).Direction = %d; want %d", i, d, want.dir) |
| } |
| } |
| } |
| |
| func TestLLongUTF8(t *testing.T) { |
| strTester := []struct { |
| str string |
| l int |
| }{ |
| {"ö", 2}, |
| {"ॡ", 3}, |
| {`𠀀`, 4}, |
| } |
| for _, st := range strTester { |
| str := st.str |
| want := st.l |
| if _, l := LookupString(str); l != want { |
| t.Errorf("LookupString(%q) length = %d; want %d", str, l, want) |
| } |
| |
| } |
| |
| } |
| |
| func TestMixedSimple(t *testing.T) { |
| str := `Uا` |
| p := Paragraph{} |
| p.SetString(str) |
| order, err := p.Order() |
| if err != nil { |
| log.Fatal(err) |
| } |
| if !p.IsLeftToRight() { |
| t.Error("p.IsLeftToRight() == false; want true") |
| } |
| |
| expectedRuns := []runInformation{ |
| {"U", LeftToRight, 0, 0}, |
| {"ا", RightToLeft, 1, 1}, |
| } |
| |
| if nr, want := order.NumRuns(), len(expectedRuns); nr != want { |
| t.Errorf("order.NumRuns() = %d; want %d", nr, want) |
| } |
| |
| for i, want := range expectedRuns { |
| r := order.Run(i) |
| if got := r.String(); got != want.str { |
| t.Errorf("Run(%d) = %q; want %q", i, got, want.str) |
| } |
| if s, e := r.Pos(); s != want.start || e != want.end { |
| t.Errorf("Run(%d).start = %d, .end = %d; want start = %d, end = %d", i, s, e, want.start, want.end) |
| } |
| if d := r.Direction(); d != want.dir { |
| t.Errorf("Run(%d).Direction = %d; want %d", i, d, want.dir) |
| } |
| } |
| } |
| |
| func TestDefaultDirection(t *testing.T) { |
| str := "+" |
| p := Paragraph{} |
| p.SetString(str, DefaultDirection(RightToLeft)) |
| _, err := p.Order() |
| if err != nil { |
| t.Error(err) |
| t.Fail() |
| } |
| if want, dir := false, p.IsLeftToRight(); want != dir { |
| t.Errorf("p.IsLeftToRight() = %t; want %t", dir, want) |
| } |
| p.SetString(str, DefaultDirection(LeftToRight)) |
| _, err = p.Order() |
| if err != nil { |
| t.Error(err) |
| t.Fail() |
| } |
| if want, dir := true, p.IsLeftToRight(); want != dir { |
| t.Errorf("p.IsLeftToRight() = %t; want %t", dir, want) |
| } |
| |
| } |
| |
| func TestEmpty(t *testing.T) { |
| p := Paragraph{} |
| p.SetBytes([]byte{}) |
| o, err := p.Order() |
| if err != nil { |
| t.Error("p.Order() return err != nil; want err == nil") |
| } |
| if nr := o.NumRuns(); nr != 0 { |
| t.Errorf("o.NumRuns() = %d; want 0", nr) |
| } |
| } |
| |
| func TestNewline(t *testing.T) { |
| str := "Hello\nworld" |
| p := Paragraph{} |
| n, err := p.SetString(str) |
| if err != nil { |
| t.Error(err) |
| } |
| // 6 is the length up to and including the \n |
| if want := 6; n != want { |
| t.Errorf("SetString(%q) = nil, %d; want nil, %d", str, n, want) |
| } |
| } |
| |
| func TestDoubleSetString(t *testing.T) { |
| str := "العاشر ليونيكود (Unicode Conference)،" |
| p := Paragraph{} |
| _, err := p.SetString(str) |
| if err != nil { |
| t.Error(err) |
| } |
| _, err = p.SetString(str) |
| if err != nil { |
| t.Error(err) |
| } |
| _, err = p.Order() |
| if err != nil { |
| t.Error(err) |
| } |
| } |
| |
| func TestReverseString(t *testing.T) { |
| input := "(Hello)" |
| want := "(olleH)" |
| if str := ReverseString(input); str != want { |
| t.Errorf("ReverseString(%s) = %q; want %q", input, str, want) |
| } |
| } |
| |
| func TestAppendReverse(t *testing.T) { |
| testcase := []struct { |
| inString string |
| outString string |
| want string |
| }{ |
| {"", "Hëllo", "Hëllo"}, |
| {"nice (wörld)", "", "(dlröw) ecin"}, |
| {"nice (wörld)", "Hëllo", "Hëllo(dlröw) ecin"}, |
| } |
| for _, tc := range testcase { |
| if r := AppendReverse([]byte(tc.outString), []byte(tc.inString)); string(r) != tc.want { |
| t.Errorf("AppendReverse([]byte(%q), []byte(%q) = %q; want %q", tc.outString, tc.inString, string(r), tc.want) |
| } |
| } |
| |
| } |