1# This Source Code Form is subject to the terms of the Mozilla Public
2# License, v. 2.0. If a copy of the MPL was not distributed with this
3# file, You can obtain one at http://mozilla.org/MPL/2.0/.
4from __future__ import absolute_import, print_function, unicode_literals
5"""Tests for the FileAvoidWrite object."""
6
7import locale
8import pytest
9import pathlib2
10from mozbuild.util import FileAvoidWrite
11from mozunit import main
12
13
14@pytest.fixture
15def tmp_path(tmpdir):
16    """Backport of the tmp_path fixture from pytest 3.9.1."""
17    return pathlib2.Path(str(tmpdir))
18
19
20def test_overwrite_contents(tmp_path):
21    file = tmp_path / "file.txt"
22    file.write_text("abc")
23
24    faw = FileAvoidWrite(str(file))
25    faw.write("bazqux")
26
27    assert faw.close() == (True, True)
28    assert file.read_text() == "bazqux"
29
30
31def test_store_new_contents(tmp_path):
32    file = tmp_path / "file.txt"
33
34    faw = FileAvoidWrite(str(file))
35    faw.write("content")
36
37    assert faw.close() == (False, True)
38    assert file.read_text() == "content"
39
40
41def test_change_binary_file_contents(tmp_path):
42    file = tmp_path / "file.dat"
43    file.write_bytes(b"\0")
44
45    faw = FileAvoidWrite(str(file), readmode="rb")
46    faw.write(b"\0\0\0")
47
48    assert faw.close() == (True, True)
49    assert file.read_bytes() == b"\0\0\0"
50
51
52def test_obj_as_context_manager(tmp_path):
53    file = tmp_path / "file.txt"
54
55    with FileAvoidWrite(str(file)) as fh:
56        fh.write("foobar")
57
58    assert file.read_text() == "foobar"
59
60
61def test_no_write_happens_if_file_contents_same(tmp_path):
62    file = tmp_path / "file.txt"
63    file.write_text("content")
64    original_write_time = file.stat().st_mtime
65
66    faw = FileAvoidWrite(str(file))
67    faw.write("content")
68
69    assert faw.close() == (True, False)
70    assert file.stat().st_mtime == original_write_time
71
72
73def test_diff_not_created_by_default(tmp_path):
74    file = tmp_path / "file.txt"
75    faw = FileAvoidWrite(str(file))
76    faw.write("dummy")
77    faw.close()
78    assert faw.diff is None
79
80
81def test_diff_update(tmp_path):
82    file = tmp_path / "diffable.txt"
83    file.write_text("old")
84
85    faw = FileAvoidWrite(str(file), capture_diff=True)
86    faw.write("new")
87    faw.close()
88
89    diff = "\n".join(faw.diff)
90    assert "-old" in diff
91    assert "+new" in diff
92
93
94@pytest.mark.skipif(
95    locale.getdefaultlocale()[1] == "cp1252",
96    reason="Fails on win32 terminals with cp1252 encoding",
97)
98def test_write_unicode(tmp_path):
99    # Unicode grinning face :D
100    binary_emoji = b"\xf0\x9f\x98\x80"
101
102    file = tmp_path / "file.dat"
103    faw = FileAvoidWrite(str(file))
104    faw.write(binary_emoji)
105    faw.close()
106
107
108if __name__ == "__main__":
109    main()
110