test: imports basic tests, all passing.

This commit is contained in:
Houmgaor
2025-11-09 12:36:56 +01:00
parent 33a195b864
commit c8c0dae8fe
11 changed files with 1298 additions and 5 deletions

View File

@@ -0,0 +1,105 @@
package bfutil
import (
"bytes"
"testing"
)
func TestUpToNull(t *testing.T) {
tests := []struct {
name string
input []byte
expected []byte
}{
{
name: "data with null terminator",
input: []byte{0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x00, 0x57, 0x6F, 0x72, 0x6C, 0x64},
expected: []byte{0x48, 0x65, 0x6C, 0x6C, 0x6F}, // "Hello"
},
{
name: "data without null terminator",
input: []byte{0x48, 0x65, 0x6C, 0x6C, 0x6F},
expected: []byte{0x48, 0x65, 0x6C, 0x6C, 0x6F}, // "Hello"
},
{
name: "data with null at start",
input: []byte{0x00, 0x48, 0x65, 0x6C, 0x6C, 0x6F},
expected: []byte{},
},
{
name: "empty slice",
input: []byte{},
expected: []byte{},
},
{
name: "only null byte",
input: []byte{0x00},
expected: []byte{},
},
{
name: "multiple null bytes",
input: []byte{0x48, 0x65, 0x00, 0x00, 0x6C, 0x6C, 0x6F},
expected: []byte{0x48, 0x65}, // "He"
},
{
name: "binary data with null",
input: []byte{0xFF, 0xAB, 0x12, 0x00, 0x34, 0x56},
expected: []byte{0xFF, 0xAB, 0x12},
},
{
name: "binary data without null",
input: []byte{0xFF, 0xAB, 0x12, 0x34, 0x56},
expected: []byte{0xFF, 0xAB, 0x12, 0x34, 0x56},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := UpToNull(tt.input)
if !bytes.Equal(result, tt.expected) {
t.Errorf("UpToNull() = %v, want %v", result, tt.expected)
}
})
}
}
func TestUpToNull_ReturnsSliceNotCopy(t *testing.T) {
// Test that UpToNull returns a slice of the original array, not a copy
input := []byte{0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x00, 0x57, 0x6F, 0x72, 0x6C, 0x64}
result := UpToNull(input)
// Verify we got the expected data
expected := []byte{0x48, 0x65, 0x6C, 0x6C, 0x6F}
if !bytes.Equal(result, expected) {
t.Errorf("UpToNull() = %v, want %v", result, expected)
}
// The result should be a slice of the input array
if len(result) > 0 && cap(result) < len(expected) {
t.Error("Result should be a slice of input array")
}
}
func BenchmarkUpToNull(b *testing.B) {
data := []byte("Hello, World!\x00Extra data here")
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = UpToNull(data)
}
}
func BenchmarkUpToNull_NoNull(b *testing.B) {
data := []byte("Hello, World! No null terminator in this string at all")
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = UpToNull(data)
}
}
func BenchmarkUpToNull_NullAtStart(b *testing.B) {
data := []byte("\x00Hello, World!")
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = UpToNull(data)
}
}

View File

@@ -0,0 +1,369 @@
package pascalstring
import (
"bytes"
"erupe-ce/common/byteframe"
"testing"
)
func TestUint8_NoTransform(t *testing.T) {
bf := byteframe.NewByteFrame()
testString := "Hello"
Uint8(bf, testString, false)
bf.Seek(0, 0)
length := bf.ReadUint8()
expectedLength := uint8(len(testString) + 1) // +1 for null terminator
if length != expectedLength {
t.Errorf("length = %d, want %d", length, expectedLength)
}
data := bf.ReadBytes(uint(length))
// Should be "Hello\x00"
expected := []byte("Hello\x00")
if !bytes.Equal(data, expected) {
t.Errorf("data = %v, want %v", data, expected)
}
}
func TestUint8_WithTransform(t *testing.T) {
bf := byteframe.NewByteFrame()
// ASCII string (no special characters)
testString := "Test"
Uint8(bf, testString, true)
bf.Seek(0, 0)
length := bf.ReadUint8()
if length == 0 {
t.Error("length should not be 0 for ASCII string")
}
data := bf.ReadBytes(uint(length))
// Should end with null terminator
if data[len(data)-1] != 0 {
t.Error("data should end with null terminator")
}
}
func TestUint8_EmptyString(t *testing.T) {
bf := byteframe.NewByteFrame()
testString := ""
Uint8(bf, testString, false)
bf.Seek(0, 0)
length := bf.ReadUint8()
if length != 1 { // Just null terminator
t.Errorf("length = %d, want 1", length)
}
data := bf.ReadBytes(uint(length))
if data[0] != 0 {
t.Error("empty string should produce just null terminator")
}
}
func TestUint16_NoTransform(t *testing.T) {
bf := byteframe.NewByteFrame()
testString := "World"
Uint16(bf, testString, false)
bf.Seek(0, 0)
length := bf.ReadUint16()
expectedLength := uint16(len(testString) + 1)
if length != expectedLength {
t.Errorf("length = %d, want %d", length, expectedLength)
}
data := bf.ReadBytes(uint(length))
expected := []byte("World\x00")
if !bytes.Equal(data, expected) {
t.Errorf("data = %v, want %v", data, expected)
}
}
func TestUint16_WithTransform(t *testing.T) {
bf := byteframe.NewByteFrame()
testString := "Test"
Uint16(bf, testString, true)
bf.Seek(0, 0)
length := bf.ReadUint16()
if length == 0 {
t.Error("length should not be 0 for ASCII string")
}
data := bf.ReadBytes(uint(length))
if data[len(data)-1] != 0 {
t.Error("data should end with null terminator")
}
}
func TestUint16_EmptyString(t *testing.T) {
bf := byteframe.NewByteFrame()
testString := ""
Uint16(bf, testString, false)
bf.Seek(0, 0)
length := bf.ReadUint16()
if length != 1 {
t.Errorf("length = %d, want 1", length)
}
}
func TestUint32_NoTransform(t *testing.T) {
bf := byteframe.NewByteFrame()
testString := "Testing"
Uint32(bf, testString, false)
bf.Seek(0, 0)
length := bf.ReadUint32()
expectedLength := uint32(len(testString) + 1)
if length != expectedLength {
t.Errorf("length = %d, want %d", length, expectedLength)
}
data := bf.ReadBytes(uint(length))
expected := []byte("Testing\x00")
if !bytes.Equal(data, expected) {
t.Errorf("data = %v, want %v", data, expected)
}
}
func TestUint32_WithTransform(t *testing.T) {
bf := byteframe.NewByteFrame()
testString := "Test"
Uint32(bf, testString, true)
bf.Seek(0, 0)
length := bf.ReadUint32()
if length == 0 {
t.Error("length should not be 0 for ASCII string")
}
data := bf.ReadBytes(uint(length))
if data[len(data)-1] != 0 {
t.Error("data should end with null terminator")
}
}
func TestUint32_EmptyString(t *testing.T) {
bf := byteframe.NewByteFrame()
testString := ""
Uint32(bf, testString, false)
bf.Seek(0, 0)
length := bf.ReadUint32()
if length != 1 {
t.Errorf("length = %d, want 1", length)
}
}
func TestUint8_LongString(t *testing.T) {
bf := byteframe.NewByteFrame()
testString := "This is a longer test string with more characters"
Uint8(bf, testString, false)
bf.Seek(0, 0)
length := bf.ReadUint8()
expectedLength := uint8(len(testString) + 1)
if length != expectedLength {
t.Errorf("length = %d, want %d", length, expectedLength)
}
data := bf.ReadBytes(uint(length))
if !bytes.HasSuffix(data, []byte{0}) {
t.Error("data should end with null terminator")
}
if !bytes.HasPrefix(data, []byte("This is")) {
t.Error("data should start with expected string")
}
}
func TestUint16_LongString(t *testing.T) {
bf := byteframe.NewByteFrame()
// Create a string longer than 255 to test uint16
testString := ""
for i := 0; i < 300; i++ {
testString += "A"
}
Uint16(bf, testString, false)
bf.Seek(0, 0)
length := bf.ReadUint16()
expectedLength := uint16(len(testString) + 1)
if length != expectedLength {
t.Errorf("length = %d, want %d", length, expectedLength)
}
data := bf.ReadBytes(uint(length))
if !bytes.HasSuffix(data, []byte{0}) {
t.Error("data should end with null terminator")
}
}
func TestAllFunctions_NullTermination(t *testing.T) {
tests := []struct {
name string
writeFn func(*byteframe.ByteFrame, string, bool)
readSize func(*byteframe.ByteFrame) uint
}{
{
name: "Uint8",
writeFn: func(bf *byteframe.ByteFrame, s string, t bool) {
Uint8(bf, s, t)
},
readSize: func(bf *byteframe.ByteFrame) uint {
return uint(bf.ReadUint8())
},
},
{
name: "Uint16",
writeFn: func(bf *byteframe.ByteFrame, s string, t bool) {
Uint16(bf, s, t)
},
readSize: func(bf *byteframe.ByteFrame) uint {
return uint(bf.ReadUint16())
},
},
{
name: "Uint32",
writeFn: func(bf *byteframe.ByteFrame, s string, t bool) {
Uint32(bf, s, t)
},
readSize: func(bf *byteframe.ByteFrame) uint {
return uint(bf.ReadUint32())
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bf := byteframe.NewByteFrame()
testString := "Test"
tt.writeFn(bf, testString, false)
bf.Seek(0, 0)
size := tt.readSize(bf)
data := bf.ReadBytes(size)
// Verify null termination
if data[len(data)-1] != 0 {
t.Errorf("%s: data should end with null terminator", tt.name)
}
// Verify length includes null terminator
if size != uint(len(testString)+1) {
t.Errorf("%s: size = %d, want %d", tt.name, size, len(testString)+1)
}
})
}
}
func TestTransform_JapaneseCharacters(t *testing.T) {
// Test with Japanese characters that should be transformed to Shift-JIS
bf := byteframe.NewByteFrame()
testString := "テスト" // "Test" in Japanese katakana
Uint16(bf, testString, true)
bf.Seek(0, 0)
length := bf.ReadUint16()
if length == 0 {
t.Error("Transformed Japanese string should have non-zero length")
}
// The transformed Shift-JIS should be different length than UTF-8
// UTF-8: 9 bytes (3 chars * 3 bytes each), Shift-JIS: 6 bytes (3 chars * 2 bytes each) + 1 null
data := bf.ReadBytes(uint(length))
if data[len(data)-1] != 0 {
t.Error("Transformed string should end with null terminator")
}
}
func TestTransform_InvalidUTF8(t *testing.T) {
// This test verifies graceful handling of encoding errors
// When transformation fails, the functions should write length 0
bf := byteframe.NewByteFrame()
// Create a string with invalid UTF-8 sequence
// Note: Go strings are generally valid UTF-8, but we can test the error path
testString := "Valid ASCII"
Uint8(bf, testString, true)
// Should succeed for ASCII characters
bf.Seek(0, 0)
length := bf.ReadUint8()
if length == 0 {
t.Error("ASCII string should transform successfully")
}
}
func BenchmarkUint8_NoTransform(b *testing.B) {
testString := "Hello, World!"
b.ResetTimer()
for i := 0; i < b.N; i++ {
bf := byteframe.NewByteFrame()
Uint8(bf, testString, false)
}
}
func BenchmarkUint8_WithTransform(b *testing.B) {
testString := "Hello, World!"
b.ResetTimer()
for i := 0; i < b.N; i++ {
bf := byteframe.NewByteFrame()
Uint8(bf, testString, true)
}
}
func BenchmarkUint16_NoTransform(b *testing.B) {
testString := "Hello, World!"
b.ResetTimer()
for i := 0; i < b.N; i++ {
bf := byteframe.NewByteFrame()
Uint16(bf, testString, false)
}
}
func BenchmarkUint32_NoTransform(b *testing.B) {
testString := "Hello, World!"
b.ResetTimer()
for i := 0; i < b.N; i++ {
bf := byteframe.NewByteFrame()
Uint32(bf, testString, false)
}
}
func BenchmarkUint16_Japanese(b *testing.B) {
testString := "テストメッセージ"
b.ResetTimer()
for i := 0; i < b.N; i++ {
bf := byteframe.NewByteFrame()
Uint16(bf, testString, true)
}
}

View File

@@ -0,0 +1,343 @@
package stringstack
import (
"testing"
)
func TestNew(t *testing.T) {
s := New()
if s == nil {
t.Fatal("New() returned nil")
}
if len(s.stack) != 0 {
t.Errorf("New() stack length = %d, want 0", len(s.stack))
}
}
func TestStringStack_Set(t *testing.T) {
s := New()
s.Set("first")
if len(s.stack) != 1 {
t.Errorf("Set() stack length = %d, want 1", len(s.stack))
}
if s.stack[0] != "first" {
t.Errorf("stack[0] = %q, want %q", s.stack[0], "first")
}
}
func TestStringStack_Set_Replaces(t *testing.T) {
s := New()
s.Push("item1")
s.Push("item2")
s.Push("item3")
// Set should replace the entire stack
s.Set("new_item")
if len(s.stack) != 1 {
t.Errorf("Set() stack length = %d, want 1", len(s.stack))
}
if s.stack[0] != "new_item" {
t.Errorf("stack[0] = %q, want %q", s.stack[0], "new_item")
}
}
func TestStringStack_Push(t *testing.T) {
s := New()
s.Push("first")
s.Push("second")
s.Push("third")
if len(s.stack) != 3 {
t.Errorf("Push() stack length = %d, want 3", len(s.stack))
}
if s.stack[0] != "first" {
t.Errorf("stack[0] = %q, want %q", s.stack[0], "first")
}
if s.stack[1] != "second" {
t.Errorf("stack[1] = %q, want %q", s.stack[1], "second")
}
if s.stack[2] != "third" {
t.Errorf("stack[2] = %q, want %q", s.stack[2], "third")
}
}
func TestStringStack_Pop(t *testing.T) {
s := New()
s.Push("first")
s.Push("second")
s.Push("third")
// Pop should return LIFO (last in, first out)
val, err := s.Pop()
if err != nil {
t.Errorf("Pop() error = %v, want nil", err)
}
if val != "third" {
t.Errorf("Pop() = %q, want %q", val, "third")
}
val, err = s.Pop()
if err != nil {
t.Errorf("Pop() error = %v, want nil", err)
}
if val != "second" {
t.Errorf("Pop() = %q, want %q", val, "second")
}
val, err = s.Pop()
if err != nil {
t.Errorf("Pop() error = %v, want nil", err)
}
if val != "first" {
t.Errorf("Pop() = %q, want %q", val, "first")
}
if len(s.stack) != 0 {
t.Errorf("stack length = %d, want 0 after popping all items", len(s.stack))
}
}
func TestStringStack_Pop_Empty(t *testing.T) {
s := New()
val, err := s.Pop()
if err == nil {
t.Error("Pop() on empty stack should return error")
}
if val != "" {
t.Errorf("Pop() on empty stack returned %q, want empty string", val)
}
expectedError := "no items on stack"
if err.Error() != expectedError {
t.Errorf("Pop() error = %q, want %q", err.Error(), expectedError)
}
}
func TestStringStack_LIFO_Behavior(t *testing.T) {
s := New()
items := []string{"A", "B", "C", "D", "E"}
for _, item := range items {
s.Push(item)
}
// Pop should return in reverse order (LIFO)
for i := len(items) - 1; i >= 0; i-- {
val, err := s.Pop()
if err != nil {
t.Fatalf("Pop() error = %v", err)
}
if val != items[i] {
t.Errorf("Pop() = %q, want %q", val, items[i])
}
}
}
func TestStringStack_PushAfterPop(t *testing.T) {
s := New()
s.Push("first")
s.Push("second")
val, _ := s.Pop()
if val != "second" {
t.Errorf("Pop() = %q, want %q", val, "second")
}
s.Push("third")
val, _ = s.Pop()
if val != "third" {
t.Errorf("Pop() = %q, want %q", val, "third")
}
val, _ = s.Pop()
if val != "first" {
t.Errorf("Pop() = %q, want %q", val, "first")
}
}
func TestStringStack_EmptyStrings(t *testing.T) {
s := New()
s.Push("")
s.Push("text")
s.Push("")
val, err := s.Pop()
if err != nil {
t.Errorf("Pop() error = %v", err)
}
if val != "" {
t.Errorf("Pop() = %q, want empty string", val)
}
val, err = s.Pop()
if err != nil {
t.Errorf("Pop() error = %v", err)
}
if val != "text" {
t.Errorf("Pop() = %q, want %q", val, "text")
}
val, err = s.Pop()
if err != nil {
t.Errorf("Pop() error = %v", err)
}
if val != "" {
t.Errorf("Pop() = %q, want empty string", val)
}
}
func TestStringStack_LongStrings(t *testing.T) {
s := New()
longString := ""
for i := 0; i < 1000; i++ {
longString += "A"
}
s.Push(longString)
val, err := s.Pop()
if err != nil {
t.Errorf("Pop() error = %v", err)
}
if val != longString {
t.Error("Pop() returned different string than pushed")
}
if len(val) != 1000 {
t.Errorf("Pop() string length = %d, want 1000", len(val))
}
}
func TestStringStack_ManyItems(t *testing.T) {
s := New()
count := 1000
// Push many items
for i := 0; i < count; i++ {
s.Push("item")
}
if len(s.stack) != count {
t.Errorf("stack length = %d, want %d", len(s.stack), count)
}
// Pop all items
for i := 0; i < count; i++ {
_, err := s.Pop()
if err != nil {
t.Errorf("Pop()[%d] error = %v", i, err)
}
}
// Should be empty now
if len(s.stack) != 0 {
t.Errorf("stack length = %d, want 0 after popping all", len(s.stack))
}
// Next pop should error
_, err := s.Pop()
if err == nil {
t.Error("Pop() on empty stack should return error")
}
}
func TestStringStack_SetAfterOperations(t *testing.T) {
s := New()
s.Push("a")
s.Push("b")
s.Push("c")
s.Pop()
s.Push("d")
// Set should clear everything
s.Set("reset")
if len(s.stack) != 1 {
t.Errorf("stack length = %d, want 1 after Set", len(s.stack))
}
val, err := s.Pop()
if err != nil {
t.Errorf("Pop() error = %v", err)
}
if val != "reset" {
t.Errorf("Pop() = %q, want %q", val, "reset")
}
}
func TestStringStack_SpecialCharacters(t *testing.T) {
s := New()
specialStrings := []string{
"Hello\nWorld",
"Tab\tSeparated",
"Quote\"Test",
"Backslash\\Test",
"Unicode: テスト",
"Emoji: 😀",
"",
" ",
" spaces ",
}
for _, str := range specialStrings {
s.Push(str)
}
// Pop in reverse order
for i := len(specialStrings) - 1; i >= 0; i-- {
val, err := s.Pop()
if err != nil {
t.Errorf("Pop() error = %v", err)
}
if val != specialStrings[i] {
t.Errorf("Pop() = %q, want %q", val, specialStrings[i])
}
}
}
func BenchmarkStringStack_Push(b *testing.B) {
s := New()
b.ResetTimer()
for i := 0; i < b.N; i++ {
s.Push("test string")
}
}
func BenchmarkStringStack_Pop(b *testing.B) {
s := New()
// Pre-populate
for i := 0; i < 10000; i++ {
s.Push("test string")
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
if len(s.stack) == 0 {
// Repopulate
for j := 0; j < 10000; j++ {
s.Push("test string")
}
}
_, _ = s.Pop()
}
}
func BenchmarkStringStack_PushPop(b *testing.B) {
s := New()
b.ResetTimer()
for i := 0; i < b.N; i++ {
s.Push("test")
_, _ = s.Pop()
}
}
func BenchmarkStringStack_Set(b *testing.B) {
s := New()
b.ResetTimer()
for i := 0; i < b.N; i++ {
s.Set("test string")
}
}