| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- package main
- import (
- "os"
- "path/filepath"
- "testing"
- )
- func TestRuleProblem(t *testing.T) {
- roots := []string{"/home", "/mnt", "/media"}
- ok := []string{"/home/u/docs", "/mnt/nas/a", "/media/u/Data/资料", "/mnt/x"}
- bad := map[string]string{
- "/etc": "只能选择",
- "/home": "本身",
- "/mnt": "本身",
- "/home/u": "用户主目录",
- "/home/u/.ssh": "隐藏",
- "/home/u/a/.git/x": "隐藏",
- "/homex/u/a": "只能选择",
- "/home/u/../../etc": "规范",
- "relative/path": "规范",
- "/srv/agent-server": "只能选择",
- "/media/u/Data/.env": "隐藏",
- }
- for _, p := range ok {
- if msg := ruleProblem(p, roots); msg != "" {
- t.Errorf("%s 应该允许,实际:%s", p, msg)
- }
- }
- for p, want := range bad {
- if msg := ruleProblem(p, roots); msg == "" || !contains(msg, want) {
- t.Errorf("%s 应该拒绝(%s),实际:%q", p, want, msg)
- }
- }
- }
- func contains(s, sub string) bool {
- return len(sub) == 0 || (len(s) >= len(sub) && indexOf(s, sub) >= 0)
- }
- func indexOf(s, sub string) int {
- for i := 0; i+len(sub) <= len(s); i++ {
- if s[i:i+len(sub)] == sub {
- return i
- }
- }
- return -1
- }
- // 用临时目录模拟允许的根目录
- func tempRoots(t *testing.T) (string, []string) {
- base, _ := filepath.EvalSymlinks(t.TempDir())
- root := filepath.Join(base, "mnt")
- if err := os.MkdirAll(filepath.Join(root, "data", "docs"), 0o755); err != nil {
- t.Fatal(err)
- }
- return base, []string{root}
- }
- func TestCheckSourceAndBrowse(t *testing.T) {
- base, roots := tempRoots(t)
- root := roots[0]
- os.MkdirAll(filepath.Join(root, "data", ".hidden"), 0o755)
- os.MkdirAll(filepath.Join(base, "outside"), 0o755)
- os.Symlink(filepath.Join(base, "outside"), filepath.Join(root, "escape"))
- os.Symlink(filepath.Join(root, "data", "docs"), filepath.Join(root, "inner"))
- os.WriteFile(filepath.Join(root, "file.txt"), []byte("x"), 0o644)
- if real, err := checkSource(filepath.Join(root, "data", "docs"), roots); err != nil || real != filepath.Join(root, "data", "docs") {
- t.Fatalf("应该通过:%v %v", real, err)
- }
- if real, err := checkSource(filepath.Join(root, "inner"), roots); err != nil || real != filepath.Join(root, "data", "docs") {
- t.Fatalf("范围内的符号链接解析为真实路径:%v %v", real, err)
- }
- cases := map[string]string{
- filepath.Join(root, "escape"): "not_allowed",
- filepath.Join(root, "data", ".hidden"): "not_allowed",
- filepath.Join(root, "file.txt"): "not_allowed",
- filepath.Join(root, "nope"): "path_missing",
- root: "not_allowed",
- "relative": "not_allowed",
- }
- for p, state := range cases {
- if _, err := checkSource(p, roots); err == nil || err.State != state {
- t.Errorf("%s 应该是 %s,实际 %v", p, state, err)
- }
- }
- res, cerr := browse(root, roots)
- if cerr != nil {
- t.Fatal(cerr)
- }
- got := map[string]browseEntry{}
- for _, e := range res.Entries {
- got[e.Name] = e
- }
- if _, ok := got["file.txt"]; ok {
- t.Error("文件不应出现在目录选择中")
- }
- if !got["data"].Selectable || got["escape"].Selectable || !got["inner"].Selectable {
- t.Errorf("可选状态不正确:%+v", got)
- }
- if res.Parent != "" {
- t.Errorf("根目录的上级应为空:%q", res.Parent)
- }
- sub, _ := browse(filepath.Join(root, "data"), roots)
- for _, e := range sub.Entries {
- if e.Name == ".hidden" {
- t.Error("隐藏目录不应出现")
- }
- }
- if _, cerr := browse(filepath.Join(base, "outside"), roots); cerr == nil {
- t.Error("不能浏览范围以外的目录")
- }
- if _, cerr := browse(filepath.Join(root, "escape"), roots); cerr == nil {
- t.Error("不能经由符号链接浏览范围以外的目录")
- }
- top, _ := browse("", roots)
- if len(top.Entries) != 1 || top.Entries[0].Selectable {
- t.Errorf("顶层列出允许的根目录且不能直接选择:%+v", top.Entries)
- }
- }
|