-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathnanoid_test.go
103 lines (91 loc) · 2.39 KB
/
nanoid_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package nanoid
import (
"math"
"strings"
"testing"
)
var urlLength = len(defaults.Alphabet)
// Test that nanoid generates URL friendly IDs
// it ('generates URL-friendly IDs')
func TestGeneratesURLFriendlyIDs(t *testing.T) {
for i := 0; i < 10; i++ {
id, err := Nanoid()
if err != nil {
t.Errorf("Nanoid error: %v", err)
}
if len(id) != defaults.Size {
t.Errorf(
"TestGeneratesURLFriendlyIDs error: length of id %v should be %v, got %v",
id,
defaults.Size,
id,
)
}
runeID := []rune(id)
for j := 0; j < len(runeID); j++ {
res := strings.Contains(defaults.Alphabet, string(runeID[j]))
if !res {
t.Errorf(
"GeneratesURLFriendlyIds error: char %v should be contained in %v",
string(runeID[j]),
defaults.Alphabet,
)
}
}
}
}
// Test that nanoid has no collisions
// it ('has no collisions')
func TestHasNoCollisions(t *testing.T) {
COUNT := 100 * 1000
used := make(map[string]bool)
for i := 0; i < COUNT; i++ {
id, err := Nanoid()
if err != nil {
t.Errorf("Nanoid error: %v", err)
}
if used[id] {
t.Errorf("Collision error! Id %v found for test arr %v", id, used)
}
used[id] = true
}
}
// Test that Nanoid has flat distribution
// it ('has flat distribution')
func TestFlatDistribution(t *testing.T) {
COUNT := 100 * 1000
instance, err := Nanoid()
if err != nil {
t.Errorf("Nanoid error: %v", err)
}
LENGTH := len(instance)
chars := make(map[byte]int)
for i := 0; i < COUNT; i++ {
id, _ := Nanoid()
for j := 0; j < LENGTH; j++ {
// https://github.com/ai/nanoid/blob/d6ad3412147fa4c2b0d404841ade245a00c2009f/test/index.test.js#L33
// if (!chars[char]) chars[char] = 0 is useless since it
// is initialized by default to 0 from Golang
chars[id[j]]++
}
}
for char, k := range chars {
distribution := float64(k) * float64(urlLength) / float64(COUNT*LENGTH)
if !toBeCloseTo(distribution, 1, 1) {
t.Errorf("Distribution error! Distribution %v found for char %v", distribution, char)
}
}
}
// utility that replicates jest.toBeCloseTo
func toBeCloseTo(value, actual, expected float64) bool {
precision := 2
// https://github.com/facebook/jest/blob/a397abaf9f08e691f8739899819fc4da41c1e476/packages/expect/src/matchers.js#L83
pass := math.Abs(expected-actual) < math.Pow10(-precision)/2
return pass
}
// Benchmark nanoid generator
func BenchmarkNanoid(b *testing.B) {
for n := 0; n < b.N; n++ {
Nanoid()
}
}