@@ -11,8 +11,8 @@ describe("getHashDigest()", () => {
11
11
[ "abc\\0💩" , "xxhash64" , "hex" , undefined , "86733ec125b93904" ] ,
12
12
[ "abc\\0💩" , "xxhash64" , "base64" , undefined , "hnM+wSW5OQQ=" ] ,
13
13
[ "abc\\0♥" , "xxhash64" , "base64" , undefined , "S5o0KX3APSA=" ] ,
14
- [ "abc\\0💩" , "xxhash64" , "base52" , undefined , "cfByjQcJZIU " ] ,
15
- [ "abc\\0♥" , "xxhash64" , "base52" , undefined , "qdLyAQjLlod " ] ,
14
+ [ "abc\\0💩" , "xxhash64" , "base52" , undefined , "acfByjQcJZIU " ] ,
15
+ [ "abc\\0♥" , "xxhash64" , "base52" , undefined , "aqdLyAQjLlod " ] ,
16
16
17
17
[ "test string" , "md4" , "hex" , 4 , "2e06" ] ,
18
18
[ "test string" , "md4" , "base64" , undefined , "Lgbt1PFiMmjFpRcw2KCyrw==" ] ,
@@ -34,7 +34,8 @@ describe("getHashDigest()", () => {
34
34
] ,
35
35
[ "test string" , "md5" , "base52" , undefined , "dJnldHSAutqUacjgfBQGLQx" ] ,
36
36
[ "test string" , "md5" , "base64" , undefined , "b421md6Yb6t6IWJbeRZYnA==" ] ,
37
- [ "test string" , "md5" , "base26" , 6 , "bhtsgu" ] ,
37
+ [ "test string" , "md5" , "base26" , undefined , "bhtsgujtzvmjtgtzlqvubqggbvgx" ] ,
38
+ [ "test string" , "md5" , "base26" , 6 , "ggbvgx" ] ,
38
39
[ "abc\\0♥" , "md5" , "hex" , undefined , "2e897b64f8050e66aff98d38f7a012c5" ] ,
39
40
[ "abc\\0💩" , "md5" , "hex" , undefined , "63ad5b3d675c5890e0c01ed339ba0187" ] ,
40
41
[ "abc\\0💩" , "md5" , "base64" , undefined , "Y61bPWdcWJDgwB7TOboBhw==" ] ,
@@ -79,3 +80,46 @@ describe("getHashDigest()", () => {
79
80
) ;
80
81
} ) ;
81
82
} ) ;
83
+
84
+ function testDistribution ( digestType , length , tableSize , iterations ) {
85
+ const lowerBound = Math . round ( iterations / 2 ) ;
86
+ const upperBound = Math . round ( iterations * 2 ) ;
87
+
88
+ const stats = [ ] ;
89
+ for ( let i = tableSize * iterations ; i -- > 0 ; ) {
90
+ const generatedString = loaderUtils . getHashDigest (
91
+ `Some input #${ i } ` ,
92
+ undefined ,
93
+ digestType ,
94
+ length
95
+ ) ;
96
+
97
+ for ( let pos = 0 ; pos < length ; pos ++ ) {
98
+ const char = generatedString [ pos ] ;
99
+ stats [ pos ] = stats [ pos ] || { } ;
100
+ stats [ pos ] [ char ] = ( stats [ pos ] [ char ] || 0 ) + 1 ;
101
+ }
102
+ }
103
+
104
+ for ( let pos = 0 ; pos < length ; pos ++ ) {
105
+ const chars = Object . keys ( stats [ pos ] ) . sort ( ) ;
106
+ test ( `distinct chars at position ${ pos } ` , ( ) => {
107
+ expect ( chars . length ) . toBe ( tableSize ) ;
108
+ } ) ;
109
+ for ( const char of chars ) {
110
+ test ( `occurences of char "${ char } " at position ${ pos } should be around ${ iterations } ` , ( ) => {
111
+ expect ( stats [ pos ] [ char ] ) . toBeLessThanOrEqual ( upperBound ) ;
112
+ expect ( stats [ pos ] [ char ] ) . toBeGreaterThanOrEqual ( lowerBound ) ;
113
+ } ) ;
114
+ }
115
+ }
116
+ }
117
+
118
+ describe ( "getHashDigest() char distribution" , ( ) => {
119
+ describe ( "should be uniform for base62" , ( ) => {
120
+ testDistribution ( "base62" , 8 , 62 , 100 ) ;
121
+ } ) ;
122
+ describe ( "should be uniform for base26" , ( ) => {
123
+ testDistribution ( "base26" , 8 , 26 , 100 ) ;
124
+ } ) ;
125
+ } ) ;
0 commit comments