Skip to content

Commit

Permalink
#9 added tests and utils
Browse files Browse the repository at this point in the history
  • Loading branch information
Anthony4m committed Dec 6, 2024
1 parent e061989 commit 1e50792
Show file tree
Hide file tree
Showing 5 changed files with 704 additions and 0 deletions.
157 changes: 157 additions & 0 deletions log/log_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package log

import (
"awesomeDB/kfile"
"os"
"path/filepath"
"strings"
"testing"
"time"
)

func TestNewLogMgr(t *testing.T) {
// Setup
tempDir := filepath.Join(os.TempDir(), "simpledb_test_"+time.Now().Format("20060102150405"))
blockSize := 400
fm, err := kfile.NewFileMgr(tempDir, blockSize)
if err != nil {
t.Fatalf("Failed to create FileMgr: %v", err)
}
defer func() {
fm.Close()
os.RemoveAll(tempDir)
}()

filename := "new_log.db"
logMgr, err := newLogMgr(fm, filename)
if err != nil {
t.Fatalf("Failed to create LogMgr for new log file: %v", err)
}
if logMgr.logsize != 0 {
t.Errorf("Expected logsize 0 for new log file, got %d", logMgr.logsize)
}

// Test for an existing log file
logMgr.Append([]byte("test record"))
logMgr.Flush()

logMgr2, err := newLogMgr(fm, filename)
if err != nil {
t.Fatalf("Failed to create LogMgr for existing log file: %v", err)
}
if logMgr2.logsize == 0 {
t.Errorf("Expected logsize > 0 for existing log file, got %d", logMgr2.logsize)
}
}

func TestAppend(t *testing.T) {
// Setup
tempDir := filepath.Join(os.TempDir(), "simpledb_test_"+time.Now().Format("20060102150405"))
var blockSize int = 400
fm, err := kfile.NewFileMgr(tempDir, blockSize)
if err != nil {
t.Fatalf("Failed to create FileMgr: %v", err)
}
defer func() {
fm.Close()
os.RemoveAll(tempDir)
}()

logMgr, err := newLogMgr(fm, "append_test.db")
if err != nil {
t.Fatalf("Failed to initialize LogMgr: %v", err)
}

// Append records and check LSN
record := []byte("test record")
for i := 0; i < 10; i++ {
lsn := logMgr.Append(record)
if lsn != i+1 {
t.Errorf("Expected LSN %d, got %d", i+1, lsn)
}
}

// Verify boundary updates correctly
boundary, _ := logMgr.logPage.GetInt(0)
if boundary <= 0 || boundary >= blockSize {
t.Errorf("Invalid boundary after append: %d", boundary)
}
}

func TestFlush(t *testing.T) {
// Setup
tempDir := filepath.Join(os.TempDir(), "simpledb_test_"+time.Now().Format("20060102150405"))
blockSize := 400
fm, err := kfile.NewFileMgr(tempDir, blockSize)
if err != nil {
t.Fatalf("Failed to create FileMgr: %v", err)
}
defer func() {
fm.Close()
os.RemoveAll(tempDir)
}()

logMgr, err := newLogMgr(fm, "flush_test.db")
if err != nil {
t.Fatalf("Failed to initialize LogMgr: %v", err)
}

// Append a record
record := []byte("flush record")
logMgr.Append(record)

// Flush and verify
err = logMgr.Flush()
if err != nil {
t.Fatalf("Flush failed: %v", err)
}

// Read the block to confirm data was written
page := kfile.NewPage(blockSize)
err = fm.Read(logMgr.currentBlock, page)
if err != nil {
t.Fatalf("Failed to read block after flush: %v", err)
}
recpos, err := logMgr.logPage.GetInt(0)
if err != nil {
t.Errorf("Error getting recpos %s", err)
}
readRecord, _ := page.GetBytes(int(recpos))
readRecordStr := string(readRecord)
readRecordStr = strings.TrimRight(readRecordStr, "\x00 ") // Trim nulls and spacesZZ
if string(readRecordStr) != string(record) {
t.Errorf("Expected record '%s', got '%s'", string(record), string(readRecord))
}
}

func TestAppendBoundary(t *testing.T) {
// Setup
tempDir := filepath.Join(os.TempDir(), "simpledb_test_"+time.Now().Format("20060102150405"))
blockSize := 400
fm, err := kfile.NewFileMgr(tempDir, blockSize)
if err != nil {
t.Fatalf("Failed to create FileMgr: %v", err)
}
defer func() {
fm.Close()
os.RemoveAll(tempDir)
}()

logMgr, err := newLogMgr(fm, "boundary_test.db")
if err != nil {
t.Fatalf("Failed to initialize LogMgr: %v", err)
}

// Append records to fill the block
record := make([]byte, 50) // Record size
for i := 0; i < blockSize/len(record)-1; i++ {
logMgr.Append(record)
}

initialBlock := logMgr.currentBlock
logMgr.Append(record)

if logMgr.currentBlock == initialBlock {
t.Errorf("Expected new block after boundary overflow, but block did not change")
}
}
92 changes: 92 additions & 0 deletions log/logmgr_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package log

//
//import (
// "awesomeDB/kfile"
// "awesomeDB/utils"
// "fmt"
// "os"
// "path/filepath"
// "testing"
// "time"
// "unsafe"
//)
//
//func TestLogMgr(t *testing.T) {
// // Setup
// tempDir := filepath.Join(os.TempDir(), "simpledb_test_"+time.Now().Format("20060102150405"))
// blockSize := 400
// fm, err := kfile.NewFileMgr(tempDir, blockSize)
// if err != nil {
// t.Fatalf("Failed to create FileMgr: %v", err)
// }
// defer func() {
// fm.Close()
// os.RemoveAll(tempDir)
// }()
//
// // Test file creation and appending
// filename := "test.db"
// _, err = fm.Append(filename)
// if err != nil {
// t.Fatalf("Failed to append block: %v", err)
// }
// lm, _ := newLogMgr(fm, filename)
//
// createRecords(t, lm, 1, 35)
// printLogRecords(t, lm, "The log file now has these records:")
//
// // Create and append additional records
// createRecords(t, lm, 36, 70)
// err = lm.Flush()
// if err != nil {
// return
// }
// printLogRecords(t, lm, "The log file now has these records:")
//}
//
//func createRecords(t *testing.T, lm *LogMgr, start, end int) {
// t.Logf("Creating records:")
// for i := start; i <= end; i++ {
// record := createLogRecord(fmt.Sprintf("record%d", i), i+100)
// lsn := lm.Append(record)
// t.Logf("Record LSN: %d", lsn)
// }
//}
//
//func printLogRecords(t *testing.T, lm *LogMgr, msg string) {
// t.Log(msg)
// iter := lm.Iterator()
// for iter.HasNext() {
// rec, err := iter.Next()
// if err != nil {
// panic(err)
// }
// page := kfile.NewPageFromBytes(rec)
// s, err := page.GetString(0)
// if err != nil {
// panic(err)
// }
// npos := utils.MaxLength(len(s))
// val, _ := page.GetInt(npos)
// t.Logf("[%s, %d]", s, val)
// }
// t.Log()
//}
//
//func createLogRecord(s string, n int) []byte {
// npos := utils.MaxLength(len(s))
// record := make([]byte, npos+int(unsafe.Sizeof(0))) // String + Integer
// page := kfile.NewPageFromBytes(record)
//
// if err := page.SetString(0, s); err != nil {
// panic(fmt.Sprintf("Failed to set string: %v", err))
// }
// if err := page.SetInt(npos, n); err != nil {
// panic(fmt.Sprintf("Failed to set int: %v", err))
// }
//
// // Log serialized record details
// fmt.Printf("Serialized record [%s, %d]: npos=%d, recordLen=%d\n", s, n, npos, len(record))
// return record
//}
139 changes: 139 additions & 0 deletions log/temp_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package log

import (
"awesomeDB/kfile"
"awesomeDB/utils"
"fmt"
"os"
"path/filepath"
"testing"
"time"
)

func TestLogMgrAppend(t *testing.T) {
// Setup
tempDir := filepath.Join(os.TempDir(), "logmgr_test_"+time.Now().Format("20060102150405"))
blockSize := 400
fm, err := kfile.NewFileMgr(tempDir, blockSize)
if err != nil {
t.Fatalf("Failed to create FileMgr: %v", err)
}
defer func() {
fm.Close()
os.RemoveAll(tempDir)
}()

filename := "test.db"
_, err = fm.Append(filename)
if err != nil {
t.Fatalf("Failed to append block: %v", err)
}
lm, err := newLogMgr(fm, filename)
if err != nil {
t.Fatalf("Failed to initialize LogMgr: %v", err)
}

// Test cases
t.Run("AppendMultipleRecordsWithinSingleBlock", func(t *testing.T) {
verifyMultipleRecordsInSingleBlock(t, lm, blockSize)
})

t.Run("AppendRecordsAcrossMultipleBlocks", func(t *testing.T) {
verifyRecordsAcrossBlocks(t, lm, blockSize)
})
}

func verifyMultipleRecordsInSingleBlock(t *testing.T, lm *LogMgr, blockSize int) {
t.Log("Testing appending multiple records within a single block...")

// Append multiple small records
record1 := createLogRecord("record1", 100)
record2 := createLogRecord("record2", 200)

lsn1 := lm.Append(record1)
lsn2 := lm.Append(record2)

// Assert LSNs
if lsn1 != 1 || lsn2 != 2 {
t.Errorf("Expected LSNs 1 and 2, got %d and %d", lsn1, lsn2)
}

// Read back records to verify correctness
iter := lm.Iterator()
records := readAllRecords(t, iter)
expected := []string{"record1, 100", "record2, 200"}
compareRecords(t, records, expected)
}

func verifyRecordsAcrossBlocks(t *testing.T, lm *LogMgr, blockSize int) {
t.Log("Testing appending records across multiple blocks...")

// Append enough records to exceed block size
// Each record is 1/5 of the block
records := []string{}
for i := 1; i <= 10; i++ {
record := createLogRecord(fmt.Sprintf("record%d", i), i*10)
lm.Append(record)
records = append(records, fmt.Sprintf("record%d, %d", i, i*10))
}

// Verify all records
iter := lm.Iterator()
readRecords := readAllRecords(t, iter)
compareRecords(t, readRecords, records)
}

func createLogRecord(s string, n int) []byte {
strOffset := utils.MaxLength(len(s))
record := make([]byte, strOffset+4) // String + Integer
page := kfile.NewPageFromBytes(record)

if err := page.SetString(0, s); err != nil {
panic(fmt.Sprintf("Failed to set string: %v", err))
}
if err := page.SetInt(strOffset, n); err != nil {
panic(fmt.Sprintf("Failed to set int: %v", err))
}

// Log serialized record details
fmt.Printf("Serialized record [%s, %d]: strOffset=%d, recordLen=%d\n", s, n, strOffset, len(record))
return record
}

func readAllRecords(t *testing.T, iter utils.Iterator[[]byte]) []string {
var records []string
for iter.HasNext() {
rec, err := iter.Next()
if err != nil {
t.Fatalf("Error reading record: %v", err)
}

page := kfile.NewPageFromBytes(rec)
s, err := page.GetString(0)
if err != nil {
t.Fatalf("Error getting string: %v", err)
}

npos := utils.MaxLength(len(s)) // Ensure alignment
n, err := page.GetInt(npos)
if err != nil {
t.Fatalf("Error getting int: %v", err)
}

record := fmt.Sprintf("%s, %d", s, n)
records = append(records, record)
t.Logf("Deserialized record: [%s, %d] (npos=%d, recLen=%d)", s, n, npos, len(rec))
}
return records
}

func compareRecords(t *testing.T, actual, expected []string) {
if len(actual) != len(expected) {
t.Errorf("Expected %d records, but got %d", len(expected), len(actual))
}
for i, rec := range actual {
if rec != expected[i] {
t.Errorf("Expected record %d to be %q, but got %q", i+1, expected[i], rec)
}
}
}
Loading

0 comments on commit 1e50792

Please sign in to comment.