mirror of
https://github.com/Buriburizaem0n/nezha_domains.git
synced 2026-09-19 09:40:12 +00:00
feat(agentcompat): add SQLite hold scoped attribution
Co-authored-by: naiba/CloudCode <hi+cloudcode@nai.ba>
This commit is contained in:
@@ -0,0 +1,204 @@
|
||||
//go:build agentcompat && linux
|
||||
|
||||
package singleton
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"database/sql/driver"
|
||||
"errors"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSQLiteDriverAdapterRecordsExplicitInsert_when_AttributionEnabled(t *testing.T) {
|
||||
resetSQLiteAttributionForTest()
|
||||
databasePath := filepath.Join(t.TempDir(), "dashboard.sqlite")
|
||||
database, err := openSQLiteAttributionTestDB(databasePath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
if closeErr := database.Close(); closeErr != nil {
|
||||
t.Error(closeErr)
|
||||
}
|
||||
})
|
||||
if _, err := database.Exec("CREATE TABLE settings (id INTEGER PRIMARY KEY, value TEXT)"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
enableSQLiteAttribution()
|
||||
transaction, err := database.Begin()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := transaction.Exec("INSERT INTO settings (value) VALUES (?)", "opaque"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !sqliteAttributionTrackerHasWrite() {
|
||||
t.Fatal("explicit insert did not record an atomic sqlite write")
|
||||
}
|
||||
if err := transaction.Commit(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSQLiteDriverAdapterRecordsPreparedExplicitInsert_when_AttributionEnabled(t *testing.T) {
|
||||
resetSQLiteAttributionForTest()
|
||||
databasePath := filepath.Join(t.TempDir(), "dashboard.sqlite")
|
||||
database, err := openSQLiteAttributionTestDB(databasePath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
if closeErr := database.Close(); closeErr != nil {
|
||||
t.Error(closeErr)
|
||||
}
|
||||
})
|
||||
if _, err := database.Exec("CREATE TABLE settings (id INTEGER PRIMARY KEY, value TEXT)"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
enableSQLiteAttribution()
|
||||
transaction, err := database.Begin()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
statement, err := transaction.Prepare("INSERT INTO settings (value) VALUES (?)")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := statement.Exec("prepared"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := statement.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !sqliteAttributionTrackerHasWrite() {
|
||||
t.Fatal("prepared explicit insert did not record an atomic sqlite write")
|
||||
}
|
||||
if err := transaction.Commit(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSQLiteDriverAdapterRejectsUnboundWrite_when_AttributionEnabled(t *testing.T) {
|
||||
database := openSQLiteAttributionTestDatabase(t)
|
||||
enableSQLiteAttribution()
|
||||
_, err := database.Exec("INSERT INTO settings (value) VALUES (?)", "unbound")
|
||||
if !errors.Is(err, ErrSQLiteAttributionUnboundWrite) {
|
||||
t.Fatalf("expected unbound write instrumentation error, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSQLiteDriverAdapterRejectsUnsupportedDSN(t *testing.T) {
|
||||
database, err := openSQLiteAttributionTestDB(":memory:")
|
||||
if err == nil {
|
||||
err = database.Ping()
|
||||
}
|
||||
if database != nil {
|
||||
t.Cleanup(func() {
|
||||
if closeErr := database.Close(); closeErr != nil {
|
||||
t.Error(closeErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
if !errors.Is(err, ErrSQLiteAttributionUnsupportedDSN) {
|
||||
t.Fatalf("expected unsupported DSN error, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func openSQLiteAttributionTestDB(path string) (*sql.DB, error) {
|
||||
registerSQLiteAttributionDriver()
|
||||
return sql.Open(sqliteAttributionDriverName, path)
|
||||
}
|
||||
|
||||
func openSQLiteAttributionTestDatabase(t *testing.T) *sql.DB {
|
||||
t.Helper()
|
||||
resetSQLiteAttributionForTest()
|
||||
database, err := openSQLiteAttributionTestDB(sqliteAttributionTestDatabasePath(t))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
if closeErr := database.Close(); closeErr != nil {
|
||||
t.Error(closeErr)
|
||||
}
|
||||
})
|
||||
if _, err := database.Exec("CREATE TABLE settings (id INTEGER PRIMARY KEY, value TEXT)"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return database
|
||||
}
|
||||
|
||||
func sqliteAttributionTestDatabasePath(t *testing.T) string {
|
||||
t.Helper()
|
||||
return filepath.Join(t.TempDir(), "dashboard.sqlite")
|
||||
}
|
||||
|
||||
func sqliteAttributionSettingsCount(t *testing.T, database *sql.DB) int {
|
||||
t.Helper()
|
||||
var count int
|
||||
if err := database.QueryRow("SELECT COUNT(*) FROM settings").Scan(&count); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func sqliteAttributionSettingValue(t *testing.T, database *sql.DB) string {
|
||||
t.Helper()
|
||||
var value string
|
||||
if err := database.QueryRow("SELECT value FROM settings LIMIT 1").Scan(&value); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func sqliteAttributionConsumeRows(rows *sql.Rows) error {
|
||||
if rows == nil {
|
||||
return nil
|
||||
}
|
||||
var identifier int64
|
||||
for rows.Next() {
|
||||
if err := rows.Scan(&identifier); err != nil {
|
||||
closeErr := rows.Close()
|
||||
return errors.Join(err, closeErr)
|
||||
}
|
||||
}
|
||||
err := rows.Err()
|
||||
closeErr := rows.Close()
|
||||
return errors.Join(err, closeErr)
|
||||
}
|
||||
|
||||
func sqliteAttributionConsumeDriverRows(rows driver.Rows) error {
|
||||
if rows == nil {
|
||||
return nil
|
||||
}
|
||||
values := make([]driver.Value, len(rows.Columns()))
|
||||
for {
|
||||
err := rows.Next(values)
|
||||
if err != nil {
|
||||
closeErr := rows.Close()
|
||||
return errors.Join(err, closeErr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func sqliteAttributionTrackerHasWrite() bool {
|
||||
return sqliteAttributionTrackerWriteEvidence().hasWrite
|
||||
}
|
||||
|
||||
type sqliteAttributionWriteEvidence struct {
|
||||
hasWrite bool
|
||||
write SQLiteWriteObservation
|
||||
}
|
||||
|
||||
func sqliteAttributionTrackerWriteEvidence() sqliteAttributionWriteEvidence {
|
||||
tracker := sqliteAttributionTracker.Load()
|
||||
tracker.mu.Lock()
|
||||
defer tracker.mu.Unlock()
|
||||
for _, held := range tracker.transactions {
|
||||
if held.hasWrite {
|
||||
return sqliteAttributionWriteEvidence{hasWrite: true, write: held.write}
|
||||
}
|
||||
}
|
||||
return sqliteAttributionWriteEvidence{}
|
||||
}
|
||||
Reference in New Issue
Block a user