summaryrefslogtreecommitdiffstats
path: root/python/mozversioncontrol/test
diff options
context:
space:
mode:
Diffstat (limited to 'python/mozversioncontrol/test')
-rw-r--r--python/mozversioncontrol/test/conftest.py74
-rw-r--r--python/mozversioncontrol/test/python.ini8
-rw-r--r--python/mozversioncontrol/test/test_commit.py74
-rw-r--r--python/mozversioncontrol/test/test_context_manager.py30
-rw-r--r--python/mozversioncontrol/test/test_push_to_try.py86
-rw-r--r--python/mozversioncontrol/test/test_workdir_outgoing.py111
-rw-r--r--python/mozversioncontrol/test/test_working_directory.py48
7 files changed, 431 insertions, 0 deletions
diff --git a/python/mozversioncontrol/test/conftest.py b/python/mozversioncontrol/test/conftest.py
new file mode 100644
index 0000000000..5c9317dafc
--- /dev/null
+++ b/python/mozversioncontrol/test/conftest.py
@@ -0,0 +1,74 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from __future__ import absolute_import
+
+import os
+import subprocess
+
+import pytest
+
+
+SETUP = {
+ "hg": [
+ """
+ echo "foo" > foo
+ echo "bar" > bar
+ hg init
+ hg add *
+ hg commit -m "Initial commit"
+ """,
+ """
+ echo "[paths]\ndefault = ../remoterepo" > .hg/hgrc
+ """,
+ ],
+ "git": [
+ """
+ echo "foo" > foo
+ echo "bar" > bar
+ git init
+ git add *
+ git commit -am "Initial commit"
+ """,
+ """
+ git remote add upstream ../remoterepo
+ git fetch upstream
+ git branch -u upstream/master
+ """,
+ ],
+}
+
+
+def shell(cmd):
+ subprocess.check_call(cmd, shell=True)
+
+
+@pytest.yield_fixture(params=["git", "hg"])
+def repo(tmpdir, request):
+ vcs = request.param
+ steps = SETUP[vcs]
+
+ if hasattr(request.module, "STEPS"):
+ steps.extend(request.module.STEPS[vcs])
+
+ # tmpdir and repo are py.path objects
+ # http://py.readthedocs.io/en/latest/path.html
+ repo = tmpdir.mkdir("repo")
+ repo.vcs = vcs
+
+ # This creates a step iterator. Each time next() is called
+ # on it, the next set of instructions will be executed.
+ repo.step = (shell(cmd) for cmd in steps)
+
+ oldcwd = os.getcwd()
+ os.chdir(repo.strpath)
+
+ next(repo.step)
+
+ repo.copy(tmpdir.join("remoterepo"))
+
+ next(repo.step)
+
+ yield repo
+ os.chdir(oldcwd)
diff --git a/python/mozversioncontrol/test/python.ini b/python/mozversioncontrol/test/python.ini
new file mode 100644
index 0000000000..a9b1b7ca3a
--- /dev/null
+++ b/python/mozversioncontrol/test/python.ini
@@ -0,0 +1,8 @@
+[DEFAULT]
+subsuite=mozversioncontrol
+
+[test_context_manager.py]
+[test_push_to_try.py]
+[test_workdir_outgoing.py]
+[test_working_directory.py]
+[test_commit.py]
diff --git a/python/mozversioncontrol/test/test_commit.py b/python/mozversioncontrol/test/test_commit.py
new file mode 100644
index 0000000000..32b80db68a
--- /dev/null
+++ b/python/mozversioncontrol/test/test_commit.py
@@ -0,0 +1,74 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from __future__ import absolute_import
+
+import mozunit
+
+from mozversioncontrol import get_repository_object
+
+STEPS = {
+ "hg": [
+ """
+ echo "bar" >> bar
+ echo "baz" > foo
+ """,
+ ],
+ "git": [
+ """
+ echo "bar" >> bar
+ echo "baz" > foo
+ """,
+ ],
+}
+
+
+def test_commit(repo):
+ vcs = get_repository_object(repo.strpath)
+ assert vcs.working_directory_clean()
+
+ # Modify both foo and bar
+ next(repo.step)
+ assert not vcs.working_directory_clean()
+
+ # Commit just bar
+ vcs.commit(
+ "Modify bar\n\nbut not baz",
+ "Testing McTesterson <test@example.org>",
+ "2017-07-14 02:40:00 UTC",
+ ["bar"],
+ )
+
+ # We only committed bar, so foo is still keeping the working dir dirty
+ assert not vcs.working_directory_clean()
+
+ if repo.vcs == "git":
+ log_cmd = ["log", "-1", "--format=%an,%ae,%at,%B"]
+ patch_cmd = ["log", "-1", "-p"]
+ else:
+ log_cmd = [
+ "log",
+ "-l",
+ "1",
+ "-T",
+ '{person(author)},{email(author)},{date(localdate(date),"%s")},{desc}',
+ ]
+ patch_cmd = ["log", "-l", "1", "-p"]
+
+ # Verify commit metadata (we rstrip to normalize trivial git/hg differences)
+ log = vcs._run(*log_cmd).rstrip()
+ assert (
+ log
+ == "Testing McTesterson,test@example.org,1500000000,Modify bar\n\nbut not baz"
+ )
+
+ # Verify only the intended file was added to the commit
+ patch = vcs._run(*patch_cmd)
+ diffs = [line for line in patch.splitlines() if "diff --git" in line]
+ assert len(diffs) == 1
+ assert diffs[0] == "diff --git a/bar b/bar"
+
+
+if __name__ == "__main__":
+ mozunit.main()
diff --git a/python/mozversioncontrol/test/test_context_manager.py b/python/mozversioncontrol/test/test_context_manager.py
new file mode 100644
index 0000000000..10e1d31fd3
--- /dev/null
+++ b/python/mozversioncontrol/test/test_context_manager.py
@@ -0,0 +1,30 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from __future__ import absolute_import
+
+import mozunit
+
+from mozversioncontrol import get_repository_object
+
+
+def test_context_manager(repo):
+ is_git = repo.vcs == "git"
+ cmd = ["show", "--no-patch"] if is_git else ["tip"]
+
+ vcs = get_repository_object(repo.strpath)
+ output_subprocess = vcs._run(*cmd)
+ assert is_git or vcs._client.server is None
+ assert "Initial commit" in output_subprocess
+
+ with vcs:
+ assert is_git or vcs._client.server is not None
+ output_client = vcs._run(*cmd)
+
+ assert is_git or vcs._client.server is None
+ assert output_subprocess == output_client
+
+
+if __name__ == "__main__":
+ mozunit.main()
diff --git a/python/mozversioncontrol/test/test_push_to_try.py b/python/mozversioncontrol/test/test_push_to_try.py
new file mode 100644
index 0000000000..b3af244807
--- /dev/null
+++ b/python/mozversioncontrol/test/test_push_to_try.py
@@ -0,0 +1,86 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from __future__ import absolute_import, unicode_literals
+
+import subprocess
+
+import mozunit
+import pytest
+
+from mozversioncontrol import (
+ get_repository_object,
+ MissingVCSExtension,
+)
+
+
+def test_push_to_try(repo, monkeypatch):
+ commit_message = "commit message"
+ vcs = get_repository_object(repo.strpath)
+
+ captured_commands = []
+
+ def fake_run(*args, **kwargs):
+ captured_commands.append(args[0])
+
+ monkeypatch.setattr(subprocess, "check_output", fake_run)
+ monkeypatch.setattr(subprocess, "check_call", fake_run)
+
+ vcs.push_to_try(commit_message)
+ tool = vcs._tool
+
+ if repo.vcs == "hg":
+ expected = [
+ (tool, "push-to-try", "-m", commit_message),
+ (tool, "revert", "-a"),
+ ]
+ else:
+ expected = [
+ (tool, "cinnabar", "--version"),
+ (
+ tool,
+ "-c",
+ "commit.gpgSign=false",
+ "commit",
+ "--allow-empty",
+ "-m",
+ commit_message,
+ ),
+ (
+ tool,
+ "push",
+ "hg::ssh://hg.mozilla.org/try",
+ "+HEAD:refs/heads/branches/default/tip",
+ ),
+ (tool, "reset", "HEAD~"),
+ ]
+
+ for i, value in enumerate(captured_commands):
+ assert value == expected[i]
+
+ assert len(captured_commands) == len(expected)
+
+
+def test_push_to_try_missing_extensions(repo, monkeypatch):
+ if repo.vcs != "git":
+ return
+
+ vcs = get_repository_object(repo.strpath)
+
+ orig = vcs._run
+
+ def cinnabar_raises(*args, **kwargs):
+ # Simulate not having git cinnabar
+ if args[0] == "cinnabar":
+ raise subprocess.CalledProcessError(1, args)
+ return orig(*args, **kwargs)
+
+ monkeypatch.setattr(vcs, "_run", cinnabar_raises)
+
+ with pytest.raises(MissingVCSExtension):
+ vcs.push_to_try("commit message")
+
+
+if __name__ == "__main__":
+ mozunit.main()
diff --git a/python/mozversioncontrol/test/test_workdir_outgoing.py b/python/mozversioncontrol/test/test_workdir_outgoing.py
new file mode 100644
index 0000000000..44bf4370a2
--- /dev/null
+++ b/python/mozversioncontrol/test/test_workdir_outgoing.py
@@ -0,0 +1,111 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from __future__ import absolute_import
+
+import os
+
+import mozunit
+
+from mozversioncontrol import get_repository_object
+
+
+STEPS = {
+ "hg": [
+ """
+ echo "bar" >> bar
+ echo "baz" > baz
+ hg add baz
+ hg rm foo
+ """,
+ """
+ hg commit -m "Remove foo; modify bar; add baz"
+ """,
+ """
+ echo ooka >> baz
+ echo newborn > baby
+ hg add baby
+ """,
+ """
+ hg commit -m "Modify baz; add baby"
+ """,
+ ],
+ "git": [
+ """
+ echo "bar" >> bar
+ echo "baz" > baz
+ git add baz
+ git rm foo
+ """,
+ """
+ git commit -am "Remove foo; modify bar; add baz"
+ """,
+ """
+ echo ooka >> baz
+ echo newborn > baby
+ git add baz baby
+ """,
+ """
+ git commit -m "Modify baz; add baby"
+ """,
+ ],
+}
+
+
+def assert_files(actual, expected):
+ assert set(map(os.path.basename, actual)) == set(expected)
+
+
+def test_workdir_outgoing(repo):
+ vcs = get_repository_object(repo.strpath)
+ assert vcs.path == repo.strpath
+
+ remotepath = "../remoterepo" if repo.vcs == "hg" else "upstream/master"
+
+ # Mutate files.
+ next(repo.step)
+
+ assert_files(vcs.get_changed_files("A", "all"), ["baz"])
+ assert_files(vcs.get_changed_files("AM", "all"), ["bar", "baz"])
+ assert_files(vcs.get_changed_files("D", "all"), ["foo"])
+ if repo.vcs == "git":
+ assert_files(vcs.get_changed_files("AM", mode="staged"), ["baz"])
+ elif repo.vcs == "hg":
+ # Mercurial does not use a staging area (and ignores the mode parameter.)
+ assert_files(vcs.get_changed_files("AM", "unstaged"), ["bar", "baz"])
+ assert_files(vcs.get_outgoing_files("AMD"), [])
+ assert_files(vcs.get_outgoing_files("AMD", remotepath), [])
+
+ # Create a commit.
+ next(repo.step)
+
+ assert_files(vcs.get_changed_files("AMD", "all"), [])
+ assert_files(vcs.get_changed_files("AMD", "staged"), [])
+ assert_files(vcs.get_outgoing_files("AMD"), ["bar", "baz", "foo"])
+ assert_files(vcs.get_outgoing_files("AMD", remotepath), ["bar", "baz", "foo"])
+
+ # Mutate again.
+ next(repo.step)
+
+ assert_files(vcs.get_changed_files("A", "all"), ["baby"])
+ assert_files(vcs.get_changed_files("AM", "all"), ["baby", "baz"])
+ assert_files(vcs.get_changed_files("D", "all"), [])
+
+ # Create a second commit.
+ next(repo.step)
+
+ assert_files(vcs.get_outgoing_files("AM"), ["bar", "baz", "baby"])
+ assert_files(vcs.get_outgoing_files("AM", remotepath), ["bar", "baz", "baby"])
+ if repo.vcs == "git":
+ assert_files(vcs.get_changed_files("AM", rev="HEAD~1"), ["bar", "baz"])
+ assert_files(vcs.get_changed_files("AM", rev="HEAD"), ["baby", "baz"])
+ else:
+ assert_files(vcs.get_changed_files("AM", rev=".^"), ["bar", "baz"])
+ assert_files(vcs.get_changed_files("AM", rev="."), ["baby", "baz"])
+ assert_files(vcs.get_changed_files("AM", rev=".^::"), ["bar", "baz", "baby"])
+ assert_files(vcs.get_changed_files("AM", rev="modifies(baz)"), ["baz", "baby"])
+
+
+if __name__ == "__main__":
+ mozunit.main()
diff --git a/python/mozversioncontrol/test/test_working_directory.py b/python/mozversioncontrol/test/test_working_directory.py
new file mode 100644
index 0000000000..11b7f360d1
--- /dev/null
+++ b/python/mozversioncontrol/test/test_working_directory.py
@@ -0,0 +1,48 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from __future__ import absolute_import
+
+import mozunit
+
+from mozversioncontrol import get_repository_object
+
+STEPS = {
+ "hg": [
+ """
+ echo "bar" >> bar
+ echo "baz" > baz
+ hg rm foo
+ """,
+ """
+ hg commit -m "Remove foo; modify bar; touch baz (but don't add it)"
+ """,
+ ],
+ "git": [
+ """
+ echo "bar" >> bar
+ echo "baz" > baz
+ git rm foo
+ """,
+ """
+ git commit -am "Remove foo; modify bar; touch baz (but don't add it)"
+ """,
+ ],
+}
+
+
+def test_working_directory_clean_untracked_files(repo):
+ vcs = get_repository_object(repo.strpath)
+ assert vcs.working_directory_clean()
+
+ next(repo.step)
+ assert not vcs.working_directory_clean()
+
+ next(repo.step)
+ assert vcs.working_directory_clean()
+ assert not vcs.working_directory_clean(untracked=True)
+
+
+if __name__ == "__main__":
+ mozunit.main()