|
| 1 | +import os |
| 2 | +from unittest.mock import ANY |
| 3 | + |
| 4 | +import pytest |
| 5 | + |
| 6 | +from dvc_objects.fs.implementations._memory import MemFS2 |
| 7 | + |
| 8 | + |
| 9 | +@pytest.fixture |
| 10 | +def m(): |
| 11 | + return MemFS2() |
| 12 | + |
| 13 | + |
| 14 | +def test_memfs_should_not_be_cached(): |
| 15 | + assert MemFS2() is not MemFS2() |
| 16 | + |
| 17 | + |
| 18 | +def test_1(m): |
| 19 | + m.touch("/somefile") # NB: is found with or without initial / |
| 20 | + m.touch("afiles/and/another") |
| 21 | + files = m.find("") |
| 22 | + assert files == ["/afiles/and/another", "/somefile"] |
| 23 | + |
| 24 | + files = sorted(m.get_mapper()) |
| 25 | + assert files == ["afiles/and/another", "somefile"] |
| 26 | + |
| 27 | + |
| 28 | +def test_strip(m): |
| 29 | + assert m._strip_protocol("") == "" |
| 30 | + assert m._strip_protocol("memory://") == "" |
| 31 | + assert m._strip_protocol("afile") == "/afile" |
| 32 | + assert m._strip_protocol("/b/c") == "/b/c" |
| 33 | + assert m._strip_protocol("/b/c/") == "/b/c" |
| 34 | + |
| 35 | + |
| 36 | +def test_put_single(m, tmpdir): |
| 37 | + fn = os.path.join(str(tmpdir), "dir") |
| 38 | + os.mkdir(fn) |
| 39 | + open(os.path.join(fn, "abc"), "w").write("text") |
| 40 | + m.put(fn, "/test") # no-op, no files |
| 41 | + assert not m.exists("/test/abc") |
| 42 | + assert not m.exists("/test/dir") |
| 43 | + m.put(fn + "/", "/test", recursive=True) |
| 44 | + assert m.cat("/test/abc") == b"text" |
| 45 | + |
| 46 | + |
| 47 | +def test_ls(m): |
| 48 | + m.touch("/dir/afile") |
| 49 | + m.touch("/dir/dir1/bfile") |
| 50 | + m.touch("/dir/dir1/cfile") |
| 51 | + |
| 52 | + assert m.ls("/", False) == ["/dir"] |
| 53 | + assert m.ls("/dir", False) == ["/dir/afile", "/dir/dir1"] |
| 54 | + assert m.ls("/dir", True)[0]["type"] == "file" |
| 55 | + assert m.ls("/dir", True)[1]["type"] == "directory" |
| 56 | + |
| 57 | + assert len(m.ls("/dir/dir1")) == 2 |
| 58 | + assert m.ls("/dir/afile") == ["/dir/afile"] |
| 59 | + assert m.ls("/dir/dir1/bfile") == ["/dir/dir1/bfile"] |
| 60 | + assert m.ls("/dir/dir1/cfile") == ["/dir/dir1/cfile"] |
| 61 | + |
| 62 | + with pytest.raises(FileNotFoundError): |
| 63 | + m.ls("/dir/not-existing-file") |
| 64 | + |
| 65 | + |
| 66 | +def test_mv_recursive(m): |
| 67 | + m.mkdir("src") |
| 68 | + m.touch("src/file.txt") |
| 69 | + m.mv("src", "dest", recursive=True) |
| 70 | + assert m.exists("dest/file.txt") |
| 71 | + assert not m.exists("src") |
| 72 | + |
| 73 | + |
| 74 | +def test_rm(m): |
| 75 | + m.touch("/dir1/dir2/file") |
| 76 | + m.rm("/dir1", recursive=True) |
| 77 | + assert not m.exists("/dir1/dir2/file") |
| 78 | + assert not m.exists("/dir1/dir2") |
| 79 | + assert not m.exists("/dir1") |
| 80 | + |
| 81 | + with pytest.raises(FileNotFoundError): |
| 82 | + m.rm("/dir1", recursive=True) |
| 83 | + |
| 84 | + |
| 85 | +def test_rm_multiple_files(m): |
| 86 | + m.touch("/dir/file1") |
| 87 | + m.touch("/dir/file2") |
| 88 | + |
| 89 | + m.rm(["/dir/file1", "/dir/file2"]) |
| 90 | + assert not m.ls("/") |
| 91 | + |
| 92 | + |
| 93 | +def test_rm_file(m): |
| 94 | + m.touch("/dir/file") |
| 95 | + with pytest.raises(IsADirectoryError): |
| 96 | + m.rm_file("/dir") |
| 97 | + |
| 98 | + with pytest.raises(FileNotFoundError): |
| 99 | + m.rm_file("/dir/foo") |
| 100 | + |
| 101 | + m.rm_file("/dir/file") |
| 102 | + assert not m.exists("/dir/file") |
| 103 | + |
| 104 | + |
| 105 | +def test_rewind(m): |
| 106 | + # https://github.com/fsspec/filesystem_spec/issues/349 |
| 107 | + with m.open("src/file.txt", "w") as f: |
| 108 | + f.write("content") |
| 109 | + with m.open("src/file.txt") as f: |
| 110 | + assert f.tell() == 0 |
| 111 | + |
| 112 | + |
| 113 | +def test_no_rewind_append_mode(m): |
| 114 | + # https://github.com/fsspec/filesystem_spec/issues/349 |
| 115 | + with m.open("src/file.txt", "w") as f: |
| 116 | + f.write("content") |
| 117 | + with m.open("src/file.txt", "a") as f: |
| 118 | + assert f.tell() == 7 |
| 119 | + |
| 120 | + |
| 121 | +def test_seekable(m): |
| 122 | + fn0 = "foo.txt" |
| 123 | + with m.open(fn0, "wb") as f: |
| 124 | + f.write(b"data") |
| 125 | + |
| 126 | + f = m.open(fn0, "rt") |
| 127 | + assert f.seekable(), "file is not seekable" |
| 128 | + f.seek(1) |
| 129 | + assert f.read(1) == "a" |
| 130 | + assert f.tell() == 2 |
| 131 | + |
| 132 | + |
| 133 | +def test_try_open_directory(m): |
| 134 | + m.touch("/dir/file") |
| 135 | + with pytest.raises(IsADirectoryError): |
| 136 | + m.open("dir") |
| 137 | + |
| 138 | + |
| 139 | +def test_try_open_not_existing_file(m): |
| 140 | + with pytest.raises(FileNotFoundError): |
| 141 | + m.open("not-existing-file") |
| 142 | + |
| 143 | + |
| 144 | +def test_try_open_file_on_super_prefix(m): |
| 145 | + m.touch("/afile") |
| 146 | + with pytest.raises(NotADirectoryError): |
| 147 | + m.open("/afile/file") |
| 148 | + |
| 149 | + |
| 150 | +def test_empty_raises(m): |
| 151 | + with pytest.raises(FileNotFoundError): |
| 152 | + m.ls("nonexistent") |
| 153 | + |
| 154 | + with pytest.raises(FileNotFoundError): |
| 155 | + m.info("nonexistent") |
| 156 | + |
| 157 | + |
| 158 | +def test_moves(m): |
| 159 | + m.touch("source.txt") |
| 160 | + m.mv("source.txt", "target.txt") |
| 161 | + |
| 162 | + m.touch("source2.txt") |
| 163 | + m.mv("source2.txt", "target2.txt", recursive=True) |
| 164 | + assert m.find("") == ["/target.txt", "/target2.txt"] |
| 165 | + |
| 166 | + |
| 167 | +def test_remove_all(m: MemFS2): |
| 168 | + m.touch("afile") |
| 169 | + m.rm("/", recursive=True) |
| 170 | + assert not m.ls("/") |
| 171 | + |
| 172 | + |
| 173 | +def test_created(m): |
| 174 | + m.touch("/dir/afile") |
| 175 | + assert m.created("/dir/afile") == m.trie["/dir/afile"].created |
| 176 | + assert m.created("/dir") is None |
| 177 | + |
| 178 | + |
| 179 | +def test_info(m): |
| 180 | + m.touch("/dir/file") |
| 181 | + |
| 182 | + assert m.info("/") == {"name": "", "size": 0, "type": "directory"} |
| 183 | + assert m.info("/dir") == {"name": "/dir", "size": 0, "type": "directory"} |
| 184 | + assert m.info("/dir/file") == { |
| 185 | + "name": "/dir/file", |
| 186 | + "size": 0, |
| 187 | + "type": "file", |
| 188 | + "created": ANY, |
| 189 | + } |
| 190 | + |
| 191 | + with pytest.raises(FileNotFoundError): |
| 192 | + m.info("/not-existing-file") |
| 193 | + |
| 194 | + |
| 195 | +def test_cp_file(m): |
| 196 | + m.pipe_file("/afile", b"content") |
| 197 | + m.cp_file("/afile", "/bfile") |
| 198 | + assert m.cat_file("/bfile") == m.cat_file("/afile") == b"content" |
| 199 | + |
| 200 | + |
| 201 | +def test_transaction(m): |
| 202 | + m.start_transaction() |
| 203 | + m.touch("/dir/afile") |
| 204 | + assert m.find("/") == [] |
| 205 | + m.end_transaction() |
| 206 | + assert m.find("/") == ["/dir/afile"] |
| 207 | + |
| 208 | + with m.transaction: |
| 209 | + m.touch("/dir/bfile") |
| 210 | + assert m.find("/") == ["/dir/afile"] |
| 211 | + assert m.find("/") == ["/dir/afile", "/dir/bfile"] |
0 commit comments