github.com/tada-team/tdproto@v1.51.57/tdmarkup/markup_scanner_test.go (about) 1 package tdmarkup 2 3 import ( 4 "regexp" 5 "testing" 6 ) 7 8 func TestToPlainNoQuotes(t *testing.T) { 9 for k, v := range map[string]struct { 10 raw string 11 plain string 12 }{ 13 "noop": { 14 raw: "123", 15 plain: "123", 16 }, 17 "quote": { 18 raw: "> 123\n456", 19 plain: "456", 20 }, 21 } { 22 t.Run(k, func(t *testing.T) { 23 s, entities := ParseString(v.raw, nil) 24 if s != v.raw { 25 t.Fatalf("invalid ParseString text.\n got: '%s'\nwant: '%s'", s, v.raw) 26 } 27 if text := ToPlain(s, entities, &ToPlainOpts{ 28 DisableQuotes: true, 29 }); text != v.plain { 30 t.Errorf( 31 "invalid ToPlainNoQuotes() output\n raw: '%s'\n got: '%s'\nwant: '%s'\n ent: %+v", 32 v.raw, text, v.plain, entities, 33 ) 34 } 35 }) 36 } 37 } 38 39 func TestParse(t *testing.T) { 40 for _, v := range MarkupTestCases { 41 t.Run(v.Title, func(t *testing.T) { 42 s, entities := ParseString(v.Raw, v.Links) 43 if s != v.Raw { 44 t.Fatalf("invalid ParseString text.\n got: '%s'\nwant: '%s'", s, v.Raw) 45 } 46 47 if v.Html != "" { 48 if text := ToHtml(s, entities); text != v.Html { 49 t.Errorf( 50 "invalid ToHtml() output\n raw: '%s'\n got: '%s'\nwant: '%s'\n ent: %+v", 51 v.Raw, text, v.Html, entities, 52 ) 53 } 54 } 55 56 if v.Plain != "" { 57 if text := ToPlain(s, entities, nil); text != v.Plain { 58 t.Errorf( 59 "invalid ToPlain() output\n raw: '%s'\n got: '%s'\nwant: '%s'\n ent: %+v", 60 v.Raw, text, v.Plain, entities, 61 ) 62 } 63 } 64 }) 65 } 66 } 67 68 func TestMustTime(t *testing.T) { 69 mustTime("2020-10-27T12:24:09.781121Z") 70 mustTime("2000-01-02T17:15:00.000000Z") 71 mustTime("2006-01-02T15:04:05.000000-0700") 72 } 73 74 func TestContainsTime(t *testing.T) { 75 for k, v := range map[string]struct { 76 text string 77 contains bool 78 }{ 79 "base format": { 80 text: "<2020-10-27T12:24:09.781121Z>", 81 contains: true, 82 }, 83 "tada format": { 84 text: "<2020-10-02T15:04:05.000000-0700>", 85 contains: true, 86 }, 87 "into chars": { 88 text: "*<2000-01-02T17:15:00.000000Z>*", 89 contains: true, 90 }, 91 "simple string": { 92 text: "asdasdasdasd", 93 contains: false, 94 }, 95 "simple string with quotes": { 96 text: "<asdasdasdasd>", 97 contains: false, 98 }, 99 "between words": { 100 text: "hello <2020-10-02T15:04:05.000000-0700> world", 101 contains: true, 102 }, 103 } { 104 t.Run(k, func(t *testing.T) { 105 if contains := ContainsTime(v.text); contains != v.contains { 106 t.Error("bad ContainsTime result. want:", v.contains, "got:", contains, "text:", v.text) 107 } 108 }) 109 } 110 } 111 112 // BenchmarkParse/regex-12 107926 11367 ns/op 1129 B/op 34 allocs/op 113 // 114 // BenchmarkParse/markupScanner-12 238516 4882 ns/op 2600 B/op 71 allocs/op 115 // => strings.Builder.Grow 116 // BenchmarkParse/markupScanner-12 323514 3734 ns/op 2584 B/op 68 allocs/op 117 func BenchmarkParse(b *testing.B) { 118 raw := "*bold* /italic/ 1234567 _3_ `code`" 119 plain := "bold italic 1234567 3 code" 120 121 b.Run("markupScanner", func(b *testing.B) { 122 b.ReportAllocs() 123 for i := 0; i < b.N; i++ { 124 s, entities := ParseString(raw, nil) 125 res := ToPlain(s, entities, nil) 126 if res != plain { 127 b.Fatalf("invalid plain, got: %s, want: %s", res, plain) 128 } 129 } 130 }) 131 132 b.Run("regex", func(b *testing.B) { 133 b.ReportAllocs() 134 for i := 0; i < b.N; i++ { 135 res := clearFormat(raw) 136 if res != plain { 137 b.Fatalf("invalid plain, got: %s, want: %s", res, plain) 138 } 139 } 140 }) 141 } 142 143 // BenchmarkNoop-12 502996 2363 ns/op 432 B/op 57 allocs/op 144 // => 145 // BenchmarkNoop-12 2903997 442.5 ns/op 192 B/op 4 allocs/op 146 func BenchmarkNoop(b *testing.B) { 147 b.ReportAllocs() 148 149 raw := "bold italic 1234567 3 code" 150 plain := "bold italic 1234567 3 code" 151 152 for i := 0; i < b.N; i++ { 153 s, entities := ParseString(raw, nil) 154 res := ToPlain(s, entities, nil) 155 if res != plain { 156 b.Fatalf("invalid plain, got: %s, want: %s", res, plain) 157 } 158 } 159 } 160 161 func mask(s string) *regexp.Regexp { 162 return regexp.MustCompile(`(^|\s)` + s + `([^\s` + s + `].*?[^\s` + s + `]|[^\s` + s + `])` + s + `(\s|$|\?|:|\.|,|!)`) 163 } 164 165 var formatRules = []*regexp.Regexp{ 166 regexp.MustCompile("(?ms)(^|\\s)```(.+?)```" + `(\s|$|\?|:|\.|,|!)`), 167 mask("`"), 168 mask(`\*`), 169 mask("/"), 170 mask("_"), 171 mask("~"), 172 } 173 174 func clearFormat(text string) string { 175 for _, regex := range formatRules { 176 text = regex.ReplaceAllStringFunc(text, func(m string) string { 177 parts := regex.FindStringSubmatch(m) 178 return parts[1] + parts[2] + parts[3] 179 }) 180 } 181 return text 182 }