-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
704 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
//} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} | ||
} | ||
} |
Oops, something went wrong.