diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 40500b8..58a8cd2 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -12,6 +12,6 @@ jobs: steps: - uses: actions/checkout@v4 - name: Build - run: go build . + run: go build ./... - name: Run tests run: go test ./... diff --git a/conversion/conversion_test.go b/conversion/conversion_test.go index bb45432..b18b04a 100644 --- a/conversion/conversion_test.go +++ b/conversion/conversion_test.go @@ -49,3 +49,61 @@ func TestConvertIndexToChar(t *testing.T) { } } } + +func TestConvertBetweenIndexAndChar(t *testing.T) { + tests := []rune{ + 'A', + 'B', + 'C', + 'X', + 'Y', + 'Z', + } + + for _, testData := range tests { + got := ConvertIndexToChar(ConvertCharToIndex(testData)) + if got != testData { + t.Errorf( + "ConvertIndexToChar and ConvertCharToIndex reciprocity test failed - got=%c, expected=%c", + got, + testData, + ) + } + } +} + +func TestConvertWiringStringToArray(t *testing.T) { + tests := []struct { + input string + expectedOutput []int + }{ + {"ABCDEFGHIJKLMNOPQRSTUVWXYZ", []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}}, + {"DCBAFEIHGMLKONJRQPVUTSZYXW", []int{3, 2, 1, 0, 5, 4, 8, 7, 6, 12, 11, 10, 14, 13, 9, 17, 16, 15, 21, 20, 19, 18, 25, 24, 23, 22}}, + {"ZYXWVUTSRQPONMLKJIHGFEDCBA", []int{25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}}, + } + + for _, testData := range tests { + got := ConvertWiringStringToArray(testData.input) + if got != [26]int(testData.expectedOutput) { + t.Errorf("ConvertWiringStringToArray(%s) failed,\ngot=%d,\nexpected=%d", testData.input, got, testData.expectedOutput) + } + } +} + +func TestInverseWiringArray(t *testing.T) { + tests := []struct { + input []int + expectedOutput []int + }{ + {[]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}, []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}}, + {[]int{19, 20, 21, 22, 23, 24, 25, 15, 16, 17, 18, 10, 11, 12, 13, 14, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3}, []int{22, 23, 24, 25, 16, 17, 18, 19, 20, 21, 11, 12, 13, 14, 15, 7, 8, 9, 10, 0, 1, 2, 3, 4, 5, 6}}, + {[]int{10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 25, 24, 23, 22, 21}, []int{10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 25, 24, 23, 22, 21}}, + } + + for _, testData := range tests { + got := InverseWiringArray([26]int(testData.input)) + if got != [26]int(testData.expectedOutput) { + t.Errorf("InverseWiringArray(%d) failed,\ngot=%d,\nexpected=%d", testData.input, got, testData.expectedOutput) + } + } +} diff --git a/machine/machine_test.go b/machine/machine_test.go index a18b4ae..9208975 100644 --- a/machine/machine_test.go +++ b/machine/machine_test.go @@ -156,6 +156,21 @@ func TestRingCase3(t *testing.T) { runTest(t, machine, "HELLOWORLD", "CDKSEVMKXJ") } +func TestProcessEmptyString(t *testing.T) { + // note: this machine configuration wouldn't be possible in real life because an operator would only + // have one of each rotor (as far as I know) + machine := &Machine{ + rotor.NewRotor(rotor.RotorII, 'F', 'D'), + rotor.NewRotor(rotor.RotorII, 'P', 'W'), + rotor.NewRotor(rotor.RotorII, 'K', 'L'), + nil, + reflector.New(reflector.ReflectorB), + createPlugboard(t, "JWYLFKREVPXTHOBCMQZG"), + } + + runTest(t, machine, "", "") +} + func TestRandomCase1(t *testing.T) { // note: this machine configuration wouldn't be possible in real life because an operator would only // have one of each rotor (as far as I know) diff --git a/main.go b/main.go deleted file mode 100644 index 70a7fe5..0000000 --- a/main.go +++ /dev/null @@ -1,7 +0,0 @@ -package main - -import "fmt" - -func main() { - fmt.Println("Hello world!") -} diff --git a/plugboard/plugboard_test.go b/plugboard/plugboard_test.go new file mode 100644 index 0000000..c73157d --- /dev/null +++ b/plugboard/plugboard_test.go @@ -0,0 +1,117 @@ +package plugboard + +import ( + "reflect" + "testing" + + "github.com/atbu/ultra/conversion" +) + +func TestEmptyPlugboardString(t *testing.T) { + tests := []string{ + "", + " ", + "\n", + "\t", + "\n\t ", + "\r\n\t ", + } + + for _, testData := range tests { + got, err := New(testData) + if got != nil { + t.Errorf("New() in plugboard package returned unexpected output - got=%v, expected=%v", got, nil) + } + if err != nil { + t.Errorf("New() in plugboard package returned unexpected error - got=%v, expected=%v", err, nil) + } + } +} + +func TestUnevenPlugboardString(t *testing.T) { + tests := []string{ + "ABC", + "ABCDE", + "ZJFIWDL", + "R", + "DPWERMS", + } + + for _, testData := range tests { + got, err := New(testData) + if got != nil { + t.Errorf("New() in plugboard package returned unexpected output - got=%v, expected=%v", got, nil) + } + if err == nil { + t.Errorf("New() in plugboard package returned no error when we expected it to - got=%v, expected=%v", err, ErrUnevenNumberOfCharacters) + } + } +} + +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'), + }}}, + } + + 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) + } + if err != nil { + t.Errorf("New() in plugboard package returned unexpected error - got=%v, expected=%v", err, nil) + } + } +} + +func TestMapSignal(t *testing.T) { + tests := []struct { + plugboardConfiguration string + inputSignal rune + expectedOutput rune + }{ + {"ABCDEFGH", 'A', 'B'}, + {"CDOFRPIT", 'D', 'C'}, + {"PLEFRD", 'Z', 'Z'}, + } + + for _, testData := range tests { + plugboard, err := New(testData.plugboardConfiguration) + if err != nil { + t.Errorf("Failed to generate plugboard for MapSignal test - err=%s", err) + } + + got := plugboard.MapSignal(conversion.ConvertCharToIndex(testData.inputSignal)) + expectedOutput := conversion.ConvertCharToIndex(testData.expectedOutput) + if got != expectedOutput { + t.Errorf("MapSignal() in plugboard package returned unexpected output - got=%v, expected=%v", got, expectedOutput) + } + } +} diff --git a/reflector/reflector_test.go b/reflector/reflector_test.go new file mode 100644 index 0000000..e5d688e --- /dev/null +++ b/reflector/reflector_test.go @@ -0,0 +1,190 @@ +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 + }{ + {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, + }}}, + } + + 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) + } + } +} + +func TestMapSignal(t *testing.T) { + tests := []struct { + configuration ReflectorConfiguration + input rune + expectedOutput rune + }{ + {ReflectorA, 'A', 'E'}, + {ReflectorNarrowB, 'Z', 'S'}, + {ReflectorC, 'C', 'P'}, + {ReflectorB, 'B', 'R'}, + {ReflectorNarrowC, 'M', 'L'}, + {ReflectorA, 'Y', 'G'}, + {ReflectorC, 'H', 'Y'}, + } + + for _, testData := range tests { + reflector := New(testData.configuration) + got := reflector.MapSignal(conversion.ConvertCharToIndex(testData.input)) + expectedOutput := conversion.ConvertCharToIndex(testData.expectedOutput) + if got != expectedOutput { + t.Errorf("MapSignal() in reflector package returned unexpected output - got=%v, expected=%v", got, expectedOutput) + } + } +} diff --git a/rotor/fourth_rotor_test.go b/rotor/fourth_rotor_test.go new file mode 100644 index 0000000..4cfdea6 --- /dev/null +++ b/rotor/fourth_rotor_test.go @@ -0,0 +1 @@ +package rotor diff --git a/rotor/rotor_test.go b/rotor/rotor_test.go new file mode 100644 index 0000000..4cfdea6 --- /dev/null +++ b/rotor/rotor_test.go @@ -0,0 +1 @@ +package rotor