Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 22 additions & 35 deletions plugboard/plugboard_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package plugboard

import (
"reflect"
"testing"

"github.com/atbu/ultra/conversion"
Expand Down Expand Up @@ -48,46 +47,34 @@ func TestUnevenPlugboardString(t *testing.T) {
}
}

func generatePlugboardPair(a rune, b rune) PlugboardPair {
return PlugboardPair{int(a - 65), int(b - 65)}
}

func TestPlugboardConstructor(t *testing.T) {
tests := []struct {
input string
expectedOutput *Plugboard
}{
{"ABCD", &Plugboard{[]PlugboardPair{
generatePlugboardPair('A', 'B'),
generatePlugboardPair('C', 'D'),
}}},
{"RKWDPT", &Plugboard{[]PlugboardPair{
generatePlugboardPair('R', 'K'),
generatePlugboardPair('W', 'D'),
generatePlugboardPair('P', 'T'),
}}},
{"QPALZMWOXNEICBRUVFGH", &Plugboard{[]PlugboardPair{
generatePlugboardPair('Q', 'P'),
generatePlugboardPair('A', 'L'),
generatePlugboardPair('Z', 'M'),
generatePlugboardPair('W', 'O'),
generatePlugboardPair('X', 'N'),
generatePlugboardPair('E', 'I'),
generatePlugboardPair('C', 'B'),
generatePlugboardPair('R', 'U'),
generatePlugboardPair('V', 'F'),
generatePlugboardPair('G', 'H'),
}}},
tests := []string{
"ABCD",
"RKWDPT",
"QPALZMWOXNEICBRUVFGH",
}

for _, testData := range tests {
got, err := New(testData.input)
if !reflect.DeepEqual(got, testData.expectedOutput) {
t.Errorf("New() in plugboard package returned unexpected output - got=%v, expected=%v", got, testData.expectedOutput)
}
for _, input := range tests {
got, err := New(input)
if err != nil {
t.Errorf("New() in plugboard package returned unexpected error - got=%v, expected=%v", err, nil)
}

// Each pair in the plugboard is derived from two consecutive characters in the input string, so we can
// derive the expected pairs from the input rather than hand-listing them.
wantPairs := len(input) / 2
if len(got.Configuration) != wantPairs {
t.Errorf("New() in plugboard package returned unexpected number of pairs - got=%v, expected=%v", len(got.Configuration), wantPairs)
continue
}

for i, pair := range got.Configuration {
wantA := conversion.ConvertCharToIndex(rune(input[i*2]))
wantB := conversion.ConvertCharToIndex(rune(input[i*2+1]))
if pair.a != wantA || pair.b != wantB {
t.Errorf("New() in plugboard package returned unexpected pair at index %d - got=%v, expected=%v", i, pair, PlugboardPair{wantA, wantB})
}
}
}
}

Expand Down
157 changes: 10 additions & 147 deletions reflector/reflector_test.go
Original file line number Diff line number Diff line change
@@ -1,165 +1,28 @@
package reflector

import (
"reflect"
"testing"

"github.com/atbu/ultra/conversion"
)

// todo to structure better

func TestConstructor(t *testing.T) {
tests := []struct {
input ReflectorConfiguration
expectedOutput *Reflector
input ReflectorConfiguration
wiringString string
}{
{ReflectorA, &Reflector{[26]int{
4,
9,
12,
25,
0,
11,
24,
23,
21,
1,
22,
5,
2,
17,
16,
20,
14,
13,
19,
18,
15,
8,
10,
7,
6,
3,
}}},
{ReflectorB, &Reflector{[26]int{
24,
17,
20,
7,
16,
18,
11,
3,
15,
23,
13,
6,
14,
10,
12,
8,
4,
1,
5,
25,
2,
22,
21,
9,
0,
19,
}}},
{ReflectorC, &Reflector{[26]int{
5,
21,
15,
9,
8,
0,
14,
24,
4,
3,
17,
25,
23,
22,
6,
2,
19,
10,
20,
16,
18,
1,
13,
12,
7,
11,
}}},
{ReflectorNarrowB, &Reflector{[26]int{
4,
13,
10,
16,
0,
20,
24,
22,
9,
8,
2,
14,
15,
1,
11,
12,
3,
23,
25,
21,
5,
19,
7,
17,
6,
18,
}}},
{ReflectorNarrowC, &Reflector{[26]int{
17,
3,
14,
1,
9,
13,
19,
10,
21,
4,
7,
12,
11,
5,
2,
22,
25,
0,
23,
6,
24,
8,
15,
18,
20,
16,
}}},
{ReflectorA, "EJMZALYXVBWFCRQUONTSPIKHGD"},
{ReflectorB, "YRUHQSLDPXNGOKMIEBFZCWVJAT"},
{ReflectorC, "FVPJIAOYEDRZXWGCTKUQSBNMHL"},
{ReflectorNarrowB, "ENKQAUYWJICOPBLMDXZVFTHRGS"},
{ReflectorNarrowC, "RDOBJNTKVEHMLFCWZAXGYIPSUQ"},
}

for _, testData := range tests {
got := New(testData.input)
if !reflect.DeepEqual(got, testData.expectedOutput) {
t.Errorf("New() in reflector package returned unexpected output - got=%v, expected=%v", got, testData.expectedOutput)
wantWiring := conversion.ConvertWiringStringToArray(testData.wiringString)
if got.Wiring != wantWiring {
t.Errorf("New() in reflector package returned unexpected wiring - got=%v, expected=%v", got.Wiring, wantWiring)
}
}
}
Expand Down
79 changes: 79 additions & 0 deletions rotor/fourth_rotor_test.go
Original file line number Diff line number Diff line change
@@ -1 +1,80 @@
package rotor

import (
"testing"

"github.com/atbu/ultra/conversion"
)

func TestNewFourthRotor(t *testing.T) {
tests := []struct {
configuration FourthRotorConfiguration
wiringString string
startingPosition rune
}{
{FourthRotorBeta, "LEYJVCNIXWPBQMDRTAKZGFUHOS", 'A'},
{FourthRotorGamma, "FSOKANUERHMBTIYCWLQPZXVGJD", 'K'},
}

for _, testData := range tests {
got := NewFourthRotor(testData.configuration, testData.startingPosition)

wantWiring := conversion.ConvertWiringStringToArray(testData.wiringString)
if got.Wiring != wantWiring {
t.Errorf("NewFourthRotor() in rotor package returned unexpected wiring - got=%v, expected=%v", got.Wiring, wantWiring)
}

wantInverseWiring := conversion.InverseWiringArray(wantWiring)
if got.InverseWiring != wantInverseWiring {
t.Errorf("NewFourthRotor() in rotor package returned unexpected inverse wiring - got=%v, expected=%v", got.InverseWiring, wantInverseWiring)
}

wantPosition := conversion.ConvertCharToIndex(testData.startingPosition)
if got.Position != wantPosition {
t.Errorf("NewFourthRotor() in rotor package returned unexpected position - got=%v, expected=%v", got.Position, wantPosition)
}
}
}

func TestFourthRotorMapSignal(t *testing.T) {
tests := []struct {
configuration FourthRotorConfiguration
startingPosition rune
input rune
inverse bool
expectedOutput rune
}{
// With position 'A' the delta is zero, so the signal maps straight through the wiring.
{FourthRotorBeta, 'A', 'A', false, 'L'},
{FourthRotorGamma, 'A', 'A', false, 'F'},
// Inverse mapping with a zero delta uses the inverse wiring. Beta maps 'A'->'L', so 'L' maps back to 'A'.
{FourthRotorBeta, 'A', 'L', true, 'A'},
}

for _, testData := range tests {
rotor := NewFourthRotor(testData.configuration, testData.startingPosition)
got := rotor.MapSignal(conversion.ConvertCharToIndex(testData.input), testData.inverse)
expectedOutput := conversion.ConvertCharToIndex(testData.expectedOutput)
if got != expectedOutput {
t.Errorf("MapSignal() in rotor package returned unexpected output - got=%v, expected=%v", got, expectedOutput)
}
}
}

// TestFourthRotorMapSignalRoundTrip verifies that mapping a signal forward and then back through a fourth rotor
// returns the original signal, across a range of positions. This exercises the position delta wrap-around math
// without needing hand-computed expected values.
func TestFourthRotorMapSignalRoundTrip(t *testing.T) {
positions := []rune{'A', 'F', 'N', 'Z'}

for _, position := range positions {
rotor := NewFourthRotor(FourthRotorGamma, position)
for signal := 0; signal < 26; signal++ {
forward := rotor.MapSignal(signal, false)
got := rotor.MapSignal(forward, true)
if got != signal {
t.Errorf("MapSignal() round-trip in rotor package failed for position=%c signal=%d - got=%v, expected=%v", position, signal, got, signal)
}
}
}
}
Loading
Loading