package qr import ( "strings" "testing" "git.wxccs.org/iceking2nd/winauth-go/internal/config" ) func TestEntryToOtpAuthGoogle(t *testing.T) { e := config.Entry{ Name: "MyGoogle", Vendor: "google", SecretRaw: "0102030405\t6\tSHA1\t30", } oa, partial, err := EntryToOtpAuth(e) if err != nil { t.Fatalf("EntryToOtpAuth: %v", err) } if partial { t.Error("Google should not be partial") } if oa.Type != "totp" { t.Errorf("Type = %q, want totp", oa.Type) } if oa.Issuer != "Google" { t.Errorf("Issuer = %q, want Google", oa.Issuer) } if oa.Label != "Google:MyGoogle" { t.Errorf("Label = %q", oa.Label) } if oa.Digits != 6 { t.Errorf("Digits = %d, want 6", oa.Digits) } if oa.Algorithm != "SHA1" { t.Errorf("Algorithm = %q, want SHA1", oa.Algorithm) } } func TestEntryToOtpAuthHOTP(t *testing.T) { e := config.Entry{ Name: "Counter", Vendor: "hotp", SecretRaw: "AABBCCDD\t6\tSHA1\t30|10", } oa, _, err := EntryToOtpAuth(e) if err != nil { t.Fatalf("EntryToOtpAuth: %v", err) } if oa.Type != "hotp" { t.Errorf("Type = %q, want hotp", oa.Type) } if oa.Counter != 10 { t.Errorf("Counter = %d, want 10", oa.Counter) } } func TestEntryToOtpAuthBattleNetPartial(t *testing.T) { e := config.Entry{ Name: "BNet", Vendor: "battlenet", SecretRaw: "AABB\t8\tSHA1\t30|53455249414C", } oa, partial, err := EntryToOtpAuth(e) if err != nil { t.Fatalf("EntryToOtpAuth: %v", err) } if !partial { t.Error("Battle.Net should be partial") } if oa.Digits != 8 { t.Errorf("Digits = %d, want 8", oa.Digits) } } func TestEntryToOtpAuthSteamPartial(t *testing.T) { e := config.Entry{ Name: "Steam", Vendor: "steam", SecretRaw: "CCDD\t5\tSHA1\t30|73657269616C|646576696365", } _, partial, err := EntryToOtpAuth(e) if err != nil { t.Fatalf("EntryToOtpAuth: %v", err) } if !partial { t.Error("Steam should be partial") } } func TestEntryToOtpAuthEmptySecret(t *testing.T) { e := config.Entry{Name: "Empty", Vendor: "google", SecretRaw: ""} if _, _, err := EntryToOtpAuth(e); err == nil { t.Error("expected error for empty secret") } } func TestURIRoundTrip(t *testing.T) { e := config.Entry{ Name: "Test", Vendor: "google", SecretRaw: "0102030405\t6\tSHA1\t30", } oa, _, err := EntryToOtpAuth(e) if err != nil { t.Fatalf("EntryToOtpAuth: %v", err) } uri := oa.URI() // Parse it back parsed, err := ParseOtpAuth(uri) if err != nil { t.Fatalf("ParseOtpAuth(%q): %v", uri, err) } if parsed.Type != "totp" { t.Errorf("Type = %q, want totp", parsed.Type) } if parsed.SecretBase32 != oa.SecretBase32 { t.Errorf("Secret mismatch: %q vs %q", parsed.SecretBase32, oa.SecretBase32) } } func TestURIHOTP(t *testing.T) { oa := &OtpAuth{ Type: "hotp", Label: "MyHOTP", SecretBase32: "JBSWY3DPEHPK3PXP", Issuer: "Test", Digits: 6, Counter: 42, } uri := oa.URI() if !strings.Contains(uri, "counter=42") { t.Errorf("URI missing counter: %s", uri) } if !strings.HasPrefix(uri, "otpauth://hotp/") { t.Errorf("URI wrong prefix: %s", uri) } } func TestURIDefaultsOmitted(t *testing.T) { oa := &OtpAuth{ Type: "totp", SecretBase32: "AAAA", Algorithm: "SHA1", Digits: 6, Period: 30, } uri := oa.URI() if strings.Contains(uri, "algorithm") { t.Errorf("SHA1 should be omitted: %s", uri) } if strings.Contains(uri, "digits") { t.Errorf("digits=6 should be omitted: %s", uri) } if strings.Contains(uri, "period") { t.Errorf("period=30 should be omitted: %s", uri) } }