Source

scm-correctness / hg-test.sh

#!/bin/bash
# -*- coding: UTF-8 -*-
#
# A test suite to validate the correctness of merging after incompatible changes.
#
# Written by Ringo De Smet
# Released in the public domain
# Published at:
# http://bitbucket.org/ringods/scm-correctness/
#
# Based on the SCM scripts written by Maciej Bliziński
# found at:
# http://automatthias.wordpress.com/2007/06/07/directory-renaming-in-scm/

. common.sh

HG() {
	hg "$@" > /dev/null 2> /dev/null
}

oneTimeSetUp() {
	# Make sure it's all clean
	rm -rf base-project tests-hg

	createBaseProject
	
	# Creating temporary folder for running git tests and make it the working folder.
	mkdir tests-hg
	PUSHD tests-hg

	# Initialize the hg repository from the base project contents 
	cp -R ../base-project hg-repo
	PUSHD hg-repo
	HG init
	HG add dir-a
	HG add dir-c
	HG commit -m "Initial project contents"
	POPD
}

oneTimeTearDown() {
	# Go back to the project folder as working folder
	POPD
}

#setUp() {
	# Working folder is <project root>/tests-hg
#}

#tearDown() {
	# Working folder is <project root>/tests-hg
#}

test_hg_1_same_file_edit_no_conflict()
{
	createExpectationScenario1
	
	# Developer A edits a file
	HG clone hg-repo hg-repo-1-branch-a
	PUSHD hg-repo-1-branch-a
	PUSHD dir-a
	echo changedline1 > foo.txt
	echo line2 >> foo.txt
	POPD
	HG commit -m "Edited foo.txt by A"
	POPD
	
	# Developer B edits the same file, but another part
	HG clone hg-repo hg-repo-1-branch-b
	PUSHD hg-repo-1-branch-b
	PUSHD dir-a
	echo addedline3 >> foo.txt
	POPD
	HG commit -m "Edited foo.txt by B"
	POPD
	
	# Developer C merges A's changes first, then B's
	HG clone hg-repo hg-repo-1-branch-c
	PUSHD hg-repo-1-branch-c
	HG pull -u ../hg-repo-1-branch-a
	HG merge
	HG commit -m "Merged A's changes"
	HG pull ../hg-repo-1-branch-b
	HG merge
	HG commit -m "Merged B's changes"
	POPD

	# Check actual repo with the expected outcome
	diff -r -x .hg hg-repo-1-branch-c expected-1
	assertEquals 0 $?

}

test_hg_2_same_file_edit_conflict()
{
	createExpectationScenario2
	
	# Developer A edits a file
	HG clone hg-repo hg-repo-2-branch-a
	PUSHD hg-repo-2-branch-a
	PUSHD dir-a
	echo line1 > foo.txt
	echo changedline2byA >> foo.txt
	POPD
	HG commit -m "Edited foo.txt by A"
	POPD
	
	# Developer B edits the same file, but another part
	HG clone hg-repo hg-repo-2-branch-b
	PUSHD hg-repo-2-branch-b
	PUSHD dir-a
	echo line1 > foo.txt
	echo changedLine2byB >> foo.txt
	POPD
	HG commit -m "Edited foo.txt by B"
	POPD
	
	# Developer C merges A's changes first, then B's
	HG clone hg-repo hg-repo-2-branch-c
	PUSHD hg-repo-2-branch-c
	HG pull -u ../hg-repo-2-branch-a
	HG merge
	HG commit -m "Merged A's changes"
	HG pull ../hg-repo-2-branch-b
	HG merge
	assertEquals 1 $?
	PUSHD dir-a
	echo line1 > foo.txt
	echo resolvedline2 >> foo.txt
	HG resolve -m foo.txt
	rm foo.txt.orig
	POPD
	HG commit -m "Merged B's changes"
	POPD

	# Check actual repo with the expected outcome
	diff -r -x .hg hg-repo-2-branch-c expected-2
	assertEquals 0 $?

}

test_hg_3_edit_and_rename_of_file()
{
	createExpectationScenario3
	
	# Developer A edits a file
	HG clone hg-repo hg-repo-3-branch-a
	PUSHD hg-repo-3-branch-a
	PUSHD dir-a
	HG mv foo.txt renamedFoo.txt
	POPD
	HG commit -m "Renamed foo.txt by A"
	POPD
	
	# Developer B edits the same file, but another part
	HG clone hg-repo hg-repo-3-branch-b
	PUSHD hg-repo-3-branch-b
	PUSHD dir-a
	echo line1 > foo.txt
	echo line2 >> foo.txt
	echo addedline3 >> foo.txt
	POPD
	HG commit -m "Edited foo.txt by B"
	POPD
	
	# Developer C merges A's changes first, then B's
	HG clone hg-repo hg-repo-3-branch-c
	PUSHD hg-repo-3-branch-c
	HG pull -u ../hg-repo-3-branch-a
	HG merge
	HG commit -m "Merged A's changes"
	HG pull ../hg-repo-3-branch-b
	HG merge
	assertEquals 0 $?
	HG commit -m "Merged B's changes"
	POPD

	# Check actual repo with the expected outcome
	diff -r -x .hg hg-repo-3-branch-c expected-3
	assertEquals 0 $?

}

test_hg_4_double_rename_of_same_file()
{
	createExpectationScenario4
	
	# Developer A renames a file
	HG clone hg-repo hg-repo-4-branch-a
	PUSHD hg-repo-4-branch-a
	PUSHD dir-a
	HG mv foo.txt fooByA.txt
	POPD
	HG commit -m "File renamed by A"
	POPD
	
	# Developer B renames the same file with a different name
	HG clone hg-repo hg-repo-4-branch-b
	PUSHD hg-repo-4-branch-b
	PUSHD dir-a
	HG mv foo.txt fooByB.txt
	POPD
	HG commit -m "File renamed by B"
	POPD
	
	# Developer C merges A's changes first, then B's
	HG clone hg-repo hg-repo-4-branch-c
	PUSHD hg-repo-4-branch-c
	HG pull ../hg-repo-4-branch-a
	HG merge
	HG commit -m "Merged A's changes"
	HG pull ../hg-repo-4-branch-b
	HG merge
	# TODO: Still has to resolve the merge conflict here
	HG commit -m "Merged B's changes"
	POPD

	# Check actual repo with the expected outcome
	diff -r -x .hg hg-repo-4-branch-c expected-4
	assertEquals 0 $?

}

test_hg_5_double_add_of_same_file()
{
	createExpectationScenario5
	
	# Developer A adds a file
	HG clone hg-repo hg-repo-5-branch-a
	PUSHD hg-repo-5-branch-a
	PUSHD dir-a
	echo line1FromA > conflictingFile.txt
	HG add conflictingFile.txt
	POPD
	HG commit -m "File added by A"
	POPD
	
	# Developer B adds the same file, other contents
	HG clone hg-repo hg-repo-5-branch-b
	PUSHD hg-repo-5-branch-b
	PUSHD dir-a
	echo line1FromB > conflictingFile.txt
	HG add conflictingFile.txt
	POPD
	HG commit -m "File added by B"
	POPD
	
	# Developer C merges A's changes first, then B's
	HG clone hg-repo hg-repo-5-branch-c
	PUSHD hg-repo-5-branch-c
	HG pull ../hg-repo-5-branch-a
	HG merge
	HG commit -m "Merged A's changes"
	HG pull ../hg-repo-5-branch-b
	HG merge
	# TODO: Still has to resolve the merge conflict here
	HG commit -m "Merged B's changes"
	POPD

	# Check actual repo with the expected outcome
	diff -r -x .hg hg-repo-5-branch-c expected-5
	assertEquals 0 $?

}

test_hg_6_rename_and_add()
{
	createExpectationScenario6

	# Developer A renames a directory
	HG clone hg-repo hg-repo-6-branch-a
	PUSHD hg-repo-6-branch-a
	HG mv dir-a dir-b
	HG commit -m "Directory renamed"
	POPD
	
	# Developer B adds a file to the same directory, before A's changes are
	# merged
	HG clone hg-repo hg-repo-6-branch-b
	PUSHD hg-repo-6-branch-b
	PUSHD dir-a
	echo addedline3 >> foo.txt
	echo line1 > bar.txt
	HG add bar.txt
	POPD
	HG commit -m "Foo modified, bar added."
	POPD
	
	# Developer C edits the foo file first, then merges A's, then B's
	HG clone hg-repo hg-repo-6-branch-c
	PUSHD hg-repo-6-branch-c
	HG pull -u ../hg-repo-6-branch-a
	HG commit -m "Merged A's changes"
	HG pull -u ../hg-repo-6-branch-b
	HG merge
	HG commit -m "Merged B's changes"
	POPD

	# Check actual repo with the expected outcome
	diff -r -x .hg hg-repo-6-branch-c expected-6
	assertEquals 0 $?

}

test_hg_9_support_empty_directories() {
	createExpectationScenario9
	
	# Clone the base repo for this scenario
	HG clone hg-repo hg-repo-9

	# Developer A adds an empty folder to the repository
	PUSHD hg-repo-9
	PUSHD dir-a
	mkdir empty
	HG add empty
	POPD
	HG commit -m "Empty directory added"
	POPD
	
	# Developer B checks out.
	HG clone hg-repo-9 hg-repo-9-empty
	
	# Check actual repo with the expected outcome
	diff -r -x .hg hg-repo-9-empty expected-9
	assertEquals 0 $?

}

test_hg_10_push_with_win32text_crlf_hook() {
	#createExpectationScenario10
	
	# Clone the base repo for this scenario
	HG clone hg-repo hg-repo-10-base

	# Install the win32text forbidcrlf hook
	PUSHD hg-repo-10-base
	echo "[extensions]" > .hg/hgrc
	echo "hgext.win32text = " >> .hg/hgrc
	echo "[hooks]" >> .hg/hgrc
	echo "pretxnchangegroup.crlf = python:hgext.win32text.forbidcrlf" >> .hg/hgrc
	POPD

	# Clone the base repo for this scenario
	HG clone hg-repo-10-base hg-repo-10-user

	# Developer A adds an empty folder to the repository
	PUSHD hg-repo-10-user
	PUSHD dir-a

	# First local commit
	echo addedline3 >> foo.txt
	echo line1 > bar.txt
	HG add bar.txt
	HG commit -m "Addes some lines"

	# Second local commit
	echo addedline4 >> foo.txt
	echo line2 >> bar.txt
	HG commit -m "Addes lines, take 2"

	# Third local commit
	echo addedline5 >> foo.txt
	hg remove bar.txt
	HG commit -m "Removed a file and changed one!"

	POPD
	
	# Now try to push the repo
	HG push
	PUSHRESULT=$?

	POPD
	
	# Check actual repo with the expected outcome
	assertEquals 0 $PUSHRESULT

}

# Load shunit2 and run loaded test suites
. ./shunit2-2.1.5/src/shell/shunit2
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.