|
| 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 | + "github.com/kyokomi/emoji" |
| 17 | + "github.com/spf13/hugo/bufferpool" |
| 18 | + "reflect" |
| 19 | + "strings" |
| 20 | + "testing" |
| 21 | +) |
| 22 | + |
| 23 | +func TestEmojiCustom(t *testing.T) { |
| 24 | + for i, this := range []struct { |
| 25 | + input string |
| 26 | + expect []byte |
| 27 | + }{ |
| 28 | + {"A :smile: a day", []byte(emoji.Sprint("A :smile: a day"))}, |
| 29 | + {"A few :smile:s a day", []byte(emoji.Sprint("A few :smile:s a day"))}, |
| 30 | + {"A :smile: and a :beer: makes the day for sure.", []byte(emoji.Sprint("A :smile: and a :beer: makes the day for sure."))}, |
| 31 | + {"A :smile: and: a :beer:", []byte(emoji.Sprint("A :smile: and: a :beer:"))}, |
| 32 | + {"A :diamond_shape_with_a_dot_inside: and then some.", []byte(emoji.Sprint("A :diamond_shape_with_a_dot_inside: and then some."))}, |
| 33 | + {":smile:", []byte(emoji.Sprint(":smile:"))}, |
| 34 | + {":smi", []byte(":smi")}, |
| 35 | + {"A :smile:", []byte(emoji.Sprint("A :smile:"))}, |
| 36 | + {":beer:!", []byte(emoji.Sprint(":beer:!"))}, |
| 37 | + {"::smile:", []byte(emoji.Sprint("::smile:"))}, |
| 38 | + {":beer::", []byte(emoji.Sprint(":beer::"))}, |
| 39 | + {" :beer: :", []byte(emoji.Sprint(" :beer: :"))}, |
| 40 | + {":beer: and :smile: and another :beer:!", []byte(emoji.Sprint(":beer: and :smile: and another :beer:!"))}, |
| 41 | + {" :beer: : ", []byte(emoji.Sprint(" :beer: : "))}, |
| 42 | + {"No smilies for you!", []byte("No smilies for you!")}, |
| 43 | + {" The motto: no smiles! ", []byte(" The motto: no smiles! ")}, |
| 44 | + {":hugo_is_the_best_static_gen:", []byte(":hugo_is_the_best_static_gen:")}, |
| 45 | + {"은행 :smile: 은행", []byte(emoji.Sprint("은행 :smile: 은행"))}, |
| 46 | + } { |
| 47 | + result := Emojify([]byte(this.input)) |
| 48 | + |
| 49 | + if !reflect.DeepEqual(result, this.expect) { |
| 50 | + t.Errorf("[%d] got '%q' but expected %q", i, result, this.expect) |
| 51 | + } |
| 52 | + |
| 53 | + } |
| 54 | +} |
| 55 | + |
| 56 | +// The Emoji benchmarks below are heavily skewed in Hugo's direction: |
| 57 | +// |
| 58 | +// Hugo have a byte slice, wants a byte slice and doesn't mind if the original is modified. |
| 59 | + |
| 60 | +func BenchmarkEmojiKyokomiFprint(b *testing.B) { |
| 61 | + |
| 62 | + f := func(in []byte) []byte { |
| 63 | + buff := bufferpool.GetBuffer() |
| 64 | + defer bufferpool.PutBuffer(buff) |
| 65 | + emoji.Fprint(buff, string(in)) |
| 66 | + |
| 67 | + bc := make([]byte, buff.Len(), buff.Len()) |
| 68 | + copy(bc, buff.Bytes()) |
| 69 | + return bc |
| 70 | + } |
| 71 | + |
| 72 | + doBenchmarkEmoji(b, f) |
| 73 | +} |
| 74 | + |
| 75 | +func BenchmarkEmojiKyokomiSprint(b *testing.B) { |
| 76 | + |
| 77 | + f := func(in []byte) []byte { |
| 78 | + return []byte(emoji.Sprint(string(in))) |
| 79 | + } |
| 80 | + |
| 81 | + doBenchmarkEmoji(b, f) |
| 82 | +} |
| 83 | + |
| 84 | +func BenchmarkHugoEmoji(b *testing.B) { |
| 85 | + doBenchmarkEmoji(b, Emojify) |
| 86 | +} |
| 87 | + |
| 88 | +func doBenchmarkEmoji(b *testing.B, f func(in []byte) []byte) { |
| 89 | + |
| 90 | + type input struct { |
| 91 | + in []byte |
| 92 | + expect []byte |
| 93 | + } |
| 94 | + |
| 95 | + data := []struct { |
| 96 | + input string |
| 97 | + expect string |
| 98 | + }{ |
| 99 | + {"A :smile: a day", emoji.Sprint("A :smile: a day")}, |
| 100 | + {"A :smile: and a :beer: day keeps the doctor away", emoji.Sprint("A :smile: and a :beer: day keeps the doctor away")}, |
| 101 | + {"A :smile: a day and 10 " + strings.Repeat(":beer: ", 10), emoji.Sprint("A :smile: a day and 10 " + strings.Repeat(":beer: ", 10))}, |
| 102 | + {"No smiles today.", "No smiles today."}, |
| 103 | + {"No smiles for you or " + strings.Repeat("you ", 1000), "No smiles for you or " + strings.Repeat("you ", 1000)}, |
| 104 | + } |
| 105 | + |
| 106 | + var in []input = make([]input, b.N*len(data)) |
| 107 | + var cnt = 0 |
| 108 | + for i := 0; i < b.N; i++ { |
| 109 | + for _, this := range data { |
| 110 | + in[cnt] = input{[]byte(this.input), []byte(this.expect)} |
| 111 | + cnt++ |
| 112 | + } |
| 113 | + } |
| 114 | + |
| 115 | + b.ResetTimer() |
| 116 | + cnt = 0 |
| 117 | + for i := 0; i < b.N; i++ { |
| 118 | + for j := range data { |
| 119 | + currIn := in[cnt] |
| 120 | + cnt++ |
| 121 | + result := f(currIn.in) |
| 122 | + if len(result) != len(currIn.expect) { |
| 123 | + b.Fatalf("[%d] emoji std, got \n%q but expected \n%q", j, result, currIn.expect) |
| 124 | + } |
| 125 | + } |
| 126 | + |
| 127 | + } |
| 128 | +} |
0 commit comments