Skip to content

Art test#50

Open
aivillio wants to merge 36 commits into
acmpesuecc:devfrom
aivillio:art_test
Open

Art test#50
aivillio wants to merge 36 commits into
acmpesuecc:devfrom
aivillio:art_test

Conversation

@aivillio

@aivillio aivillio commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Art test

Description

TO test all of Art's CRUD functions and some edge cases, fixed a tiny bug with insert where it would not update the same key if they had different values

Changes

  • Added tests covering ART Create, Read, Update, and Delete operations.
  • Added tests for edge cases, including node growth/shrink behavior and duplicate key updates.
  • Renamed test functions to follow a more consistent naming convention.
  • Fixed a bug in Insert where updating an existing key with a new value did not correctly replace the old value

Tests

Ran the art test suite

Bhuviiiii-prog and others added 30 commits March 19, 2026 23:08
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
o
Merge branch 'artDev' of github.com:Bhuviiiii-prog/radFS into artDev
Copilot AI review requested due to automatic review settings June 9, 2026 12:10

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR replaces the directory entry storage from a Go map to an Adaptive Radix Tree (ART) and wires it into the FUSE filesystem implementation.

Changes:

  • Introduce an internal art package (insert/search/delete/traversal) with tests and a demo command.
  • Refactor internal/fs directory operations to use art.Tree and RWMutexes instead of a map[string]fs.Node.
  • Add a filesystem-level rename test and update existing fs tests to reflect the ART-backed directory representation.

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
internal/fs/fs.go Initialize root directory with an ART and insert the initial hello.txt file.
internal/fs/dir.go Switch directory CRUD operations (Lookup/ReadDirAll/Mkdir/Create/Remove/Rename) to ART APIs and RWMutexes.
internal/fs/file.go Update locking for Attr and fix slice allocation type conversions.
internal/fs/fs_test.go Update tests to query the ART tree and add a rename test.
internal/art/* Add ART implementation (nodes, insert/search/delete, traversal/print helpers) plus unit tests.
cmd/radFS/arttest/main.go Add a standalone command for manual ART growth/shrink verification.
docs/weekly/angelo/week_4.md Add weekly progress notes related to ART work.
Comments suppressed due to low confidence (2)

internal/fs/dir.go:1

  • The previous implementation updated the parent directory’s mtime/ctime when creating a child; this version no longer updates them in Mkdir. If timestamps are part of your filesystem semantics, update d.mtime and d.ctime after inserting the new entry (similar to Remove).`
package fs

internal/fs/dir.go:1

  • Similar to Mkdir, Create no longer updates the containing directory’s mtime/ctime after adding an entry. Consider restoring the parent timestamp update to preserve expected directory metadata behavior.`
package fs

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/fs/dir.go
Comment on lines 55 to +61
func (d *Dir) Lookup(ctx context.Context, name string) (fs.Node, error) {
d.fs.DebugPrint("LOOKUP", "fetching", name)

d.mu.Lock()
defer d.mu.Unlock()
d.mu.RLock()
defer d.mu.RUnlock()

node, ok := d.Nodes[name]
v, ok := d.tree.Search([]byte(name))
Comment thread internal/fs/dir.go
Comment on lines 66 to +68
d.atime = time.Now()

return node, nil
return v.(fs.Node), nil
Comment thread internal/fs/dir.go
Comment on lines 72 to 92
func (d *Dir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
d.fs.DebugPrint("READDIR", "inode", d.inode)

d.mu.Lock()
defer d.mu.Unlock()
d.mu.RLock()
defer d.mu.RUnlock()

var entries []fuse.Dirent
for name, node := range d.Nodes {
var dt fuse.DirentType

switch node.(type) {
d.tree.ForEach(func(b []byte, i interface{}) { //traverses tree and appends the dirent to entries
name := string(b)
var dtype fuse.DirentType
switch i.(type) {
case *File:
dtype = fuse.DT_File
case *Dir:
dt = fuse.DT_Dir
default:
dt = fuse.DT_File
}
dtype = fuse.DT_Dir

entries = append(entries, fuse.Dirent{Name: name, Type: dt})
}
}
entries = append(entries, fuse.Dirent{Name: name, Type: dtype})
})

d.atime = time.Now()
Comment thread internal/fs/dir.go
Comment on lines +81 to +89
var dtype fuse.DirentType
switch i.(type) {
case *File:
dtype = fuse.DT_File
case *Dir:
dt = fuse.DT_Dir
default:
dt = fuse.DT_File
}
dtype = fuse.DT_Dir

entries = append(entries, fuse.Dirent{Name: name, Type: dt})
}
}
entries = append(entries, fuse.Dirent{Name: name, Type: dtype})
Comment thread internal/art/util.go
Comment on lines +128 to +137
func removechild(n *Node, k byte) *Node {
in := n.innerNode
_, pos := findchild(k, n)

// If child doesn't exist, return original node (search loop only for node 4 and 16)
if pos == -1 && in.nodeType <= Node16 {
return n
}

switch in.nodeType {
Comment thread internal/art/search.go
Comment on lines +8 to +13
if isleaf(n) {
if string(n.leaf.key) == string(key) {
return n
}
return nil
}
Comment thread internal/fs/fs.go
Comment on lines 7 to +10
"time"

"bazil.org/fuse/fs"
"github.com/acmpesuecc/radFS/internal/art"
Comment thread internal/fs/fs.go
Comment on lines +45 to +46
uid: uint32(os.Getuid()), //permissions implemnet based on userid
gid: uint32(os.Getgid()), //permissions implement based on groupid
Comment thread internal/fs/fs.go
atime: time.Now(),
mtime: time.Now(),
ctime: time.Now(),
uid: uint32(os.Getuid()), //permissions implemnet based on userid
Comment thread internal/fs/dir.go
Comment on lines +224 to +235
// if destination exists → overwrite
if existing, exists := newParent.tree.Search([]byte(req.NewName)); exists {
// if it's a directory, check if empty
if dir, ok := existing.(*Dir); ok {
dir.mu.RLock()
defer dir.mu.RUnlock()
if !dir.tree.Empty() {
return syscall.ENOTEMPTY
}
}
newParent.tree.Delete([]byte(req.NewName))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants