Ctrl K
ComunidadGuías…

utils/files_test.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package utils

import (
	"os"
	"path/filepath"
	"testing"
)

func TestURL2filename(t *testing.T) {
	tests := []struct {
		dirname string
		urlpath string
		want    string
	}{
		{"/srv", "/index.html", "/srv" + Pathsep + "index.html"},
		{"/srv/", "/index.html", "/srv/index.html"},
		{"/srv", "/sub/page.md", "/srv" + Pathsep + "sub/page.md"},
		{"/srv", "relative.txt", "/srv/relative.txt"},
		{"/srv", "/../etc/passwd", "/srv" + Pathsep},
		{"/srv", "//admin/secret.lua", "/srv" + Pathsep + "admin" + Pathsep + "secret.lua"},
		{"/srv", "/a/./b//c", "/srv" + Pathsep + "a" + Pathsep + "b" + Pathsep + "c"},
		{"/srv", "/sub/", "/srv" + Pathsep + "sub" + Pathsep},
		{"/srv", "/", "/srv" + Pathsep},
	}
	for _, tt := range tests {
		got := URL2filename(tt.dirname, tt.urlpath)
		if got != tt.want {
			t.Errorf("URL2filename(%q, %q) = %q, want %q", tt.dirname, tt.urlpath, got, tt.want)
		}
	}
}

// Containment helper: only descendants of root should pass.
func TestWithinDir(t *testing.T) {
	root := t.TempDir()
	cases := []struct {
		name string
		path string
		want bool
	}{
		{"root itself", root, true},
		{"direct child", filepath.Join(root, "a.js"), true},
		{"nested child", filepath.Join(root, "sub", "a.js"), true},
		{"sibling", filepath.Join(root, "..", "other"), false},
		{"ancestor", filepath.Dir(root), false},
	}
	for _, c := range cases {
		if got := WithinDir(root, c.path); got != c.want {
			t.Errorf("%s: WithinDir(%q,%q) = %v, want %v", c.name, root, c.path, got, c.want)
		}
	}
}

func TestGetFilenames(t *testing.T) {
	dir, err := os.MkdirTemp("", "algernon-test")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(dir)

	// Create some files
	for _, name := range []string{"a.txt", "b.md", "c.html"} {
		if err := os.WriteFile(dir+"/"+name, []byte("x"), 0o644); err != nil {
			t.Fatal(err)
		}
	}

	filenames := GetFilenames(dir)
	if len(filenames) != 3 {
		t.Errorf("GetFilenames returned %d files, want 3", len(filenames))
	}

	// Non-existent directory returns empty slice
	filenames = GetFilenames("/nonexistent_dir_xyz")
	if len(filenames) != 0 {
		t.Errorf("GetFilenames on nonexistent dir returned %d files, want 0", len(filenames))
	}
}

func TestDescribeBytes(t *testing.T) {
	tests := []struct {
		size int64
		want string
	}{
		{0, "0 KiB"},
		{1024, "1 KiB"},
		{512, "0 KiB"},
		{1048576, "1 MiB"},
		{2097152, "2 MiB"},
		{10240, "10 KiB"},
	}
	for _, tt := range tests {
		got := DescribeBytes(tt.size)
		if got != tt.want {
			t.Errorf("DescribeBytes(%d) = %q, want %q", tt.size, got, tt.want)
		}
	}
}

func TestResolvesWithinDir(t *testing.T) {
	outside := t.TempDir()
	secret := filepath.Join(outside, "secret.txt")
	if err := os.WriteFile(secret, []byte("secret"), 0o600); err != nil {
		t.Fatal(err)
	}
	root := t.TempDir()
	inside := filepath.Join(root, "inside.txt")
	if err := os.WriteFile(inside, []byte("ok"), 0o600); err != nil {
		t.Fatal(err)
	}
	links := map[string]string{
		"leak":       secret,
		"leakdir":    outside,
		"insidelink": inside,
	}
	for name, target := range links {
		if err := os.Symlink(target, filepath.Join(root, name)); err != nil {
			t.Skip("symlinks are not supported here:", err)
		}
	}
	for p, want := range map[string]bool{
		inside:                                       true,
		filepath.Join(root, "insidelink"):            true,
		filepath.Join(root, "missing.txt"):           true,
		filepath.Join(root, "leak"):                  false,
		filepath.Join(root, "leakdir"):               false,
		filepath.Join(root, "leakdir", "secret.txt"): false,
	} {
		if got := ResolvesWithinDir(root, p); got != want {
			t.Errorf("ResolvesWithinDir(root, %s) = %v, want %v", p, got, want)
		}
	}

	// The root itself may be a symlink, like /srv/www -> /data/www
	rootLink := filepath.Join(t.TempDir(), "rootlink")
	if err := os.Symlink(root, rootLink); err != nil {
		t.Fatal(err)
	}
	if !ResolvesWithinDir(rootLink, filepath.Join(rootLink, "inside.txt")) {
		t.Error("a file in a symlinked root should be within the root")
	}
	if ResolvesWithinDir(rootLink, filepath.Join(rootLink, "leak")) {
		t.Error("a symlink out of a symlinked root should not be within the root")
	}
}