emoji_test.go (4507B)
1 // Copyright 2016 The Hugo Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 package helpers
14
15 import (
16 "math"
17 "reflect"
18 "strings"
19 "testing"
20
21 "github.com/gohugoio/hugo/bufferpool"
22 "github.com/kyokomi/emoji/v2"
23 )
24
25 func TestEmojiCustom(t *testing.T) {
26 for i, this := range []struct {
27 input string
28 expect []byte
29 }{
30 {"A :smile: a day", []byte("A š a day")},
31 {"A few :smile:s a day", []byte("A few šs a day")},
32 {"A :smile: and a :beer: makes the day for sure.", []byte("A š and a šŗ makes the day for sure.")},
33 {"A :smile: and: a :beer:", []byte("A š and: a šŗ")},
34 {"A :diamond_shape_with_a_dot_inside: and then some.", []byte("A š and then some.")},
35 {":smile:", []byte("š")},
36 {":smi", []byte(":smi")},
37 {"A :smile:", []byte("A š")},
38 {":beer:!", []byte("šŗ!")},
39 {"::smile:", []byte(":š")},
40 {":beer::", []byte("šŗ:")},
41 {" :beer: :", []byte(" šŗ :")},
42 {":beer: and :smile: and another :beer:!", []byte("šŗ and š and another šŗ!")},
43 {" :beer: : ", []byte(" šŗ : ")},
44 {"No smilies for you!", []byte("No smilies for you!")},
45 {" The motto: no smiles! ", []byte(" The motto: no smiles! ")},
46 {":hugo_is_the_best_static_gen:", []byte(":hugo_is_the_best_static_gen:")},
47 {"ģķ :smile: ģķ", []byte("ģķ š ģķ")},
48 // #2198
49 {"See: A :beer:!", []byte("See: A šŗ!")},
50 {`Aaaaaaaaaa: aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa.
51
52 :beer:`, []byte(`Aaaaaaaaaa: aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa.
53
54 šŗ`)},
55 {"test :\n```bash\nthis is a test\n```\n\ntest\n\n:cool::blush:::pizza:\\:blush : : blush: :pizza:", []byte("test :\n```bash\nthis is a test\n```\n\ntest\n\nšš:š\\:blush : : blush: š")},
56 {
57 // 2391
58 "[a](http://gohugo.io) :smile: [r](http://gohugo.io/introduction/overview/) :beer:",
59 []byte(`[a](http://gohugo.io) š [r](http://gohugo.io/introduction/overview/) šŗ`),
60 },
61 } {
62
63 result := Emojify([]byte(this.input))
64
65 if !reflect.DeepEqual(result, this.expect) {
66 t.Errorf("[%d] got %q but expected %q", i, result, this.expect)
67 }
68
69 }
70 }
71
72 // The Emoji benchmarks below are heavily skewed in Hugo's direction:
73 //
74 // Hugo have a byte slice, wants a byte slice and doesn't mind if the original is modified.
75
76 func BenchmarkEmojiKyokomiFprint(b *testing.B) {
77 f := func(in []byte) []byte {
78 buff := bufferpool.GetBuffer()
79 defer bufferpool.PutBuffer(buff)
80 emoji.Fprint(buff, string(in))
81
82 bc := make([]byte, buff.Len())
83 copy(bc, buff.Bytes())
84 return bc
85 }
86
87 doBenchmarkEmoji(b, f)
88 }
89
90 func BenchmarkEmojiKyokomiSprint(b *testing.B) {
91 f := func(in []byte) []byte {
92 return []byte(emoji.Sprint(string(in)))
93 }
94
95 doBenchmarkEmoji(b, f)
96 }
97
98 func BenchmarkHugoEmoji(b *testing.B) {
99 doBenchmarkEmoji(b, Emojify)
100 }
101
102 func doBenchmarkEmoji(b *testing.B, f func(in []byte) []byte) {
103 type input struct {
104 in []byte
105 expect []byte
106 }
107
108 data := []struct {
109 input string
110 expect string
111 }{
112 {"A :smile: a day", emoji.Sprint("A :smile: a day")},
113 {"A :smile: and a :beer: day keeps the doctor away", emoji.Sprint("A :smile: and a :beer: day keeps the doctor away")},
114 {"A :smile: a day and 10 " + strings.Repeat(":beer: ", 10), emoji.Sprint("A :smile: a day and 10 " + strings.Repeat(":beer: ", 10))},
115 {"No smiles today.", "No smiles today."},
116 {"No smiles for you or " + strings.Repeat("you ", 1000), "No smiles for you or " + strings.Repeat("you ", 1000)},
117 }
118
119 in := make([]input, b.N*len(data))
120 cnt := 0
121 for i := 0; i < b.N; i++ {
122 for _, this := range data {
123 in[cnt] = input{[]byte(this.input), []byte(this.expect)}
124 cnt++
125 }
126 }
127
128 b.ResetTimer()
129 cnt = 0
130 for i := 0; i < b.N; i++ {
131 for j := range data {
132 currIn := in[cnt]
133 cnt++
134 result := f(currIn.in)
135 // The Emoji implementations gives slightly different output.
136 diffLen := len(result) - len(currIn.expect)
137 diffLen = int(math.Abs(float64(diffLen)))
138 if diffLen > 30 {
139 b.Fatalf("[%d] emoji std, got \n%q but expected \n%q", j, result, currIn.expect)
140 }
141 }
142 }
143 }