github.com/dennwc/btrfs@v0.0.0-20221026161108-3097362dc072/btrfs_test.go (about) 1 package btrfs 2 3 import ( 4 "github.com/dennwc/btrfs/test" 5 "io" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 "reflect" 10 "sort" 11 "testing" 12 ) 13 14 const sizeDef = 256 * 1024 * 1024 15 16 func TestOpen(t *testing.T) { 17 dir, closer := btrfstest.New(t, sizeDef) 18 defer closer() 19 fs, err := Open(dir, true) 20 if err != nil { 21 t.Fatal(err) 22 } 23 if err = fs.Close(); err != nil { 24 t.Fatal(err) 25 } 26 } 27 28 func TestIsSubvolume(t *testing.T) { 29 dir, closer := btrfstest.New(t, sizeDef) 30 defer closer() 31 32 isSubvol := func(path string, expect bool) { 33 ok, err := IsSubVolume(path) 34 if err != nil { 35 t.Errorf("failed to check subvolume %v: %v", path, err) 36 return 37 } else if ok != expect { 38 t.Errorf("unexpected result for %v", path) 39 } 40 } 41 mkdir := func(path string) { 42 path = filepath.Join(dir, path) 43 if err := os.MkdirAll(path, 0755); err != nil { 44 t.Fatalf("cannot create dir %v: %v", path, err) 45 } 46 isSubvol(path, false) 47 } 48 49 mksub := func(path string) { 50 path = filepath.Join(dir, path) 51 if err := CreateSubVolume(path); err != nil { 52 t.Fatalf("cannot create subvolume %v: %v", path, err) 53 } 54 isSubvol(path, true) 55 } 56 57 mksub("v1") 58 59 mkdir("v1/d2") 60 mksub("v1/v2") 61 62 mkdir("v1/d2/d3") 63 mksub("v1/d2/v3") 64 65 mkdir("v1/v2/d3") 66 mksub("v1/v2/v3") 67 68 mkdir("d1") 69 70 mkdir("d1/d2") 71 mksub("d1/v2") 72 73 mkdir("d1/d2/d3") 74 mksub("d1/d2/v3") 75 76 mkdir("d1/v2/d3") 77 mksub("d1/v2/v3") 78 } 79 80 func TestSubvolumes(t *testing.T) { 81 dir, closer := btrfstest.New(t, sizeDef) 82 defer closer() 83 fs, err := Open(dir, false) 84 if err != nil { 85 t.Fatal(err) 86 } 87 defer fs.Close() 88 89 mksub := func(in string, path string) { 90 if in != "" { 91 path = filepath.Join(dir, in, path) 92 } else { 93 path = filepath.Join(dir, path) 94 } 95 if err := CreateSubVolume(path); err != nil { 96 t.Fatalf("cannot create subvolume %v: %v", path, err) 97 } 98 } 99 delsub := func(path string) { 100 path = filepath.Join(dir, path) 101 if err := DeleteSubVolume(path); err != nil { 102 t.Fatalf("cannot delete subvolume %v: %v", path, err) 103 } 104 } 105 expect := func(exp []string) { 106 subs, err := fs.ListSubvolumes(nil) 107 if err != nil { 108 t.Fatal(err) 109 } 110 var got []string 111 for _, s := range subs { 112 if s.UUID.IsZero() { 113 t.Fatalf("zero uuid in %+v", s) 114 } 115 if s.Path != "" { 116 got = append(got, s.Path) 117 } 118 } 119 sort.Strings(got) 120 sort.Strings(exp) 121 if !reflect.DeepEqual(got, exp) { 122 t.Fatalf("list failed:\ngot: %v\nvs\nexp: %v", got, exp) 123 } 124 } 125 126 names := []string{"foo", "bar", "baz"} 127 for _, name := range names { 128 mksub("", name) 129 } 130 for _, name := range names { 131 mksub(names[0], name) 132 } 133 expect([]string{ 134 "foo", "bar", "baz", 135 "foo/foo", "foo/bar", "foo/baz", 136 }) 137 delsub("foo/bar") 138 expect([]string{ 139 "foo", "bar", "baz", 140 "foo/foo", "foo/baz", 141 }) 142 143 path := filepath.Join(names[0], names[2]) 144 mksub(path, "new") 145 path = filepath.Join(path, "new") 146 147 id, err := getPathRootID(filepath.Join(dir, path)) 148 if err != nil { 149 t.Fatal(err) 150 } 151 info, err := subvolSearchByRootID(fs.f, id, "") 152 if err != nil { 153 t.Fatal(err) 154 } else if info.Path != path { 155 t.Fatalf("wrong path returned: %v vs %v", info.Path, path) 156 } 157 } 158 159 func TestCompression(t *testing.T) { 160 dir, closer := btrfstest.New(t, sizeDef) 161 defer closer() 162 fs, err := Open(dir, true) 163 if err != nil { 164 t.Fatal(err) 165 } 166 defer fs.Close() 167 if err := fs.CreateSubVolume("sub"); err != nil { 168 t.Fatal(err) 169 } 170 path := filepath.Join(dir, "sub") 171 172 if err := SetCompression(path, LZO); err != nil { 173 t.Fatal(err) 174 } 175 if c, err := GetCompression(path); err != nil { 176 t.Fatal(err) 177 } else if c != LZO { 178 t.Fatalf("unexpected compression returned: %q", string(c)) 179 } 180 } 181 182 func TestCloneFile(t *testing.T) { 183 dir, closer := btrfstest.New(t, sizeDef) 184 defer closer() 185 186 f1, err := os.Create(filepath.Join(dir, "1.dat")) 187 if err != nil { 188 t.Fatal(err) 189 } 190 defer f1.Close() 191 192 const data = "btrfs_test" 193 _, err = f1.WriteString(data) 194 if err != nil { 195 t.Fatal(err) 196 } 197 198 f2, err := os.Create(filepath.Join(dir, "2.dat")) 199 if err != nil { 200 t.Fatal(err) 201 } 202 defer f2.Close() 203 204 err = CloneFile(f2, f1) 205 if err != nil { 206 t.Fatal(err) 207 } 208 209 buf := make([]byte, len(data)) 210 n, err := f2.Read(buf) 211 if err != nil && err != io.EOF { 212 t.Fatal(err) 213 } 214 buf = buf[:n] 215 if string(buf) != data { 216 t.Fatalf("wrong data returned: %q", string(buf)) 217 } 218 } 219 220 func TestResize(t *testing.T) { 221 dir, err := ioutil.TempDir("", "btrfs_data_") 222 if err != nil { 223 t.Fatal(err) 224 } 225 defer os.RemoveAll(dir) 226 fname := filepath.Join(dir, "data") 227 if err = btrfstest.Mkfs(fname, sizeDef); err != nil { 228 t.Fatal(err) 229 } 230 mnt := filepath.Join(dir, "mnt") 231 if err = os.MkdirAll(mnt, 0755); err != nil { 232 t.Fatal(err) 233 } 234 if err = btrfstest.Mount(mnt, fname); err != nil { 235 t.Fatal(err) 236 } 237 defer btrfstest.Unmount(mnt) 238 239 fs, err := Open(mnt, false) 240 if err != nil { 241 t.Fatal(err) 242 } 243 st, err := fs.Usage() 244 fs.Close() 245 if err != nil { 246 t.Fatal(err) 247 } 248 249 if err = btrfstest.Unmount(mnt); err != nil { 250 t.Fatal(err) 251 } 252 var newSize int64 = sizeDef 253 newSize = int64(float64(newSize) * 1.1) 254 if err = os.Truncate(fname, newSize); err != nil { 255 t.Fatal(err) 256 } 257 if err = btrfstest.Mount(mnt, fname); err != nil { 258 t.Fatal(err) 259 } 260 261 fs, err = Open(mnt, false) 262 if err != nil { 263 t.Fatal(err) 264 } 265 defer fs.Close() 266 267 if err = fs.ResizeToMax(); err != nil { 268 t.Fatal(err) 269 } 270 271 st2, err := fs.Usage() 272 if err != nil { 273 t.Fatal(err) 274 } else if st.Total >= st2.Total { 275 t.Fatal("to resized:", st.Total, st2.Total) 276 } 277 }