Skip to content

Commit 8c8b8c3

Browse files
author
MPCoreDeveloper
committed
aaarghhh
1 parent 0d7e3ce commit 8c8b8c3

File tree

18 files changed

+155741
-158
lines changed

18 files changed

+155741
-158
lines changed

SharpCoreDB.Benchmarks/Comparative/ComparativeInsertBenchmarks.cs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -368,20 +368,23 @@ public void SQLite_File_WAL_FullSync_BulkInsert()
368368
// FAIR COMPARISON: Configure SQLite with durability equivalent to SharpCoreDB
369369
// This shows the TRUE performance cost of full durability guarantees
370370

371-
using var cmd = sqliteFile?.CreateCommand();
372-
373-
// Enable WAL mode
374-
cmd!.CommandText = "PRAGMA journal_mode = WAL";
375-
cmd.ExecuteNonQuery();
376-
377-
// CRITICAL: Set synchronous to FULL for equivalent durability to SharpCoreDB FullSync
378-
// This forces fsync after each transaction commit (like SharpCoreDB)
379-
cmd.CommandText = "PRAGMA synchronous = FULL";
380-
cmd.ExecuteNonQuery();
371+
// Configure SQLite PRAGMAS BEFORE transaction
372+
using (var pragmaCmd = sqliteFile?.CreateCommand())
373+
{
374+
pragmaCmd!.CommandText = "PRAGMA journal_mode = WAL";
375+
pragmaCmd.ExecuteNonQuery();
376+
377+
// CRITICAL: Set synchronous to FULL for equivalent durability to SharpCoreDB FullSync
378+
// This forces fsync after each transaction commit (like SharpCoreDB)
379+
pragmaCmd.CommandText = "PRAGMA synchronous = FULL";
380+
pragmaCmd.ExecuteNonQuery();
381+
}
381382

382383
var users = dataGenerator.GenerateUsers(RecordCount);
383384

384385
using var transaction = sqliteFile?.BeginTransaction();
386+
using var cmd = sqliteFile?.CreateCommand();
387+
cmd!.Transaction = transaction;
385388
cmd.CommandText = @"
386389
INSERT OR REPLACE INTO users (id, name, email, age, created_at, is_active)
387390
VALUES (@id, @name, @email, @age, @created_at, @is_active)";

SharpCoreDB.Benchmarks/Comparative/ComparativeSelectBenchmarks.cs

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,28 @@ private void VerifySetup()
230230
}
231231
else
232232
{
233-
Console.WriteLine($" ? SharpCoreDB (Encrypted): Verified (found user ID 1)");
233+
// ENHANCED: Validate the data integrity
234+
var row = testResults[0];
235+
if (!row.ContainsKey("id") || !row.ContainsKey("name") || !row.ContainsKey("email"))
236+
{
237+
errors.Add($"SharpCoreDB (Encrypted): Incomplete row data - missing fields");
238+
}
239+
else if (row["id"] == null || row["id"] == DBNull.Value)
240+
{
241+
errors.Add($"SharpCoreDB (Encrypted): ID field is null");
242+
}
243+
else if ((int)row["id"] != 1)
244+
{
245+
errors.Add($"SharpCoreDB (Encrypted): Expected ID 1, got {row["id"]}");
246+
}
247+
else if (string.IsNullOrEmpty(row["name"]?.ToString()))
248+
{
249+
errors.Add($"SharpCoreDB (Encrypted): Name field is empty (data corruption!)");
250+
}
251+
else
252+
{
253+
Console.WriteLine($" ? SharpCoreDB (Encrypted): Verified (ID={row["id"]}, Name={row["name"]})");
254+
}
234255
}
235256
}
236257
catch (Exception ex)
@@ -248,7 +269,28 @@ private void VerifySetup()
248269
}
249270
else
250271
{
251-
Console.WriteLine($" ? SharpCoreDB (No Encryption): Verified (found user ID 1)");
272+
// ENHANCED: Validate the data integrity
273+
var row = testResults[0];
274+
if (!row.ContainsKey("id") || !row.ContainsKey("name") || !row.ContainsKey("email"))
275+
{
276+
errors.Add($"SharpCoreDB (No Encryption): Incomplete row data - missing fields");
277+
}
278+
else if (row["id"] == null || row["id"] == DBNull.Value)
279+
{
280+
errors.Add($"SharpCoreDB (No Encryption): ID field is null");
281+
}
282+
else if ((int)row["id"] != 1)
283+
{
284+
errors.Add($"SharpCoreDB (No Encryption): Expected ID 1, got {row["id"]}");
285+
}
286+
else if (string.IsNullOrEmpty(row["name"]?.ToString()))
287+
{
288+
errors.Add($"SharpCoreDB (No Encryption): Name field is empty (data corruption!)");
289+
}
290+
else
291+
{
292+
Console.WriteLine($" ? SharpCoreDB (No Encryption): Verified (ID={row["id"]}, Name={row["name"]})");
293+
}
252294
}
253295
}
254296
catch (Exception ex)

SharpCoreDB.Tests/BufferedWalTests.cs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Microsoft.Extensions.DependencyInjection;
22
using System.Diagnostics;
3+
using SharpCoreDB.Interfaces;
34

45
namespace SharpCoreDB.Tests;
56

@@ -12,6 +13,7 @@ public class BufferedWalTests : IDisposable
1213
private readonly string _testDbPath;
1314
private readonly IServiceProvider _serviceProvider;
1415
private readonly DatabaseFactory _factory;
16+
private readonly List<IDatabase> _openDatabases = new();
1517

1618
public BufferedWalTests()
1719
{
@@ -27,10 +29,48 @@ public BufferedWalTests()
2729

2830
public void Dispose()
2931
{
32+
// Dispose all open database instances first
33+
foreach (var db in _openDatabases)
34+
{
35+
try
36+
{
37+
(db as IDisposable)?.Dispose();
38+
}
39+
catch
40+
{
41+
// Ignore errors during disposal
42+
}
43+
}
44+
_openDatabases.Clear();
45+
46+
// Give OS time to release file handles
47+
System.Threading.Thread.Sleep(100);
48+
3049
// Clean up test databases after each test
3150
if (Directory.Exists(_testDbPath))
3251
{
33-
Directory.Delete(_testDbPath, true);
52+
try
53+
{
54+
Directory.Delete(_testDbPath, true);
55+
}
56+
catch
57+
{
58+
// If cleanup fails, try again with retries
59+
for (int i = 0; i < 3; i++)
60+
{
61+
try
62+
{
63+
System.Threading.Thread.Sleep(100 * (i + 1));
64+
if (Directory.Exists(_testDbPath))
65+
Directory.Delete(_testDbPath, true);
66+
break;
67+
}
68+
catch when (i < 2)
69+
{
70+
// Retry
71+
}
72+
}
73+
}
3474
}
3575
}
3676

@@ -40,6 +80,7 @@ public void BufferedWal_BasicOperations_WorksCorrectly()
4080
// Arrange - Use HighPerformance config with buffered WAL
4181
var config = DatabaseConfig.HighPerformance;
4282
var db = _factory.Create(_testDbPath, "testPassword", false, config);
83+
_openDatabases.Add(db);
4384

4485
// Act - Create table and perform multiple inserts (should use buffered WAL)
4586
db.ExecuteSQL("CREATE TABLE test (id INTEGER, name TEXT, value INTEGER)");
@@ -60,14 +101,21 @@ public void BufferedWal_DataPersistence_WorksCorrectly()
60101

61102
// Act - Create database, insert data with buffered WAL
62103
var db1 = _factory.Create(_testDbPath, "testPassword", false, config);
104+
_openDatabases.Add(db1);
63105
db1.ExecuteSQL("CREATE TABLE data (id INTEGER, value TEXT)");
64106
for (int i = 0; i < 150; i++)
65107
{
66108
db1.ExecuteSQL("INSERT INTO data VALUES (?, ?)", new Dictionary<string, object?> { { "0", i }, { "1", $"value{i}" } });
67109
}
68110

111+
// Close first database before opening second
112+
(db1 as IDisposable)?.Dispose();
113+
_openDatabases.Remove(db1);
114+
System.Threading.Thread.Sleep(100);
115+
69116
// Reopen database
70117
var db2 = _factory.Create(_testDbPath, "testPassword", false, config);
118+
_openDatabases.Add(db2);
71119
db2.ExecuteSQL("SELECT * FROM data WHERE id = '100'");
72120

73121
// Assert - Data persisted correctly with buffered WAL
@@ -84,6 +132,7 @@ public void BufferedWal_LargeBufferSize_WorksCorrectly()
84132
WalBufferSize = 2 * 1024 * 1024 // 2MB buffer
85133
};
86134
var db = _factory.Create(_testDbPath, "testPassword", false, config);
135+
_openDatabases.Add(db);
87136

88137
// Act - Perform many inserts that should benefit from large buffer
89138
db.ExecuteSQL("CREATE TABLE entries (id INTEGER, data TEXT)");
@@ -102,6 +151,7 @@ public void BufferedWal_MixedOperations_WorksCorrectly()
102151
// Arrange
103152
var config = DatabaseConfig.HighPerformance;
104153
var db = _factory.Create(_testDbPath, "testPassword", false, config);
154+
_openDatabases.Add(db);
105155

106156
// Act - Mix of different operations
107157
db.ExecuteSQL("CREATE TABLE mixed (id INTEGER PRIMARY KEY, name TEXT, active BOOLEAN)");
@@ -142,6 +192,7 @@ public void BufferedWal_PerformanceImprovement_IsMeasurable()
142192
};
143193

144194
var db = _factory.Create(_testDbPath, "testPassword", false, config);
195+
_openDatabases.Add(db);
145196
db.ExecuteSQL("CREATE TABLE perf_test (id INTEGER, data TEXT, value INTEGER)");
146197

147198
// Act - Measure time for bulk inserts

SharpCoreDB.Tests/DdlTests.cs

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,38 @@ public DdlTests()
3737

3838
public void Dispose()
3939
{
40-
this.db.Dispose();
40+
try
41+
{
42+
this.db.Dispose();
43+
}
44+
catch { }
45+
46+
// Force garbage collection and wait for finalizers to complete
47+
// This ensures all file handles are released before cleanup
48+
GC.Collect();
49+
GC.WaitForPendingFinalizers();
50+
GC.Collect();
51+
52+
// Wait for file handles to be released before cleanup
53+
System.Threading.Thread.Sleep(250);
54+
4155
if (Directory.Exists(this.testDbPath))
4256
{
4357
try
4458
{
45-
Directory.Delete(this.testDbPath, recursive: true);
59+
// Try to delete with retry logic
60+
for (int i = 0; i < 5; i++)
61+
{
62+
try
63+
{
64+
Directory.Delete(this.testDbPath, recursive: true);
65+
break;
66+
}
67+
catch when (i < 4)
68+
{
69+
System.Threading.Thread.Sleep(150 * (i + 1));
70+
}
71+
}
4672
}
4773
catch
4874
{
@@ -83,7 +109,8 @@ public void DropTable_DeletesDataFile()
83109
// Act
84110
this.db.ExecuteSQL("DROP TABLE temp");
85111

86-
// Assert
112+
// Assert - wait for file to be deleted
113+
System.Threading.Thread.Sleep(100);
87114
Assert.False(File.Exists(dataFile), "Data file should be deleted after DROP TABLE");
88115
}
89116

@@ -212,7 +239,8 @@ public void AlterTableRename_RenamesDataFile()
212239
// Act
213240
this.db.ExecuteSQL("ALTER TABLE old_name RENAME TO new_name");
214241

215-
// Assert
242+
// Assert - wait for file operations to complete
243+
System.Threading.Thread.Sleep(100);
216244
Assert.False(File.Exists(oldFile), "Old data file should not exist");
217245
Assert.True(File.Exists(newFile), "New data file should exist");
218246
}
@@ -303,6 +331,9 @@ public void DDL_DropAndRecreate_Success()
303331
// Drop table
304332
this.db.ExecuteSQL("DROP TABLE temp");
305333

334+
// Wait for file handles to be released - give OS time to close file
335+
System.Threading.Thread.Sleep(200);
336+
306337
// Recreate with different schema
307338
this.db.ExecuteSQL("CREATE TABLE temp (id INTEGER PRIMARY KEY, value INTEGER)");
308339
this.db.ExecuteSQL("INSERT INTO temp VALUES (1, 42)");

0 commit comments

Comments
 (0)