[DEPRECATED] Go implementation of plcbundle
at rust-test 218 lines 5.8 kB view raw
1package types_test 2 3import ( 4 "bytes" 5 "fmt" 6 "testing" 7 8 "tangled.org/atscan.net/plcbundle/internal/types" 9) 10 11// ==================================================================================== 12// CONSTANT VALIDATION TESTS 13// ==================================================================================== 14 15func TestConstants(t *testing.T) { 16 t.Run("BundleSize", func(t *testing.T) { 17 if types.BUNDLE_SIZE != 10000 { 18 t.Errorf("BUNDLE_SIZE = %d, want 10000", types.BUNDLE_SIZE) 19 } 20 21 // Ensure it's a reasonable size 22 if types.BUNDLE_SIZE < 1000 { 23 t.Error("BUNDLE_SIZE too small") 24 } 25 26 if types.BUNDLE_SIZE > 100000 { 27 t.Error("BUNDLE_SIZE too large") 28 } 29 }) 30 31 t.Run("IndexFile", func(t *testing.T) { 32 if types.INDEX_FILE != "plc_bundles.json" { 33 t.Errorf("INDEX_FILE = %s, want plc_bundles.json", types.INDEX_FILE) 34 } 35 36 // Should be a valid filename 37 if types.INDEX_FILE == "" { 38 t.Error("INDEX_FILE should not be empty") 39 } 40 41 // Should have .json extension 42 if len(types.INDEX_FILE) < 5 || types.INDEX_FILE[len(types.INDEX_FILE)-5:] != ".json" { 43 t.Error("INDEX_FILE should have .json extension") 44 } 45 }) 46 47 t.Run("IndexVersion", func(t *testing.T) { 48 if types.INDEX_VERSION != "1.0" { 49 t.Errorf("INDEX_VERSION = %s, want 1.0", types.INDEX_VERSION) 50 } 51 52 // Should follow semantic versioning format (at least major.minor) 53 if len(types.INDEX_VERSION) < 3 { 54 t.Error("INDEX_VERSION should follow semantic versioning") 55 } 56 }) 57} 58 59// ==================================================================================== 60// LOGGER INTERFACE COMPLIANCE TESTS 61// ==================================================================================== 62 63func TestLoggerInterface(t *testing.T) { 64 t.Run("MockLoggerImplementsInterface", func(t *testing.T) { 65 var logger types.Logger = &mockLogger{} 66 67 // Should compile and not panic 68 logger.Printf("test %s", "message") 69 logger.Println("test", "message") 70 }) 71 72 t.Run("BufferedLoggerImplementation", func(t *testing.T) { 73 buf := &bytes.Buffer{} 74 logger := &bufferedLogger{buf: buf} 75 76 // Cast to interface 77 var _ types.Logger = logger 78 79 logger.Printf("formatted %s %d", "message", 42) 80 logger.Println("plain", "message") 81 82 output := buf.String() 83 84 if !containsString(output, "formatted message 42") { 85 t.Error("Printf output not captured") 86 } 87 88 if !containsString(output, "plain message") { 89 t.Error("Println output not captured") 90 } 91 }) 92 93 t.Run("NullLoggerImplementation", func(t *testing.T) { 94 // Logger that discards all output 95 logger := &nullLogger{} 96 97 // Should not panic 98 var _ types.Logger = logger 99 logger.Printf("test %s", "ignored") 100 logger.Println("also", "ignored") 101 }) 102 103 t.Run("MultiLoggerImplementation", func(t *testing.T) { 104 // Logger that writes to multiple destinations 105 buf1 := &bytes.Buffer{} 106 buf2 := &bytes.Buffer{} 107 108 logger := &multiLogger{ 109 loggers: []types.Logger{ 110 &bufferedLogger{buf: buf1}, 111 &bufferedLogger{buf: buf2}, 112 }, 113 } 114 115 var _ types.Logger = logger 116 117 logger.Printf("test %s", "message") 118 119 // Both buffers should have the message 120 if !containsString(buf1.String(), "test message") { 121 t.Error("first logger didn't receive message") 122 } 123 124 if !containsString(buf2.String(), "test message") { 125 t.Error("second logger didn't receive message") 126 } 127 }) 128} 129 130// ==================================================================================== 131// CONSTANT USAGE IN CALCULATIONS 132// ==================================================================================== 133 134func TestConstantUsage(t *testing.T) { 135 t.Run("GlobalPositionCalculation", func(t *testing.T) { 136 // Global position = bundleNumber * BUNDLE_SIZE + position 137 bundleNumber := 42 138 position := 1337 139 140 globalPos := bundleNumber*types.BUNDLE_SIZE + position 141 expected := 420000 + 1337 142 143 if globalPos != expected { 144 t.Errorf("global position calculation incorrect: got %d, want %d", globalPos, expected) 145 } 146 }) 147 148 t.Run("BundleFromGlobalPosition", func(t *testing.T) { 149 globalPos := 88410345 150 151 bundleNumber := globalPos / types.BUNDLE_SIZE 152 position := globalPos % types.BUNDLE_SIZE 153 154 if bundleNumber != 8841 { 155 t.Errorf("bundle calculation wrong: got %d, want 8841", bundleNumber) 156 } 157 158 if position != 345 { 159 t.Errorf("position calculation wrong: got %d, want 345", position) 160 } 161 }) 162 163 t.Run("OperationCountPerBundle", func(t *testing.T) { 164 // Each bundle should have exactly BUNDLE_SIZE operations 165 bundleCount := 100 166 totalOps := bundleCount * types.BUNDLE_SIZE 167 168 if totalOps != 1000000 { 169 t.Errorf("total ops calculation: got %d, want 1000000", totalOps) 170 } 171 }) 172} 173 174// ==================================================================================== 175// HELPER IMPLEMENTATIONS 176// ==================================================================================== 177 178type mockLogger struct{} 179 180func (l *mockLogger) Printf(format string, v ...interface{}) {} 181func (l *mockLogger) Println(v ...interface{}) {} 182 183type bufferedLogger struct { 184 buf *bytes.Buffer 185} 186 187func (l *bufferedLogger) Printf(format string, v ...interface{}) { 188 fmt.Fprintf(l.buf, format+"\n", v...) 189} 190 191func (l *bufferedLogger) Println(v ...interface{}) { 192 fmt.Fprintln(l.buf, v...) 193} 194 195type nullLogger struct{} 196 197func (l *nullLogger) Printf(format string, v ...interface{}) {} 198func (l *nullLogger) Println(v ...interface{}) {} 199 200type multiLogger struct { 201 loggers []types.Logger 202} 203 204func (l *multiLogger) Printf(format string, v ...interface{}) { 205 for _, logger := range l.loggers { 206 logger.Printf(format, v...) 207 } 208} 209 210func (l *multiLogger) Println(v ...interface{}) { 211 for _, logger := range l.loggers { 212 logger.Println(v...) 213 } 214} 215 216func containsString(haystack, needle string) bool { 217 return bytes.Contains([]byte(haystack), []byte(needle)) 218}