@@ -155,7 +155,10 @@ func TestShareWords(t *testing.T) {
155155 data [i ] = byte (i )
156156 }
157157 share := NewShare (2 , 1 , 5 , 3 , "Alice" , data )
158- words := share .Words ()
158+ words , err := share .Words ()
159+ if err != nil {
160+ t .Fatalf ("Words() error: %v" , err )
161+ }
159162 if len (words ) != 25 {
160163 t .Errorf ("expected 25 words for 33-byte share (24 data + 1 meta), got %d" , len (words ))
161164 }
@@ -184,8 +187,8 @@ func TestDecodeShareWordsRoundTrip(t *testing.T) {
184187 {"index 5" , 5 , 5 },
185188 {"index 15 (max exact)" , 15 , 15 },
186189 {"index 16 (sentinel)" , 16 , 0 }, // above 15 → stored as 0
187- {"index 100 (sentinel)" , 100 , 0 }, // above 15 → stored as 0
188- {"index 255 (sentinel)" , 255 , 0 }, // above 15 → stored as 0
190+ {"index 100 (sentinel)" , 100 , 0 }, // above 15 → stored as 0
191+ {"index 255 (sentinel)" , 255 , 0 }, // above 15 → stored as 0
189192 }
190193
191194 for _ , tt := range tests {
@@ -195,7 +198,10 @@ func TestDecodeShareWordsRoundTrip(t *testing.T) {
195198 data [i ] = byte (i * 7 )
196199 }
197200 share := NewShare (2 , tt .index , 5 , 3 , "Test" , data )
198- words := share .Words ()
201+ words , err := share .Words ()
202+ if err != nil {
203+ t .Fatalf ("Words() error: %v" , err )
204+ }
199205 if len (words ) != 25 {
200206 t .Fatalf ("expected 25 words, got %d" , len (words ))
201207 }
@@ -222,19 +228,22 @@ func TestWord25ChecksumDetectsTransposition(t *testing.T) {
222228 data [i ] = byte (i * 13 )
223229 }
224230 share := NewShare (2 , 3 , 5 , 3 , "Test" , data )
225- words := share .Words ()
231+ words , err := share .Words ()
232+ if err != nil {
233+ t .Fatalf ("Words() error: %v" , err )
234+ }
226235
227236 // Swap words 0 and 1 (adjacent transposition in data words)
228237 swapped := make ([]string , len (words ))
229238 copy (swapped , words )
230239 swapped [0 ], swapped [1 ] = swapped [1 ], swapped [0 ]
231240
232- _ , _ , err := DecodeShareWords (swapped )
233- if err == nil {
241+ _ , _ , decErr := DecodeShareWords (swapped )
242+ if decErr == nil {
234243 t .Error ("expected checksum error for transposed words, got nil" )
235244 }
236- if ! strings .Contains (err .Error (), "checksum" ) {
237- t .Errorf ("expected checksum error, got: %v" , err )
245+ if ! strings .Contains (decErr .Error (), "checksum" ) {
246+ t .Errorf ("expected checksum error, got: %v" , decErr )
238247 }
239248}
240249
@@ -246,7 +255,10 @@ func TestWord25ChecksumDetectsSubstitution(t *testing.T) {
246255 data [i ] = byte (i * 13 )
247256 }
248257 share := NewShare (2 , 3 , 5 , 3 , "Test" , data )
249- words := share .Words ()
258+ words , err := share .Words ()
259+ if err != nil {
260+ t .Fatalf ("Words() error: %v" , err )
261+ }
250262
251263 // Replace word 5 with a different BIP39 word
252264 modified := make ([]string , len (words ))
@@ -258,7 +270,7 @@ func TestWord25ChecksumDetectsSubstitution(t *testing.T) {
258270 }
259271 modified [5 ] = replacement
260272
261- _ , _ , err : = DecodeShareWords (modified )
273+ _ , _ , err = DecodeShareWords (modified )
262274 if err == nil {
263275 t .Error ("expected checksum error for substituted word, got nil" )
264276 }
@@ -328,3 +340,94 @@ func TestWord25ChecksumDifferentData(t *testing.T) {
328340 t .Logf ("warning: checksums collided (1/128 chance) — not a bug, but unexpected" )
329341 }
330342}
343+
344+ func TestWordsV1ShareReturnsError (t * testing.T ) {
345+ data := make ([]byte , 33 )
346+ share := NewShare (1 , 1 , 5 , 3 , "Alice" , data )
347+ _ , err := share .Words ()
348+ if err == nil {
349+ t .Fatal ("expected error for v1 share" )
350+ }
351+ if ! strings .Contains (err .Error (), "version 2" ) {
352+ t .Errorf ("expected version error, got: %v" , err )
353+ }
354+ }
355+
356+ func TestDecodeShareWordsWrongCount (t * testing.T ) {
357+ tests := []struct {
358+ name string
359+ count int
360+ }{
361+ {"0 words" , 0 },
362+ {"1 word" , 1 },
363+ {"10 words" , 10 },
364+ {"24 words" , 24 },
365+ {"26 words" , 26 },
366+ }
367+
368+ for _ , tt := range tests {
369+ t .Run (tt .name , func (t * testing.T ) {
370+ words := make ([]string , tt .count )
371+ for i := range words {
372+ words [i ] = "abandon"
373+ }
374+ _ , _ , err := DecodeShareWords (words )
375+ if err == nil {
376+ t .Fatalf ("expected error for %d words" , tt .count )
377+ }
378+ if ! strings .Contains (err .Error (), "expected 25 words" ) {
379+ t .Errorf ("expected word count error, got: %v" , err )
380+ }
381+ })
382+ }
383+ }
384+
385+ func TestDecodeWordsMixedCase (t * testing.T ) {
386+ data := make ([]byte , 33 )
387+ for i := range data {
388+ data [i ] = byte (i * 7 )
389+ }
390+ words := EncodeWords (data )
391+
392+ // Uppercase some words
393+ mixed := make ([]string , len (words ))
394+ for i , w := range words {
395+ if i % 2 == 0 {
396+ mixed [i ] = strings .ToUpper (w )
397+ } else {
398+ // Capitalize first letter
399+ mixed [i ] = strings .ToUpper (w [:1 ]) + w [1 :]
400+ }
401+ }
402+
403+ decoded , err := DecodeWords (mixed )
404+ if err != nil {
405+ t .Fatalf ("DecodeWords should handle mixed case, got error: %v" , err )
406+ }
407+ if ! bytes .Equal (decoded , data ) {
408+ t .Errorf ("mixed-case round-trip mismatch" )
409+ }
410+ }
411+
412+ func TestSuggestWordNoMatch (t * testing.T ) {
413+ // Strings far from any BIP39 word (distance > 2)
414+ tests := []string {"zzzzzzz" , "qqqqqq" , "xylophone" }
415+ for _ , input := range tests {
416+ got := SuggestWord (input )
417+ if got != "" {
418+ t .Errorf ("SuggestWord(%q) = %q, want empty string (no close match)" , input , got )
419+ }
420+ }
421+ }
422+
423+ func TestWordsNegativeIndexReturnsError (t * testing.T ) {
424+ data := make ([]byte , 33 )
425+ share := NewShare (2 , - 1 , 5 , 3 , "Alice" , data )
426+ _ , err := share .Words ()
427+ if err == nil {
428+ t .Fatal ("expected error for negative index" )
429+ }
430+ if ! strings .Contains (err .Error (), "non-negative" ) {
431+ t .Errorf ("expected non-negative error, got: %v" , err )
432+ }
433+ }
0 commit comments