diff options
Diffstat (limited to 'pkg/icingadb/objectpacker/objectpacker_test.go')
-rw-r--r-- | pkg/icingadb/objectpacker/objectpacker_test.go | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/pkg/icingadb/objectpacker/objectpacker_test.go b/pkg/icingadb/objectpacker/objectpacker_test.go new file mode 100644 index 0000000..e377d77 --- /dev/null +++ b/pkg/icingadb/objectpacker/objectpacker_test.go @@ -0,0 +1,195 @@ +package objectpacker + +import ( + "bytes" + "github.com/icinga/icingadb/pkg/types" + "github.com/pkg/errors" + "io" + "testing" +) + +// limitedWriter allows writing a specific amount of data. +type limitedWriter struct { + // limit specifies how many bytes to allow to write. + limit int +} + +var _ io.Writer = (*limitedWriter)(nil) + +// Write returns io.EOF once lw.limit is exceeded, nil otherwise. +func (lw *limitedWriter) Write(p []byte) (n int, err error) { + if len(p) <= lw.limit { + lw.limit -= len(p) + return len(p), nil + } + + n = lw.limit + err = io.EOF + + lw.limit = 0 + return +} + +func TestLimitedWriter_Write(t *testing.T) { + assertLimitedWriter_Write(t, 3, []byte{1, 2}, 2, nil, 1) + assertLimitedWriter_Write(t, 3, []byte{1, 2, 3}, 3, nil, 0) + assertLimitedWriter_Write(t, 3, []byte{1, 2, 3, 4}, 3, io.EOF, 0) + assertLimitedWriter_Write(t, 0, []byte{1}, 0, io.EOF, 0) + assertLimitedWriter_Write(t, 0, nil, 0, nil, 0) +} + +func assertLimitedWriter_Write(t *testing.T, limitBefore int, p []byte, n int, err error, limitAfter int) { + t.Helper() + + lw := limitedWriter{limitBefore} + actualN, actualErr := lw.Write(p) + + if !errors.Is(actualErr, err) { + t.Errorf("_, err := (&limitedWriter{%d}).Write(%#v); err != %#v", limitBefore, p, err) + } + + if actualN != n { + t.Errorf("n, _ := (&limitedWriter{%d}).Write(%#v); n != %d", limitBefore, p, n) + } + + if lw.limit != limitAfter { + t.Errorf("lw := limitedWriter{%d}; lw.Write(%#v); lw.limit != %d", limitBefore, p, limitAfter) + } +} + +func TestPackAny(t *testing.T) { + assertPackAny(t, nil, []byte{0}) + assertPackAny(t, false, []byte{1}) + assertPackAny(t, true, []byte{2}) + + assertPackAnyPanic(t, -42, 0) + assertPackAnyPanic(t, int8(-42), 0) + assertPackAnyPanic(t, int16(-42), 0) + assertPackAnyPanic(t, int32(-42), 0) + assertPackAnyPanic(t, int64(-42), 0) + + assertPackAnyPanic(t, uint(42), 0) + assertPackAnyPanic(t, uint8(42), 0) + assertPackAnyPanic(t, uint16(42), 0) + assertPackAnyPanic(t, uint32(42), 0) + assertPackAnyPanic(t, uint64(42), 0) + assertPackAnyPanic(t, uintptr(42), 0) + + assertPackAnyPanic(t, float32(-42.5), 0) + assertPackAny(t, -42.5, []byte{3, 0xc0, 0x45, 0x40, 0, 0, 0, 0, 0}) + + assertPackAnyPanic(t, []struct{}(nil), 9) + assertPackAnyPanic(t, []struct{}{}, 9) + + assertPackAny(t, []interface{}{nil, true, -42.5}, []byte{ + 5, 0, 0, 0, 0, 0, 0, 0, 3, + 0, + 2, + 3, 0xc0, 0x45, 0x40, 0, 0, 0, 0, 0, + }) + + assertPackAny(t, []string{"", "a"}, []byte{ + 5, 0, 0, 0, 0, 0, 0, 0, 2, + 4, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 1, 'a', + }) + + assertPackAnyPanic(t, []interface{}{0 + 0i}, 9) + + assertPackAnyPanic(t, map[struct{}]struct{}(nil), 9) + assertPackAnyPanic(t, map[struct{}]struct{}{}, 9) + + assertPackAny(t, map[interface{}]interface{}{true: "", "nil": -42.5}, []byte{ + 6, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 3, 'n', 'i', 'l', + 3, 0xc0, 0x45, 0x40, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 't', 'r', 'u', 'e', + 4, 0, 0, 0, 0, 0, 0, 0, 0, + }) + + assertPackAny(t, map[string]float64{"": 42}, []byte{ + 6, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 3, 0x40, 0x45, 0, 0, 0, 0, 0, 0, + }) + + assertPackAny(t, map[[1]byte]bool{{42}: true}, []byte{ + 6, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 1, 42, + 2, + }) + + assertPackAnyPanic(t, map[struct{}]struct{}{{}: {}}, 9) + + assertPackAny(t, (*string)(nil), []byte{0}) + assertPackAnyPanic(t, (*int)(nil), 0) + assertPackAny(t, new(float64), []byte{3, 0, 0, 0, 0, 0, 0, 0, 0}) + + assertPackAny(t, "", []byte{4, 0, 0, 0, 0, 0, 0, 0, 0}) + assertPackAny(t, "a", []byte{4, 0, 0, 0, 0, 0, 0, 0, 1, 'a'}) + assertPackAny(t, "รค", []byte{4, 0, 0, 0, 0, 0, 0, 0, 2, 0xc3, 0xa4}) + + { + var binary [256]byte + for i := range binary { + binary[i] = byte(i) + } + + assertPackAny(t, binary, append([]byte{4, 0, 0, 0, 0, 0, 0, 1, 0}, binary[:]...)) + assertPackAny(t, binary[:], append([]byte{4, 0, 0, 0, 0, 0, 0, 1, 0}, binary[:]...)) + assertPackAny(t, types.Binary(binary[:]), append([]byte{4, 0, 0, 0, 0, 0, 0, 1, 0}, binary[:]...)) + } + + { + type myByte byte + assertPackAnyPanic(t, []myByte(nil), 9) + } + + assertPackAnyPanic(t, complex64(0+0i), 0) + assertPackAnyPanic(t, 0+0i, 0) + assertPackAnyPanic(t, make(chan struct{}), 0) + assertPackAnyPanic(t, func() {}, 0) + assertPackAnyPanic(t, struct{}{}, 0) + assertPackAnyPanic(t, uintptr(0), 0) +} + +func assertPackAny(t *testing.T, in interface{}, out []byte) { + t.Helper() + + { + buf := &bytes.Buffer{} + if err := PackAny(in, buf); err == nil { + if !bytes.Equal(buf.Bytes(), out) { + t.Errorf("buf := &bytes.Buffer{}; packAny(%#v, buf); !bytes.Equal(buf.Bytes(), %#v)", in, out) + } + } else { + t.Errorf("packAny(%#v, &bytes.Buffer{}) != nil", in) + } + } + + for i := 0; i < len(out); i++ { + if !errors.Is(PackAny(in, &limitedWriter{i}), io.EOF) { + t.Errorf("packAny(%#v, &limitedWriter{%d}) != io.EOF", in, i) + } + } +} + +func assertPackAnyPanic(t *testing.T, in interface{}, allowToWrite int) { + t.Helper() + + for i := 0; i < allowToWrite; i++ { + if !errors.Is(PackAny(in, &limitedWriter{i}), io.EOF) { + t.Errorf("packAny(%#v, &limitedWriter{%d}) != io.EOF", in, i) + } + } + + defer func() { + t.Helper() + + if r := recover(); r == nil { + t.Errorf("packAny(%#v, &limitedWriter{%d}) didn't panic", in, allowToWrite) + } + }() + + _ = PackAny(in, &limitedWriter{allowToWrite}) +} |