From 48ee419f377e32b2e19f39c4bc4270e53f03d134 Mon Sep 17 00:00:00 2001 From: ryan-awad Date: Tue, 1 Oct 2024 15:21:34 -0400 Subject: [PATCH] Handling file permission and existance errors --- hnsw.go | 19 ++++++++++ tests/hnswgo_test.go | 84 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 102 insertions(+), 1 deletion(-) diff --git a/hnsw.go b/hnsw.go index 2c6134f..c4c7efb 100644 --- a/hnsw.go +++ b/hnsw.go @@ -10,6 +10,7 @@ import ( "errors" "fmt" "math" + "os" "unsafe" ) @@ -130,6 +131,11 @@ func LoadIndex(location string, dim int, spaceType string, maxElements uint32) ( return nil, errors.New("max elements must be >= 1") } + // checking the location's validity and permissions + if _, err := os.ReadFile(location); err != nil { + return nil, err + } + index := new(Index) index.dimensions = dim index.spaceType = spaceType @@ -165,6 +171,19 @@ func (i *Index) SaveToDisk(location string) error { if location == "" { return errors.New("location cannot be blank") } + + // checking the location's validity and permissions + if _, err := os.Stat(location); os.IsNotExist(err) { // file does not exist yet + if _, err := os.Create(location); err != nil { + return err + } + if err := os.Remove(location); err != nil { + return err + } + } else if os.IsPermission(err) { + return err + } + cLocation := C.CString(location) defer C.free(unsafe.Pointer(cLocation)) C.saveHNSW(i.index, cLocation) diff --git a/tests/hnswgo_test.go b/tests/hnswgo_test.go index abeb5d7..b11fda4 100644 --- a/tests/hnswgo_test.go +++ b/tests/hnswgo_test.go @@ -497,6 +497,76 @@ func TestSaveToDiskEmptyPath(t *testing.T) { } } +func TestSaveToDiskInvalidPath(t *testing.T) { + index, err := setup() + if err != nil { + t.Fatal(err.Error()) + } + defer index.Free() + + // sample vectors + vectors := [][]float32{ + {1.2, 3.4}, + {2.1, 4.5}, + {0.5, 1.7}, + {3.3, 2.2}, + {4.8, 5.6}, + {7.1, 8.2}, + {9.0, 0.4}, + {6.3, 3.5}, + {2.9, 7.8}, + {5.0, 1.1}, + } + + // insert sample vectors + for i, v := range vectors { + if err := index.InsertVector(v, uint64(i)); err != nil { + t.Fatalf("An error occured when inserting vector %v: %s", v, err.Error()) + } + } + + if err := index.SaveToDisk("/some/fake/path/index.bin"); err == nil { + t.Fatal("No error occured when setting the location to an invalid path") + } else if !os.IsNotExist(err) { + t.Fatalf("Unexpected error received: %s", err.Error()) + } +} + +func TestSaveToDiskInvalidPerms(t *testing.T) { + index, err := setup() + if err != nil { + t.Fatal(err.Error()) + } + defer index.Free() + + // sample vectors + vectors := [][]float32{ + {1.2, 3.4}, + {2.1, 4.5}, + {0.5, 1.7}, + {3.3, 2.2}, + {4.8, 5.6}, + {7.1, 8.2}, + {9.0, 0.4}, + {6.3, 3.5}, + {2.9, 7.8}, + {5.0, 1.1}, + } + + // insert sample vectors + for i, v := range vectors { + if err := index.InsertVector(v, uint64(i)); err != nil { + t.Fatalf("An error occured when inserting vector %v: %s", v, err.Error()) + } + } + + if err := index.SaveToDisk("/tmp/perm_test/index.bin"); err == nil { + t.Fatal("No error occured when setting the location to a path with elevated permissions") + } else if !os.IsPermission(err) { + t.Fatalf("Unexpected error received: %s", err.Error()) + } +} + func TestLoadIndexSuccess(t *testing.T) { index, err := hnswgo.LoadIndex("/tmp/saved_data.bin", 2, "l2", uint32(10000)) // same as whats in setup() if err != nil { @@ -540,7 +610,19 @@ func TestLoadIndexInvalidPath(t *testing.T) { } if err == nil { t.Fatal("No error occured when trying to load an index with a fake location.") - } else if err.Error() != "Cannot open file" { + } else if !os.IsNotExist(err) { + t.Fatalf("Unexpected error received: %s", err.Error()) + } +} + +func TestLoadIndexInvalidPerms(t *testing.T) { + index, err := hnswgo.LoadIndex("/root/index.bin", 2, "l2", uint32(10000)) + if index != nil { + defer index.Free() + } + if err == nil { + t.Fatal("No error occured when trying to load an index with a fake location.") + } else if !os.IsPermission(err) { t.Fatalf("Unexpected error received: %s", err.Error()) } }