krz/keycask

Password manager: Swift core library, CLI for macOS/Linux/Windows, iOS/macOS app. cli password-manager swift

Tests/KeycaskCoreTests/GeneratorTests.swift

main
keycask/Tests/KeycaskCoreTests/GeneratorTests.swift history · blame · raw

57 lines · 2033 bytes

 1import Testing
 2
 3@testable import KeycaskCore
 4
 5@Suite struct GeneratorTests {
 6    struct Counter: RandomNumberGenerator {
 7        var n: UInt64 = 0
 8        mutating func next() -> UInt64 {
 9            n &+= 0x9E37_79B9_7F4A_7C15
10            return n
11        }
12    }
13
14    @Test func wordlistHas7776UniqueWords() {
15        #expect(Wordlist.words.count == 7776)
16        #expect(Set(Wordlist.words).count == 7776)
17        #expect(Wordlist.words.first == "abacus")
18        #expect(Wordlist.words.allSatisfy { !$0.isEmpty && !$0.contains(" ") })
19    }
20
21    @Test func passwordHasRequestedLengthFromTheAlphabet() {
22        let allowed = Set(Generator.alphabet)
23        for length in [1, 8, 24, 64] {
24            let p = Generator.password(length: length)
25            #expect(p.count == length)
26            #expect(p.allSatisfy { allowed.contains($0) })
27        }
28        #expect(Generator.password(length: 0) == "")
29    }
30
31    @Test func alphabetCoversAllClasses() {
32        let s = String(Generator.alphabet)
33        #expect(s.contains("A") && s.contains("z") && s.contains("7") && s.contains("!"))
34        #expect(Set(Generator.alphabet).count == Generator.alphabet.count)
35    }
36
37    @Test func passphraseUsesWordsFromTheList() {
38        var a = Counter()
39        var b = Counter()
40        let produced = Generator.passphrase(words: 5, using: &a)
41        let count = UInt32(Wordlist.words.count)
42        let expected = (0..<5).map { _ in Wordlist.words[Int(b.next(upperBound: count))] }
43            .joined(separator: Generator.wordSeparator)
44        #expect(produced == expected)
45        #expect(Generator.passphrase(words: 0) == "")
46        #expect(!Generator.passphrase(words: 3).isEmpty)
47    }
48
49    @Test func seededOutputIsReproducible() {
50        var a = Counter()
51        var b = Counter()
52        #expect(
53            Generator.password(length: 16, using: &a) == Generator.password(length: 16, using: &b))
54        #expect(
55            Generator.passphrase(words: 3, using: &a) == Generator.passphrase(words: 3, using: &b))
56    }
57}