From f6b200be4c8b90c26886c6cdd5809abac8c4ac15 Mon Sep 17 00:00:00 2001 From: James Moger Date: Wed, 27 Mar 2013 12:46:05 -0400 Subject: Reorganized to Apache Standard Directory Layout & integrated Moxie This is a massive commit which reorganizes the entire project structure (although it is still monolithic), removes the Build classes, and switches to Moxie, a smarter Ant build tookit based on the original Gitblit Build classes. The Ant build script will likely require additional fine-tuning, but this is big step forward. --- src/test/java/com/gitblit/tests/ActivityTest.java | 34 + .../java/com/gitblit/tests/ArrayUtilsTest.java | 67 + src/test/java/com/gitblit/tests/Base64Test.java | 34 + .../java/com/gitblit/tests/ByteFormatTest.java | 36 + src/test/java/com/gitblit/tests/DiffUtilsTest.java | 129 + .../java/com/gitblit/tests/FanoutServiceTest.java | 172 ++ .../java/com/gitblit/tests/FederationTests.java | 166 ++ src/test/java/com/gitblit/tests/FileUtilsTest.java | 86 + src/test/java/com/gitblit/tests/GitBlitSuite.java | 232 ++ src/test/java/com/gitblit/tests/GitBlitTest.java | 187 ++ .../java/com/gitblit/tests/GitServletTest.java | 775 ++++++ .../java/com/gitblit/tests/GroovyScriptTest.java | 399 +++ src/test/java/com/gitblit/tests/IssuesTest.java | 231 ++ src/test/java/com/gitblit/tests/JGitUtilsTest.java | 472 ++++ src/test/java/com/gitblit/tests/JsonUtilsTest.java | 61 + .../com/gitblit/tests/LdapUserServiceTest.java | 174 ++ .../java/com/gitblit/tests/LuceneExecutorTest.java | 181 ++ src/test/java/com/gitblit/tests/MailTest.java | 41 + .../java/com/gitblit/tests/MarkdownUtilsTest.java | 54 + .../java/com/gitblit/tests/MetricUtilsTest.java | 54 + .../java/com/gitblit/tests/ObjectCacheTest.java | 47 + .../java/com/gitblit/tests/PermissionsTest.java | 2635 ++++++++++++++++++++ src/test/java/com/gitblit/tests/PushLogTest.java | 37 + .../com/gitblit/tests/RedmineUserServiceTest.java | 72 + .../com/gitblit/tests/RepositoryModelTest.java | 96 + src/test/java/com/gitblit/tests/RpcTests.java | 382 +++ .../java/com/gitblit/tests/StringUtilsTest.java | 160 ++ .../com/gitblit/tests/SyndicationUtilsTest.java | 96 + .../java/com/gitblit/tests/TicgitUtilsTest.java | 87 + src/test/java/com/gitblit/tests/TimeUtilsTest.java | 111 + .../java/com/gitblit/tests/UserServiceTest.java | 245 ++ src/test/java/com/gitblit/tests/X509UtilsTest.java | 184 ++ .../com/gitblit/tests/mock/MemorySettings.java | 50 + .../tests/resources/ldapUserServiceSampleData.ldif | 108 + .../java/de/akquinet/devops/GitBlit4UITests.java | 25 + .../de/akquinet/devops/GitBlitServer4UITests.java | 62 + .../java/de/akquinet/devops/GitblitRunnable.java | 134 + .../de/akquinet/devops/LaunchWithUITestConfig.java | 128 + .../de/akquinet/devops/ManualUITestLaunch.java | 15 + .../de/akquinet/devops/test/ui/TestUISuite.java | 33 + .../test/ui/cases/UI_MultiAdminSupportTest.java | 93 + .../devops/test/ui/generic/AbstractUITest.java | 96 + .../java/de/akquinet/devops/test/ui/view/Exp.java | 45 + .../devops/test/ui/view/GitblitDashboardView.java | 100 + .../devops/test/ui/view/GitblitPageView.java | 73 + .../akquinet/devops/test/ui/view/RepoEditView.java | 158 ++ .../akquinet/devops/test/ui/view/RepoListView.java | 130 + 47 files changed, 8987 insertions(+) create mode 100644 src/test/java/com/gitblit/tests/ActivityTest.java create mode 100644 src/test/java/com/gitblit/tests/ArrayUtilsTest.java create mode 100644 src/test/java/com/gitblit/tests/Base64Test.java create mode 100644 src/test/java/com/gitblit/tests/ByteFormatTest.java create mode 100644 src/test/java/com/gitblit/tests/DiffUtilsTest.java create mode 100644 src/test/java/com/gitblit/tests/FanoutServiceTest.java create mode 100644 src/test/java/com/gitblit/tests/FederationTests.java create mode 100644 src/test/java/com/gitblit/tests/FileUtilsTest.java create mode 100644 src/test/java/com/gitblit/tests/GitBlitSuite.java create mode 100644 src/test/java/com/gitblit/tests/GitBlitTest.java create mode 100644 src/test/java/com/gitblit/tests/GitServletTest.java create mode 100644 src/test/java/com/gitblit/tests/GroovyScriptTest.java create mode 100644 src/test/java/com/gitblit/tests/IssuesTest.java create mode 100644 src/test/java/com/gitblit/tests/JGitUtilsTest.java create mode 100644 src/test/java/com/gitblit/tests/JsonUtilsTest.java create mode 100644 src/test/java/com/gitblit/tests/LdapUserServiceTest.java create mode 100644 src/test/java/com/gitblit/tests/LuceneExecutorTest.java create mode 100644 src/test/java/com/gitblit/tests/MailTest.java create mode 100644 src/test/java/com/gitblit/tests/MarkdownUtilsTest.java create mode 100644 src/test/java/com/gitblit/tests/MetricUtilsTest.java create mode 100644 src/test/java/com/gitblit/tests/ObjectCacheTest.java create mode 100644 src/test/java/com/gitblit/tests/PermissionsTest.java create mode 100644 src/test/java/com/gitblit/tests/PushLogTest.java create mode 100644 src/test/java/com/gitblit/tests/RedmineUserServiceTest.java create mode 100644 src/test/java/com/gitblit/tests/RepositoryModelTest.java create mode 100644 src/test/java/com/gitblit/tests/RpcTests.java create mode 100644 src/test/java/com/gitblit/tests/StringUtilsTest.java create mode 100644 src/test/java/com/gitblit/tests/SyndicationUtilsTest.java create mode 100644 src/test/java/com/gitblit/tests/TicgitUtilsTest.java create mode 100644 src/test/java/com/gitblit/tests/TimeUtilsTest.java create mode 100644 src/test/java/com/gitblit/tests/UserServiceTest.java create mode 100644 src/test/java/com/gitblit/tests/X509UtilsTest.java create mode 100644 src/test/java/com/gitblit/tests/mock/MemorySettings.java create mode 100644 src/test/java/com/gitblit/tests/resources/ldapUserServiceSampleData.ldif create mode 100644 src/test/java/de/akquinet/devops/GitBlit4UITests.java create mode 100644 src/test/java/de/akquinet/devops/GitBlitServer4UITests.java create mode 100644 src/test/java/de/akquinet/devops/GitblitRunnable.java create mode 100644 src/test/java/de/akquinet/devops/LaunchWithUITestConfig.java create mode 100644 src/test/java/de/akquinet/devops/ManualUITestLaunch.java create mode 100644 src/test/java/de/akquinet/devops/test/ui/TestUISuite.java create mode 100644 src/test/java/de/akquinet/devops/test/ui/cases/UI_MultiAdminSupportTest.java create mode 100644 src/test/java/de/akquinet/devops/test/ui/generic/AbstractUITest.java create mode 100644 src/test/java/de/akquinet/devops/test/ui/view/Exp.java create mode 100644 src/test/java/de/akquinet/devops/test/ui/view/GitblitDashboardView.java create mode 100644 src/test/java/de/akquinet/devops/test/ui/view/GitblitPageView.java create mode 100644 src/test/java/de/akquinet/devops/test/ui/view/RepoEditView.java create mode 100644 src/test/java/de/akquinet/devops/test/ui/view/RepoListView.java (limited to 'src/test/java') diff --git a/src/test/java/com/gitblit/tests/ActivityTest.java b/src/test/java/com/gitblit/tests/ActivityTest.java new file mode 100644 index 00000000..22713260 --- /dev/null +++ b/src/test/java/com/gitblit/tests/ActivityTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2011 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; + +import org.junit.Test; + +import com.gitblit.models.GravatarProfile; +import com.gitblit.utils.ActivityUtils; + +public class ActivityTest { + + @Test + public void testGravatarProfile() throws IOException { + GravatarProfile profile = ActivityUtils.getGravatarProfile("beau@dentedreality.com.au"); + assertEquals("beau", profile.preferredUsername); + } +} \ No newline at end of file diff --git a/src/test/java/com/gitblit/tests/ArrayUtilsTest.java b/src/test/java/com/gitblit/tests/ArrayUtilsTest.java new file mode 100644 index 00000000..8a38afbb --- /dev/null +++ b/src/test/java/com/gitblit/tests/ArrayUtilsTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2012 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.junit.Test; + +import com.gitblit.utils.ArrayUtils; + +public class ArrayUtilsTest { + + @Test + public void testArrays() { + Object [] nullArray = null; + assertTrue(ArrayUtils.isEmpty(nullArray)); + + Object [] emptyArray = new Object[0]; + assertTrue(ArrayUtils.isEmpty(emptyArray)); + + assertFalse(ArrayUtils.isEmpty(new String [] { "" })); + } + + @Test + public void testLists() { + List nullList = null; + assertTrue(ArrayUtils.isEmpty(nullList)); + + List emptyList = new ArrayList(); + assertTrue(ArrayUtils.isEmpty(emptyList)); + + List list = Arrays.asList(""); + assertFalse(ArrayUtils.isEmpty(list)); + } + + @Test + public void testSets() { + Set nullSet = null; + assertTrue(ArrayUtils.isEmpty(nullSet)); + + Set emptySet = new HashSet(); + assertTrue(ArrayUtils.isEmpty(emptySet)); + + Set set = new HashSet(Arrays.asList("")); + assertFalse(ArrayUtils.isEmpty(set)); + } +} \ No newline at end of file diff --git a/src/test/java/com/gitblit/tests/Base64Test.java b/src/test/java/com/gitblit/tests/Base64Test.java new file mode 100644 index 00000000..2962c36f --- /dev/null +++ b/src/test/java/com/gitblit/tests/Base64Test.java @@ -0,0 +1,34 @@ +/* + * Copyright 2011 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.gitblit.utils.Base64; + +public class Base64Test { + + @Test + public void testBase64() { + String source = "this is a test"; + String base64 = Base64.encodeBytes(source.getBytes()); + assertEquals("dGhpcyBpcyBhIHRlc3Q=", base64); + String decoded = new String(Base64.decode(base64)); + assertEquals(source, decoded); + } +} \ No newline at end of file diff --git a/src/test/java/com/gitblit/tests/ByteFormatTest.java b/src/test/java/com/gitblit/tests/ByteFormatTest.java new file mode 100644 index 00000000..d59055e7 --- /dev/null +++ b/src/test/java/com/gitblit/tests/ByteFormatTest.java @@ -0,0 +1,36 @@ +/* + * Copyright 2011 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.gitblit.utils.ByteFormat; + +public class ByteFormatTest { + + @Test + public void testByteFormat() throws Exception { + ByteFormat format = new ByteFormat(); + assertEquals("10 b", format.format(10)); + assertEquals("10 KB", format.format(1024 * 10)); + assertEquals("1,000 KB", format.format(1024 * 1000)); + assertEquals("2.0 MB", format.format(2 * 1024 * 1000)); + assertEquals("1,000.0 MB", format.format(1024 * 1024 * 1000)); + assertEquals("2.0 GB", format.format(2 * 1024 * 1024 * 1000)); + } +} diff --git a/src/test/java/com/gitblit/tests/DiffUtilsTest.java b/src/test/java/com/gitblit/tests/DiffUtilsTest.java new file mode 100644 index 00000000..53eff313 --- /dev/null +++ b/src/test/java/com/gitblit/tests/DiffUtilsTest.java @@ -0,0 +1,129 @@ +/* + * Copyright 2011 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.junit.Test; + +import com.gitblit.models.AnnotatedLine; +import com.gitblit.utils.DiffUtils; +import com.gitblit.utils.DiffUtils.DiffOutputType; +import com.gitblit.utils.JGitUtils; + +public class DiffUtilsTest { + + @Test + public void testDiffOutputTypes() throws Exception { + assertEquals(DiffOutputType.PLAIN, DiffOutputType.forName("plain")); + assertEquals(DiffOutputType.GITWEB, DiffOutputType.forName("gitweb")); + assertEquals(DiffOutputType.GITBLIT, DiffOutputType.forName("gitblit")); + assertEquals(null, DiffOutputType.forName(null)); + } + + @Test + public void testParentCommitDiff() throws Exception { + Repository repository = GitBlitSuite.getHelloworldRepository(); + RevCommit commit = JGitUtils.getCommit(repository, + "1d0c2933a4ae69c362f76797d42d6bd182d05176"); + String diff = DiffUtils.getCommitDiff(repository, commit, DiffOutputType.PLAIN); + repository.close(); + assertTrue(diff != null && diff.length() > 0); + String expected = "- system.out.println(\"Hello World\");\n+ System.out.println(\"Hello World\""; + assertTrue(diff.indexOf(expected) > -1); + } + + @Test + public void testArbitraryCommitDiff() throws Exception { + Repository repository = GitBlitSuite.getHelloworldRepository(); + RevCommit baseCommit = JGitUtils.getCommit(repository, + "8baf6a833b5579384d9b9ceb8a16b5d0ea2ec4ca"); + RevCommit commit = JGitUtils.getCommit(repository, + "1d0c2933a4ae69c362f76797d42d6bd182d05176"); + String diff = DiffUtils.getDiff(repository, baseCommit, commit, DiffOutputType.PLAIN); + repository.close(); + assertTrue(diff != null && diff.length() > 0); + String expected = "- system.out.println(\"Hello World\");\n+ System.out.println(\"Hello World\""; + assertTrue(diff.indexOf(expected) > -1); + } + + @Test + public void testPlainFileDiff() throws Exception { + Repository repository = GitBlitSuite.getHelloworldRepository(); + RevCommit commit = JGitUtils.getCommit(repository, + "1d0c2933a4ae69c362f76797d42d6bd182d05176"); + String diff = DiffUtils.getDiff(repository, commit, "java.java", DiffOutputType.PLAIN); + repository.close(); + assertTrue(diff != null && diff.length() > 0); + String expected = "- system.out.println(\"Hello World\");\n+ System.out.println(\"Hello World\""; + assertTrue(diff.indexOf(expected) > -1); + } + + @Test + public void testFilePatch() throws Exception { + Repository repository = GitBlitSuite.getHelloworldRepository(); + RevCommit commit = JGitUtils.getCommit(repository, + "1d0c2933a4ae69c362f76797d42d6bd182d05176"); + String patch = DiffUtils.getCommitPatch(repository, null, commit, "java.java"); + repository.close(); + assertTrue(patch != null && patch.length() > 0); + String expected = "- system.out.println(\"Hello World\");\n+ System.out.println(\"Hello World\""; + assertTrue(patch.indexOf(expected) > -1); + } + + @Test + public void testArbitraryFilePatch() throws Exception { + Repository repository = GitBlitSuite.getHelloworldRepository(); + RevCommit baseCommit = JGitUtils.getCommit(repository, + "8baf6a833b5579384d9b9ceb8a16b5d0ea2ec4ca"); + RevCommit commit = JGitUtils.getCommit(repository, + "1d0c2933a4ae69c362f76797d42d6bd182d05176"); + String patch = DiffUtils.getCommitPatch(repository, baseCommit, commit, "java.java"); + repository.close(); + assertTrue(patch != null && patch.length() > 0); + String expected = "- system.out.println(\"Hello World\");\n+ System.out.println(\"Hello World\""; + assertTrue(patch.indexOf(expected) > -1); + } + + @Test + public void testArbitraryCommitPatch() throws Exception { + Repository repository = GitBlitSuite.getHelloworldRepository(); + RevCommit baseCommit = JGitUtils.getCommit(repository, + "8baf6a833b5579384d9b9ceb8a16b5d0ea2ec4ca"); + RevCommit commit = JGitUtils.getCommit(repository, + "1d0c2933a4ae69c362f76797d42d6bd182d05176"); + String patch = DiffUtils.getCommitPatch(repository, baseCommit, commit, null); + repository.close(); + assertTrue(patch != null && patch.length() > 0); + String expected = "- system.out.println(\"Hello World\");\n+ System.out.println(\"Hello World\""; + assertTrue(patch.indexOf(expected) > -1); + } + + @Test + public void testBlame() throws Exception { + Repository repository = GitBlitSuite.getHelloworldRepository(); + List lines = DiffUtils.blame(repository, "java.java", + "1d0c2933a4ae69c362f76797d42d6bd182d05176"); + repository.close(); + assertTrue(lines.size() > 0); + assertEquals("c6d31dccf5cc75e8e46299fc62d38f60ec6d41e0", lines.get(0).commitId); + } +} diff --git a/src/test/java/com/gitblit/tests/FanoutServiceTest.java b/src/test/java/com/gitblit/tests/FanoutServiceTest.java new file mode 100644 index 00000000..28e5d82d --- /dev/null +++ b/src/test/java/com/gitblit/tests/FanoutServiceTest.java @@ -0,0 +1,172 @@ +/* + * Copyright 2013 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; + +import java.text.MessageFormat; +import java.util.Date; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.Test; + +import com.gitblit.fanout.FanoutService; +import com.gitblit.fanout.FanoutClient; +import com.gitblit.fanout.FanoutClient.FanoutAdapter; +import com.gitblit.fanout.FanoutNioService; +import com.gitblit.fanout.FanoutService; +import com.gitblit.fanout.FanoutSocketService; + +public class FanoutServiceTest { + + int fanoutPort = FanoutService.DEFAULT_PORT; + + @Test + public void testNioPubSub() throws Exception { + testPubSub(new FanoutNioService(fanoutPort)); + } + + @Test + public void testSocketPubSub() throws Exception { + testPubSub(new FanoutSocketService(fanoutPort)); + } + + @Test + public void testNioDisruptionAndRecovery() throws Exception { + testDisruption(new FanoutNioService(fanoutPort)); + } + + @Test + public void testSocketDisruptionAndRecovery() throws Exception { + testDisruption(new FanoutSocketService(fanoutPort)); + } + + protected void testPubSub(FanoutService service) throws Exception { + System.out.println(MessageFormat.format("\n\n========================================\nPUBSUB TEST {0}\n========================================\n\n", service.toString())); + service.startSynchronously(); + + final Map announcementsA = new ConcurrentHashMap(); + FanoutClient clientA = new FanoutClient("localhost", fanoutPort); + clientA.addListener(new FanoutAdapter() { + + @Override + public void announcement(String channel, String message) { + announcementsA.put(channel, message); + } + }); + + clientA.startSynchronously(); + + final Map announcementsB = new ConcurrentHashMap(); + FanoutClient clientB = new FanoutClient("localhost", fanoutPort); + clientB.addListener(new FanoutAdapter() { + @Override + public void announcement(String channel, String message) { + announcementsB.put(channel, message); + } + }); + clientB.startSynchronously(); + + + // subscribe clients A and B to the channels + clientA.subscribe("a"); + clientA.subscribe("b"); + clientA.subscribe("c"); + + clientB.subscribe("a"); + clientB.subscribe("b"); + clientB.subscribe("c"); + + // give async messages a chance to be delivered + Thread.sleep(1000); + + clientA.announce("a", "apple"); + clientA.announce("b", "banana"); + clientA.announce("c", "cantelope"); + + clientB.announce("a", "avocado"); + clientB.announce("b", "beet"); + clientB.announce("c", "carrot"); + + // give async messages a chance to be delivered + Thread.sleep(2000); + + // confirm that client B received client A's announcements + assertEquals("apple", announcementsB.get("a")); + assertEquals("banana", announcementsB.get("b")); + assertEquals("cantelope", announcementsB.get("c")); + + // confirm that client A received client B's announcements + assertEquals("avocado", announcementsA.get("a")); + assertEquals("beet", announcementsA.get("b")); + assertEquals("carrot", announcementsA.get("c")); + + clientA.stop(); + clientB.stop(); + service.stop(); + } + + protected void testDisruption(FanoutService service) throws Exception { + System.out.println(MessageFormat.format("\n\n========================================\nDISRUPTION TEST {0}\n========================================\n\n", service.toString())); + service.startSynchronously(); + + final AtomicInteger pongCount = new AtomicInteger(0); + FanoutClient client = new FanoutClient("localhost", fanoutPort); + client.addListener(new FanoutAdapter() { + @Override + public void pong(Date timestamp) { + pongCount.incrementAndGet(); + } + }); + client.startSynchronously(); + + // ping and wait for pong + client.ping(); + Thread.sleep(500); + + // restart client + client.stop(); + Thread.sleep(1000); + client.startSynchronously(); + + // ping and wait for pong + client.ping(); + Thread.sleep(500); + + assertEquals(2, pongCount.get()); + + // now disrupt service + service.stop(); + Thread.sleep(2000); + service.startSynchronously(); + + // wait for reconnect + Thread.sleep(2000); + + // ping and wait for pong + client.ping(); + Thread.sleep(500); + + // kill all + client.stop(); + service.stop(); + + // confirm expected pong count + assertEquals(3, pongCount.get()); + } +} \ No newline at end of file diff --git a/src/test/java/com/gitblit/tests/FederationTests.java b/src/test/java/com/gitblit/tests/FederationTests.java new file mode 100644 index 00000000..ced500a5 --- /dev/null +++ b/src/test/java/com/gitblit/tests/FederationTests.java @@ -0,0 +1,166 @@ +/* + * Copyright 2011 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.gitblit.Constants.AccessRestrictionType; +import com.gitblit.Constants.FederationProposalResult; +import com.gitblit.Constants.FederationRequest; +import com.gitblit.Constants.FederationToken; +import com.gitblit.models.FederationModel; +import com.gitblit.models.FederationProposal; +import com.gitblit.models.RepositoryModel; +import com.gitblit.models.TeamModel; +import com.gitblit.models.UserModel; +import com.gitblit.utils.FederationUtils; +import com.gitblit.utils.JsonUtils; +import com.gitblit.utils.RpcUtils; + +public class FederationTests { + + String url = GitBlitSuite.url; + String account = GitBlitSuite.account; + String password = GitBlitSuite.password; + String token = "d7cc58921a80b37e0329a4dae2f9af38bf61ef5c"; + + private static final AtomicBoolean started = new AtomicBoolean(false); + + @BeforeClass + public static void startGitblit() throws Exception { + started.set(GitBlitSuite.startGitblit()); + } + + @AfterClass + public static void stopGitblit() throws Exception { + if (started.get()) { + GitBlitSuite.stopGitblit(); + } + } + + @Test + public void testProposal() throws Exception { + // create dummy repository data + Map repositories = new HashMap(); + for (int i = 0; i < 5; i++) { + RepositoryModel model = new RepositoryModel(); + model.accessRestriction = AccessRestrictionType.VIEW; + model.description = "cloneable repository " + i; + model.lastChange = new Date(); + model.addOwner("adminuser"); + model.name = "repo" + i + ".git"; + model.size = "5 MB"; + model.hasCommits = true; + repositories.put(model.name, model); + } + + FederationProposal proposal = new FederationProposal("http://testurl", FederationToken.ALL, + "testtoken", repositories); + + // propose federation + assertEquals("proposal refused", FederationUtils.propose(url, proposal), + FederationProposalResult.NO_PROPOSALS); + } + + @Test + public void testJsonRepositories() throws Exception { + String requrl = FederationUtils.asLink(url, token, FederationRequest.PULL_REPOSITORIES); + String json = JsonUtils.retrieveJsonString(requrl, null, null); + assertNotNull(json); + } + + @Test + public void testJsonUsers() throws Exception { + String requrl = FederationUtils.asLink(url, token, FederationRequest.PULL_USERS); + String json = JsonUtils.retrieveJsonString(requrl, null, null); + assertNotNull(json); + } + + @Test + public void testJsonTeams() throws Exception { + String requrl = FederationUtils.asLink(url, token, FederationRequest.PULL_TEAMS); + String json = JsonUtils.retrieveJsonString(requrl, null, null); + assertNotNull(json); + } + + private FederationModel getRegistration() { + FederationModel model = new FederationModel("localhost"); + model.url = this.url; + model.token = this.token; + return model; + } + + @Test + public void testPullRepositories() throws Exception { + Map repos = FederationUtils.getRepositories(getRegistration(), + false); + assertNotNull(repos); + assertTrue(repos.size() > 0); + } + + @Test + public void testPullUsers() throws Exception { + List users = FederationUtils.getUsers(getRegistration()); + assertNotNull(users); + // admin is excluded + assertEquals(0, users.size()); + + UserModel newUser = new UserModel("test"); + newUser.password = "whocares"; + assertTrue(RpcUtils.createUser(newUser, url, account, password.toCharArray())); + + TeamModel team = new TeamModel("testteam"); + team.addUser("test"); + team.addRepositoryPermission("helloworld.git"); + assertTrue(RpcUtils.createTeam(team, url, account, password.toCharArray())); + + users = FederationUtils.getUsers(getRegistration()); + assertNotNull(users); + assertEquals(1, users.size()); + + newUser = users.get(0); + assertTrue(newUser.isTeamMember("testteam")); + + assertTrue(RpcUtils.deleteUser(newUser, url, account, password.toCharArray())); + assertTrue(RpcUtils.deleteTeam(team, url, account, password.toCharArray())); + } + + @Test + public void testPullTeams() throws Exception { + List teams = FederationUtils.getTeams(getRegistration()); + assertNotNull(teams); + assertTrue(teams.size() > 0); + } + + @Test + public void testPullScripts() throws Exception { + Map scripts = FederationUtils.getScripts(getRegistration()); + assertNotNull(scripts); + assertTrue(scripts.keySet().contains("sendmail")); + } +} diff --git a/src/test/java/com/gitblit/tests/FileUtilsTest.java b/src/test/java/com/gitblit/tests/FileUtilsTest.java new file mode 100644 index 00000000..8e5cf8a6 --- /dev/null +++ b/src/test/java/com/gitblit/tests/FileUtilsTest.java @@ -0,0 +1,86 @@ +/* + * Copyright 2011 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; + +import org.junit.Test; + +import com.gitblit.utils.FileUtils; + +public class FileUtilsTest { + + @Test + public void testReadContent() throws Exception { + File dir = new File(System.getProperty("user.dir")); + String rawContent = FileUtils.readContent(new File(dir, "LICENSE"), "\n"); + assertTrue(rawContent.trim().startsWith("Apache License")); + } + + @Test + public void testWriteContent() throws Exception { + String contentA = "this is a test"; + File tmp = File.createTempFile("gitblit-", ".test"); + FileUtils.writeContent(tmp, contentA); + String contentB = FileUtils.readContent(tmp, "\n").trim(); + assertEquals(contentA, contentB); + } + + @Test + public void testFolderSize() throws Exception { + assertEquals(-1, FileUtils.folderSize(null)); + assertEquals(-1, FileUtils.folderSize(new File(System.getProperty("user.dir"), "pretend"))); + + File dir = new File(System.getProperty("user.dir"), "distrib"); + long size = FileUtils.folderSize(dir); + assertTrue("size is actually " + size, size >= 470000L); + + File file = new File(System.getProperty("user.dir"), "LICENSE"); + size = FileUtils.folderSize(file); + assertEquals("size is actually " + size, 11556L, size); + } + + @Test + public void testStringSizes() throws Exception { + assertEquals(50 * FileUtils.KB, FileUtils.convertSizeToInt("50k", 0)); + assertEquals(50 * FileUtils.MB, FileUtils.convertSizeToInt("50m", 0)); + assertEquals(2 * FileUtils.GB, FileUtils.convertSizeToInt("2g", 0)); + + assertEquals(50 * FileUtils.KB, FileUtils.convertSizeToInt("50kb", 0)); + assertEquals(50 * FileUtils.MB, FileUtils.convertSizeToInt("50mb", 0)); + assertEquals(2 * FileUtils.GB, FileUtils.convertSizeToInt("2gb", 0)); + + assertEquals(50L * FileUtils.KB, FileUtils.convertSizeToLong("50k", 0)); + assertEquals(50L * FileUtils.MB, FileUtils.convertSizeToLong("50m", 0)); + assertEquals(50L * FileUtils.GB, FileUtils.convertSizeToLong("50g", 0)); + + assertEquals(50L * FileUtils.KB, FileUtils.convertSizeToLong("50kb", 0)); + assertEquals(50L * FileUtils.MB, FileUtils.convertSizeToLong("50mb", 0)); + assertEquals(50L * FileUtils.GB, FileUtils.convertSizeToLong("50gb", 0)); + + assertEquals(50 * FileUtils.KB, FileUtils.convertSizeToInt("50 k", 0)); + assertEquals(50 * FileUtils.MB, FileUtils.convertSizeToInt("50 m", 0)); + assertEquals(2 * FileUtils.GB, FileUtils.convertSizeToInt("2 g", 0)); + + assertEquals(50 * FileUtils.KB, FileUtils.convertSizeToInt("50 kb", 0)); + assertEquals(50 * FileUtils.MB, FileUtils.convertSizeToInt("50 mb", 0)); + assertEquals(2 * FileUtils.GB, FileUtils.convertSizeToInt("2 gb", 0)); + + } +} \ No newline at end of file diff --git a/src/test/java/com/gitblit/tests/GitBlitSuite.java b/src/test/java/com/gitblit/tests/GitBlitSuite.java new file mode 100644 index 00000000..b0179c37 --- /dev/null +++ b/src/test/java/com/gitblit/tests/GitBlitSuite.java @@ -0,0 +1,232 @@ +/* + * Copyright 2011 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import java.io.File; +import java.lang.reflect.Field; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.RepositoryCache; +import org.eclipse.jgit.lib.RepositoryCache.FileKey; +import org.eclipse.jgit.storage.file.FileRepository; +import org.eclipse.jgit.util.FS; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +import com.gitblit.GitBlit; +import com.gitblit.GitBlitException; +import com.gitblit.GitBlitServer; +import com.gitblit.models.RepositoryModel; +import com.gitblit.utils.JGitUtils; + +/** + * The GitBlitSuite uses test-gitblit.properties and test-users.conf. The suite + * is fairly comprehensive for all lower-level functionality. Wicket pages are + * currently not unit-tested. + * + * This suite starts a Gitblit server instance within the same JVM instance as + * the unit tests. This allows the unit tests to access the GitBlit static + * singleton while also being able to communicate with the instance via tcp/ip + * for testing rpc requests, federation requests, and git servlet operations. + * + * @author James Moger + * + */ +@RunWith(Suite.class) +@SuiteClasses({ ArrayUtilsTest.class, FileUtilsTest.class, TimeUtilsTest.class, + StringUtilsTest.class, Base64Test.class, JsonUtilsTest.class, ByteFormatTest.class, + ObjectCacheTest.class, PermissionsTest.class, UserServiceTest.class, LdapUserServiceTest.class, + MarkdownUtilsTest.class, JGitUtilsTest.class, SyndicationUtilsTest.class, + DiffUtilsTest.class, MetricUtilsTest.class, TicgitUtilsTest.class, X509UtilsTest.class, + GitBlitTest.class, FederationTests.class, RpcTests.class, GitServletTest.class, + GroovyScriptTest.class, LuceneExecutorTest.class, IssuesTest.class, RepositoryModelTest.class, + FanoutServiceTest.class }) +public class GitBlitSuite { + + public static final File REPOSITORIES = new File("data/git"); + + static int port = 8280; + static int shutdownPort = 8281; + + public static String url = "http://localhost:" + port; + public static String account = "admin"; + public static String password = "admin"; + + private static AtomicBoolean started = new AtomicBoolean(false); + + public static Repository getHelloworldRepository() throws Exception { + return new FileRepository(new File(REPOSITORIES, "helloworld.git")); + } + + public static Repository getTicgitRepository() throws Exception { + return new FileRepository(new File(REPOSITORIES, "ticgit.git")); + } + + public static Repository getJGitRepository() throws Exception { + return new FileRepository(new File(REPOSITORIES, "test/jgit.git")); + } + + public static Repository getAmbitionRepository() throws Exception { + return new FileRepository(new File(REPOSITORIES, "test/ambition.git")); + } + + public static Repository getTheoreticalPhysicsRepository() throws Exception { + return new FileRepository(new File(REPOSITORIES, "test/theoretical-physics.git")); + } + + public static Repository getIssuesTestRepository() throws Exception { + JGitUtils.createRepository(REPOSITORIES, "gb-issues.git").close(); + return new FileRepository(new File(REPOSITORIES, "gb-issues.git")); + } + + public static Repository getGitectiveRepository() throws Exception { + return new FileRepository(new File(REPOSITORIES, "test/gitective.git")); + } + + public static boolean startGitblit() throws Exception { + if (started.get()) { + // already started + return false; + } + + GitServletTest.deleteWorkingFolders(); + + // Start a Gitblit instance + Executors.newSingleThreadExecutor().execute(new Runnable() { + public void run() { + GitBlitServer.main("--httpPort", "" + port, "--httpsPort", "0", "--shutdownPort", + "" + shutdownPort, "--repositoriesFolder", + "\"" + GitBlitSuite.REPOSITORIES.getAbsolutePath() + "\"", "--userService", + "test-users.conf", "--settings", "test-gitblit.properties", + "--baseFolder", "data"); + } + }); + + // Wait a few seconds for it to be running + Thread.sleep(2500); + + started.set(true); + return true; + } + + public static void stopGitblit() throws Exception { + // Stop Gitblit + GitBlitServer.main("--stop", "--shutdownPort", "" + shutdownPort); + + // Wait a few seconds for it to be running + Thread.sleep(5000); + } + + @BeforeClass + public static void setUp() throws Exception { + startGitblit(); + + if (REPOSITORIES.exists() || REPOSITORIES.mkdirs()) { + cloneOrFetch("helloworld.git", "https://github.com/git/hello-world.git"); + cloneOrFetch("ticgit.git", "https://github.com/schacon/ticgit.git"); + cloneOrFetch("test/jgit.git", "https://github.com/eclipse/jgit.git"); + cloneOrFetch("test/helloworld.git", "https://github.com/git/hello-world.git"); + cloneOrFetch("test/ambition.git", "https://github.com/defunkt/ambition.git"); + cloneOrFetch("test/theoretical-physics.git", "https://github.com/certik/theoretical-physics.git"); + cloneOrFetch("test/gitective.git", "https://github.com/kevinsawicki/gitective.git"); + + enableTickets("ticgit.git"); + enableDocs("ticgit.git"); + showRemoteBranches("ticgit.git"); + showRemoteBranches("test/jgit.git"); + } + } + + @AfterClass + public static void tearDown() throws Exception { + stopGitblit(); + } + + private static void cloneOrFetch(String name, String fromUrl) throws Exception { + System.out.print("Fetching " + name + "... "); + JGitUtils.cloneRepository(REPOSITORIES, name, fromUrl); + System.out.println("done."); + } + + private static void enableTickets(String repositoryName) { + try { + RepositoryModel model = GitBlit.self().getRepositoryModel(repositoryName); + model.useTickets = true; + GitBlit.self().updateRepositoryModel(model.name, model, false); + } catch (GitBlitException g) { + g.printStackTrace(); + } + } + + private static void enableDocs(String repositoryName) { + try { + RepositoryModel model = GitBlit.self().getRepositoryModel(repositoryName); + model.useDocs = true; + GitBlit.self().updateRepositoryModel(model.name, model, false); + } catch (GitBlitException g) { + g.printStackTrace(); + } + } + + private static void showRemoteBranches(String repositoryName) { + try { + RepositoryModel model = GitBlit.self().getRepositoryModel(repositoryName); + model.showRemoteBranches = true; + GitBlit.self().updateRepositoryModel(model.name, model, false); + } catch (GitBlitException g) { + g.printStackTrace(); + } + } + + public static void close(File repository) { + try { + File gitDir = FileKey.resolve(repository, FS.detect()); + if (gitDir != null && gitDir.exists()) { + close(RepositoryCache.open(FileKey.exact(gitDir, FS.detect()))); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static void close(Git git) { + close(git.getRepository()); + } + + public static void close(Repository r) { + RepositoryCache.close(r); + + // assume 2 uses in case reflection fails + int uses = 2; + try { + Field useCnt = Repository.class.getDeclaredField("useCnt"); + useCnt.setAccessible(true); + uses = ((AtomicInteger) useCnt.get(r)).get(); + } catch (Exception e) { + e.printStackTrace(); + } + for (int i = 0; i < uses; i++) { + r.close(); + } + } +} diff --git a/src/test/java/com/gitblit/tests/GitBlitTest.java b/src/test/java/com/gitblit/tests/GitBlitTest.java new file mode 100644 index 00000000..786614f8 --- /dev/null +++ b/src/test/java/com/gitblit/tests/GitBlitTest.java @@ -0,0 +1,187 @@ +/* + * Copyright 2011 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; + +import com.gitblit.Constants.AccessRestrictionType; +import com.gitblit.FileSettings; +import com.gitblit.GitBlit; +import com.gitblit.models.RepositoryModel; +import com.gitblit.models.UserModel; + +public class GitBlitTest { + + @Test + public void testRepositoryModel() throws Exception { + List repositories = GitBlit.self().getRepositoryList(); + assertTrue("Repository list is empty!", repositories.size() > 0); + assertTrue( + "Missing Helloworld repository!", + repositories.contains(GitBlitSuite.getHelloworldRepository().getDirectory() + .getName())); + RepositoryModel model = GitBlit.self().getRepositoryModel( + GitBlitSuite.getHelloworldRepository().getDirectory().getName()); + assertTrue("Helloworld model is null!", model != null); + assertEquals(GitBlitSuite.getHelloworldRepository().getDirectory().getName(), model.name); + assertTrue(GitBlit.self().calculateSize(model) > 22000L); + } + + @Test + public void testUserModel() throws Exception { + List users = GitBlit.self().getAllUsernames(); + assertTrue("No users found!", users.size() > 0); + assertTrue("Admin not found", users.contains("admin")); + UserModel user = GitBlit.self().getUserModel("admin"); + assertEquals("admin", user.toString()); + assertTrue("Admin missing #admin role!", user.canAdmin); + user.canAdmin = false; + assertFalse("Admin should not have #admin!", user.canAdmin); + String repository = GitBlitSuite.getHelloworldRepository().getDirectory().getName(); + RepositoryModel repositoryModel = GitBlit.self().getRepositoryModel(repository); + repositoryModel.accessRestriction = AccessRestrictionType.VIEW; + assertFalse("Admin can still access repository!", + user.canView(repositoryModel)); + user.addRepositoryPermission(repository); + assertTrue("Admin can't access repository!", user.canView(repositoryModel)); + assertEquals(GitBlit.self().getRepositoryModel(user, "pretend"), null); + assertNotNull(GitBlit.self().getRepositoryModel(user, repository)); + assertTrue(GitBlit.self().getRepositoryModels(user).size() > 0); + } + + @Test + public void testUserModelVerification() throws Exception { + UserModel user = new UserModel("james"); + user.displayName = "James Moger"; + + assertTrue(user.is("James", null)); + assertTrue(user.is("James", "")); + assertTrue(user.is("JaMeS", "anything")); + + assertTrue(user.is("james moger", null)); + assertTrue(user.is("james moger", "")); + assertTrue(user.is("james moger", "anything")); + + assertFalse(user.is("joe", null)); + assertFalse(user.is("joe", "")); + assertFalse(user.is("joe", "anything")); + + // specify email address which results in address verification + user.emailAddress = "something"; + + assertFalse(user.is("James", null)); + assertFalse(user.is("James", "")); + assertFalse(user.is("JaMeS", "anything")); + + assertFalse(user.is("james moger", null)); + assertFalse(user.is("james moger", "")); + assertFalse(user.is("james moger", "anything")); + + assertTrue(user.is("JaMeS", user.emailAddress)); + assertTrue(user.is("JaMeS mOgEr", user.emailAddress)); + } + + @Test + public void testAccessRestrictionTypes() throws Exception { + assertTrue(AccessRestrictionType.PUSH.exceeds(AccessRestrictionType.NONE)); + assertTrue(AccessRestrictionType.CLONE.exceeds(AccessRestrictionType.PUSH)); + assertTrue(AccessRestrictionType.VIEW.exceeds(AccessRestrictionType.CLONE)); + + assertFalse(AccessRestrictionType.NONE.exceeds(AccessRestrictionType.PUSH)); + assertFalse(AccessRestrictionType.PUSH.exceeds(AccessRestrictionType.CLONE)); + assertFalse(AccessRestrictionType.CLONE.exceeds(AccessRestrictionType.VIEW)); + + assertTrue(AccessRestrictionType.PUSH.atLeast(AccessRestrictionType.NONE)); + assertTrue(AccessRestrictionType.CLONE.atLeast(AccessRestrictionType.PUSH)); + assertTrue(AccessRestrictionType.VIEW.atLeast(AccessRestrictionType.CLONE)); + + assertFalse(AccessRestrictionType.NONE.atLeast(AccessRestrictionType.PUSH)); + assertFalse(AccessRestrictionType.PUSH.atLeast(AccessRestrictionType.CLONE)); + assertFalse(AccessRestrictionType.CLONE.atLeast(AccessRestrictionType.VIEW)); + + assertTrue(AccessRestrictionType.PUSH.toString().equals("PUSH")); + assertTrue(AccessRestrictionType.CLONE.toString().equals("CLONE")); + assertTrue(AccessRestrictionType.VIEW.toString().equals("VIEW")); + + assertEquals(AccessRestrictionType.NONE, AccessRestrictionType.fromName("none")); + assertEquals(AccessRestrictionType.PUSH, AccessRestrictionType.fromName("push")); + assertEquals(AccessRestrictionType.CLONE, AccessRestrictionType.fromName("clone")); + assertEquals(AccessRestrictionType.VIEW, AccessRestrictionType.fromName("view")); + } + + @Test + public void testFileSettings() throws Exception { + FileSettings settings = new FileSettings("distrib/gitblit.properties"); + assertEquals(true, settings.getBoolean("missing", true)); + assertEquals("default", settings.getString("missing", "default")); + assertEquals(10, settings.getInteger("missing", 10)); + assertEquals(5, settings.getInteger("realm.realmFile", 5)); + + assertTrue(settings.getBoolean("git.enableGitServlet", false)); + assertEquals("${baseFolder}/users.conf", settings.getString("realm.userService", null)); + assertEquals(5, settings.getInteger("realm.minPasswordLength", 0)); + List mdExtensions = settings.getStrings("web.markdownExtensions"); + assertTrue(mdExtensions.size() > 0); + assertTrue(mdExtensions.contains("md")); + + List keys = settings.getAllKeys("server"); + assertTrue(keys.size() > 0); + assertTrue(keys.contains("server.httpsPort")); + + assertTrue(settings.getChar("web.forwardSlashCharacter", ' ') == '/'); + } + + @Test + public void testGitblitSettings() throws Exception { + // These are already tested by above test method. + assertTrue(GitBlit.getBoolean("missing", true)); + assertEquals("default", GitBlit.getString("missing", "default")); + assertEquals(10, GitBlit.getInteger("missing", 10)); + assertEquals(5, GitBlit.getInteger("realm.userService", 5)); + + assertTrue(GitBlit.getBoolean("git.enableGitServlet", false)); + assertEquals("test-users.conf", GitBlit.getString("realm.userService", null)); + assertEquals(5, GitBlit.getInteger("realm.minPasswordLength", 0)); + List mdExtensions = GitBlit.getStrings("web.markdownExtensions"); + assertTrue(mdExtensions.size() > 0); + assertTrue(mdExtensions.contains("md")); + + List keys = GitBlit.getAllKeys("server"); + assertTrue(keys.size() > 0); + assertTrue(keys.contains("server.httpsPort")); + + assertTrue(GitBlit.getChar("web.forwardSlashCharacter", ' ') == '/'); + assertFalse(GitBlit.isDebugMode()); + } + + @Test + public void testAuthentication() throws Exception { + assertTrue(GitBlit.self().authenticate("admin", "admin".toCharArray()) != null); + } + + @Test + public void testRepositories() throws Exception { + assertTrue(GitBlit.self().getRepository("missing") == null); + assertTrue(GitBlit.self().getRepositoryModel("missing") == null); + } +} diff --git a/src/test/java/com/gitblit/tests/GitServletTest.java b/src/test/java/com/gitblit/tests/GitServletTest.java new file mode 100644 index 00000000..a05b3650 --- /dev/null +++ b/src/test/java/com/gitblit/tests/GitServletTest.java @@ -0,0 +1,775 @@ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.text.MessageFormat; +import java.util.Date; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.eclipse.jgit.api.CloneCommand; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.ResetCommand.ResetType; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.storage.file.FileRepository; +import org.eclipse.jgit.transport.CredentialsProvider; +import org.eclipse.jgit.transport.PushResult; +import org.eclipse.jgit.transport.RefSpec; +import org.eclipse.jgit.transport.RemoteRefUpdate; +import org.eclipse.jgit.transport.RemoteRefUpdate.Status; +import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; +import org.eclipse.jgit.util.FileUtils; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.gitblit.Constants.AccessPermission; +import com.gitblit.Constants.AccessRestrictionType; +import com.gitblit.Constants.AuthorizationControl; +import com.gitblit.GitBlit; +import com.gitblit.Keys; +import com.gitblit.models.PushLogEntry; +import com.gitblit.models.RepositoryModel; +import com.gitblit.models.UserModel; +import com.gitblit.utils.ArrayUtils; +import com.gitblit.utils.JGitUtils; +import com.gitblit.utils.PushLogUtils; + +public class GitServletTest { + + static File ticgitFolder = new File(GitBlitSuite.REPOSITORIES, "working/ticgit"); + + static File ticgit2Folder = new File(GitBlitSuite.REPOSITORIES, "working/ticgit2"); + + static File jgitFolder = new File(GitBlitSuite.REPOSITORIES, "working/jgit"); + + static File jgit2Folder = new File(GitBlitSuite.REPOSITORIES, "working/jgit2"); + + String url = GitBlitSuite.url; + String account = GitBlitSuite.account; + String password = GitBlitSuite.password; + + private static final AtomicBoolean started = new AtomicBoolean(false); + + @BeforeClass + public static void startGitblit() throws Exception { + started.set(GitBlitSuite.startGitblit()); + } + + @AfterClass + public static void stopGitblit() throws Exception { + if (started.get()) { + GitBlitSuite.stopGitblit(); + deleteWorkingFolders(); + } + } + + public static void deleteWorkingFolders() throws Exception { + if (ticgitFolder.exists()) { + GitBlitSuite.close(ticgitFolder); + FileUtils.delete(ticgitFolder, FileUtils.RECURSIVE); + } + if (ticgit2Folder.exists()) { + GitBlitSuite.close(ticgit2Folder); + FileUtils.delete(ticgit2Folder, FileUtils.RECURSIVE); + } + if (jgitFolder.exists()) { + GitBlitSuite.close(jgitFolder); + FileUtils.delete(jgitFolder, FileUtils.RECURSIVE); + } + if (jgit2Folder.exists()) { + GitBlitSuite.close(jgit2Folder); + FileUtils.delete(jgit2Folder, FileUtils.RECURSIVE); + } + } + + @Test + public void testClone() throws Exception { + GitBlitSuite.close(ticgitFolder); + if (ticgitFolder.exists()) { + FileUtils.delete(ticgitFolder, FileUtils.RECURSIVE | FileUtils.RETRY); + } + + CloneCommand clone = Git.cloneRepository(); + clone.setURI(MessageFormat.format("{0}/git/ticgit.git", url)); + clone.setDirectory(ticgitFolder); + clone.setBare(false); + clone.setCloneAllBranches(true); + clone.setCredentialsProvider(new UsernamePasswordCredentialsProvider(account, password)); + GitBlitSuite.close(clone.call()); + assertTrue(true); + } + + @Test + public void testBogusLoginClone() throws Exception { + // restrict repository access + RepositoryModel model = GitBlit.self().getRepositoryModel("ticgit.git"); + model.accessRestriction = AccessRestrictionType.CLONE; + GitBlit.self().updateRepositoryModel(model.name, model, false); + + // delete any existing working folder + boolean cloned = false; + try { + CloneCommand clone = Git.cloneRepository(); + clone.setURI(MessageFormat.format("{0}/git/ticgit.git", url)); + clone.setDirectory(ticgit2Folder); + clone.setBare(false); + clone.setCloneAllBranches(true); + clone.setCredentialsProvider(new UsernamePasswordCredentialsProvider("bogus", "bogus")); + GitBlitSuite.close(clone.call()); + cloned = true; + } catch (Exception e) { + // swallow the exception which we expect + } + + // restore anonymous repository access + model.accessRestriction = AccessRestrictionType.NONE; + GitBlit.self().updateRepositoryModel(model.name, model, false); + + assertFalse("Bogus login cloned a repository?!", cloned); + } + + @Test + public void testUnauthorizedLoginClone() throws Exception { + // restrict repository access + RepositoryModel model = GitBlit.self().getRepositoryModel("ticgit.git"); + model.accessRestriction = AccessRestrictionType.CLONE; + model.authorizationControl = AuthorizationControl.NAMED; + UserModel user = new UserModel("james"); + user.password = "james"; + GitBlit.self().updateUserModel(user.username, user, true); + GitBlit.self().updateRepositoryModel(model.name, model, false); + + FileUtils.delete(ticgit2Folder, FileUtils.RECURSIVE); + + // delete any existing working folder + boolean cloned = false; + try { + CloneCommand clone = Git.cloneRepository(); + clone.setURI(MessageFormat.format("{0}/git/ticgit.git", url)); + clone.setDirectory(ticgit2Folder); + clone.setBare(false); + clone.setCloneAllBranches(true); + clone.setCredentialsProvider(new UsernamePasswordCredentialsProvider(user.username, user.password)); + GitBlitSuite.close(clone.call()); + cloned = true; + } catch (Exception e) { + // swallow the exception which we expect + } + + assertFalse("Unauthorized login cloned a repository?!", cloned); + + FileUtils.delete(ticgit2Folder, FileUtils.RECURSIVE); + + // switch to authenticated + model.authorizationControl = AuthorizationControl.AUTHENTICATED; + GitBlit.self().updateRepositoryModel(model.name, model, false); + + // try clone again + cloned = false; + CloneCommand clone = Git.cloneRepository(); + clone.setURI(MessageFormat.format("{0}/git/ticgit.git", url)); + clone.setDirectory(ticgit2Folder); + clone.setBare(false); + clone.setCloneAllBranches(true); + clone.setCredentialsProvider(new UsernamePasswordCredentialsProvider(user.username, user.password)); + GitBlitSuite.close(clone.call()); + cloned = true; + + assertTrue("Authenticated login could not clone!", cloned); + + FileUtils.delete(ticgit2Folder, FileUtils.RECURSIVE); + + // restore anonymous repository access + model.accessRestriction = AccessRestrictionType.NONE; + model.authorizationControl = AuthorizationControl.NAMED; + GitBlit.self().updateRepositoryModel(model.name, model, false); + GitBlit.self().deleteUser(user.username); + } + + @Test + public void testAnonymousPush() throws Exception { + GitBlitSuite.close(ticgitFolder); + if (ticgitFolder.exists()) { + FileUtils.delete(ticgitFolder, FileUtils.RECURSIVE | FileUtils.RETRY); + } + + CloneCommand clone = Git.cloneRepository(); + clone.setURI(MessageFormat.format("{0}/git/ticgit.git", url)); + clone.setDirectory(ticgitFolder); + clone.setBare(false); + clone.setCloneAllBranches(true); + clone.setCredentialsProvider(new UsernamePasswordCredentialsProvider(account, password)); + GitBlitSuite.close(clone.call()); + assertTrue(true); + + Git git = Git.open(ticgitFolder); + File file = new File(ticgitFolder, "TODO"); + OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(file, true), Constants.CHARSET); + BufferedWriter w = new BufferedWriter(os); + w.write("// hellol中文 " + new Date().toString() + "\n"); + w.close(); + git.add().addFilepattern(file.getName()).call(); + git.commit().setMessage("test commit").call(); + git.push().setPushAll().call(); + GitBlitSuite.close(git); + } + + @Test + public void testSubfolderPush() throws Exception { + GitBlitSuite.close(jgitFolder); + if (jgitFolder.exists()) { + FileUtils.delete(jgitFolder, FileUtils.RECURSIVE | FileUtils.RETRY); + } + + CloneCommand clone = Git.cloneRepository(); + clone.setURI(MessageFormat.format("{0}/git/test/jgit.git", url)); + clone.setDirectory(jgitFolder); + clone.setBare(false); + clone.setCloneAllBranches(true); + clone.setCredentialsProvider(new UsernamePasswordCredentialsProvider(account, password)); + GitBlitSuite.close(clone.call()); + assertTrue(true); + + Git git = Git.open(jgitFolder); + File file = new File(jgitFolder, "TODO"); + OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(file, true), Constants.CHARSET); + BufferedWriter w = new BufferedWriter(os); + w.write("// " + new Date().toString() + "\n"); + w.close(); + git.add().addFilepattern(file.getName()).call(); + git.commit().setMessage("test commit").call(); + git.push().setPushAll().call(); + GitBlitSuite.close(git); + } + + @Test + public void testPushToFrozenRepo() throws Exception { + GitBlitSuite.close(jgitFolder); + if (jgitFolder.exists()) { + FileUtils.delete(jgitFolder, FileUtils.RECURSIVE | FileUtils.RETRY); + } + + CloneCommand clone = Git.cloneRepository(); + clone.setURI(MessageFormat.format("{0}/git/test/jgit.git", url)); + clone.setDirectory(jgitFolder); + clone.setBare(false); + clone.setCloneAllBranches(true); + clone.setCredentialsProvider(new UsernamePasswordCredentialsProvider(account, password)); + GitBlitSuite.close(clone.call()); + assertTrue(true); + + // freeze repo + RepositoryModel model = GitBlit.self().getRepositoryModel("test/jgit.git"); + model.isFrozen = true; + GitBlit.self().updateRepositoryModel(model.name, model, false); + + Git git = Git.open(jgitFolder); + File file = new File(jgitFolder, "TODO"); + OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(file, true), Constants.CHARSET); + BufferedWriter w = new BufferedWriter(os); + w.write("// " + new Date().toString() + "\n"); + w.close(); + git.add().addFilepattern(file.getName()).call(); + git.commit().setMessage("test commit").call(); + + try { + git.push().setPushAll().call(); + assertTrue(false); + } catch (Exception e) { + assertTrue(e.getCause().getMessage().contains("access forbidden")); + } + + // unfreeze repo + model.isFrozen = false; + GitBlit.self().updateRepositoryModel(model.name, model, false); + + git.push().setPushAll().call(); + GitBlitSuite.close(git); + } + + @Test + public void testPushToNonBareRepository() throws Exception { + CloneCommand clone = Git.cloneRepository(); + clone.setURI(MessageFormat.format("{0}/git/working/jgit", url)); + clone.setDirectory(jgit2Folder); + clone.setBare(false); + clone.setCloneAllBranches(true); + clone.setCredentialsProvider(new UsernamePasswordCredentialsProvider(account, password)); + GitBlitSuite.close(clone.call()); + assertTrue(true); + + Git git = Git.open(jgit2Folder); + File file = new File(jgit2Folder, "NONBARE"); + OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(file, true), Constants.CHARSET); + BufferedWriter w = new BufferedWriter(os); + w.write("// " + new Date().toString() + "\n"); + w.close(); + git.add().addFilepattern(file.getName()).call(); + git.commit().setMessage("test commit followed by push to non-bare repository").call(); + try { + git.push().setPushAll().call(); + assertTrue(false); + } catch (Exception e) { + assertTrue(e.getCause().getMessage().contains("git-receive-pack not permitted")); + } + GitBlitSuite.close(git); + } + + @Test + public void testCommitterVerification() throws Exception { + UserModel user = new UserModel("james"); + user.password = "james"; + + // account only uses account name to verify + testCommitterVerification(user, user.username, null, true); + // committer email address is ignored because account does not specify email + testCommitterVerification(user, user.username, "something", true); + // completely different committer + testCommitterVerification(user, "joe", null, false); + + // test display name verification + user.displayName = "James Moger"; + testCommitterVerification(user, user.displayName, null, true); + testCommitterVerification(user, user.displayName, "something", true); + testCommitterVerification(user, "joe", null, false); + + // test email address verification + user.emailAddress = "something"; + testCommitterVerification(user, user.displayName, null, false); + testCommitterVerification(user, user.displayName, "somethingelse", false); + testCommitterVerification(user, user.displayName, user.emailAddress, true); + + // use same email address but with different committer + testCommitterVerification(user, "joe", "somethingelse", false); + } + + private void testCommitterVerification(UserModel user, String displayName, String emailAddress, boolean expectedSuccess) throws Exception { + + if (GitBlit.self().getUserModel(user.username) != null) { + GitBlit.self().deleteUser(user.username); + } + + CredentialsProvider cp = new UsernamePasswordCredentialsProvider(user.username, user.password); + + // fork from original to a temporary bare repo + File verification = new File(GitBlitSuite.REPOSITORIES, "refchecks/verify-committer.git"); + if (verification.exists()) { + FileUtils.delete(verification, FileUtils.RECURSIVE); + } + CloneCommand clone = Git.cloneRepository(); + clone.setURI(MessageFormat.format("{0}/git/ticgit.git", url)); + clone.setDirectory(verification); + clone.setBare(true); + clone.setCloneAllBranches(true); + clone.setCredentialsProvider(cp); + GitBlitSuite.close(clone.call()); + + // require push permissions and committer verification + RepositoryModel model = GitBlit.self().getRepositoryModel("refchecks/verify-committer.git"); + model.authorizationControl = AuthorizationControl.NAMED; + model.accessRestriction = AccessRestrictionType.PUSH; + model.verifyCommitter = true; + + // grant user push permission + user.setRepositoryPermission(model.name, AccessPermission.PUSH); + + GitBlit.self().updateUserModel(user.username, user, true); + GitBlit.self().updateRepositoryModel(model.name, model, false); + + // clone temp bare repo to working copy + File local = new File(GitBlitSuite.REPOSITORIES, "refchecks/verify-wc"); + if (local.exists()) { + FileUtils.delete(local, FileUtils.RECURSIVE); + } + clone = Git.cloneRepository(); + clone.setURI(MessageFormat.format("{0}/git/{1}", url, model.name)); + clone.setDirectory(local); + clone.setBare(false); + clone.setCloneAllBranches(true); + clone.setCredentialsProvider(cp); + GitBlitSuite.close(clone.call()); + + Git git = Git.open(local); + + // force an identity which may or may not match the account's identity + git.getRepository().getConfig().setString("user", null, "name", displayName); + git.getRepository().getConfig().setString("user", null, "email", emailAddress); + git.getRepository().getConfig().save(); + + // commit a file and push it + File file = new File(local, "PUSHCHK"); + OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(file, true), Constants.CHARSET); + BufferedWriter w = new BufferedWriter(os); + w.write("// " + new Date().toString() + "\n"); + w.close(); + git.add().addFilepattern(file.getName()).call(); + git.commit().setMessage("push test").call(); + Iterable results = git.push().setCredentialsProvider(cp).setRemote("origin").call(); + + for (PushResult result : results) { + RemoteRefUpdate ref = result.getRemoteUpdate("refs/heads/master"); + Status status = ref.getStatus(); + if (expectedSuccess) { + assertTrue("Verification failed! User was NOT able to push commit! " + status.name(), Status.OK.equals(status)); + } else { + assertTrue("Verification failed! User was able to push commit! " + status.name(), Status.REJECTED_OTHER_REASON.equals(status)); + } + } + + GitBlitSuite.close(git); + // close serving repository + GitBlitSuite.close(verification); + } + + @Test + public void testBlockClone() throws Exception { + testRefChange(AccessPermission.VIEW, null, null, null); + } + + @Test + public void testBlockPush() throws Exception { + testRefChange(AccessPermission.CLONE, null, null, null); + } + + @Test + public void testBlockBranchCreation() throws Exception { + testRefChange(AccessPermission.PUSH, Status.REJECTED_OTHER_REASON, null, null); + } + + @Test + public void testBlockBranchDeletion() throws Exception { + testRefChange(AccessPermission.CREATE, Status.OK, Status.REJECTED_OTHER_REASON, null); + } + + @Test + public void testBlockBranchRewind() throws Exception { + testRefChange(AccessPermission.DELETE, Status.OK, Status.OK, Status.REJECTED_OTHER_REASON); + } + + @Test + public void testBranchRewind() throws Exception { + testRefChange(AccessPermission.REWIND, Status.OK, Status.OK, Status.OK); + } + + private void testRefChange(AccessPermission permission, Status expectedCreate, Status expectedDelete, Status expectedRewind) throws Exception { + + UserModel user = new UserModel("james"); + user.password = "james"; + + if (GitBlit.self().getUserModel(user.username) != null) { + GitBlit.self().deleteUser(user.username); + } + + CredentialsProvider cp = new UsernamePasswordCredentialsProvider(user.username, user.password); + + // fork from original to a temporary bare repo + File refChecks = new File(GitBlitSuite.REPOSITORIES, "refchecks/ticgit.git"); + if (refChecks.exists()) { + FileUtils.delete(refChecks, FileUtils.RECURSIVE); + } + CloneCommand clone = Git.cloneRepository(); + clone.setURI(MessageFormat.format("{0}/git/ticgit.git", url)); + clone.setDirectory(refChecks); + clone.setBare(true); + clone.setCloneAllBranches(true); + clone.setCredentialsProvider(cp); + GitBlitSuite.close(clone.call()); + + // elevate repository to clone permission + RepositoryModel model = GitBlit.self().getRepositoryModel("refchecks/ticgit.git"); + switch (permission) { + case VIEW: + model.accessRestriction = AccessRestrictionType.CLONE; + break; + case CLONE: + model.accessRestriction = AccessRestrictionType.CLONE; + break; + default: + model.accessRestriction = AccessRestrictionType.PUSH; + } + model.authorizationControl = AuthorizationControl.NAMED; + + // grant user specified + user.setRepositoryPermission(model.name, permission); + + GitBlit.self().updateUserModel(user.username, user, true); + GitBlit.self().updateRepositoryModel(model.name, model, false); + + // clone temp bare repo to working copy + File local = new File(GitBlitSuite.REPOSITORIES, "refchecks/ticgit-wc"); + if (local.exists()) { + FileUtils.delete(local, FileUtils.RECURSIVE); + } + clone = Git.cloneRepository(); + clone.setURI(MessageFormat.format("{0}/git/{1}", url, model.name)); + clone.setDirectory(local); + clone.setBare(false); + clone.setCloneAllBranches(true); + clone.setCredentialsProvider(cp); + + try { + GitBlitSuite.close(clone.call()); + } catch (GitAPIException e) { + if (permission.atLeast(AccessPermission.CLONE)) { + throw e; + } else { + // close serving repository + GitBlitSuite.close(refChecks); + + // user does not have clone permission + assertTrue(e.getMessage(), e.getMessage().contains("not permitted")); + return; + } + } + + Git git = Git.open(local); + + // commit a file and push it + File file = new File(local, "PUSHCHK"); + OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(file, true), Constants.CHARSET); + BufferedWriter w = new BufferedWriter(os); + w.write("// " + new Date().toString() + "\n"); + w.close(); + git.add().addFilepattern(file.getName()).call(); + git.commit().setMessage("push test").call(); + Iterable results = null; + try { + results = git.push().setCredentialsProvider(cp).setRemote("origin").call(); + } catch (GitAPIException e) { + if (permission.atLeast(AccessPermission.PUSH)) { + throw e; + } else { + // close serving repository + GitBlitSuite.close(refChecks); + + // user does not have push permission + assertTrue(e.getMessage(), e.getMessage().contains("not permitted")); + GitBlitSuite.close(git); + return; + } + } + + for (PushResult result : results) { + RemoteRefUpdate ref = result.getRemoteUpdate("refs/heads/master"); + Status status = ref.getStatus(); + if (permission.atLeast(AccessPermission.PUSH)) { + assertTrue("User failed to push commit?! " + status.name(), Status.OK.equals(status)); + } else { + // close serving repository + GitBlitSuite.close(refChecks); + + assertTrue("User was able to push commit! " + status.name(), Status.REJECTED_OTHER_REASON.equals(status)); + GitBlitSuite.close(git); + // skip delete test + return; + } + } + + // create a local branch and push the new branch back to the origin + git.branchCreate().setName("protectme").call(); + RefSpec refSpec = new RefSpec("refs/heads/protectme:refs/heads/protectme"); + results = git.push().setCredentialsProvider(cp).setRefSpecs(refSpec).setRemote("origin").call(); + for (PushResult result : results) { + RemoteRefUpdate ref = result.getRemoteUpdate("refs/heads/protectme"); + Status status = ref.getStatus(); + if (Status.OK.equals(expectedCreate)) { + assertTrue("User failed to push creation?! " + status.name(), status.equals(expectedCreate)); + } else { + // close serving repository + GitBlitSuite.close(refChecks); + + assertTrue("User was able to push ref creation! " + status.name(), status.equals(expectedCreate)); + GitBlitSuite.close(git); + // skip delete test + return; + } + } + + // delete the branch locally + git.branchDelete().setBranchNames("protectme").call(); + + // push a delete ref command + refSpec = new RefSpec(":refs/heads/protectme"); + results = git.push().setCredentialsProvider(cp).setRefSpecs(refSpec).setRemote("origin").call(); + for (PushResult result : results) { + RemoteRefUpdate ref = result.getRemoteUpdate("refs/heads/protectme"); + Status status = ref.getStatus(); + if (Status.OK.equals(expectedDelete)) { + assertTrue("User failed to push ref deletion?! " + status.name(), status.equals(Status.OK)); + } else { + // close serving repository + GitBlitSuite.close(refChecks); + + assertTrue("User was able to push ref deletion?! " + status.name(), status.equals(expectedDelete)); + GitBlitSuite.close(git); + // skip rewind test + return; + } + } + + // rewind master by two commits + git.reset().setRef("HEAD~2").setMode(ResetType.HARD).call(); + + // commit a change on this detached HEAD + file = new File(local, "REWINDCHK"); + os = new OutputStreamWriter(new FileOutputStream(file, true), Constants.CHARSET); + w = new BufferedWriter(os); + w.write("// " + new Date().toString() + "\n"); + w.close(); + git.add().addFilepattern(file.getName()).call(); + RevCommit commit = git.commit().setMessage("rewind master and new commit").call(); + + // Reset master to our new commit now we our local branch tip is no longer + // upstream of the remote branch tip. It is an alternate tip of the branch. + JGitUtils.setBranchRef(git.getRepository(), "refs/heads/master", commit.getName()); + + // Try pushing our new tip to the origin. + // This requires the server to "rewind" it's master branch and update it + // to point to our alternate tip. This leaves the original master tip + // unreferenced. + results = git.push().setCredentialsProvider(cp).setRemote("origin").setForce(true).call(); + for (PushResult result : results) { + RemoteRefUpdate ref = result.getRemoteUpdate("refs/heads/master"); + Status status = ref.getStatus(); + if (Status.OK.equals(expectedRewind)) { + assertTrue("User failed to rewind master?! " + status.name(), status.equals(expectedRewind)); + } else { + assertTrue("User was able to rewind master?! " + status.name(), status.equals(expectedRewind)); + } + } + GitBlitSuite.close(git); + + // close serving repository + GitBlitSuite.close(refChecks); + + GitBlit.self().deleteUser(user.username); + } + + @Test + public void testCreateOnPush() throws Exception { + testCreateOnPush(false, false); + testCreateOnPush(true, false); + testCreateOnPush(false, true); + } + + private void testCreateOnPush(boolean canCreate, boolean canAdmin) throws Exception { + + UserModel user = new UserModel("sampleuser"); + user.password = user.username; + + if (GitBlit.self().getUserModel(user.username) != null) { + GitBlit.self().deleteUser(user.username); + } + + user.canCreate = canCreate; + user.canAdmin = canAdmin; + + GitBlit.self().updateUserModel(user.username, user, true); + + CredentialsProvider cp = new UsernamePasswordCredentialsProvider(user.username, user.password); + + // fork from original to a temporary bare repo + File tmpFolder = File.createTempFile("gitblit", "").getParentFile(); + File createCheck = new File(tmpFolder, "ticgit.git"); + if (createCheck.exists()) { + FileUtils.delete(createCheck, FileUtils.RECURSIVE); + } + + File personalRepo = new File(GitBlitSuite.REPOSITORIES, MessageFormat.format("~{0}/ticgit.git", user.username)); + GitBlitSuite.close(personalRepo); + if (personalRepo.exists()) { + FileUtils.delete(personalRepo, FileUtils.RECURSIVE); + } + + File projectRepo = new File(GitBlitSuite.REPOSITORIES, "project/ticgit.git"); + GitBlitSuite.close(projectRepo); + if (projectRepo.exists()) { + FileUtils.delete(projectRepo, FileUtils.RECURSIVE); + } + + CloneCommand clone = Git.cloneRepository(); + clone.setURI(MessageFormat.format("{0}/git/ticgit.git", url)); + clone.setDirectory(createCheck); + clone.setBare(true); + clone.setCloneAllBranches(true); + clone.setCredentialsProvider(cp); + Git git = clone.call(); + + GitBlitSuite.close(personalRepo); + + // add a personal repository remote and a project remote + git.getRepository().getConfig().setString("remote", "user", "url", MessageFormat.format("{0}/git/~{1}/ticgit.git", url, user.username)); + git.getRepository().getConfig().setString("remote", "project", "url", MessageFormat.format("{0}/git/project/ticgit.git", url)); + git.getRepository().getConfig().save(); + + // push to non-existent user repository + try { + Iterable results = git.push().setRemote("user").setPushAll().setCredentialsProvider(cp).call(); + + for (PushResult result : results) { + RemoteRefUpdate ref = result.getRemoteUpdate("refs/heads/master"); + Status status = ref.getStatus(); + assertTrue("User failed to create repository?! " + status.name(), Status.OK.equals(status)); + } + + assertTrue("User canAdmin:" + user.canAdmin + " canCreate:" + user.canCreate, user.canAdmin || user.canCreate); + + // confirm default personal repository permissions + RepositoryModel model = GitBlit.self().getRepositoryModel(MessageFormat.format("~{0}/ticgit.git", user.username)); + assertEquals("Unexpected owner", user.username, ArrayUtils.toString(model.owners)); + assertEquals("Unexpected authorization control", AuthorizationControl.NAMED, model.authorizationControl); + assertEquals("Unexpected access restriction", AccessRestrictionType.VIEW, model.accessRestriction); + + } catch (GitAPIException e) { + assertTrue(e.getMessage(), e.getMessage().contains("git-receive-pack not found")); + assertFalse("User canAdmin:" + user.canAdmin + " canCreate:" + user.canCreate, user.canAdmin || user.canCreate); + } + + // push to non-existent project repository + try { + Iterable results = git.push().setRemote("project").setPushAll().setCredentialsProvider(cp).call(); + GitBlitSuite.close(git); + + for (PushResult result : results) { + RemoteRefUpdate ref = result.getRemoteUpdate("refs/heads/master"); + Status status = ref.getStatus(); + assertTrue("User failed to create repository?! " + status.name(), Status.OK.equals(status)); + } + + assertTrue("User canAdmin:" + user.canAdmin, user.canAdmin); + + // confirm default project repository permissions + RepositoryModel model = GitBlit.self().getRepositoryModel("project/ticgit.git"); + assertEquals("Unexpected owner", user.username, ArrayUtils.toString(model.owners)); + assertEquals("Unexpected authorization control", AuthorizationControl.fromName(GitBlit.getString(Keys.git.defaultAuthorizationControl, "NAMED")), model.authorizationControl); + assertEquals("Unexpected access restriction", AccessRestrictionType.fromName(GitBlit.getString(Keys.git.defaultAccessRestriction, "NONE")), model.accessRestriction); + + } catch (GitAPIException e) { + assertTrue(e.getMessage(), e.getMessage().contains("git-receive-pack not found")); + assertFalse("User canAdmin:" + user.canAdmin, user.canAdmin); + } + + GitBlitSuite.close(git); + GitBlit.self().deleteUser(user.username); + } + + @Test + public void testPushLog() throws IOException { + String name = "refchecks/ticgit.git"; + File refChecks = new File(GitBlitSuite.REPOSITORIES, name); + FileRepository repository = new FileRepository(refChecks); + List pushes = PushLogUtils.getPushLog(name, repository); + GitBlitSuite.close(repository); + assertTrue("Repository has an empty push log!", pushes.size() > 0); + } +} diff --git a/src/test/java/com/gitblit/tests/GroovyScriptTest.java b/src/test/java/com/gitblit/tests/GroovyScriptTest.java new file mode 100644 index 00000000..2954fa1d --- /dev/null +++ b/src/test/java/com/gitblit/tests/GroovyScriptTest.java @@ -0,0 +1,399 @@ +/* + * Copyright 2011 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import groovy.lang.Binding; +import groovy.util.GroovyScriptEngine; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.transport.ReceiveCommand; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.gitblit.GitBlit; +import com.gitblit.GitBlitException; +import com.gitblit.models.RepositoryModel; +import com.gitblit.models.TeamModel; +import com.gitblit.models.UserModel; +import com.gitblit.utils.StringUtils; + +/** + * Test class for Groovy scripts. Mostly this is to facilitate development. + * + * @author James Moger + * + */ +public class GroovyScriptTest { + + private static final AtomicBoolean started = new AtomicBoolean(false); + + @BeforeClass + public static void startGitblit() throws Exception { + started.set(GitBlitSuite.startGitblit()); + } + + @AfterClass + public static void stopGitblit() throws Exception { + if (started.get()) { + GitBlitSuite.stopGitblit(); + } + } + + @Test + public void testFogbugz() throws Exception { + MockGitblit gitblit = new MockGitblit(); + MockLogger logger = new MockLogger(); + MockClientLogger clientLogger = new MockClientLogger(); + List commands = new ArrayList(); + commands.add(new ReceiveCommand(ObjectId + .fromString("c18877690322dfc6ae3e37bb7f7085a24e94e887"), ObjectId + .fromString("3fa7c46d11b11d61f1cbadc6888be5d0eae21969"), "refs/heads/master")); + commands.add(new ReceiveCommand(ObjectId + .fromString("c18877690322dfc6ae3e37bb7f7085a24e94e887"), ObjectId + .fromString("3fa7c46d11b11d61f1cbadc6888be5d0eae21969"), "refs/heads/master2")); + + RepositoryModel repository = GitBlit.self().getRepositoryModel("helloworld.git"); + repository.customFields = new HashMap(); + repository.customFields.put( "fogbugzUrl", "http://bugs.test.com" ); + repository.customFields.put( "fogbugzRepositoryId", "1" ); + repository.customFields.put( "fogbugzCommitMessageRegex", "\\s*[Bb][Uu][Gg][(Zz)(Ss)]*\\s*[(IDs)]*\\s*[#:; ]+((\\d+[ ,:;#]*)+)" ); + + test("fogbugz.groovy", gitblit, logger, clientLogger, commands, repository); + } + + @Test + public void testSendHtmlMail() throws Exception { + MockGitblit gitblit = new MockGitblit(); + MockLogger logger = new MockLogger(); + MockClientLogger clientLogger = new MockClientLogger(); + List commands = new ArrayList(); + commands.add(new ReceiveCommand(ObjectId + .fromString("c18877690322dfc6ae3e37bb7f7085a24e94e887"), ObjectId + .fromString("3fa7c46d11b11d61f1cbadc6888be5d0eae21969"), "refs/heads/master")); + commands.add(new ReceiveCommand(ObjectId + .fromString("c18877690322dfc6ae3e37bb7f7085a24e94e887"), ObjectId + .fromString("3fa7c46d11b11d61f1cbadc6888be5d0eae21969"), "refs/heads/master2")); + + RepositoryModel repository = GitBlit.self().getRepositoryModel("helloworld.git"); + repository.mailingLists.add("list@helloworld.git"); + + test("sendmail-html.groovy", gitblit, logger, clientLogger, commands, repository); + assertEquals(1, logger.messages.size()); + assertEquals(1, gitblit.messages.size()); + MockMail m = gitblit.messages.get(0); + assertEquals(5, m.toAddresses.size()); + assertTrue(m.message.contains("BIT")); + assertTrue(m.message.contains("")); + } + + @Test + public void testSendMail() throws Exception { + MockGitblit gitblit = new MockGitblit(); + MockLogger logger = new MockLogger(); + MockClientLogger clientLogger = new MockClientLogger(); + List commands = new ArrayList(); + commands.add(new ReceiveCommand(ObjectId + .fromString("c18877690322dfc6ae3e37bb7f7085a24e94e887"), ObjectId + .fromString("3fa7c46d11b11d61f1cbadc6888be5d0eae21969"), "refs/heads/master")); + commands.add(new ReceiveCommand(ObjectId + .fromString("c18877690322dfc6ae3e37bb7f7085a24e94e887"), ObjectId + .fromString("3fa7c46d11b11d61f1cbadc6888be5d0eae21969"), "refs/heads/master2")); + + RepositoryModel repository = GitBlit.self().getRepositoryModel("helloworld.git"); + repository.mailingLists.add("list@helloworld.git"); + + test("sendmail.groovy", gitblit, logger, clientLogger, commands, repository); + assertEquals(1, logger.messages.size()); + assertEquals(1, gitblit.messages.size()); + MockMail m = gitblit.messages.get(0); + assertEquals(5, m.toAddresses.size()); + assertTrue(m.message.contains("BIT")); + } + + @Test + public void testProtectRefsCreateBranch() throws Exception { + MockGitblit gitblit = new MockGitblit(); + MockLogger logger = new MockLogger(); + MockClientLogger clientLogger = new MockClientLogger(); + List commands = new ArrayList(); + commands.add(new ReceiveCommand(ObjectId.zeroId(), ObjectId + .fromString("3fa7c46d11b11d61f1cbadc6888be5d0eae21969"), "refs/heads/master")); + + RepositoryModel repository = new RepositoryModel("ex@mple.git", "", "admin", new Date()); + + test("protect-refs.groovy", gitblit, logger, clientLogger, commands, repository); + } + + @Test + public void testProtectRefsCreateTag() throws Exception { + MockGitblit gitblit = new MockGitblit(); + MockLogger logger = new MockLogger(); + MockClientLogger clientLogger = new MockClientLogger(); + List commands = new ArrayList(); + commands.add(new ReceiveCommand(ObjectId.zeroId(), ObjectId + .fromString("3fa7c46d11b11d61f1cbadc6888be5d0eae21969"), "refs/tags/v1.0")); + + RepositoryModel repository = new RepositoryModel("ex@mple.git", "", "admin", new Date()); + + test("protect-refs.groovy", gitblit, logger, clientLogger, commands, repository); + assertEquals(0, logger.messages.size()); + } + + @Test + public void testProtectRefsFastForward() throws Exception { + MockGitblit gitblit = new MockGitblit(); + MockLogger logger = new MockLogger(); + MockClientLogger clientLogger = new MockClientLogger(); + List commands = new ArrayList(); + commands.add(new ReceiveCommand(ObjectId + .fromString("c18877690322dfc6ae3e37bb7f7085a24e94e887"), ObjectId + .fromString("3fa7c46d11b11d61f1cbadc6888be5d0eae21969"), "refs/heads/master")); + + RepositoryModel repository = new RepositoryModel("ex@mple.git", "", "admin", new Date()); + + test("protect-refs.groovy", gitblit, logger, clientLogger, commands, repository); + assertEquals(0, logger.messages.size()); + } + + @Test + public void testProtectRefsDeleteMasterBranch() throws Exception { + MockGitblit gitblit = new MockGitblit(); + MockLogger logger = new MockLogger(); + MockClientLogger clientLogger = new MockClientLogger(); + List commands = new ArrayList(); + ReceiveCommand command = new ReceiveCommand(ObjectId + .fromString("3fa7c46d11b11d61f1cbadc6888be5d0eae21969"), ObjectId.zeroId(), + "refs/heads/master"); + commands.add(command); + + RepositoryModel repository = new RepositoryModel("ex@mple.git", "", "admin", new Date()); + + test("protect-refs.groovy", gitblit, logger, clientLogger, commands, repository); + assertEquals(ReceiveCommand.Result.REJECTED_NODELETE, command.getResult()); + assertEquals(0, logger.messages.size()); + } + + @Test + public void testProtectRefsDeleteOtherBranch() throws Exception { + MockGitblit gitblit = new MockGitblit(); + MockLogger logger = new MockLogger(); + MockClientLogger clientLogger = new MockClientLogger(); + List commands = new ArrayList(); + commands.add(new ReceiveCommand(ObjectId + .fromString("3fa7c46d11b11d61f1cbadc6888be5d0eae21969"), ObjectId.zeroId(), + "refs/heads/other")); + + RepositoryModel repository = new RepositoryModel("ex@mple.git", "", "admin", new Date()); + + test("protect-refs.groovy", gitblit, logger, clientLogger, commands, repository); + assertEquals(0, logger.messages.size()); + } + + @Test + public void testProtectRefsDeleteTag() throws Exception { + MockGitblit gitblit = new MockGitblit(); + MockLogger logger = new MockLogger(); + MockClientLogger clientLogger = new MockClientLogger(); + List commands = new ArrayList(); + ReceiveCommand command = new ReceiveCommand(ObjectId + .fromString("3fa7c46d11b11d61f1cbadc6888be5d0eae21969"), ObjectId.zeroId(), + "refs/tags/v1.0"); + commands.add(command); + + RepositoryModel repository = new RepositoryModel("ex@mple.git", "", "admin", new Date()); + + test("protect-refs.groovy", gitblit, logger, clientLogger, commands, repository); + assertEquals(ReceiveCommand.Result.REJECTED_NODELETE, command.getResult()); + assertEquals(0, logger.messages.size()); + } + + @Test + public void testBlockPush() throws Exception { + MockGitblit gitblit = new MockGitblit(); + MockLogger logger = new MockLogger(); + MockClientLogger clientLogger = new MockClientLogger(); + List commands = new ArrayList(); + commands.add(new ReceiveCommand(ObjectId + .fromString("c18877690322dfc6ae3e37bb7f7085a24e94e887"), ObjectId + .fromString("3fa7c46d11b11d61f1cbadc6888be5d0eae21969"), "refs/heads/master")); + + RepositoryModel repository = new RepositoryModel("ex@mple.git", "", "admin", new Date()); + + try { + test("blockpush.groovy", gitblit, logger, clientLogger, commands, repository); + assertTrue("blockpush should have failed!", false); + } catch (GitBlitException e) { + assertTrue(e.getMessage().contains("failed")); + } + } + + @Test + public void testClientLogging() throws Exception { + MockGitblit gitblit = new MockGitblit(); + MockLogger logger = new MockLogger(); + MockClientLogger clientLogger = new MockClientLogger(); + List commands = new ArrayList(); + commands.add(new ReceiveCommand(ObjectId + .fromString("c18877690322dfc6ae3e37bb7f7085a24e94e887"), ObjectId + .fromString("3fa7c46d11b11d61f1cbadc6888be5d0eae21969"), "refs/heads/master")); + + RepositoryModel repository = new RepositoryModel("ex@mple.git", "", "admin", new Date()); + + File groovyDir = GitBlit.getGroovyScriptsFolder(); + File tempScript = File.createTempFile("testClientLogging", "groovy", groovyDir); + tempScript.deleteOnExit(); + + BufferedWriter writer = new BufferedWriter(new FileWriter(tempScript)); + + writer.write("clientLogger.info('this is a test message')\n"); + writer.flush(); + writer.close(); + + test(tempScript.getName(), gitblit, logger, clientLogger, commands, repository); + assertTrue("Message Missing", clientLogger.messages.contains("this is a test message")); + } + + private void test(String script, MockGitblit gitblit, MockLogger logger, MockClientLogger clientLogger, + List commands, RepositoryModel repository) throws Exception { + + UserModel user = new UserModel("mock"); + + String gitblitUrl = GitBlitSuite.url; + + File groovyDir = GitBlit.getGroovyScriptsFolder(); + GroovyScriptEngine gse = new GroovyScriptEngine(groovyDir.getAbsolutePath()); + + Binding binding = new Binding(); + binding.setVariable("gitblit", gitblit); + binding.setVariable("repository", repository); + binding.setVariable("user", user); + binding.setVariable("commands", commands); + binding.setVariable("url", gitblitUrl); + binding.setVariable("logger", logger); + binding.setVariable("clientLogger", clientLogger); + + Object result = gse.run(script, binding); + if (result instanceof Boolean) { + if (!((Boolean) result)) { + throw new GitBlitException(MessageFormat.format( + "Groovy script {0} has failed! Hook scripts aborted.", script)); + } + } + } + + class MockGitblit { + List messages = new ArrayList(); + + public Repository getRepository(String name) throws Exception { + return GitBlitSuite.getHelloworldRepository(); + } + + public List getStrings(String key) { + return Arrays.asList("alpha@aaa.com", "beta@bee.com", "gamma@see.com"); + } + + public List getRepositoryTeams(RepositoryModel repository) { + return Arrays.asList("testteam"); + } + + public TeamModel getTeamModel(String name) { + TeamModel model = new TeamModel(name); + model.mailingLists.add("list@" + name + ".com"); + return model; + } + + public String getString(String key, String dv) { + return dv; + } + + public boolean getBoolean(String key, boolean dv) { + return dv; + } + + public void sendMail(String subject, String message, Collection toAddresses) { + messages.add(new MockMail(subject, message, toAddresses)); + } + public void sendHtmlMail(String subject, String message, Collection toAddresses) { + messages.add(new MockMail(subject, message, toAddresses)); + } + } + + class MockLogger { + List messages = new ArrayList(); + + public void info(String message) { + messages.add(message); + } + } + + class MockClientLogger { + List messages = new ArrayList(); + + public void info(String message) { + messages.add(message); + } + + public void error(String message) { + messages.add(message); + } + + public void error(String message, Throwable t) { + PrintWriter writer = new PrintWriter(new StringWriter()); + if (!StringUtils.isEmpty(message)) { + writer.append(message); + writer.append('\n'); + } + t.printStackTrace(writer); + messages.add(writer.toString()); + } + } + + class MockMail { + final Collection toAddresses; + final String subject; + final String message; + + MockMail(String subject, String message, Collection toAddresses) { + this.subject = subject; + this.message = message; + this.toAddresses = toAddresses; + } + + @Override + public String toString() { + return StringUtils.flattenStrings(toAddresses, ", ") + "\n\n" + subject + "\n\n" + + message; + } + } +} diff --git a/src/test/java/com/gitblit/tests/IssuesTest.java b/src/test/java/com/gitblit/tests/IssuesTest.java new file mode 100644 index 00000000..54cac335 --- /dev/null +++ b/src/test/java/com/gitblit/tests/IssuesTest.java @@ -0,0 +1,231 @@ +/* + * Copyright 2012 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.bouncycastle.util.Arrays; +import org.eclipse.jgit.lib.Repository; +import org.junit.Test; + +import com.gitblit.LuceneExecutor; +import com.gitblit.models.IssueModel; +import com.gitblit.models.IssueModel.Attachment; +import com.gitblit.models.IssueModel.Change; +import com.gitblit.models.IssueModel.Field; +import com.gitblit.models.IssueModel.Priority; +import com.gitblit.models.IssueModel.Status; +import com.gitblit.models.SearchResult; +import com.gitblit.utils.FileUtils; +import com.gitblit.utils.IssueUtils; +import com.gitblit.utils.IssueUtils.IssueFilter; + +/** + * Tests the mechanics of distributed issue management on the gb-issues branch. + * + * @author James Moger + * + */ +public class IssuesTest { + + @Test + public void testLifecycle() throws Exception { + Repository repository = GitBlitSuite.getIssuesTestRepository(); + String name = FileUtils.getRelativePath(GitBlitSuite.REPOSITORIES, repository.getDirectory()); + + // create and insert an issue + Change c1 = newChange("testCreation() " + Long.toHexString(System.currentTimeMillis())); + IssueModel issue = IssueUtils.createIssue(repository, c1); + assertNotNull(issue.id); + + // retrieve issue and compare + IssueModel constructed = IssueUtils.getIssue(repository, issue.id); + compare(issue, constructed); + + assertEquals(1, constructed.changes.size()); + + // C1: create the issue + c1 = newChange("testUpdates() " + Long.toHexString(System.currentTimeMillis())); + issue = IssueUtils.createIssue(repository, c1); + assertNotNull(issue.id); + + constructed = IssueUtils.getIssue(repository, issue.id); + compare(issue, constructed); + assertEquals(1, constructed.changes.size()); + + // C2: set owner + Change c2 = new Change("C2"); + c2.comment("I'll fix this"); + c2.setField(Field.Owner, c2.author); + assertTrue(IssueUtils.updateIssue(repository, issue.id, c2)); + constructed = IssueUtils.getIssue(repository, issue.id); + assertEquals(2, constructed.changes.size()); + assertEquals(c2.author, constructed.owner); + + // C3: add a note + Change c3 = new Change("C3"); + c3.comment("yeah, this is working"); + assertTrue(IssueUtils.updateIssue(repository, issue.id, c3)); + constructed = IssueUtils.getIssue(repository, issue.id); + assertEquals(3, constructed.changes.size()); + + // C4: add attachment + Change c4 = new Change("C4"); + Attachment a = newAttachment(); + c4.addAttachment(a); + assertTrue(IssueUtils.updateIssue(repository, issue.id, c4)); + + Attachment a1 = IssueUtils.getIssueAttachment(repository, issue.id, a.name); + assertEquals(a.content.length, a1.content.length); + assertTrue(Arrays.areEqual(a.content, a1.content)); + + // C5: close the issue + Change c5 = new Change("C5"); + c5.comment("closing issue"); + c5.setField(Field.Status, Status.Fixed); + assertTrue(IssueUtils.updateIssue(repository, issue.id, c5)); + + // retrieve issue again + constructed = IssueUtils.getIssue(repository, issue.id); + + assertEquals(5, constructed.changes.size()); + assertTrue(constructed.status.isClosed()); + + List allIssues = IssueUtils.getIssues(repository, null); + List openIssues = IssueUtils.getIssues(repository, new IssueFilter() { + @Override + public boolean accept(IssueModel issue) { + return !issue.status.isClosed(); + } + }); + List closedIssues = IssueUtils.getIssues(repository, new IssueFilter() { + @Override + public boolean accept(IssueModel issue) { + return issue.status.isClosed(); + } + }); + + assertTrue(allIssues.size() > 0); + assertEquals(1, openIssues.size()); + assertEquals(1, closedIssues.size()); + + // build a new Lucene index + LuceneExecutor lucene = new LuceneExecutor(null, GitBlitSuite.REPOSITORIES); + lucene.deleteIndex(name); + for (IssueModel anIssue : allIssues) { + lucene.index(name, anIssue); + } + List hits = lucene.search("working", 1, 10, name); + assertTrue(hits.size() == 1); + + // reindex an issue + issue = allIssues.get(0); + Change change = new Change("reindex"); + change.comment("this is a test of reindexing an issue"); + IssueUtils.updateIssue(repository, issue.id, change); + issue = IssueUtils.getIssue(repository, issue.id); + lucene.index(name, issue); + + hits = lucene.search("working", 1, 10, name); + assertTrue(hits.size() == 1); + + + // delete all issues + for (IssueModel anIssue : allIssues) { + assertTrue(IssueUtils.deleteIssue(repository, anIssue.id, "D")); + } + + lucene.close(); + repository.close(); + } + + @Test + public void testChangeComment() throws Exception { + Repository repository = GitBlitSuite.getIssuesTestRepository(); + // C1: create the issue + Change c1 = newChange("testChangeComment() " + Long.toHexString(System.currentTimeMillis())); + IssueModel issue = IssueUtils.createIssue(repository, c1); + assertNotNull(issue.id); + assertTrue(issue.changes.get(0).hasComment()); + + assertTrue(IssueUtils.changeComment(repository, issue, c1, "E1", "I changed the comment")); + issue = IssueUtils.getIssue(repository, issue.id); + assertTrue(issue.changes.get(0).hasComment()); + assertEquals("I changed the comment", issue.changes.get(0).comment.text); + + assertTrue(IssueUtils.deleteIssue(repository, issue.id, "D")); + + repository.close(); + } + + @Test + public void testDeleteComment() throws Exception { + Repository repository = GitBlitSuite.getIssuesTestRepository(); + // C1: create the issue + Change c1 = newChange("testDeleteComment() " + Long.toHexString(System.currentTimeMillis())); + IssueModel issue = IssueUtils.createIssue(repository, c1); + assertNotNull(issue.id); + assertTrue(issue.changes.get(0).hasComment()); + + assertTrue(IssueUtils.deleteComment(repository, issue, c1, "D1")); + issue = IssueUtils.getIssue(repository, issue.id); + assertEquals(1, issue.changes.size()); + assertFalse(issue.changes.get(0).hasComment()); + + issue = IssueUtils.getIssue(repository, issue.id, false); + assertEquals(2, issue.changes.size()); + assertTrue(issue.changes.get(0).hasComment()); + assertFalse(issue.changes.get(1).hasComment()); + + assertTrue(IssueUtils.deleteIssue(repository, issue.id, "D")); + + repository.close(); + } + + private Change newChange(String summary) { + Change change = new Change("C1"); + change.setField(Field.Summary, summary); + change.setField(Field.Description, "this is my description"); + change.setField(Field.Priority, Priority.High); + change.setField(Field.Labels, "helpdesk"); + change.comment("my comment"); + return change; + } + + private Attachment newAttachment() { + Attachment attachment = new Attachment(Long.toHexString(System.currentTimeMillis()) + + ".txt"); + attachment.content = new byte[] { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a }; + return attachment; + } + + private void compare(IssueModel issue, IssueModel constructed) { + assertEquals(issue.id, constructed.id); + assertEquals(issue.reporter, constructed.reporter); + assertEquals(issue.owner, constructed.owner); + assertEquals(issue.summary, constructed.summary); + assertEquals(issue.description, constructed.description); + assertEquals(issue.created, constructed.created); + + assertTrue(issue.hasLabel("helpdesk")); + } +} \ No newline at end of file diff --git a/src/test/java/com/gitblit/tests/JGitUtilsTest.java b/src/test/java/com/gitblit/tests/JGitUtilsTest.java new file mode 100644 index 00000000..ce72a46f --- /dev/null +++ b/src/test/java/com/gitblit/tests/JGitUtilsTest.java @@ -0,0 +1,472 @@ +/* + * Copyright 2011 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.FileOutputStream; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import org.eclipse.jgit.diff.DiffEntry.ChangeType; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.PersonIdent; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.RepositoryCache; +import org.eclipse.jgit.lib.RepositoryCache.FileKey; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevTree; +import org.eclipse.jgit.util.FS; +import org.eclipse.jgit.util.FileUtils; +import org.junit.Test; + +import com.gitblit.Constants.SearchType; +import com.gitblit.GitBlit; +import com.gitblit.Keys; +import com.gitblit.models.GitNote; +import com.gitblit.models.PathModel; +import com.gitblit.models.PathModel.PathChangeModel; +import com.gitblit.models.RefModel; +import com.gitblit.utils.CompressionUtils; +import com.gitblit.utils.JGitUtils; +import com.gitblit.utils.StringUtils; + +public class JGitUtilsTest { + + @Test + public void testDisplayName() throws Exception { + assertEquals("Napoleon Bonaparte", + JGitUtils.getDisplayName(new PersonIdent("Napoleon Bonaparte", ""))); + assertEquals("", + JGitUtils.getDisplayName(new PersonIdent("", "someone@somewhere.com"))); + assertEquals("Napoleon Bonaparte ", + JGitUtils.getDisplayName(new PersonIdent("Napoleon Bonaparte", + "someone@somewhere.com"))); + } + + @Test + public void testFindRepositories() { + List list = JGitUtils.getRepositoryList(null, false, true, -1, null); + assertEquals(0, list.size()); + list.addAll(JGitUtils.getRepositoryList(new File("DoesNotExist"), true, true, -1, null)); + assertEquals(0, list.size()); + list.addAll(JGitUtils.getRepositoryList(GitBlitSuite.REPOSITORIES, false, true, -1, null)); + assertTrue("No repositories found in " + GitBlitSuite.REPOSITORIES, list.size() > 0); + } + + @Test + public void testFindExclusions() { + List list = JGitUtils.getRepositoryList(GitBlitSuite.REPOSITORIES, false, true, -1, null); + assertTrue("Missing jgit repository?!", list.contains("test/jgit.git")); + + list = JGitUtils.getRepositoryList(GitBlitSuite.REPOSITORIES, false, true, -1, Arrays.asList("test/jgit\\.git")); + assertFalse("Repository exclusion failed!", list.contains("test/jgit.git")); + + list = JGitUtils.getRepositoryList(GitBlitSuite.REPOSITORIES, false, true, -1, Arrays.asList("test/*")); + assertFalse("Repository exclusion failed!", list.contains("test/jgit.git")); + + list = JGitUtils.getRepositoryList(GitBlitSuite.REPOSITORIES, false, true, -1, Arrays.asList(".*jgit.*")); + assertFalse("Repository exclusion failed!", list.contains("test/jgit.git")); + assertFalse("Repository exclusion failed!", list.contains("working/jgit")); + assertFalse("Repository exclusion failed!", list.contains("working/jgit2")); + + } + + @Test + public void testOpenRepository() throws Exception { + Repository repository = GitBlitSuite.getHelloworldRepository(); + repository.close(); + assertNotNull("Could not find repository!", repository); + } + + @Test + public void testFirstCommit() throws Exception { + assertEquals(new Date(0), JGitUtils.getFirstChange(null, null)); + + Repository repository = GitBlitSuite.getHelloworldRepository(); + RevCommit commit = JGitUtils.getFirstCommit(repository, null); + Date firstChange = JGitUtils.getFirstChange(repository, null); + repository.close(); + assertNotNull("Could not get first commit!", commit); + assertEquals("Incorrect first commit!", "f554664a346629dc2b839f7292d06bad2db4aece", + commit.getName()); + assertTrue(firstChange.equals(new Date(commit.getCommitTime() * 1000L))); + } + + @Test + public void testLastCommit() throws Exception { + assertEquals(new Date(0), JGitUtils.getLastChange(null)); + + Repository repository = GitBlitSuite.getHelloworldRepository(); + assertTrue(JGitUtils.getCommit(repository, null) != null); + Date date = JGitUtils.getLastChange(repository); + repository.close(); + assertNotNull("Could not get last repository change date!", date); + } + + @Test + public void testCreateRepository() throws Exception { + String[] repositories = { "NewTestRepository.git", "NewTestRepository" }; + for (String repositoryName : repositories) { + Repository repository = JGitUtils.createRepository(GitBlitSuite.REPOSITORIES, + repositoryName); + File folder = FileKey.resolve(new File(GitBlitSuite.REPOSITORIES, repositoryName), + FS.DETECTED); + assertNotNull(repository); + assertFalse(JGitUtils.hasCommits(repository)); + assertNull(JGitUtils.getFirstCommit(repository, null)); + assertEquals(folder.lastModified(), JGitUtils.getFirstChange(repository, null) + .getTime()); + assertEquals(folder.lastModified(), JGitUtils.getLastChange(repository).getTime()); + assertNull(JGitUtils.getCommit(repository, null)); + repository.close(); + RepositoryCache.close(repository); + FileUtils.delete(repository.getDirectory(), FileUtils.RECURSIVE); + } + } + + @Test + public void testRefs() throws Exception { + Repository repository = GitBlitSuite.getJGitRepository(); + Map> map = JGitUtils.getAllRefs(repository); + repository.close(); + assertTrue(map.size() > 0); + for (Map.Entry> entry : map.entrySet()) { + List list = entry.getValue(); + for (RefModel ref : list) { + if (ref.displayName.equals("refs/tags/spearce-gpg-pub")) { + assertEquals("refs/tags/spearce-gpg-pub", ref.toString()); + assertEquals("8bbde7aacf771a9afb6992434f1ae413e010c6d8", ref.getObjectId() + .getName()); + assertEquals("spearce@spearce.org", ref.getAuthorIdent().getEmailAddress()); + assertTrue(ref.getShortMessage().startsWith("GPG key")); + assertTrue(ref.getFullMessage().startsWith("GPG key")); + assertEquals(Constants.OBJ_BLOB, ref.getReferencedObjectType()); + } else if (ref.displayName.equals("refs/tags/v0.12.1")) { + assertTrue(ref.isAnnotatedTag()); + } + } + } + } + + @Test + public void testBranches() throws Exception { + Repository repository = GitBlitSuite.getJGitRepository(); + assertTrue(JGitUtils.getLocalBranches(repository, true, 0).size() == 0); + for (RefModel model : JGitUtils.getLocalBranches(repository, true, -1)) { + assertTrue(model.getName().startsWith(Constants.R_HEADS)); + assertTrue(model.equals(model)); + assertFalse(model.equals("")); + assertTrue(model.hashCode() == model.getReferencedObjectId().hashCode() + + model.getName().hashCode()); + assertTrue(model.getShortMessage().equals(model.getShortMessage())); + } + for (RefModel model : JGitUtils.getRemoteBranches(repository, true, -1)) { + assertTrue(model.getName().startsWith(Constants.R_REMOTES)); + assertTrue(model.equals(model)); + assertFalse(model.equals("")); + assertTrue(model.hashCode() == model.getReferencedObjectId().hashCode() + + model.getName().hashCode()); + assertTrue(model.getShortMessage().equals(model.getShortMessage())); + } + assertTrue(JGitUtils.getRemoteBranches(repository, true, 8).size() == 8); + repository.close(); + } + + @Test + public void testTags() throws Exception { + Repository repository = GitBlitSuite.getJGitRepository(); + assertTrue(JGitUtils.getTags(repository, true, 5).size() == 5); + for (RefModel model : JGitUtils.getTags(repository, true, -1)) { + if (model.getObjectId().getName().equals("d28091fb2977077471138fe97da1440e0e8ae0da")) { + assertTrue("Not an annotated tag!", model.isAnnotatedTag()); + } + assertTrue(model.getName().startsWith(Constants.R_TAGS)); + assertTrue(model.equals(model)); + assertFalse(model.equals("")); + assertTrue(model.hashCode() == model.getReferencedObjectId().hashCode() + + model.getName().hashCode()); + } + repository.close(); + + repository = GitBlitSuite.getGitectiveRepository(); + for (RefModel model : JGitUtils.getTags(repository, true, -1)) { + if (model.getObjectId().getName().equals("035254295a9bba11f72b1f9d6791a6b957abee7b")) { + assertFalse(model.isAnnotatedTag()); + assertTrue(model.getAuthorIdent().getEmailAddress().equals("kevinsawicki@gmail.com")); + assertEquals("Add scm and issue tracker elements to pom.xml\n", model.getFullMessage()); + } + } + repository.close(); + } + + @Test + public void testCommitNotes() throws Exception { + Repository repository = GitBlitSuite.getJGitRepository(); + RevCommit commit = JGitUtils.getCommit(repository, + "690c268c793bfc218982130fbfc25870f292295e"); + List list = JGitUtils.getNotesOnCommit(repository, commit); + repository.close(); + assertTrue(list.size() > 0); + assertEquals("183474d554e6f68478a02d9d7888b67a9338cdff", list.get(0).notesRef + .getReferencedObjectId().getName()); + } + + @Test + public void testRelinkHEAD() throws Exception { + Repository repository = GitBlitSuite.getJGitRepository(); + // confirm HEAD is master + String currentRef = JGitUtils.getHEADRef(repository); + assertEquals("refs/heads/master", currentRef); + List availableHeads = JGitUtils.getAvailableHeadTargets(repository); + assertTrue(availableHeads.size() > 0); + + // set HEAD to stable-1.2 + JGitUtils.setHEADtoRef(repository, "refs/heads/stable-1.2"); + currentRef = JGitUtils.getHEADRef(repository); + assertEquals("refs/heads/stable-1.2", currentRef); + + // restore HEAD to master + JGitUtils.setHEADtoRef(repository, "refs/heads/master"); + currentRef = JGitUtils.getHEADRef(repository); + assertEquals("refs/heads/master", currentRef); + + repository.close(); + } + + @Test + public void testRelinkBranch() throws Exception { + Repository repository = GitBlitSuite.getJGitRepository(); + + // create/set the branch + JGitUtils.setBranchRef(repository, "refs/heads/reftest", "3b358ce514ec655d3ff67de1430994d8428cdb04"); + assertEquals(1, JGitUtils.getAllRefs(repository).get(ObjectId.fromString("3b358ce514ec655d3ff67de1430994d8428cdb04")).size()); + assertEquals(null, JGitUtils.getAllRefs(repository).get(ObjectId.fromString("755dfdb40948f5c1ec79e06bde3b0a78c352f27f"))); + + // reset the branch + JGitUtils.setBranchRef(repository, "refs/heads/reftest", "755dfdb40948f5c1ec79e06bde3b0a78c352f27f"); + assertEquals(null, JGitUtils.getAllRefs(repository).get(ObjectId.fromString("3b358ce514ec655d3ff67de1430994d8428cdb04"))); + assertEquals(1, JGitUtils.getAllRefs(repository).get(ObjectId.fromString("755dfdb40948f5c1ec79e06bde3b0a78c352f27f")).size()); + + // delete the branch + assertTrue(JGitUtils.deleteBranchRef(repository, "refs/heads/reftest")); + repository.close(); + } + + @Test + public void testCreateOrphanedBranch() throws Exception { + Repository repository = JGitUtils.createRepository(GitBlitSuite.REPOSITORIES, "orphantest"); + assertTrue(JGitUtils.createOrphanBranch(repository, + "x" + Long.toHexString(System.currentTimeMillis()).toUpperCase(), null)); + FileUtils.delete(repository.getDirectory(), FileUtils.RECURSIVE); + } + + @Test + public void testStringContent() throws Exception { + Repository repository = GitBlitSuite.getHelloworldRepository(); + String contentA = JGitUtils.getStringContent(repository, (RevTree) null, "java.java"); + RevCommit commit = JGitUtils.getCommit(repository, Constants.HEAD); + String contentB = JGitUtils.getStringContent(repository, commit.getTree(), "java.java"); + String contentC = JGitUtils.getStringContent(repository, commit.getTree(), "missing.txt"); + + // manually construct a blob, calculate the hash, lookup the hash in git + StringBuilder sb = new StringBuilder(); + sb.append("blob ").append(contentA.length()).append('\0'); + sb.append(contentA); + String sha1 = StringUtils.getSHA1(sb.toString()); + String contentD = JGitUtils.getStringContent(repository, sha1); + repository.close(); + assertTrue("ContentA is null!", contentA != null && contentA.length() > 0); + assertTrue("ContentB is null!", contentB != null && contentB.length() > 0); + assertTrue(contentA.equals(contentB)); + assertNull(contentC); + assertTrue(contentA.equals(contentD)); + } + + @Test + public void testFilesInCommit() throws Exception { + Repository repository = GitBlitSuite.getHelloworldRepository(); + RevCommit commit = JGitUtils.getCommit(repository, + "1d0c2933a4ae69c362f76797d42d6bd182d05176"); + List paths = JGitUtils.getFilesInCommit(repository, commit); + + commit = JGitUtils.getCommit(repository, "af0e9b2891fda85afc119f04a69acf7348922830"); + List deletions = JGitUtils.getFilesInCommit(repository, commit); + + commit = JGitUtils.getFirstCommit(repository, null); + List additions = JGitUtils.getFilesInCommit(repository, commit); + + List latestChanges = JGitUtils.getFilesInCommit(repository, null); + + repository.close(); + assertTrue("No changed paths found!", paths.size() == 1); + for (PathChangeModel path : paths) { + assertTrue("PathChangeModel hashcode incorrect!", + path.hashCode() == (path.commitId.hashCode() + path.path.hashCode())); + assertTrue("PathChangeModel equals itself failed!", path.equals(path)); + assertFalse("PathChangeModel equals string failed!", path.equals("")); + } + assertEquals(ChangeType.DELETE, deletions.get(0).changeType); + assertEquals(ChangeType.ADD, additions.get(0).changeType); + assertTrue(latestChanges.size() > 0); + } + + @Test + public void testFilesInPath() throws Exception { + assertEquals(0, JGitUtils.getFilesInPath(null, null, null).size()); + Repository repository = GitBlitSuite.getHelloworldRepository(); + List files = JGitUtils.getFilesInPath(repository, null, null); + repository.close(); + assertTrue(files.size() > 10); + } + + @Test + public void testDocuments() throws Exception { + Repository repository = GitBlitSuite.getTicgitRepository(); + List extensions = GitBlit.getStrings(Keys.web.markdownExtensions); + List markdownDocs = JGitUtils.getDocuments(repository, extensions); + List markdownDocs2 = JGitUtils.getDocuments(repository, + Arrays.asList(new String[] { ".mkd", ".md" })); + List allFiles = JGitUtils.getDocuments(repository, null); + repository.close(); + assertTrue(markdownDocs.size() > 0); + assertTrue(markdownDocs2.size() > 0); + assertTrue(allFiles.size() > markdownDocs.size()); + } + + @Test + public void testFileModes() throws Exception { + assertEquals("drwxr-xr-x", JGitUtils.getPermissionsFromMode(FileMode.TREE.getBits())); + assertEquals("-rw-r--r--", + JGitUtils.getPermissionsFromMode(FileMode.REGULAR_FILE.getBits())); + assertEquals("-rwxr-xr-x", + JGitUtils.getPermissionsFromMode(FileMode.EXECUTABLE_FILE.getBits())); + assertEquals("symlink", JGitUtils.getPermissionsFromMode(FileMode.SYMLINK.getBits())); + assertEquals("submodule", JGitUtils.getPermissionsFromMode(FileMode.GITLINK.getBits())); + assertEquals("missing", JGitUtils.getPermissionsFromMode(FileMode.MISSING.getBits())); + } + + @Test + public void testRevlog() throws Exception { + assertTrue(JGitUtils.getRevLog(null, 0).size() == 0); + List commits = JGitUtils.getRevLog(null, 10); + assertEquals(0, commits.size()); + + Repository repository = GitBlitSuite.getHelloworldRepository(); + // get most recent 10 commits + commits = JGitUtils.getRevLog(repository, 10); + assertEquals(10, commits.size()); + + // test paging and offset by getting the 10th most recent commit + RevCommit lastCommit = JGitUtils.getRevLog(repository, null, 9, 1).get(0); + assertEquals(lastCommit, commits.get(9)); + + // grab the two most recent commits to java.java + commits = JGitUtils.getRevLog(repository, null, "java.java", 0, 2); + assertEquals(2, commits.size()); + + // grab the commits since 2008-07-15 + commits = JGitUtils.getRevLog(repository, null, + new SimpleDateFormat("yyyy-MM-dd").parse("2008-07-15")); + assertEquals(12, commits.size()); + repository.close(); + } + + @Test + public void testRevLogRange() throws Exception { + Repository repository = GitBlitSuite.getHelloworldRepository(); + List commits = JGitUtils.getRevLog(repository, + "fbd14fa6d1a01d4aefa1fca725792683800fc67e", + "85a0e4087b8439c0aa6b1f4f9e08c26052ab7e87"); + repository.close(); + assertEquals(14, commits.size()); + } + + @Test + public void testSearchTypes() throws Exception { + assertEquals(SearchType.COMMIT, SearchType.forName("commit")); + assertEquals(SearchType.COMMITTER, SearchType.forName("committer")); + assertEquals(SearchType.AUTHOR, SearchType.forName("author")); + assertEquals(SearchType.COMMIT, SearchType.forName("unknown")); + + assertEquals("commit", SearchType.COMMIT.toString()); + assertEquals("committer", SearchType.COMMITTER.toString()); + assertEquals("author", SearchType.AUTHOR.toString()); + } + + @Test + public void testSearchRevlogs() throws Exception { + assertEquals(0, JGitUtils.searchRevlogs(null, null, "java", SearchType.COMMIT, 0, 0).size()); + List results = JGitUtils.searchRevlogs(null, null, "java", SearchType.COMMIT, 0, + 3); + assertEquals(0, results.size()); + + // test commit message search + Repository repository = GitBlitSuite.getHelloworldRepository(); + results = JGitUtils.searchRevlogs(repository, null, "java", SearchType.COMMIT, 0, 3); + assertEquals(3, results.size()); + + // test author search + results = JGitUtils.searchRevlogs(repository, null, "timothy", SearchType.AUTHOR, 0, -1); + assertEquals(1, results.size()); + + // test committer search + results = JGitUtils.searchRevlogs(repository, null, "mike", SearchType.COMMITTER, 0, 10); + assertEquals(10, results.size()); + + // test paging and offset + RevCommit commit = JGitUtils.searchRevlogs(repository, null, "mike", SearchType.COMMITTER, + 9, 1).get(0); + assertEquals(results.get(9), commit); + + repository.close(); + } + + @Test + public void testZip() throws Exception { + assertFalse(CompressionUtils.zip(null, null, null, null)); + Repository repository = GitBlitSuite.getHelloworldRepository(); + File zipFileA = new File(GitBlitSuite.REPOSITORIES, "helloworld.zip"); + FileOutputStream fosA = new FileOutputStream(zipFileA); + boolean successA = CompressionUtils.zip(repository, null, Constants.HEAD, fosA); + fosA.close(); + + File zipFileB = new File(GitBlitSuite.REPOSITORIES, "helloworld-java.zip"); + FileOutputStream fosB = new FileOutputStream(zipFileB); + boolean successB = CompressionUtils.zip(repository, "java.java", Constants.HEAD, fosB); + fosB.close(); + + repository.close(); + assertTrue("Failed to generate zip file!", successA); + assertTrue(zipFileA.length() > 0); + zipFileA.delete(); + + assertTrue("Failed to generate zip file!", successB); + assertTrue(zipFileB.length() > 0); + zipFileB.delete(); + } + +} \ No newline at end of file diff --git a/src/test/java/com/gitblit/tests/JsonUtilsTest.java b/src/test/java/com/gitblit/tests/JsonUtilsTest.java new file mode 100644 index 00000000..cf058441 --- /dev/null +++ b/src/test/java/com/gitblit/tests/JsonUtilsTest.java @@ -0,0 +1,61 @@ +/* + * Copyright 2011 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import org.junit.Test; + +import com.gitblit.utils.JsonUtils; +import com.google.gson.reflect.TypeToken; + +public class JsonUtilsTest { + + @Test + public void testSerialization() { + Map map = new HashMap(); + map.put("a", "alligator"); + map.put("b", "bear"); + map.put("c", "caterpillar"); + map.put("d", "dingo"); + map.put("e", "eagle"); + String json = JsonUtils.toJsonString(map); + assertEquals( + "{\n \"d\": \"dingo\",\n \"e\": \"eagle\",\n \"b\": \"bear\",\n \"c\": \"caterpillar\",\n \"a\": \"alligator\"\n}", + json); + Map map2 = JsonUtils.fromJsonString(json, + new TypeToken>() { + }.getType()); + assertEquals(map, map2); + + SomeJsonObject someJson = new SomeJsonObject(); + json = JsonUtils.toJsonString(someJson); + SomeJsonObject someJson2 = JsonUtils.fromJsonString(json, SomeJsonObject.class); + assertEquals(someJson.name, someJson2.name); + SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd HHmmss"); + assertEquals(df.format(someJson.date), df.format(someJson2.date)); + } + + private class SomeJsonObject { + Date date = new Date(); + String name = "myJson"; + } +} \ No newline at end of file diff --git a/src/test/java/com/gitblit/tests/LdapUserServiceTest.java b/src/test/java/com/gitblit/tests/LdapUserServiceTest.java new file mode 100644 index 00000000..a928f4a5 --- /dev/null +++ b/src/test/java/com/gitblit/tests/LdapUserServiceTest.java @@ -0,0 +1,174 @@ +/* + * Copyright 2012 John Crygier + * Copyright 2012 gitblit.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.gitblit.LdapUserService; +import com.gitblit.models.UserModel; +import com.gitblit.tests.mock.MemorySettings; +import com.gitblit.utils.StringUtils; +import com.unboundid.ldap.listener.InMemoryDirectoryServer; +import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig; +import com.unboundid.ldap.listener.InMemoryListenerConfig; +import com.unboundid.ldif.LDIFReader; + +/** + * An Integration test for LDAP that tests going against an in-memory UnboundID + * LDAP server. + * + * @author jcrygier + * + */ +public class LdapUserServiceTest { + + private LdapUserService ldapUserService; + + static int ldapPort = 1389; + + @BeforeClass + public static void createInMemoryLdapServer() throws Exception { + InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig("dc=MyDomain"); + config.addAdditionalBindCredentials("cn=Directory Manager", "password"); + config.setListenerConfigs(InMemoryListenerConfig.createLDAPConfig("default", ldapPort)); + config.setSchema(null); + + InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config); + ds.importFromLDIF(true, new LDIFReader(LdapUserServiceTest.class.getResourceAsStream("resources/ldapUserServiceSampleData.ldif"))); + ds.startListening(); + } + + @Before + public void createLdapUserService() { + ldapUserService = new LdapUserService(); + ldapUserService.setup(getSettings()); + } + + private MemorySettings getSettings() { + Map backingMap = new HashMap(); + backingMap.put("realm.ldap.server", "ldap://localhost:" + ldapPort); + backingMap.put("realm.ldap.domain", ""); + backingMap.put("realm.ldap.username", "cn=Directory Manager"); + backingMap.put("realm.ldap.password", "password"); + backingMap.put("realm.ldap.backingUserService", "users.conf"); + backingMap.put("realm.ldap.maintainTeams", "true"); + backingMap.put("realm.ldap.accountBase", "OU=Users,OU=UserControl,OU=MyOrganization,DC=MyDomain"); + backingMap.put("realm.ldap.accountPattern", "(&(objectClass=person)(sAMAccountName=${username}))"); + backingMap.put("realm.ldap.groupBase", "OU=Groups,OU=UserControl,OU=MyOrganization,DC=MyDomain"); + backingMap.put("realm.ldap.groupPattern", "(&(objectClass=group)(member=${dn}))"); + backingMap.put("realm.ldap.admins", "UserThree @Git_Admins \"@Git Admins\""); + backingMap.put("realm.ldap.displayName", "displayName"); + backingMap.put("realm.ldap.email", "email"); + + MemorySettings ms = new MemorySettings(backingMap); + return ms; + } + + @Test + public void testAuthenticate() { + UserModel userOneModel = ldapUserService.authenticate("UserOne", "userOnePassword".toCharArray()); + assertNotNull(userOneModel); + assertNotNull(userOneModel.getTeam("git_admins")); + assertNotNull(userOneModel.getTeam("git_users")); + assertTrue(userOneModel.canAdmin); + + UserModel userOneModelFailedAuth = ldapUserService.authenticate("UserOne", "userTwoPassword".toCharArray()); + assertNull(userOneModelFailedAuth); + + UserModel userTwoModel = ldapUserService.authenticate("UserTwo", "userTwoPassword".toCharArray()); + assertNotNull(userTwoModel); + assertNotNull(userTwoModel.getTeam("git_users")); + assertNull(userTwoModel.getTeam("git_admins")); + assertNotNull(userTwoModel.getTeam("git admins")); + assertTrue(userTwoModel.canAdmin); + + UserModel userThreeModel = ldapUserService.authenticate("UserThree", "userThreePassword".toCharArray()); + assertNotNull(userThreeModel); + assertNotNull(userThreeModel.getTeam("git_users")); + assertNull(userThreeModel.getTeam("git_admins")); + assertTrue(userThreeModel.canAdmin); + } + + @Test + public void testDisplayName() { + UserModel userOneModel = ldapUserService.authenticate("UserOne", "userOnePassword".toCharArray()); + assertNotNull(userOneModel); + assertEquals("User One", userOneModel.displayName); + + // Test more complicated scenarios - concat + MemorySettings ms = getSettings(); + ms.put("realm.ldap.displayName", "${personalTitle}. ${givenName} ${surname}"); + ldapUserService = new LdapUserService(); + ldapUserService.setup(ms); + + userOneModel = ldapUserService.authenticate("UserOne", "userOnePassword".toCharArray()); + assertNotNull(userOneModel); + assertEquals("Mr. User One", userOneModel.displayName); + } + + @Test + public void testEmail() { + UserModel userOneModel = ldapUserService.authenticate("UserOne", "userOnePassword".toCharArray()); + assertNotNull(userOneModel); + assertEquals("userone@gitblit.com", userOneModel.emailAddress); + + // Test more complicated scenarios - concat + MemorySettings ms = getSettings(); + ms.put("realm.ldap.email", "${givenName}.${surname}@gitblit.com"); + ldapUserService = new LdapUserService(); + ldapUserService.setup(ms); + + userOneModel = ldapUserService.authenticate("UserOne", "userOnePassword".toCharArray()); + assertNotNull(userOneModel); + assertEquals("User.One@gitblit.com", userOneModel.emailAddress); + } + + @Test + public void testLdapInjection() { + // Inject so "(&(objectClass=person)(sAMAccountName=${username}))" becomes "(&(objectClass=person)(sAMAccountName=*)(userPassword=userOnePassword))" + // Thus searching by password + + UserModel userOneModel = ldapUserService.authenticate("*)(userPassword=userOnePassword", "userOnePassword".toCharArray()); + assertNull(userOneModel); + } + + @Test + public void testLocalAccount() { + UserModel localAccount = new UserModel("bruce"); + localAccount.displayName = "Bruce Campbell"; + localAccount.password = StringUtils.MD5_TYPE + StringUtils.getMD5("gimmesomesugar"); + ldapUserService.deleteUser(localAccount.username); + assertTrue("Failed to add local account", + ldapUserService.updateUserModel(localAccount)); + assertEquals("Accounts are not equal!", + localAccount, + ldapUserService.authenticate(localAccount.username, "gimmesomesugar".toCharArray())); + assertTrue("Failed to delete local account!", + ldapUserService.deleteUser(localAccount.username)); + } + +} diff --git a/src/test/java/com/gitblit/tests/LuceneExecutorTest.java b/src/test/java/com/gitblit/tests/LuceneExecutorTest.java new file mode 100644 index 00000000..6b45b9fe --- /dev/null +++ b/src/test/java/com/gitblit/tests/LuceneExecutorTest.java @@ -0,0 +1,181 @@ +/* + * Copyright 2012 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.jgit.lib.Repository; +import org.junit.Test; + +import com.gitblit.LuceneExecutor; +import com.gitblit.models.RefModel; +import com.gitblit.models.RepositoryModel; +import com.gitblit.models.SearchResult; +import com.gitblit.tests.mock.MemorySettings; +import com.gitblit.utils.FileUtils; +import com.gitblit.utils.JGitUtils; + +/** + * Tests Lucene indexing and querying. + * + * @author James Moger + * + */ +public class LuceneExecutorTest { + + private LuceneExecutor newLuceneExecutor() { + Map map = new HashMap(); + MemorySettings settings = new MemorySettings(map); + return new LuceneExecutor(settings, GitBlitSuite.REPOSITORIES); + } + + private RepositoryModel newRepositoryModel(Repository repository) { + RepositoryModel model = new RepositoryModel(); + model.name = FileUtils.getRelativePath(GitBlitSuite.REPOSITORIES, repository.getDirectory()); + model.hasCommits = JGitUtils.hasCommits(repository); + + // index all local branches + model.indexedBranches = new ArrayList(); + for (RefModel ref : JGitUtils.getLocalBranches(repository, true, -1)) { + model.indexedBranches.add(ref.getName()); + } + return model; + } + + @Test + public void testIndex() throws Exception { + LuceneExecutor lucene = newLuceneExecutor(); + + // reindex helloworld + Repository repository = GitBlitSuite.getHelloworldRepository(); + RepositoryModel model = newRepositoryModel(repository); + lucene.reindex(model, repository); + repository.close(); + + SearchResult result = lucene.search("type:blob AND path:bit.bit", 1, 1, model.name).get(0); + assertEquals("Mike Donaghy", result.author); + result = lucene.search("type:blob AND path:clipper.prg", 1, 1, model.name).get(0); + assertEquals("tinogomes", result.author); + + // reindex theoretical physics + repository = GitBlitSuite.getTheoreticalPhysicsRepository(); + model = newRepositoryModel(repository); + lucene.reindex(model, repository); + repository.close(); + + // reindex JGit + repository = GitBlitSuite.getJGitRepository(); + model = newRepositoryModel(repository); + lucene.reindex(model, repository); + repository.close(); + + lucene.close(); + } + + @Test + public void testQuery() throws Exception { + LuceneExecutor lucene = new LuceneExecutor(null, GitBlitSuite.REPOSITORIES); + + // 2 occurrences on the master branch + Repository repository = GitBlitSuite.getHelloworldRepository(); + RepositoryModel model = newRepositoryModel(repository); + repository.close(); + + List results = lucene.search("ada", 1, 10, model.name); + assertEquals(2, results.size()); + for (SearchResult res : results) { + assertEquals("refs/heads/master", res.branch); + } + + // author test + results = lucene.search("author: tinogomes AND type:commit", 1, 10, model.name); + assertEquals(2, results.size()); + + // blob test + results = lucene.search("type: blob AND \"import std.stdio\"", 1, 10, model.name); + assertEquals(1, results.size()); + assertEquals("d.D", results.get(0).path); + + // 1 occurrence on the gh-pages branch + repository = GitBlitSuite.getTheoreticalPhysicsRepository(); + model = newRepositoryModel(repository); + repository.close(); + + results = lucene.search("\"add the .nojekyll file\"", 1, 10, model.name); + assertEquals(1, results.size()); + assertEquals("Ondrej Certik", results.get(0).author); + assertEquals("2648c0c98f2101180715b4d432fc58d0e21a51d7", results.get(0).commitId); + assertEquals("refs/heads/gh-pages", results.get(0).branch); + + results = lucene.search("type:blob AND \"src/intro.rst\"", 1, 10, model.name); + assertEquals(4, results.size()); + + // hash id tests + results = lucene.search("commit:57c4f26f157ece24b02f4f10f5f68db1d2ce7ff5", 1, 10, model.name); + assertEquals(1, results.size()); + + results = lucene.search("commit:57c4f26f157*", 1, 10, model.name); + assertEquals(1, results.size()); + + // annotated tag test + repository = GitBlitSuite.getJGitRepository(); + model = newRepositoryModel(repository); + repository.close(); + + results = lucene.search("I663208919f297836a9c16bf458e4a43ffaca4c12", 1, 10, model.name); + assertEquals(1, results.size()); + assertEquals("[v1.3.0.201202151440-r]", results.get(0).tags.toString()); + + lucene.close(); + } + + @Test + public void testMultiSearch() throws Exception { + LuceneExecutor lucene = newLuceneExecutor(); + List list = new ArrayList(); + Repository repository = GitBlitSuite.getHelloworldRepository(); + list.add(newRepositoryModel(repository).name); + repository.close(); + + repository = GitBlitSuite.getJGitRepository(); + list.add(newRepositoryModel(repository).name); + repository.close(); + + List results = lucene.search("test", 1, 10, list); + lucene.close(); + assertEquals(10, results.size()); + } + + @Test + public void testDeleteBlobFromIndex() throws Exception { + // start with a fresh reindex of entire repository + LuceneExecutor lucene = newLuceneExecutor(); + Repository repository = GitBlitSuite.getHelloworldRepository(); + RepositoryModel model = newRepositoryModel(repository); + lucene.reindex(model, repository); + + // now delete a blob + assertTrue(lucene.deleteBlob(model.name, "refs/heads/master", "java.java")); + assertFalse(lucene.deleteBlob(model.name, "refs/heads/master", "java.java")); + } +} \ No newline at end of file diff --git a/src/test/java/com/gitblit/tests/MailTest.java b/src/test/java/com/gitblit/tests/MailTest.java new file mode 100644 index 00000000..05d55a24 --- /dev/null +++ b/src/test/java/com/gitblit/tests/MailTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2011 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertTrue; + +import javax.mail.Message; + +import org.junit.Test; + +import com.gitblit.FileSettings; +import com.gitblit.MailExecutor; + +public class MailTest { + + @Test + public void testSendMail() throws Exception { + FileSettings settings = new FileSettings("mailtest.properties"); + MailExecutor mail = new MailExecutor(settings); + Message message = mail.createMessageForAdministrators(); + message.setSubject("Test"); + message.setText("this is a test"); + mail.queue(message); + mail.run(); + + assertTrue("mail queue is not empty!", mail.hasEmptyQueue()); + } +} diff --git a/src/test/java/com/gitblit/tests/MarkdownUtilsTest.java b/src/test/java/com/gitblit/tests/MarkdownUtilsTest.java new file mode 100644 index 00000000..cd7ca020 --- /dev/null +++ b/src/test/java/com/gitblit/tests/MarkdownUtilsTest.java @@ -0,0 +1,54 @@ +/* + * Copyright 2011 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.text.ParseException; + +import org.junit.Test; + +import com.gitblit.utils.MarkdownUtils; + +public class MarkdownUtilsTest { + + @Test + public void testMarkdown() throws Exception { + assertEquals("

H1

", MarkdownUtils.transformMarkdown("# H1")); + assertEquals("

H2

", MarkdownUtils.transformMarkdown("## H2")); + assertEquals("

THIS is a test

", + MarkdownUtils.transformMarkdown("**THIS** is a test")); + assertEquals("

** THIS ** is a test

", + MarkdownUtils.transformMarkdown("** THIS ** is a test")); + assertEquals("

**THIS ** is a test

", + MarkdownUtils.transformMarkdown("**THIS ** is a test")); + assertEquals("

** THIS** is a test

", + MarkdownUtils.transformMarkdown("** THIS** is a test")); + + assertEquals("
test
", + MarkdownUtils.transformMarkdown("
test
")); + assertEquals("
<test>
", + MarkdownUtils.transformMarkdown("
<test>
")); + + try { + MarkdownUtils.transformMarkdown((String) null); + assertTrue(false); + } catch (ParseException p) { + assertTrue(p != null); + } + } +} \ No newline at end of file diff --git a/src/test/java/com/gitblit/tests/MetricUtilsTest.java b/src/test/java/com/gitblit/tests/MetricUtilsTest.java new file mode 100644 index 00000000..bb8261af --- /dev/null +++ b/src/test/java/com/gitblit/tests/MetricUtilsTest.java @@ -0,0 +1,54 @@ +/* + * Copyright 2011 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.List; +import java.util.TimeZone; + +import org.eclipse.jgit.lib.Repository; +import org.junit.Test; + +import com.gitblit.models.Metric; +import com.gitblit.utils.MetricUtils; + +public class MetricUtilsTest { + + @Test + public void testMetrics() throws Exception { + testMetrics(GitBlitSuite.getHelloworldRepository()); + testMetrics(GitBlitSuite.getJGitRepository()); + } + + private void testMetrics(Repository repository) throws Exception { + List metrics = MetricUtils.getDateMetrics(repository, null, true, null, + TimeZone.getDefault()); + repository.close(); + assertTrue("No date metrics found!", metrics.size() > 0); + } + + @Test + public void testAuthorMetrics() throws Exception { + Repository repository = GitBlitSuite.getHelloworldRepository(); + List byEmail = MetricUtils.getAuthorMetrics(repository, null, true); + List byName = MetricUtils.getAuthorMetrics(repository, null, false); + repository.close(); + assertEquals("No author metrics found!", 9, byEmail.size()); + assertEquals("No author metrics found!", 8, byName.size()); + } +} \ No newline at end of file diff --git a/src/test/java/com/gitblit/tests/ObjectCacheTest.java b/src/test/java/com/gitblit/tests/ObjectCacheTest.java new file mode 100644 index 00000000..8d07fe65 --- /dev/null +++ b/src/test/java/com/gitblit/tests/ObjectCacheTest.java @@ -0,0 +1,47 @@ +/* + * Copyright 2011 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.Date; + +import org.junit.Test; + +import com.gitblit.utils.ObjectCache; + +public class ObjectCacheTest { + + @Test + public void testCache() throws Exception { + ObjectCache cache = new ObjectCache(); + cache.updateObject("test", "alpha"); + Date date = cache.getDate("test"); + assertTrue("cache date is not working!", cache.hasCurrent("test", date)); + // The cache is time-based (msecs) so we insert this artificial sleep to + // ensure that time (msecs) advances. The ObjectCache class is suitable + // for Gitblit's needs but may not be suitable for other needs. + Thread.sleep(10); + cache.updateObject("test", "beta"); + assertFalse("update cache date is not working!", cache.hasCurrent("test", date)); + assertEquals("unexpected cache object", cache.getObject("test"), "beta"); + assertEquals("beta", cache.remove("test")); + assertEquals(null, cache.getObject("test")); + assertEquals(null, cache.remove("test")); + } +} diff --git a/src/test/java/com/gitblit/tests/PermissionsTest.java b/src/test/java/com/gitblit/tests/PermissionsTest.java new file mode 100644 index 00000000..5a951042 --- /dev/null +++ b/src/test/java/com/gitblit/tests/PermissionsTest.java @@ -0,0 +1,2635 @@ +/* + * Copyright 2012 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import java.util.Date; + +import junit.framework.Assert; + +import org.junit.Test; + +import com.gitblit.Constants.AccessPermission; +import com.gitblit.Constants.AccessRestrictionType; +import com.gitblit.Constants.AuthorizationControl; +import com.gitblit.models.RepositoryModel; +import com.gitblit.models.TeamModel; +import com.gitblit.models.UserModel; + +/** + * Comprehensive, brute-force test of all permutations of discrete permissions. + * + * @author James Moger + * + */ +public class PermissionsTest extends Assert { + + /** + * Admin access rights/permissions + */ + @Test + public void testAdmin() throws Exception { + UserModel user = new UserModel("admin"); + user.canAdmin = true; + + for (AccessRestrictionType ar : AccessRestrictionType.values()) { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = ar; + + assertTrue("admin CAN NOT view!", user.canView(repository)); + assertTrue("admin CAN NOT clone!", user.canClone(repository)); + assertTrue("admin CAN NOT push!", user.canPush(repository)); + + assertTrue("admin CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("admin CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("admin CAN NOT rewind ref!", user.canRewindRef(repository)); + + assertTrue("admin CAN NOT fork!", user.canFork(repository)); + + assertTrue("admin CAN NOT delete!", user.canDelete(repository)); + assertTrue("admin CAN NOT edit!", user.canEdit(repository)); + } + } + + /** + * Anonymous access rights/permissions + */ + @Test + public void testAnonymous_NONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.NONE; + + UserModel user = UserModel.ANONYMOUS; + + // all permissions, except fork + assertTrue("anonymous CAN NOT view!", user.canView(repository)); + assertTrue("anonymous CAN NOT clone!", user.canClone(repository)); + assertTrue("anonymous CAN NOT push!", user.canPush(repository)); + + assertTrue("anonymous CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("anonymous CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("anonymous CAN NOT rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + assertFalse("anonymous CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertFalse("anonymous CAN fork!", user.canFork(repository)); + + assertFalse("anonymous CAN delete!", user.canDelete(repository)); + assertFalse("anonymous CAN edit!", user.canEdit(repository)); + } + + @Test + public void testAnonymous_PUSH() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.PUSH; + + UserModel user = UserModel.ANONYMOUS; + + assertTrue("anonymous CAN NOT view!", user.canView(repository)); + assertTrue("anonymous CAN NOT clone!", user.canClone(repository)); + assertFalse("anonymous CAN push!", user.canPush(repository)); + + assertFalse("anonymous CAN create ref!", user.canCreateRef(repository)); + assertFalse("anonymous CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("anonymous CAN rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + assertFalse("anonymous CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertFalse("anonymous CAN fork!", user.canFork(repository)); + } + + @Test + public void testAnonymous_CLONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.CLONE; + + UserModel user = UserModel.ANONYMOUS; + + assertTrue("anonymous CAN NOT view!", user.canView(repository)); + assertFalse("anonymous CAN clone!", user.canClone(repository)); + assertFalse("anonymous CAN push!", user.canPush(repository)); + + assertFalse("anonymous CAN create ref!", user.canCreateRef(repository)); + assertFalse("anonymous CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("anonymous CAN rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + assertFalse("anonymous CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertFalse("anonymous CAN fork!", user.canFork(repository)); + } + + @Test + public void testAnonymous_VIEW() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + UserModel user = UserModel.ANONYMOUS; + + assertFalse("anonymous CAN view!", user.canView(repository)); + assertFalse("anonymous CAN clone!", user.canClone(repository)); + assertFalse("anonymous CAN push!", user.canPush(repository)); + + assertFalse("anonymous CAN create ref!", user.canCreateRef(repository)); + assertFalse("anonymous CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("anonymous CAN rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + assertFalse("anonymous CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertFalse("anonymous CAN fork!", user.canFork(repository)); + } + + /** + * Authenticated access rights/permissions + */ + @Test + public void testAuthenticated_NONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.AUTHENTICATED; + repository.accessRestriction = AccessRestrictionType.NONE; + + UserModel user = new UserModel("test"); + + // all permissions, except fork + assertTrue("authenticated CAN NOT view!", user.canView(repository)); + assertTrue("authenticated CAN NOT clone!", user.canClone(repository)); + assertTrue("authenticated CAN NOT push!", user.canPush(repository)); + + assertTrue("authenticated CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("authenticated CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("authenticated CAN NOT rewind ref!", user.canRewindRef(repository)); + + user.canFork = false; + repository.allowForks = false; + assertFalse("authenticated CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertFalse("authenticated CAN fork!", user.canFork(repository)); + user.canFork = true; + assertTrue("authenticated CAN NOT fork!", user.canFork(repository)); + + assertFalse("authenticated CAN delete!", user.canDelete(repository)); + assertFalse("authenticated CAN edit!", user.canEdit(repository)); + } + + @Test + public void testAuthenticated_PUSH() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.AUTHENTICATED; + repository.accessRestriction = AccessRestrictionType.PUSH; + + UserModel user = new UserModel("test"); + + assertTrue("authenticated CAN NOT view!", user.canView(repository)); + assertTrue("authenticated CAN NOT clone!", user.canClone(repository)); + assertTrue("authenticated CAN NOT push!", user.canPush(repository)); + + assertTrue("authenticated CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("authenticated CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("authenticated CAN NOT rewind ref!", user.canRewindRef(repository)); + + user.canFork = false; + repository.allowForks = false; + assertFalse("authenticated CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertFalse("authenticated CAN fork!", user.canFork(repository)); + user.canFork = true; + assertTrue("authenticated CAN NOT fork!", user.canFork(repository)); + } + + @Test + public void testAuthenticated_CLONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.AUTHENTICATED; + repository.accessRestriction = AccessRestrictionType.CLONE; + + UserModel user = new UserModel("test"); + + assertTrue("authenticated CAN NOT view!", user.canView(repository)); + assertTrue("authenticated CAN NOT clone!", user.canClone(repository)); + assertTrue("authenticated CAN NOT push!", user.canPush(repository)); + + assertTrue("authenticated CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("authenticated CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("authenticated CAN NOT rewind ref!", user.canRewindRef(repository)); + + user.canFork = false; + repository.allowForks = false; + assertFalse("authenticated CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertFalse("authenticated CAN fork!", user.canFork(repository)); + user.canFork = true; + assertTrue("authenticated CAN NOT fork!", user.canFork(repository)); + } + + @Test + public void testAuthenticated_VIEW() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.AUTHENTICATED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + UserModel user = new UserModel("test"); + + assertTrue("authenticated CAN NOT view!", user.canView(repository)); + assertTrue("authenticated CAN NOT clone!", user.canClone(repository)); + assertTrue("authenticated CAN NOT push!", user.canPush(repository)); + + assertTrue("authenticated CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("authenticated CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("authenticated CAN NOT rewind ref!", user.canRewindRef(repository)); + + user.canFork = false; + repository.allowForks = false; + assertFalse("authenticated CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertFalse("authenticated CAN fork!", user.canFork(repository)); + user.canFork = true; + assertTrue("authenticated CAN NOT fork!", user.canFork(repository)); + } + + /** + * NONE_NONE = NO access restriction, NO access permission + */ + @Test + public void testNamed_NONE_NONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.NONE; + + UserModel user = new UserModel("test"); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertTrue("named CAN NOT clone!", user.canClone(repository)); + assertTrue("named CAN NOT push!", user.canPush(repository)); + + assertTrue("named CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("named CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("named CAN NOT rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertTrue("named CAN NOT fork!", user.canFork(repository)); + + assertFalse("named CAN delete!", user.canDelete(repository)); + assertFalse("named CAN edit!", user.canEdit(repository)); + } + + /** + * PUSH_NONE = PUSH access restriction, NO access permission + */ + @Test + public void testNamed_PUSH_NONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.PUSH; + + UserModel user = new UserModel("test"); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertTrue("named CAN NOT clone!", user.canClone(repository)); + assertFalse("named CAN push!", user.canPush(repository)); + + assertFalse("named CAN create ref!", user.canCreateRef(repository)); + assertFalse("named CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("named CAN rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertTrue("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * CLONE_NONE = CLONE access restriction, NO access permission + */ + @Test + public void testNamed_CLONE_NONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.CLONE; + + UserModel user = new UserModel("test"); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertFalse("named CAN clone!", user.canClone(repository)); + assertFalse("named CAN push!", user.canPush(repository)); + + assertFalse("named CAN create ref!", user.canCreateRef(repository)); + assertFalse("named CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("named CAN rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertFalse("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * VIEW_NONE = VIEW access restriction, NO access permission + */ + @Test + public void testNamed_VIEW_NONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + UserModel user = new UserModel("test"); + + assertFalse("named CAN view!", user.canView(repository)); + assertFalse("named CAN clone!", user.canClone(repository)); + assertFalse("named CAN push!", user.canPush(repository)); + + assertFalse("named CAN create ref!", user.canCreateRef(repository)); + assertFalse("named CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("named CAN rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertFalse("named CAN NOT fork!", user.canFork(repository)); + } + + + /** + * NONE_VIEW = NO access restriction, VIEW access permission. + * (not useful scenario) + */ + @Test + public void testNamed_NONE_VIEW() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.NONE; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(repository.name, AccessPermission.VIEW); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertTrue("named CAN NOT clone!", user.canClone(repository)); + assertTrue("named CAN NOT push!", user.canPush(repository)); + + assertTrue("named CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("named CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("named CAN NOT rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertTrue("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * PUSH_VIEW = PUSH access restriction, VIEW access permission + */ + @Test + public void testNamed_PUSH_VIEW() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.PUSH; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(repository.name, AccessPermission.VIEW); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertTrue("named CAN NOT clone!", user.canClone(repository)); + assertFalse("named CAN push!", user.canPush(repository)); + + assertFalse("named CAN create ref!", user.canCreateRef(repository)); + assertFalse("named CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("named CAN rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertTrue("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * CLONE_VIEW = CLONE access restriction, VIEW access permission + */ + @Test + public void testNamed_CLONE_VIEW() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.CLONE; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(repository.name, AccessPermission.VIEW); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertFalse("named CAN clone!", user.canClone(repository)); + assertFalse("named CAN push!", user.canPush(repository)); + + assertFalse("named CAN create ref!", user.canCreateRef(repository)); + assertFalse("named CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("named CAN rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertFalse("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * VIEW_VIEW = VIEW access restriction, VIEW access permission + */ + @Test + public void testNamed_VIEW_VIEW() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(repository.name, AccessPermission.VIEW); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertFalse("named CAN clone!", user.canClone(repository)); + assertFalse("named CAN push!", user.canPush(repository)); + + assertFalse("named CAN create ref!", user.canCreateRef(repository)); + assertFalse("named CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("named CAN rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertFalse("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * NONE_CLONE = NO access restriction, CLONE access permission. + * (not useful scenario) + */ + @Test + public void testNamed_NONE_CLONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.NONE; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(repository.name, AccessPermission.CLONE); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertTrue("named CAN NOT clone!", user.canClone(repository)); + assertTrue("named CAN NOT push!", user.canPush(repository)); + + assertTrue("named CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("named CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("named CAN NOT rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertTrue("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * PUSH_CLONE = PUSH access restriction, CLONE access permission + */ + @Test + public void testNamed_PUSH_READ() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.PUSH; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(repository.name, AccessPermission.CLONE); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertTrue("named CAN NOT clone!", user.canClone(repository)); + assertFalse("named CAN push!", user.canPush(repository)); + + assertFalse("named CAN create ref!", user.canCreateRef(repository)); + assertFalse("named CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("named CAN rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertTrue("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * CLONE_CLONE = CLONE access restriction, CLONE access permission + */ + @Test + public void testNamed_CLONE_CLONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.CLONE; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(repository.name, AccessPermission.CLONE); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertTrue("named CAN NOT clone!", user.canClone(repository)); + assertFalse("named CAN push!", user.canPush(repository)); + + assertFalse("named CAN create ref!", user.canCreateRef(repository)); + assertFalse("named CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("named CAN rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertTrue("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * VIEW_CLONE = VIEW access restriction, CLONE access permission + */ + @Test + public void testNamed_VIEW_CLONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(repository.name, AccessPermission.CLONE); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertTrue("named CAN NOT clone!", user.canClone(repository)); + assertFalse("named CAN push!", user.canPush(repository)); + + assertFalse("named CAN create ref!", user.canCreateRef(repository)); + assertFalse("named CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("named CAN rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertTrue("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * NONE_PUSH = NO access restriction, PUSH access permission. + * (not useful scenario) + */ + @Test + public void testNamed_NONE_PUSH() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.NONE; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(repository.name, AccessPermission.PUSH); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertTrue("named CAN NOT clone!", user.canClone(repository)); + assertTrue("named CAN NOT push!", user.canPush(repository)); + + assertTrue("named CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("named CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("named CAN NOT rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertTrue("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * PUSH_PUSH = PUSH access restriction, PUSH access permission + */ + @Test + public void testNamed_PUSH_PUSH() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.PUSH; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(repository.name, AccessPermission.PUSH); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertTrue("named CAN NOT clone!", user.canClone(repository)); + assertTrue("named CAN NOT push!", user.canPush(repository)); + + assertFalse("named CAN create ref!", user.canCreateRef(repository)); + assertFalse("named CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("named CAN rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertTrue("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * CLONE_PUSH = CLONE access restriction, PUSH access permission + */ + @Test + public void testNamed_CLONE_PUSH() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.CLONE; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(repository.name, AccessPermission.PUSH); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertTrue("named CAN NOT clone!", user.canClone(repository)); + assertTrue("named CAN NOT push!", user.canPush(repository)); + + assertFalse("named CAN create ref!", user.canCreateRef(repository)); + assertFalse("named CAN delete red!", user.canDeleteRef(repository)); + assertFalse("named CAN rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertTrue("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * VIEW_PUSH = VIEW access restriction, PUSH access permission + */ + @Test + public void testNamed_VIEW_PUSH() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(repository.name, AccessPermission.PUSH); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertTrue("named CAN NOT clone!", user.canClone(repository)); + assertTrue("named CAN not push!", user.canPush(repository)); + + assertFalse("named CAN create ref!", user.canCreateRef(repository)); + assertFalse("named CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("named CAN rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertTrue("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * NONE_CREATE = NO access restriction, CREATE access permission. + * (not useful scenario) + */ + @Test + public void testNamed_NONE_CREATE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.NONE; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(repository.name, AccessPermission.CREATE); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertTrue("named CAN NOT clone!", user.canClone(repository)); + assertTrue("named CAN NOT push!", user.canPush(repository)); + + assertTrue("named CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("named CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("named CAN NOT rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertTrue("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * PUSH_CREATE = PUSH access restriction, CREATE access permission + */ + @Test + public void testNamed_PUSH_CREATE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.PUSH; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(repository.name, AccessPermission.CREATE); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertTrue("named CAN NOT clone!", user.canClone(repository)); + assertTrue("named CAN NOT push!", user.canPush(repository)); + + assertTrue("named CAN NOT create ref!", user.canCreateRef(repository)); + assertFalse("named CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("named CAN rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertTrue("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * CLONE_CREATE = CLONE access restriction, CREATE access permission + */ + @Test + public void testNamed_CLONE_CREATE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.CLONE; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(repository.name, AccessPermission.CREATE); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertTrue("named CAN NOT clone!", user.canClone(repository)); + assertTrue("named CAN NOT push!", user.canPush(repository)); + + assertTrue("named CAN NOT create ref!", user.canCreateRef(repository)); + assertFalse("named CAN delete red!", user.canDeleteRef(repository)); + assertFalse("named CAN rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertTrue("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * VIEW_CREATE = VIEW access restriction, CREATE access permission + */ + @Test + public void testNamed_VIEW_CREATE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(repository.name, AccessPermission.CREATE); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertTrue("named CAN NOT clone!", user.canClone(repository)); + assertTrue("named CAN not push!", user.canPush(repository)); + + assertTrue("named CAN NOT create ref!", user.canCreateRef(repository)); + assertFalse("named CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("named CAN rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertTrue("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * NONE_DELETE = NO access restriction, DELETE access permission. + * (not useful scenario) + */ + @Test + public void testNamed_NONE_DELETE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.NONE; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(repository.name, AccessPermission.DELETE); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertTrue("named CAN NOT clone!", user.canClone(repository)); + assertTrue("named CAN NOT push!", user.canPush(repository)); + + assertTrue("named CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("named CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("named CAN NOT rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertTrue("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * PUSH_DELETE = PUSH access restriction, DELETE access permission + */ + @Test + public void testNamed_PUSH_DELETE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.PUSH; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(repository.name, AccessPermission.DELETE); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertTrue("named CAN NOT clone!", user.canClone(repository)); + assertTrue("named CAN NOT push!", user.canPush(repository)); + + assertTrue("named CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("named CAN NOT delete ref!", user.canDeleteRef(repository)); + assertFalse("named CAN rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertTrue("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * CLONE_DELETE = CLONE access restriction, DELETE access permission + */ + @Test + public void testNamed_CLONE_DELETE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.CLONE; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(repository.name, AccessPermission.DELETE); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertTrue("named CAN NOT clone!", user.canClone(repository)); + assertTrue("named CAN NOT push!", user.canPush(repository)); + + assertTrue("named CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("named CAN NOT delete red!", user.canDeleteRef(repository)); + assertFalse("named CAN rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertTrue("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * VIEW_DELETE = VIEW access restriction, DELETE access permission + */ + @Test + public void testNamed_VIEW_DELETE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(repository.name, AccessPermission.DELETE); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertTrue("named CAN NOT clone!", user.canClone(repository)); + assertTrue("named CAN not push!", user.canPush(repository)); + + assertTrue("named CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("named CAN NOT delete ref!", user.canDeleteRef(repository)); + assertFalse("named CAN rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertTrue("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * NONE_REWIND = NO access restriction, REWIND access permission. + * (not useful scenario) + */ + @Test + public void testNamed_NONE_REWIND() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.NONE; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(repository.name, AccessPermission.REWIND); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertTrue("named CAN NOT clone!", user.canClone(repository)); + assertTrue("named CAN NOT push!", user.canPush(repository)); + + assertTrue("named CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("named CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("named CAN NOT rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertTrue("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * PUSH_REWIND = PUSH access restriction, REWIND access permission + */ + @Test + public void testNamed_PUSH_REWIND() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.PUSH; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(repository.name, AccessPermission.REWIND); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertTrue("named CAN NOT clone!", user.canClone(repository)); + assertTrue("named CAN NOT push!", user.canPush(repository)); + + assertTrue("named CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("named CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("named CAN NOT rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertTrue("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * CLONE_REWIND = CLONE access restriction, REWIND access permission + */ + @Test + public void testNamed_CLONE_REWIND() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.CLONE; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(repository.name, AccessPermission.REWIND); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertTrue("named CAN NOT clone!", user.canClone(repository)); + assertTrue("named CAN NOT push!", user.canPush(repository)); + + assertTrue("named CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("named CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("named CAN NOT rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertTrue("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * VIEW_REWIND = VIEW access restriction, REWIND access permission + */ + @Test + public void testNamed_VIEW_REWIND() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(repository.name, AccessPermission.REWIND); + + assertTrue("named CAN NOT view!", user.canView(repository)); + assertTrue("named CAN NOT clone!", user.canClone(repository)); + assertTrue("named CAN NOT push!", user.canPush(repository)); + + assertTrue("named CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("named CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("named CAN NOT rewind ref!", user.canRewindRef(repository)); + + repository.allowForks = false; + user.canFork = false; + assertFalse("named CAN fork!", user.canFork(repository)); + user.canFork = true; + assertFalse("named CAN fork!", user.canFork(repository)); + repository.allowForks = true; + assertTrue("named CAN NOT fork!", user.canFork(repository)); + } + + /** + * NONE_NONE = NO access restriction, NO access permission + */ + @Test + public void testTeam_NONE_NONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.NONE; + + TeamModel team = new TeamModel("test"); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertTrue("team CAN NOT clone!", team.canClone(repository)); + assertTrue("team CAN NOT push!", team.canPush(repository)); + + assertTrue("team CAN NOT create ref!", team.canCreateRef(repository)); + assertTrue("team CAN NOT delete ref!", team.canDeleteRef(repository)); + assertTrue("team CAN NOT rewind ref!", team.canRewindRef(repository)); + } + + /** + * PUSH_NONE = PUSH access restriction, NO access permission + */ + @Test + public void testTeam_PUSH_NONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.PUSH; + + TeamModel team = new TeamModel("test"); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertTrue("team CAN NOT clone!", team.canClone(repository)); + assertFalse("team CAN push!", team.canPush(repository)); + + assertFalse("team CAN create ref!", team.canCreateRef(repository)); + assertFalse("team CAN delete ref!", team.canDeleteRef(repository)); + assertFalse("team CAN rewind ref!", team.canRewindRef(repository)); + } + + /** + * CLONE_NONE = CLONE access restriction, NO access permission + */ + @Test + public void testTeam_CLONE_NONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.CLONE; + + TeamModel team = new TeamModel("test"); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertFalse("team CAN clone!", team.canClone(repository)); + assertFalse("team CAN push!", team.canPush(repository)); + + assertFalse("team CAN create ref!", team.canCreateRef(repository)); + assertFalse("team CAN delete ref!", team.canDeleteRef(repository)); + assertFalse("team CAN rewind ref!", team.canRewindRef(repository)); + } + + /** + * VIEW_NONE = VIEW access restriction, NO access permission + */ + @Test + public void testTeam_VIEW_NONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + TeamModel team = new TeamModel("test"); + + assertFalse("team CAN view!", team.canView(repository)); + assertFalse("team CAN clone!", team.canClone(repository)); + assertFalse("team CAN push!", team.canPush(repository)); + + assertFalse("team CAN create ref!", team.canCreateRef(repository)); + assertFalse("team CAN delete ref!", team.canDeleteRef(repository)); + assertFalse("team CAN rewind ref!", team.canRewindRef(repository)); + } + + /** + * NONE_PUSH = NO access restriction, PUSH access permission + * (not useful scenario) + */ + @Test + public void testTeam_NONE_PUSH() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.NONE; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.PUSH); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertTrue("team CAN NOT clone!", team.canClone(repository)); + assertTrue("team CAN NOT push!", team.canPush(repository)); + + assertTrue("team CAN NOT create ref!", team.canCreateRef(repository)); + assertTrue("team CAN NOT delete ref!", team.canDeleteRef(repository)); + assertTrue("team CAN NOT rewind ref!", team.canRewindRef(repository)); + } + + /** + * PUSH_PUSH = PUSH access restriction, PUSH access permission + */ + @Test + public void testTeam_PUSH_PUSH() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.PUSH; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.PUSH); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertTrue("team CAN NOT clone!", team.canClone(repository)); + assertTrue("team CAN NOT push!", team.canPush(repository)); + + assertFalse("team CAN create ref!", team.canCreateRef(repository)); + assertFalse("team CAN delete ref!", team.canDeleteRef(repository)); + assertFalse("team CAN rewind ref!", team.canRewindRef(repository)); + } + + /** + * CLONE_PUSH = CLONE access restriction, PUSH access permission + */ + @Test + public void testTeam_CLONE_PUSH() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.CLONE; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.PUSH); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertTrue("team CAN NOT clone!", team.canClone(repository)); + assertTrue("team CAN NOT push!", team.canPush(repository)); + + assertFalse("team CAN create ref!", team.canCreateRef(repository)); + assertFalse("team CAN delete ref!", team.canDeleteRef(repository)); + assertFalse("team CAN rewind ref!", team.canRewindRef(repository)); + } + + /** + * VIEW_PUSH = VIEW access restriction, PUSH access permission + */ + @Test + public void testTeam_VIEW_PUSH() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.PUSH); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertTrue("team CAN NOT clone!", team.canClone(repository)); + assertTrue("team CAN NOT push!", team.canPush(repository)); + + assertFalse("team CAN create ref!", team.canCreateRef(repository)); + assertFalse("team CAN delete ref!", team.canDeleteRef(repository)); + assertFalse("team CAN rewind ref!", team.canRewindRef(repository)); + } + + /** + * NONE_CREATE = NO access restriction, CREATE access permission + * (not useful scenario) + */ + @Test + public void testTeam_NONE_CREATE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.NONE; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.CREATE); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertTrue("team CAN NOT clone!", team.canClone(repository)); + assertTrue("team CAN NOT push!", team.canPush(repository)); + + assertTrue("team CAN NOT create ref!", team.canCreateRef(repository)); + assertTrue("team CAN NOT delete ref!", team.canDeleteRef(repository)); + assertTrue("team CAN NOT rewind ref!", team.canRewindRef(repository)); + } + + /** + * PUSH_CREATE = PUSH access restriction, CREATE access permission + */ + @Test + public void testTeam_PUSH_CREATE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.PUSH; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.CREATE); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertTrue("team CAN NOT clone!", team.canClone(repository)); + assertTrue("team CAN NOT push!", team.canPush(repository)); + + assertTrue("team CAN NOT create ref!", team.canCreateRef(repository)); + assertFalse("team CAN delete ref!", team.canDeleteRef(repository)); + assertFalse("team CAN rewind ref!", team.canRewindRef(repository)); + } + + /** + * CLONE_CREATE = CLONE access restriction, CREATE access permission + */ + @Test + public void testTeam_CLONE_CREATE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.CLONE; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.CREATE); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertTrue("team CAN NOT clone!", team.canClone(repository)); + assertTrue("team CAN NOT push!", team.canPush(repository)); + + assertTrue("team CAN NOT create ref!", team.canCreateRef(repository)); + assertFalse("team CAN delete ref!", team.canDeleteRef(repository)); + assertFalse("team CAN rewind ref!", team.canRewindRef(repository)); + } + + /** + * VIEW_CREATE = VIEW access restriction, CREATE access permission + */ + @Test + public void testTeam_VIEW_CREATE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.CREATE); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertTrue("team CAN NOT clone!", team.canClone(repository)); + assertTrue("team CAN NOT push!", team.canPush(repository)); + + assertTrue("team CAN NOT create ref!", team.canCreateRef(repository)); + assertFalse("team CAN delete ref!", team.canDeleteRef(repository)); + assertFalse("team CAN rewind ref!", team.canRewindRef(repository)); + } + + /** + * NONE_DELETE = NO access restriction, DELETE access permission + * (not useful scenario) + */ + @Test + public void testTeam_NONE_DELETE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.NONE; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.DELETE); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertTrue("team CAN NOT clone!", team.canClone(repository)); + assertTrue("team CAN NOT push!", team.canPush(repository)); + + assertTrue("team CAN NOT create ref!", team.canCreateRef(repository)); + assertTrue("team CAN NOT delete ref!", team.canDeleteRef(repository)); + assertTrue("team CAN NOT rewind ref!", team.canRewindRef(repository)); + } + + /** + * PUSH_DELETE = PUSH access restriction, DELETE access permission + */ + @Test + public void testTeam_PUSH_DELETE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.PUSH; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.DELETE); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertTrue("team CAN NOT clone!", team.canClone(repository)); + assertTrue("team CAN NOT push!", team.canPush(repository)); + + assertTrue("team CAN NOT create ref!", team.canCreateRef(repository)); + assertTrue("team CAN NOT delete ref!", team.canDeleteRef(repository)); + assertFalse("team CAN rewind ref!", team.canRewindRef(repository)); + } + + /** + * CLONE_DELETE = CLONE access restriction, DELETE access permission + */ + @Test + public void testTeam_CLONE_DELETE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.CLONE; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.DELETE); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertTrue("team CAN NOT clone!", team.canClone(repository)); + assertTrue("team CAN NOT push!", team.canPush(repository)); + + assertTrue("team CAN NOT create ref!", team.canCreateRef(repository)); + assertTrue("team CAN NOT delete ref!", team.canDeleteRef(repository)); + assertFalse("team CAN rewind ref!", team.canRewindRef(repository)); + } + + /** + * VIEW_DELETE = VIEW access restriction, DELETE access permission + */ + @Test + public void testTeam_VIEW_DELETE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.DELETE); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertTrue("team CAN NOT clone!", team.canClone(repository)); + assertTrue("team CAN NOT push!", team.canPush(repository)); + + assertTrue("team CAN NOT create ref!", team.canCreateRef(repository)); + assertTrue("team CAN NOT delete ref!", team.canDeleteRef(repository)); + assertFalse("team CAN rewind ref!", team.canRewindRef(repository)); + } + + /** + * NONE_REWIND = NO access restriction, REWIND access permission + * (not useful scenario) + */ + @Test + public void testTeam_NONE_REWIND() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.NONE; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.REWIND); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertTrue("team CAN NOT clone!", team.canClone(repository)); + assertTrue("team CAN NOT push!", team.canPush(repository)); + + assertTrue("team CAN NOT create ref!", team.canCreateRef(repository)); + assertTrue("team CAN NOT delete ref!", team.canDeleteRef(repository)); + assertTrue("team CAN NOT rewind ref!", team.canRewindRef(repository)); + } + + /** + * PUSH_REWIND = PUSH access restriction, REWIND access permission + */ + @Test + public void testTeam_PUSH_REWIND() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.PUSH; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.REWIND); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertTrue("team CAN NOT clone!", team.canClone(repository)); + assertTrue("team CAN NOT push!", team.canPush(repository)); + + assertTrue("team CAN NOT create ref!", team.canCreateRef(repository)); + assertTrue("team CAN NOT delete ref!", team.canDeleteRef(repository)); + assertTrue("team CAN NOT rewind ref!", team.canRewindRef(repository)); + } + + /** + * CLONE_REWIND = CLONE access restriction, REWIND access permission + */ + @Test + public void testTeam_CLONE_REWIND() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.CLONE; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.REWIND); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertTrue("team CAN NOT clone!", team.canClone(repository)); + assertTrue("team CAN NOT push!", team.canPush(repository)); + + assertTrue("team CAN NOT create ref!", team.canCreateRef(repository)); + assertTrue("team CAN NOT delete ref!", team.canDeleteRef(repository)); + assertTrue("team CAN NOT rewind ref!", team.canRewindRef(repository)); + } + + /** + * VIEW_REWIND = VIEW access restriction, REWIND access permission + */ + @Test + public void testTeam_VIEW_REWIND() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.REWIND); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertTrue("team CAN NOT clone!", team.canClone(repository)); + assertTrue("team CAN NOT push!", team.canPush(repository)); + + assertTrue("team CAN NOT create ref!", team.canCreateRef(repository)); + assertTrue("team CAN NOT delete ref!", team.canDeleteRef(repository)); + assertTrue("team CAN NOT rewind ref!", team.canRewindRef(repository)); + } + + /** + * NONE_CLONE = NO access restriction, CLONE access permission + * (not useful scenario) + */ + @Test + public void testTeam_NONE_CLONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.NONE; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.CLONE); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertTrue("team CAN NOT clone!", team.canClone(repository)); + assertTrue("team CAN NOT push!", team.canPush(repository)); + + assertTrue("team CAN NOT create ref!", team.canCreateRef(repository)); + assertTrue("team CAN NOT delete ref!", team.canDeleteRef(repository)); + assertTrue("team CAN NOT rewind ref!", team.canRewindRef(repository)); + } + + /** + * PUSH_CLONE = PUSH access restriction, CLONE access permission + */ + @Test + public void testTeam_PUSH_CLONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.PUSH; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.CLONE); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertTrue("team CAN NOT clone!", team.canClone(repository)); + assertFalse("team CAN push!", team.canPush(repository)); + + assertFalse("team CAN create ref!", team.canCreateRef(repository)); + assertFalse("team CAN delete ref!", team.canDeleteRef(repository)); + assertFalse("team CAN rewind ref!", team.canRewindRef(repository)); + } + + /** + * CLONE_CLONE = CLONE access restriction, CLONE access permission + */ + @Test + public void testTeam_CLONE_CLONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.CLONE; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.CLONE); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertTrue("team CAN NOT clone!", team.canClone(repository)); + assertFalse("team CAN push!", team.canPush(repository)); + + assertFalse("team CAN create ref!", team.canCreateRef(repository)); + assertFalse("team CAN delete ref!", team.canDeleteRef(repository)); + assertFalse("team CAN rewind ref!", team.canRewindRef(repository)); + } + + /** + * VIEW_CLONE = VIEW access restriction, CLONE access permission + */ + @Test + public void testTeam_VIEW_CLONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.CLONE); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertTrue("team CAN NOT clone!", team.canClone(repository)); + assertFalse("team CAN push!", team.canPush(repository)); + + assertFalse("team CAN create ref!", team.canCreateRef(repository)); + assertFalse("team CAN delete ref!", team.canDeleteRef(repository)); + assertFalse("team CAN rewind ref!", team.canRewindRef(repository)); + } + + /** + * NONE_VIEW = NO access restriction, VIEW access permission + * (not useful scenario) + */ + @Test + public void testTeam_NONE_VIEW() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.NONE; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.VIEW); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertTrue("team CAN NOT clone!", team.canClone(repository)); + assertTrue("team CAN NOT push!", team.canPush(repository)); + + assertTrue("team CAN NOT create ref!", team.canCreateRef(repository)); + assertTrue("team CAN NOT delete ref!", team.canDeleteRef(repository)); + assertTrue("team CAN NOT rewind ref!", team.canRewindRef(repository)); + } + + /** + * PUSH_VIEW = PUSH access restriction, VIEW access permission + */ + @Test + public void testTeam_PUSH_VIEW() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.PUSH; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.VIEW); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertTrue("team CAN NOT clone!", team.canClone(repository)); + assertFalse("team CAN push!", team.canPush(repository)); + + assertFalse("team CAN create ref!", team.canCreateRef(repository)); + assertFalse("team CAN delete ref!", team.canDeleteRef(repository)); + assertFalse("team CAN rewind ref!", team.canRewindRef(repository)); + } + + /** + * CLONE_VIEW = CLONE access restriction, VIEW access permission + */ + @Test + public void testTeam_CLONE_VIEW() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.CLONE; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.VIEW); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertFalse("team CAN clone!", team.canClone(repository)); + assertFalse("team CAN push!", team.canPush(repository)); + + assertFalse("team CAN create ref!", team.canCreateRef(repository)); + assertFalse("team CAN delete ref!", team.canDeleteRef(repository)); + assertFalse("team CAN rewind ref!", team.canRewindRef(repository)); + } + + /** + * VIEW_VIEW = VIEW access restriction, VIEW access permission + */ + @Test + public void testTeam_VIEW_VIEW() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.VIEW); + + assertTrue("team CAN NOT view!", team.canView(repository)); + assertFalse("team CAN clone!", team.canClone(repository)); + assertFalse("team CAN push!", team.canPush(repository)); + + assertFalse("team CAN create ref!", team.canCreateRef(repository)); + assertFalse("team CAN delete ref!", team.canDeleteRef(repository)); + assertFalse("team CAN rewind ref!", team.canRewindRef(repository)); + } + + /** + * NONE_NONE = NO access restriction, NO access permission + */ + @Test + public void testTeamMember_NONE_NONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.NONE; + + TeamModel team = new TeamModel("test"); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertTrue("team member CAN NOT clone!", user.canClone(repository)); + assertTrue("team member CAN NOT push!", user.canPush(repository)); + + assertTrue("team member CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("team member CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("team member CAN NOT rewind ref!", user.canRewindRef(repository)); + } + + /** + * PUSH_NONE = PUSH access restriction, NO access permission + */ + @Test + public void testTeamMember_PUSH_NONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.PUSH; + + TeamModel team = new TeamModel("test"); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertTrue("team member CAN NOT clone!", user.canClone(repository)); + assertFalse("team member CAN push!", user.canPush(repository)); + + assertFalse("team member CAN create ref!", user.canCreateRef(repository)); + assertFalse("team member CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("team member CAN rewind ref!", user.canRewindRef(repository)); + } + + /** + * CLONE_NONE = CLONE access restriction, NO access permission + */ + @Test + public void testTeamMember_CLONE_NONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.CLONE; + + TeamModel team = new TeamModel("test"); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertFalse("team member CAN clone!", user.canClone(repository)); + assertFalse("team member CAN push!", user.canPush(repository)); + + assertFalse("team member CAN create ref!", user.canCreateRef(repository)); + assertFalse("team member CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("team member CAN rewind ref!", user.canRewindRef(repository)); + } + + /** + * VIEW_NONE = VIEW access restriction, NO access permission + */ + @Test + public void testTeamMember_VIEW_NONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + TeamModel team = new TeamModel("test"); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertFalse("team member CAN view!", user.canView(repository)); + assertFalse("team member CAN clone!", user.canClone(repository)); + assertFalse("team member CAN push!", user.canPush(repository)); + + assertFalse("team member CAN create ref!", user.canCreateRef(repository)); + assertFalse("team member CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("team member CAN rewind ref!", user.canRewindRef(repository)); + } + + /** + * NONE_PUSH = NO access restriction, PUSH access permission + * (not useful scenario) + */ + @Test + public void testTeamMember_NONE_PUSH() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.NONE; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.PUSH); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertTrue("team member CAN NOT clone!", user.canClone(repository)); + assertTrue("team member CAN NOT push!", user.canPush(repository)); + + assertTrue("team member CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("team member CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("team member CAN NOT rewind ref!", user.canRewindRef(repository)); + } + + /** + * PUSH_PUSH = PUSH access restriction, PUSH access permission + */ + @Test + public void testTeamMember_PUSH_PUSH() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.PUSH; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.PUSH); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertTrue("team member CAN NOT clone!", user.canClone(repository)); + assertTrue("team member CAN NOT push!", user.canPush(repository)); + + assertFalse("team member CAN create ref!", user.canCreateRef(repository)); + assertFalse("team member CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("team member CAN rewind ref!", user.canRewindRef(repository)); + } + + /** + * CLONE_PUSH = CLONE access restriction, PUSH access permission + */ + @Test + public void testTeamMember_CLONE_PUSH() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.CLONE; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.PUSH); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertTrue("team member CAN NOT clone!", user.canClone(repository)); + assertTrue("team member CAN NOT push!", user.canPush(repository)); + + assertFalse("team member CAN create ref!", user.canCreateRef(repository)); + assertFalse("team member CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("team member CAN rewind ref!", user.canRewindRef(repository)); + } + + /** + * VIEW_PUSH = VIEW access restriction, PUSH access permission + */ + @Test + public void testTeamMember_VIEW_PUSH() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.PUSH); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertTrue("team member CAN NOT clone!", user.canClone(repository)); + assertTrue("team member CAN NOT push!", user.canPush(repository)); + + assertFalse("team member CAN create ref!", user.canCreateRef(repository)); + assertFalse("team member CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("team member CAN rewind ref!", user.canRewindRef(repository)); + } + + /** + * NONE_CREATE = NO access restriction, CREATE access permission + * (not useful scenario) + */ + @Test + public void testTeamMember_NONE_CREATE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.NONE; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.CREATE); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertTrue("team member CAN NOT clone!", user.canClone(repository)); + assertTrue("team member CAN NOT push!", user.canPush(repository)); + + assertTrue("team member CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("team member CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("team member CAN NOT rewind ref!", user.canRewindRef(repository)); + } + + /** + * PUSH_CREATE = PUSH access restriction, CREATE access permission + */ + @Test + public void testTeamMember_PUSH_CREATE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.PUSH; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.CREATE); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertTrue("team member CAN NOT clone!", user.canClone(repository)); + assertTrue("team member CAN NOT push!", user.canPush(repository)); + + assertTrue("team member CAN NOT create ref!", user.canCreateRef(repository)); + assertFalse("team member CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("team member CAN rewind ref!", user.canRewindRef(repository)); + } + + /** + * CLONE_CREATE = CLONE access restriction, CREATE access permission + */ + @Test + public void testTeamMember_CLONE_CREATE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.CLONE; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.CREATE); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertTrue("team member CAN NOT clone!", user.canClone(repository)); + assertTrue("team member CAN NOT push!", user.canPush(repository)); + + assertTrue("team member CAN NOT create ref!", user.canCreateRef(repository)); + assertFalse("team member CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("team member CAN rewind ref!", user.canRewindRef(repository)); + } + + /** + * VIEW_CREATE = VIEW access restriction, CREATE access permission + */ + @Test + public void testTeamMember_VIEW_CREATE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.CREATE); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertTrue("team member CAN NOT clone!", user.canClone(repository)); + assertTrue("team member CAN NOT push!", user.canPush(repository)); + + assertTrue("team member CAN NOT create ref!", user.canCreateRef(repository)); + assertFalse("team member CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("team member CAN rewind ref!", user.canRewindRef(repository)); + } + + /** + * NONE_DELETE = NO access restriction, DELETE access permission + * (not useful scenario) + */ + @Test + public void testTeamMember_NONE_DELETE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.NONE; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.DELETE); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertTrue("team member CAN NOT clone!", user.canClone(repository)); + assertTrue("team member CAN NOT push!", user.canPush(repository)); + + assertTrue("team member CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("team member CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("team member CAN NOT rewind ref!", user.canRewindRef(repository)); + } + + /** + * PUSH_DELETE = PUSH access restriction, DELETE access permission + */ + @Test + public void testTeamMember_PUSH_DELETE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.PUSH; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.DELETE); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertTrue("team member CAN NOT clone!", user.canClone(repository)); + assertTrue("team member CAN NOT push!", user.canPush(repository)); + + assertTrue("team member CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("team member CAN NOT delete ref!", user.canDeleteRef(repository)); + assertFalse("team member CAN rewind ref!", user.canRewindRef(repository)); + } + + /** + * CLONE_DELETE = CLONE access restriction, DELETE access permission + */ + @Test + public void testTeamMember_CLONE_DELETE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.CLONE; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.DELETE); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertTrue("team member CAN NOT clone!", user.canClone(repository)); + assertTrue("team member CAN NOT push!", user.canPush(repository)); + + assertTrue("team member CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("team member CAN NOT delete ref!", user.canDeleteRef(repository)); + assertFalse("team member CAN rewind ref!", user.canRewindRef(repository)); + } + + /** + * VIEW_DELETE = VIEW access restriction, DELETE access permission + */ + @Test + public void testTeamMember_VIEW_DELETE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.DELETE); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertTrue("team member CAN NOT clone!", user.canClone(repository)); + assertTrue("team member CAN NOT push!", user.canPush(repository)); + + assertTrue("team member CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("team member CAN NOT delete ref!", user.canDeleteRef(repository)); + assertFalse("team member CAN rewind ref!", user.canRewindRef(repository)); + } + + /** + * NONE_REWIND = NO access restriction, REWIND access permission + * (not useful scenario) + */ + @Test + public void testTeamMember_NONE_REWIND() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.NONE; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.REWIND); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertTrue("team member CAN NOT clone!", user.canClone(repository)); + assertTrue("team member CAN NOT push!", user.canPush(repository)); + + assertTrue("team member CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("team member CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("team member CAN NOT rewind ref!", user.canRewindRef(repository)); + } + + /** + * PUSH_REWIND = PUSH access restriction, REWIND access permission + */ + @Test + public void testTeamMember_PUSH_REWIND() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.PUSH; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.REWIND); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertTrue("team member CAN NOT clone!", user.canClone(repository)); + assertTrue("team member CAN NOT push!", user.canPush(repository)); + + assertTrue("team member CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("team member CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("team member CAN NOT rewind ref!", user.canRewindRef(repository)); + } + + /** + * CLONE_REWIND = CLONE access restriction, REWIND access permission + */ + @Test + public void testTeamMember_CLONE_REWIND() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.CLONE; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.REWIND); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertTrue("team member CAN NOT clone!", user.canClone(repository)); + assertTrue("team member CAN NOT push!", user.canPush(repository)); + + assertTrue("team member CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("team member CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("team member CAN NOT rewind ref!", user.canRewindRef(repository)); + } + + /** + * VIEW_REWIND = VIEW access restriction, REWIND access permission + */ + @Test + public void testTeamMember_VIEW_REWIND() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.REWIND); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertTrue("team member CAN NOT clone!", user.canClone(repository)); + assertTrue("team member CAN NOT push!", user.canPush(repository)); + + assertTrue("team member CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("team member CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("team member CAN NOT rewind ref!", user.canRewindRef(repository)); + } + + /** + * NONE_CLONE = NO access restriction, CLONE access permission + * (not useful scenario) + */ + @Test + public void testTeamMember_NONE_CLONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.NONE; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.CLONE); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertTrue("team member CAN NOT clone!", user.canClone(repository)); + assertTrue("team member CAN NOT push!", user.canPush(repository)); + + assertTrue("team member CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("team member CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("team member CAN NOT rewind ref!", user.canRewindRef(repository)); + } + + /** + * PUSH_CLONE = PUSH access restriction, CLONE access permission + */ + @Test + public void testTeamMember_PUSH_CLONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.PUSH; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.CLONE); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertTrue("team member CAN NOT clone!", user.canClone(repository)); + assertFalse("team member CAN push!", user.canPush(repository)); + + assertFalse("team member CAN create ref!", user.canCreateRef(repository)); + assertFalse("team member CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("team member CAN rewind ref!", user.canRewindRef(repository)); + } + + /** + * CLONE_CLONE = CLONE access restriction, CLONE access permission + */ + @Test + public void testTeamMember_CLONE_CLONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.CLONE; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.CLONE); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertTrue("team member CAN NOT clone!", user.canClone(repository)); + assertFalse("team member CAN push!", user.canPush(repository)); + + assertFalse("team member CAN create ref!", user.canCreateRef(repository)); + assertFalse("team member CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("team member CAN rewind ref!", user.canRewindRef(repository)); + } + + /** + * VIEW_CLONE = VIEW access restriction, CLONE access permission + */ + @Test + public void testTeamMember_VIEW_CLONE() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.CLONE); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertTrue("team member CAN NOT clone!", user.canClone(repository)); + assertFalse("team member CAN push!", user.canPush(repository)); + + assertFalse("team member CAN create ref!", user.canCreateRef(repository)); + assertFalse("team member CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("team member CAN rewind ref!", user.canRewindRef(repository)); + } + + /** + * NONE_VIEW = NO access restriction, VIEW access permission + * (not useful scenario) + */ + @Test + public void testTeamMember_NONE_VIEW() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.NONE; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.VIEW); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertTrue("team member CAN NOT clone!", user.canClone(repository)); + assertTrue("team member CAN NOT push!", user.canPush(repository)); + + assertTrue("team member CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("team member CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("team member CAN NOT rewind ref!", user.canRewindRef(repository)); + } + + /** + * PUSH_VIEW = PUSH access restriction, VIEW access permission + */ + @Test + public void testTeamMember_PUSH_VIEW() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.PUSH; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.VIEW); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertTrue("team member CAN NOT clone!", user.canClone(repository)); + assertFalse("team member CAN push!", user.canPush(repository)); + + assertFalse("team member CAN create ref!", user.canCreateRef(repository)); + assertFalse("team member CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("team member CAN rewind ref!", user.canRewindRef(repository)); + } + + /** + * CLONE_VIEW = CLONE access restriction, VIEW access permission + */ + @Test + public void testTeamMember_CLONE_VIEW() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.CLONE; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.VIEW); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertFalse("team member CAN clone!", user.canClone(repository)); + assertFalse("team member CAN push!", user.canPush(repository)); + + assertFalse("team member CAN create ref!", user.canCreateRef(repository)); + assertFalse("team member CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("team member CAN rewind ref!", user.canRewindRef(repository)); + } + + /** + * VIEW_VIEW = VIEW access restriction, VIEW access permission + */ + @Test + public void testTeamMember_VIEW_VIEW() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + TeamModel team = new TeamModel("test"); + team.setRepositoryPermission(repository.name, AccessPermission.VIEW); + UserModel user = new UserModel("test"); + user.teams.add(team); + + assertTrue("team member CAN NOT view!", user.canView(repository)); + assertFalse("team member CAN clone!", user.canClone(repository)); + assertFalse("team member CAN push!", user.canPush(repository)); + + assertFalse("team member CAN create ref!", user.canCreateRef(repository)); + assertFalse("team member CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("team member CAN rewind ref!", user.canRewindRef(repository)); + } + + @Test + public void testOwner() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + UserModel user = new UserModel("test"); + repository.addOwner(user.username); + + assertFalse("user SHOULD NOT HAVE a repository permission!", user.hasRepositoryPermission(repository.name)); + assertTrue("owner CAN NOT view!", user.canView(repository)); + assertTrue("owner CAN NOT clone!", user.canClone(repository)); + assertTrue("owner CAN NOT push!", user.canPush(repository)); + + assertTrue("owner CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("owner CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("owner CAN NOT rewind ref!", user.canRewindRef(repository)); + + assertTrue("owner CAN NOT fork!", user.canFork(repository)); + + assertFalse("owner CAN NOT delete!", user.canDelete(repository)); + assertTrue("owner CAN NOT edit!", user.canEdit(repository)); + } + + @Test + public void testMultipleOwners() throws Exception { + RepositoryModel repository = new RepositoryModel("myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + UserModel user = new UserModel("test"); + repository.addOwner(user.username); + UserModel user2 = new UserModel("test2"); + repository.addOwner(user2.username); + + // first owner + assertFalse("user SHOULD NOT HAVE a repository permission!", user.hasRepositoryPermission(repository.name)); + assertTrue("owner CAN NOT view!", user.canView(repository)); + assertTrue("owner CAN NOT clone!", user.canClone(repository)); + assertTrue("owner CAN NOT push!", user.canPush(repository)); + + assertTrue("owner CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("owner CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("owner CAN NOT rewind ref!", user.canRewindRef(repository)); + + assertTrue("owner CAN NOT fork!", user.canFork(repository)); + + assertFalse("owner CAN NOT delete!", user.canDelete(repository)); + assertTrue("owner CAN NOT edit!", user.canEdit(repository)); + + // second owner + assertFalse("user SHOULD NOT HAVE a repository permission!", user2.hasRepositoryPermission(repository.name)); + assertTrue("owner CAN NOT view!", user2.canView(repository)); + assertTrue("owner CAN NOT clone!", user2.canClone(repository)); + assertTrue("owner CAN NOT push!", user2.canPush(repository)); + + assertTrue("owner CAN NOT create ref!", user2.canCreateRef(repository)); + assertTrue("owner CAN NOT delete ref!", user2.canDeleteRef(repository)); + assertTrue("owner CAN NOT rewind ref!", user2.canRewindRef(repository)); + + assertTrue("owner CAN NOT fork!", user2.canFork(repository)); + + assertFalse("owner CAN NOT delete!", user2.canDelete(repository)); + assertTrue("owner CAN NOT edit!", user2.canEdit(repository)); + + assertTrue(repository.isOwner(user.username)); + assertTrue(repository.isOwner(user2.username)); + } + + @Test + public void testOwnerPersonalRepository() throws Exception { + RepositoryModel repository = new RepositoryModel("~test/myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + UserModel user = new UserModel("test"); + repository.addOwner(user.username); + + assertFalse("user SHOULD NOT HAVE a repository permission!", user.hasRepositoryPermission(repository.name)); + assertTrue("user CAN NOT view!", user.canView(repository)); + assertTrue("user CAN NOT clone!", user.canClone(repository)); + assertTrue("user CAN NOT push!", user.canPush(repository)); + + assertTrue("user CAN NOT create ref!", user.canCreateRef(repository)); + assertTrue("user CAN NOT delete ref!", user.canDeleteRef(repository)); + assertTrue("user CAN NOT rewind ref!", user.canRewindRef(repository)); + + assertFalse("user CAN fork!", user.canFork(repository)); + + assertTrue("user CAN NOT delete!", user.canDelete(repository)); + assertTrue("user CAN NOT edit!", user.canEdit(repository)); + } + + @Test + public void testVisitorPersonalRepository() throws Exception { + RepositoryModel repository = new RepositoryModel("~test/myrepo.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + UserModel user = new UserModel("visitor"); + repository.addOwner("test"); + + assertFalse("user HAS a repository permission!", user.hasRepositoryPermission(repository.name)); + assertFalse("user CAN view!", user.canView(repository)); + assertFalse("user CAN clone!", user.canClone(repository)); + assertFalse("user CAN push!", user.canPush(repository)); + + assertFalse("user CAN create ref!", user.canCreateRef(repository)); + assertFalse("user CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("user CAN rewind ref!", user.canRewindRef(repository)); + + assertFalse("user CAN fork!", user.canFork(repository)); + + assertFalse("user CAN delete!", user.canDelete(repository)); + assertFalse("user CAN edit!", user.canEdit(repository)); + } + + @Test + public void testRegexMatching() throws Exception { + RepositoryModel repository = new RepositoryModel("ubercool/_my-r/e~po.git", null, null, new Date()); + repository.authorizationControl = AuthorizationControl.NAMED; + repository.accessRestriction = AccessRestrictionType.VIEW; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission("ubercool/[A-Z0-9-~_\\./]+", AccessPermission.CLONE); + + assertTrue("user DOES NOT HAVE a repository permission!", user.hasRepositoryPermission(repository.name)); + assertTrue("user CAN NOT view!", user.canView(repository)); + assertTrue("user CAN NOT clone!", user.canClone(repository)); + assertFalse("user CAN push!", user.canPush(repository)); + + assertFalse("user CAN create ref!", user.canCreateRef(repository)); + assertFalse("user CAN delete ref!", user.canDeleteRef(repository)); + assertFalse("user CAN rewind ref!", user.canRewindRef(repository)); + + assertFalse("user CAN fork!", user.canFork(repository)); + + assertFalse("user CAN delete!", user.canDelete(repository)); + assertFalse("user CAN edit!", user.canEdit(repository)); + } + + @Test + public void testRegexIncludeCommonExcludePersonal() throws Exception { + + UserModel user = new UserModel("test"); + user.setRepositoryPermission("[^~].*", AccessPermission.CLONE); + + // common + RepositoryModel common = new RepositoryModel("ubercool/_my-r/e~po.git", null, null, new Date()); + common.authorizationControl = AuthorizationControl.NAMED; + common.accessRestriction = AccessRestrictionType.VIEW; + + assertTrue("user DOES NOT HAVE a repository permission!", user.hasRepositoryPermission(common.name)); + assertTrue("user CAN NOT view!", user.canView(common)); + assertTrue("user CAN NOT clone!", user.canClone(common)); + assertFalse("user CAN push!", user.canPush(common)); + + assertFalse("user CAN create ref!", user.canCreateRef(common)); + assertFalse("user CAN delete ref!", user.canDeleteRef(common)); + assertFalse("user CAN rewind ref!", user.canRewindRef(common)); + + assertFalse("user CAN fork!", user.canFork(common)); + + assertFalse("user CAN delete!", user.canDelete(common)); + assertFalse("user CAN edit!", user.canEdit(common)); + + // personal + RepositoryModel personal = new RepositoryModel("~ubercool/_my-r/e~po.git", null, null, new Date()); + personal.authorizationControl = AuthorizationControl.NAMED; + personal.accessRestriction = AccessRestrictionType.VIEW; + + assertFalse("user HAS a repository permission!", user.hasRepositoryPermission(personal.name)); + assertFalse("user CAN NOT view!", user.canView(personal)); + assertFalse("user CAN NOT clone!", user.canClone(personal)); + assertFalse("user CAN push!", user.canPush(personal)); + + assertFalse("user CAN create ref!", user.canCreateRef(personal)); + assertFalse("user CAN delete ref!", user.canDeleteRef(personal)); + assertFalse("user CAN rewind ref!", user.canRewindRef(personal)); + + assertFalse("user CAN fork!", user.canFork(personal)); + + assertFalse("user CAN delete!", user.canDelete(personal)); + assertFalse("user CAN edit!", user.canEdit(personal)); + } + + @Test + public void testRegexMatching2() throws Exception { + RepositoryModel personal = new RepositoryModel("~ubercool/_my-r/e~po.git", null, null, new Date()); + personal.authorizationControl = AuthorizationControl.NAMED; + personal.accessRestriction = AccessRestrictionType.VIEW; + + UserModel user = new UserModel("test"); + // permit all repositories excluding all personal rpeositories + user.setRepositoryPermission("[^~].*", AccessPermission.CLONE); + // permitall ~ubercool repositories + user.setRepositoryPermission("~ubercool/.*", AccessPermission.CLONE); + + // personal + assertTrue("user DOES NOT HAVE a repository permission!", user.hasRepositoryPermission(personal.name)); + assertTrue("user CAN NOT view!", user.canView(personal)); + assertTrue("user CAN NOT clone!", user.canClone(personal)); + assertFalse("user CAN push!", user.canPush(personal)); + + assertFalse("user CAN create ref!", user.canCreateRef(personal)); + assertFalse("user CAN delete ref!", user.canDeleteRef(personal)); + assertFalse("user CAN rewind ref!", user.canRewindRef(personal)); + + assertFalse("user CAN fork!", user.canFork(personal)); + + assertFalse("user CAN delete!", user.canDelete(personal)); + assertFalse("user CAN edit!", user.canEdit(personal)); + } + + @Test + public void testRegexOrder() throws Exception { + RepositoryModel personal = new RepositoryModel("~ubercool/_my-r/e~po.git", null, null, new Date()); + personal.authorizationControl = AuthorizationControl.NAMED; + personal.accessRestriction = AccessRestrictionType.VIEW; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission(".*", AccessPermission.PUSH); + user.setRepositoryPermission("~ubercool/.*", AccessPermission.CLONE); + + // has PUSH access because first match is PUSH permission + assertTrue("user HAS a repository permission!", user.hasRepositoryPermission(personal.name)); + assertTrue("user CAN NOT view!", user.canView(personal)); + assertTrue("user CAN NOT clone!", user.canClone(personal)); + assertTrue("user CAN NOT push!", user.canPush(personal)); + + assertFalse("user CAN create ref!", user.canCreateRef(personal)); + assertFalse("user CAN delete ref!", user.canDeleteRef(personal)); + assertFalse("user CAN rewind ref!", user.canRewindRef(personal)); + + assertFalse("user CAN fork!", user.canFork(personal)); + + assertFalse("user CAN delete!", user.canDelete(personal)); + assertFalse("user CAN edit!", user.canEdit(personal)); + + user.permissions.clear(); + user.setRepositoryPermission("~ubercool/.*", AccessPermission.CLONE); + user.setRepositoryPermission(".*", AccessPermission.PUSH); + + // has CLONE access because first match is CLONE permission + assertTrue("user HAS a repository permission!", user.hasRepositoryPermission(personal.name)); + assertTrue("user CAN NOT view!", user.canView(personal)); + assertTrue("user CAN NOT clone!", user.canClone(personal)); + assertFalse("user CAN push!", user.canPush(personal)); + + assertFalse("user CAN create ref!", user.canCreateRef(personal)); + assertFalse("user CAN delete ref!", user.canDeleteRef(personal)); + assertFalse("user CAN rewind ref!", user.canRewindRef(personal)); + + assertFalse("user CAN fork!", user.canFork(personal)); + + assertFalse("user CAN delete!", user.canDelete(personal)); + assertFalse("user CAN edit!", user.canEdit(personal)); + } + + @Test + public void testExclusion() throws Exception { + RepositoryModel personal = new RepositoryModel("~ubercool/_my-r/e~po.git", null, null, new Date()); + personal.authorizationControl = AuthorizationControl.NAMED; + personal.accessRestriction = AccessRestrictionType.VIEW; + + UserModel user = new UserModel("test"); + user.setRepositoryPermission("~ubercool/.*", AccessPermission.EXCLUDE); + user.setRepositoryPermission(".*", AccessPermission.PUSH); + + // has EXCLUDE access because first match is EXCLUDE permission + assertTrue("user DOES NOT HAVE a repository permission!", user.hasRepositoryPermission(personal.name)); + assertFalse("user CAN NOT view!", user.canView(personal)); + assertFalse("user CAN NOT clone!", user.canClone(personal)); + assertFalse("user CAN push!", user.canPush(personal)); + + assertFalse("user CAN create ref!", user.canCreateRef(personal)); + assertFalse("user CAN delete ref!", user.canDeleteRef(personal)); + assertFalse("user CAN rewind ref!", user.canRewindRef(personal)); + + assertFalse("user CAN fork!", user.canFork(personal)); + + assertFalse("user CAN delete!", user.canDelete(personal)); + assertFalse("user CAN edit!", user.canEdit(personal)); + } + + @Test + public void testAdminTeamInheritance() throws Exception { + UserModel user = new UserModel("test"); + TeamModel team = new TeamModel("team"); + team.canAdmin = true; + user.teams.add(team); + assertTrue("User did not inherit admin privileges", user.canAdmin()); + } + + @Test + public void testForkTeamInheritance() throws Exception { + UserModel user = new UserModel("test"); + TeamModel team = new TeamModel("team"); + team.canFork = true; + user.teams.add(team); + assertTrue("User did not inherit fork privileges", user.canFork()); + } + + @Test + public void testCreateTeamInheritance() throws Exception { + UserModel user = new UserModel("test"); + TeamModel team = new TeamModel("team"); + team.canCreate= true; + user.teams.add(team); + assertTrue("User did not inherit create privileges", user.canCreate()); + } + +} diff --git a/src/test/java/com/gitblit/tests/PushLogTest.java b/src/test/java/com/gitblit/tests/PushLogTest.java new file mode 100644 index 00000000..aa4cf418 --- /dev/null +++ b/src/test/java/com/gitblit/tests/PushLogTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2013 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import org.eclipse.jgit.storage.file.FileRepository; +import org.junit.Test; + +import com.gitblit.models.PushLogEntry; +import com.gitblit.utils.PushLogUtils; + +public class PushLogTest { + + @Test + public void testPushLog() throws IOException { + String name = "~james/helloworld.git"; + FileRepository repository = new FileRepository(new File(GitBlitSuite.REPOSITORIES, name)); + List pushes = PushLogUtils.getPushLog(name, repository); + GitBlitSuite.close(repository); + } +} \ No newline at end of file diff --git a/src/test/java/com/gitblit/tests/RedmineUserServiceTest.java b/src/test/java/com/gitblit/tests/RedmineUserServiceTest.java new file mode 100644 index 00000000..12fa73ff --- /dev/null +++ b/src/test/java/com/gitblit/tests/RedmineUserServiceTest.java @@ -0,0 +1,72 @@ +package com.gitblit.tests; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; + +import org.junit.Test; + +import com.gitblit.RedmineUserService; +import com.gitblit.models.UserModel; +import com.gitblit.tests.mock.MemorySettings; +import com.gitblit.utils.StringUtils; + +public class RedmineUserServiceTest { + + private static final String JSON = "{\"user\":{\"created_on\":\"2011-03-28T00:41:29Z\",\"lastname\":\"foo\"," + + "\"last_login_on\":\"2012-09-06T23:59:26Z\",\"firstname\":\"baz\"," + + "\"id\":4,\"login\":\"RedmineUserId\",\"mail\":\"baz@example.com\"}}"; + + private static final String NOT_ADMIN_JSON = "{\"user\":{\"lastname\":\"foo\"," + + "\"last_login_on\":\"2012-09-08T13:59:01Z\",\"created_on\":\"2009-03-17T14:25:50Z\"," + + "\"mail\":\"baz@example.com\",\"id\":5,\"firstname\":\"baz\"}}"; + + @Test + public void testAuthenticate() throws Exception { + RedmineUserService redmineUserService = new RedmineUserService(); + redmineUserService.setup(new MemorySettings(new HashMap())); + redmineUserService.setTestingCurrentUserAsJson(JSON); + UserModel userModel = redmineUserService.authenticate("RedmineAdminId", "RedmineAPIKey".toCharArray()); + assertThat(userModel.getName(), is("redmineadminid")); + assertThat(userModel.getDisplayName(), is("baz foo")); + assertThat(userModel.emailAddress, is("baz@example.com")); + assertNotNull(userModel.cookie); + assertThat(userModel.canAdmin, is(true)); + } + + @Test + public void testAuthenticateNotAdminUser() throws Exception { + RedmineUserService redmineUserService = new RedmineUserService(); + redmineUserService.setup(new MemorySettings(new HashMap())); + redmineUserService.setTestingCurrentUserAsJson(NOT_ADMIN_JSON); + UserModel userModel = redmineUserService.authenticate("RedmineUserId", "RedmineAPIKey".toCharArray()); + assertThat(userModel.getName(), is("redmineuserid")); + assertThat(userModel.getDisplayName(), is("baz foo")); + assertThat(userModel.emailAddress, is("baz@example.com")); + assertNotNull(userModel.cookie); + assertThat(userModel.canAdmin, is(false)); + } + + @Test + public void testLocalAccount() { + RedmineUserService redmineUserService = new RedmineUserService(); + redmineUserService.setup(new MemorySettings(new HashMap())); + + UserModel localAccount = new UserModel("bruce"); + localAccount.displayName = "Bruce Campbell"; + localAccount.password = StringUtils.MD5_TYPE + StringUtils.getMD5("gimmesomesugar"); + redmineUserService.deleteUser(localAccount.username); + assertTrue("Failed to add local account", + redmineUserService.updateUserModel(localAccount)); + assertEquals("Accounts are not equal!", + localAccount, + redmineUserService.authenticate(localAccount.username, "gimmesomesugar".toCharArray())); + assertTrue("Failed to delete local account!", + redmineUserService.deleteUser(localAccount.username)); + } + +} diff --git a/src/test/java/com/gitblit/tests/RepositoryModelTest.java b/src/test/java/com/gitblit/tests/RepositoryModelTest.java new file mode 100644 index 00000000..1fe3fbd0 --- /dev/null +++ b/src/test/java/com/gitblit/tests/RepositoryModelTest.java @@ -0,0 +1,96 @@ +/* + * Copyright 2012 John Crygier + * Copyright 2012 gitblit.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; + +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.StoredConfig; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.gitblit.Constants; +import com.gitblit.GitBlit; +import com.gitblit.models.RepositoryModel; + +public class RepositoryModelTest { + + private static boolean wasStarted = false; + + @BeforeClass + public static void startGitBlit() throws Exception { + wasStarted = GitBlitSuite.startGitblit() == false; + } + + @AfterClass + public static void stopGitBlit() throws Exception { + if (wasStarted == false) + GitBlitSuite.stopGitblit(); + } + + @Before + public void initializeConfiguration() throws Exception{ + Repository r = GitBlitSuite.getHelloworldRepository(); + StoredConfig config = r.getConfig(); + + config.unsetSection(Constants.CONFIG_GITBLIT, Constants.CONFIG_CUSTOM_FIELDS); + config.setString(Constants.CONFIG_GITBLIT, Constants.CONFIG_CUSTOM_FIELDS, "commitMessageRegEx", "\\d"); + config.setString(Constants.CONFIG_GITBLIT, Constants.CONFIG_CUSTOM_FIELDS, "anotherProperty", "Hello"); + + config.save(); + } + + @After + public void teardownConfiguration() throws Exception { + Repository r = GitBlitSuite.getHelloworldRepository(); + StoredConfig config = r.getConfig(); + + config.unsetSection(Constants.CONFIG_GITBLIT, Constants.CONFIG_CUSTOM_FIELDS); + config.save(); + } + + @Test + public void testGetCustomProperty() throws Exception { + RepositoryModel model = GitBlit.self().getRepositoryModel( + GitBlitSuite.getHelloworldRepository().getDirectory().getName()); + + assertEquals("\\d", model.customFields.get("commitMessageRegEx")); + assertEquals("Hello", model.customFields.get("anotherProperty")); + } + + @Test + public void testSetCustomProperty() throws Exception { + RepositoryModel model = GitBlit.self().getRepositoryModel( + GitBlitSuite.getHelloworldRepository().getDirectory().getName()); + + assertEquals("\\d", model.customFields.get("commitMessageRegEx")); + assertEquals("Hello", model.customFields.get("anotherProperty")); + + assertEquals("Hello", model.customFields.put("anotherProperty", "GoodBye")); + GitBlit.self().updateRepositoryModel(model.name, model, false); + + model = GitBlit.self().getRepositoryModel( + GitBlitSuite.getHelloworldRepository().getDirectory().getName()); + + assertEquals("\\d", model.customFields.get("commitMessageRegEx")); + assertEquals("GoodBye", model.customFields.get("anotherProperty")); + } + +} diff --git a/src/test/java/com/gitblit/tests/RpcTests.java b/src/test/java/com/gitblit/tests/RpcTests.java new file mode 100644 index 00000000..3241a8ab --- /dev/null +++ b/src/test/java/com/gitblit/tests/RpcTests.java @@ -0,0 +1,382 @@ +/* + * Copyright 2011 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.gitblit.Constants.AccessPermission; +import com.gitblit.Constants.AccessRestrictionType; +import com.gitblit.Constants.AuthorizationControl; +import com.gitblit.Constants.PermissionType; +import com.gitblit.Constants.RegistrantType; +import com.gitblit.GitBlitException.UnauthorizedException; +import com.gitblit.Keys; +import com.gitblit.RpcServlet; +import com.gitblit.models.RegistrantAccessPermission; +import com.gitblit.models.FederationModel; +import com.gitblit.models.FederationProposal; +import com.gitblit.models.FederationSet; +import com.gitblit.models.RepositoryModel; +import com.gitblit.models.ServerSettings; +import com.gitblit.models.ServerStatus; +import com.gitblit.models.TeamModel; +import com.gitblit.models.UserModel; +import com.gitblit.utils.RpcUtils; + +/** + * Tests all the rpc client utility methods, the rpc filter and rpc servlet. + * + * @author James Moger + * + */ +public class RpcTests { + + String url = GitBlitSuite.url; + String account = GitBlitSuite.account; + String password = GitBlitSuite.password; + + private static final AtomicBoolean started = new AtomicBoolean(false); + + @BeforeClass + public static void startGitblit() throws Exception { + started.set(GitBlitSuite.startGitblit()); + } + + @AfterClass + public static void stopGitblit() throws Exception { + if (started.get()) { + GitBlitSuite.stopGitblit(); + } + } + + @Test + public void testGetProtocolVersion() throws IOException { + int protocol = RpcUtils.getProtocolVersion(url, null, null); + assertEquals(RpcServlet.PROTOCOL_VERSION, protocol); + } + + @Test + public void testListRepositories() throws IOException { + Map map = RpcUtils.getRepositories(url, null, null); + assertNotNull("Repository list is null!", map); + assertTrue("Repository list is empty!", map.size() > 0); + } + + @Test + public void testListUsers() throws IOException { + List list = null; + try { + list = RpcUtils.getUsers(url, null, null); + } catch (UnauthorizedException e) { + } + assertNull("Server allows anyone to admin!", list); + + list = RpcUtils.getUsers(url, "admin", "admin".toCharArray()); + assertTrue("User list is empty!", list.size() > 0); + } + + @Test + public void testListTeams() throws IOException { + List list = null; + try { + list = RpcUtils.getTeams(url, null, null); + } catch (UnauthorizedException e) { + } + assertNull("Server allows anyone to admin!", list); + + list = RpcUtils.getTeams(url, "admin", "admin".toCharArray()); + assertTrue("Team list is empty!", list.size() > 0); + assertEquals("admins", list.get(0).name); + } + + @Test + public void testUserAdministration() throws IOException { + UserModel user = new UserModel("garbage"); + user.canAdmin = true; + user.password = "whocares"; + + // create + assertTrue("Failed to create user!", + RpcUtils.createUser(user, url, account, password.toCharArray())); + + UserModel retrievedUser = findUser(user.username); + assertNotNull("Failed to find " + user.username, retrievedUser); + assertTrue("Retrieved user can not administer Gitblit", retrievedUser.canAdmin); + + // rename and toggle admin permission + String originalName = user.username; + user.username = "garbage2"; + user.canAdmin = false; + assertTrue("Failed to update user!", + RpcUtils.updateUser(originalName, user, url, account, password.toCharArray())); + + retrievedUser = findUser(user.username); + assertNotNull("Failed to find " + user.username, retrievedUser); + assertTrue("Retrieved user did not update", !retrievedUser.canAdmin); + + // delete + assertTrue("Failed to delete " + user.username, + RpcUtils.deleteUser(retrievedUser, url, account, password.toCharArray())); + + retrievedUser = findUser(user.username); + assertNull("Failed to delete " + user.username, retrievedUser); + } + + private UserModel findUser(String name) throws IOException { + List users = RpcUtils.getUsers(url, account, password.toCharArray()); + UserModel retrievedUser = null; + for (UserModel model : users) { + if (model.username.equalsIgnoreCase(name)) { + retrievedUser = model; + break; + } + } + return retrievedUser; + } + + @Test + public void testRepositoryAdministration() throws IOException { + RepositoryModel model = new RepositoryModel(); + model.name = "garbagerepo.git"; + model.description = "created by RpcUtils"; + model.addOwner("garbage"); + model.accessRestriction = AccessRestrictionType.VIEW; + model.authorizationControl = AuthorizationControl.AUTHENTICATED; + + // create + assertTrue("Failed to create repository!", + RpcUtils.createRepository(model, url, account, password.toCharArray())); + + RepositoryModel retrievedRepository = findRepository(model.name); + assertNotNull("Failed to find " + model.name, retrievedRepository); + assertEquals(AccessRestrictionType.VIEW, retrievedRepository.accessRestriction); + assertEquals(AuthorizationControl.AUTHENTICATED, retrievedRepository.authorizationControl); + + // rename and change access restriciton + String originalName = model.name; + model.name = "garbagerepo2.git"; + model.accessRestriction = AccessRestrictionType.PUSH; + model.authorizationControl = AuthorizationControl.NAMED; + assertTrue("Failed to update repository!", RpcUtils.updateRepository(originalName, model, + url, account, password.toCharArray())); + + retrievedRepository = findRepository(model.name); + assertNotNull("Failed to find " + model.name, retrievedRepository); + assertTrue("Access retriction type is wrong", + AccessRestrictionType.PUSH.equals(retrievedRepository.accessRestriction)); + + // memberships + UserModel testMember = new UserModel("justadded"); + assertTrue(RpcUtils.createUser(testMember, url, account, password.toCharArray())); + + List permissions = RpcUtils.getRepositoryMemberPermissions(retrievedRepository, url, account, + password.toCharArray()); + assertEquals("Membership permissions is not empty!", 0, permissions.size()); + permissions.add(new RegistrantAccessPermission(testMember.username, AccessPermission.PUSH, PermissionType.EXPLICIT, RegistrantType.USER, null, true)); + assertTrue( + "Failed to set member permissions!", + RpcUtils.setRepositoryMemberPermissions(retrievedRepository, permissions, url, account, + password.toCharArray())); + permissions = RpcUtils.getRepositoryMemberPermissions(retrievedRepository, url, account, + password.toCharArray()); + boolean foundMember = false; + for (RegistrantAccessPermission permission : permissions) { + if (permission.registrant.equalsIgnoreCase(testMember.username)) { + foundMember = true; + assertEquals(AccessPermission.PUSH, permission.permission); + break; + } + } + assertTrue("Failed to find member!", foundMember); + + // delete + assertTrue("Failed to delete " + model.name, RpcUtils.deleteRepository(retrievedRepository, + url, account, password.toCharArray())); + + retrievedRepository = findRepository(model.name); + assertNull("Failed to delete " + model.name, retrievedRepository); + + for (UserModel u : RpcUtils.getUsers(url, account, password.toCharArray())) { + if (u.username.equals(testMember.username)) { + assertTrue(RpcUtils.deleteUser(u, url, account, password.toCharArray())); + break; + } + } + } + + private RepositoryModel findRepository(String name) throws IOException { + Map repositories = RpcUtils.getRepositories(url, account, + password.toCharArray()); + RepositoryModel retrievedRepository = null; + for (RepositoryModel model : repositories.values()) { + if (model.name.equalsIgnoreCase(name)) { + retrievedRepository = model; + break; + } + } + return retrievedRepository; + } + + @Test + public void testTeamAdministration() throws IOException { + List teams = RpcUtils.getTeams(url, account, password.toCharArray()); + assertEquals(1, teams.size()); + + // Create the A-Team + TeamModel aTeam = new TeamModel("A-Team"); + aTeam.users.add("admin"); + aTeam.addRepositoryPermission("helloworld.git"); + assertTrue(RpcUtils.createTeam(aTeam, url, account, password.toCharArray())); + + aTeam = null; + teams = RpcUtils.getTeams(url, account, password.toCharArray()); + assertEquals(2, teams.size()); + for (TeamModel team : teams) { + if (team.name.equals("A-Team")) { + aTeam = team; + break; + } + } + assertNotNull(aTeam); + assertTrue(aTeam.hasUser("admin")); + assertTrue(aTeam.hasRepositoryPermission("helloworld.git")); + + RepositoryModel helloworld = null; + Map repositories = RpcUtils.getRepositories(url, account, + password.toCharArray()); + for (RepositoryModel repository : repositories.values()) { + if (repository.name.equals("helloworld.git")) { + helloworld = repository; + break; + } + } + assertNotNull(helloworld); + + // Confirm that we have added the team + List helloworldTeams = RpcUtils.getRepositoryTeams(helloworld, url, account, + password.toCharArray()); + assertEquals(1, helloworldTeams.size()); + assertTrue(helloworldTeams.contains(aTeam.name)); + + // set no teams + List permissions = new ArrayList(); + for (String team : helloworldTeams) { + permissions.add(new RegistrantAccessPermission(team, AccessPermission.NONE, PermissionType.EXPLICIT, RegistrantType.TEAM, null, true)); + } + assertTrue(RpcUtils.setRepositoryTeamPermissions(helloworld, permissions, url, account, + password.toCharArray())); + helloworldTeams = RpcUtils.getRepositoryTeams(helloworld, url, account, + password.toCharArray()); + assertEquals(0, helloworldTeams.size()); + + // delete the A-Team + assertTrue(RpcUtils.deleteTeam(aTeam, url, account, password.toCharArray())); + + teams = RpcUtils.getTeams(url, account, password.toCharArray()); + assertEquals(1, teams.size()); + } + + @Test + public void testFederationRegistrations() throws Exception { + List registrations = RpcUtils.getFederationRegistrations(url, account, + password.toCharArray()); + assertTrue("No federation registrations were retrieved!", registrations.size() >= 0); + } + + @Test + public void testFederationResultRegistrations() throws Exception { + List registrations = RpcUtils.getFederationResultRegistrations(url, + account, password.toCharArray()); + assertTrue("No federation result registrations were retrieved!", registrations.size() >= 0); + } + + @Test + public void testFederationProposals() throws Exception { + List proposals = RpcUtils.getFederationProposals(url, account, + password.toCharArray()); + assertTrue("No federation proposals were retrieved!", proposals.size() >= 0); + } + + @Test + public void testFederationSets() throws Exception { + List sets = RpcUtils.getFederationSets(url, account, password.toCharArray()); + assertTrue("No federation sets were retrieved!", sets.size() >= 0); + } + + @Test + public void testSettings() throws Exception { + ServerSettings settings = RpcUtils.getSettings(url, account, password.toCharArray()); + assertNotNull("No settings were retrieved!", settings); + } + + @Test + public void testServerStatus() throws Exception { + ServerStatus status = RpcUtils.getStatus(url, account, password.toCharArray()); + assertNotNull("No status was retrieved!", status); + } + + @Test + public void testUpdateSettings() throws Exception { + Map updated = new HashMap(); + + // grab current setting + ServerSettings settings = RpcUtils.getSettings(url, account, password.toCharArray()); + boolean showSizes = settings.get(Keys.web.showRepositorySizes).getBoolean(true); + showSizes = !showSizes; + + // update setting + updated.put(Keys.web.showRepositorySizes, String.valueOf(showSizes)); + boolean success = RpcUtils.updateSettings(updated, url, account, password.toCharArray()); + assertTrue("Failed to update server settings", success); + + // confirm setting change + settings = RpcUtils.getSettings(url, account, password.toCharArray()); + boolean newValue = settings.get(Keys.web.showRepositorySizes).getBoolean(false); + assertEquals(newValue, showSizes); + + // restore setting + newValue = !newValue; + updated.put(Keys.web.showRepositorySizes, String.valueOf(newValue)); + success = RpcUtils.updateSettings(updated, url, account, password.toCharArray()); + assertTrue("Failed to update server settings", success); + settings = RpcUtils.getSettings(url, account, password.toCharArray()); + showSizes = settings.get(Keys.web.showRepositorySizes).getBoolean(true); + assertEquals(newValue, showSizes); + } + + @Test + public void testBranches() throws Exception { + Map> branches = RpcUtils.getBranches(url, account, + password.toCharArray()); + assertNotNull(branches); + assertTrue(branches.size() > 0); + } +} diff --git a/src/test/java/com/gitblit/tests/StringUtilsTest.java b/src/test/java/com/gitblit/tests/StringUtilsTest.java new file mode 100644 index 00000000..bcf3a99c --- /dev/null +++ b/src/test/java/com/gitblit/tests/StringUtilsTest.java @@ -0,0 +1,160 @@ +/* + * Copyright 2011 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.List; + +import org.junit.Test; + +import com.gitblit.utils.StringUtils; + +public class StringUtilsTest { + + @Test + public void testIsEmpty() throws Exception { + assertTrue(StringUtils.isEmpty(null)); + assertTrue(StringUtils.isEmpty("")); + assertTrue(StringUtils.isEmpty(" ")); + assertFalse(StringUtils.isEmpty("A")); + } + + @Test + public void testBreakLinesForHtml() throws Exception { + String input = "this\nis\r\na\rtest\r\n\r\nof\n\nline\r\rbreaking"; + String output = "this
is
a
test

of

line

breaking"; + assertEquals(output, StringUtils.breakLinesForHtml(input)); + } + + @Test + public void testEncodeUrl() throws Exception { + String input = "test /"; + String output = "test%20%2F"; + assertEquals(output, StringUtils.encodeURL(input)); + } + + @Test + public void testEscapeForHtml() throws Exception { + String input = "& < > \" \t"; + String outputNoChange = "& < > " \t"; + String outputChange = "& < > "     "; + assertEquals(outputNoChange, StringUtils.escapeForHtml(input, false)); + assertEquals(outputChange, StringUtils.escapeForHtml(input, true)); + } + + @Test + public void testDecodeForHtml() throws Exception { + String input = "& < > ""; + String output = "& < > \""; + assertEquals(output, StringUtils.decodeFromHtml(input)); + } + + @Test + public void testFlattenStrings() throws Exception { + String[] strings = { "A", "B", "C", "D" }; + assertEquals("A B C D", StringUtils.flattenStrings(Arrays.asList(strings))); + } + + @Test + public void testTrim() throws Exception { + String input = "123456789 123456789 123456789 123456789 123456789 123456789 123456789 "; + String output = "123456789 123456789 123456789 123456789 123456789 1234567..."; + assertEquals(output, StringUtils.trimString(input, 60)); + assertEquals(input, StringUtils.trimString(input, input.length())); + } + + @Test + public void testPadding() throws Exception { + String input = "test"; + assertEquals(" test", StringUtils.leftPad(input, 6 + input.length(), ' ')); + assertEquals("test ", StringUtils.rightPad(input, 6 + input.length(), ' ')); + + assertEquals(input, StringUtils.leftPad(input, input.length(), ' ')); + assertEquals(input, StringUtils.rightPad(input, input.length(), ' ')); + } + + @Test + public void testSHA1() throws Exception { + assertEquals("bd9dbf5aae1a3862dd1526723246b20206e5fc37", + StringUtils.getSHA1("blob 16\000what is up, doc?")); + } + + @Test + public void testMD5() throws Exception { + assertEquals("77fb8d95331f0d557472f6776d3aedf6", + StringUtils.getMD5("blob 16\000what is up, doc?")); + } + + @Test + public void testRootPath() throws Exception { + String input = "/nested/path/to/repository"; + String output = "/nested/path/to"; + assertEquals(output, StringUtils.getRootPath(input)); + assertEquals("", StringUtils.getRootPath("repository")); + } + + @Test + public void testStringsFromValue() throws Exception { + List strings = StringUtils.getStringsFromValue("\"A A \" B \"C C\" D \"\" \"E\""); + assertEquals(6, strings.size()); + assertEquals("A A", strings.get(0)); + assertEquals("B", strings.get(1)); + assertEquals("C C", strings.get(2)); + assertEquals("D", strings.get(3)); + assertEquals("", strings.get(4)); + assertEquals("E", strings.get(5)); + + strings = StringUtils.getStringsFromValue("\"A A \", B, \"C C\", D, \"\", \"E\"", ","); + assertEquals(6, strings.size()); + assertEquals("A A", strings.get(0)); + assertEquals("B", strings.get(1)); + assertEquals("C C", strings.get(2)); + assertEquals("D", strings.get(3)); + assertEquals("", strings.get(4)); + assertEquals("E", strings.get(5)); + } + + @Test + public void testStringsFromValue2() throws Exception { + List strings = StringUtils.getStringsFromValue("common/* libraries/*"); + assertEquals(2, strings.size()); + assertEquals("common/*", strings.get(0)); + assertEquals("libraries/*", strings.get(1)); + } + + @Test + public void testFuzzyMatching() throws Exception { + assertTrue(StringUtils.fuzzyMatch("12345", "12345")); + assertTrue(StringUtils.fuzzyMatch("AbCdEf", "abcdef")); + assertTrue(StringUtils.fuzzyMatch("AbCdEf", "abc*")); + assertTrue(StringUtils.fuzzyMatch("AbCdEf", "*def")); + assertTrue(StringUtils.fuzzyMatch("AbCdEfHIJ", "abc*hij")); + + assertFalse(StringUtils.fuzzyMatch("123", "12345")); + assertFalse(StringUtils.fuzzyMatch("AbCdEfHIJ", "abc*hhh")); + } + + @Test + public void testGetRepositoryPath() throws Exception { + assertEquals("gitblit/gitblit.git", StringUtils.extractRepositoryPath("git://github.com/gitblit/gitblit.git", new String [] { ".*?://github.com/(.*)" })); + assertEquals("gitblit.git", StringUtils.extractRepositoryPath("git://github.com/gitblit/gitblit.git", new String [] { ".*?://github.com/[^/].*?/(.*)" })); + assertEquals("gitblit.git", StringUtils.extractRepositoryPath("git://github.com/gitblit/gitblit.git")); + } +} diff --git a/src/test/java/com/gitblit/tests/SyndicationUtilsTest.java b/src/test/java/com/gitblit/tests/SyndicationUtilsTest.java new file mode 100644 index 00000000..75fbd7ca --- /dev/null +++ b/src/test/java/com/gitblit/tests/SyndicationUtilsTest.java @@ -0,0 +1,96 @@ +/* + * Copyright 2011 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.junit.Test; + +import com.gitblit.Constants.SearchType; +import com.gitblit.models.FeedEntryModel; +import com.gitblit.utils.SyndicationUtils; + +public class SyndicationUtilsTest { + + @Test + public void testSyndication() throws Exception { + List entries = new ArrayList(); + for (int i = 0; i < 10; i++) { + FeedEntryModel entry = new FeedEntryModel(); + entry.title = "Title " + i; + entry.author = "Author " + i; + entry.link = "Link " + i; + entry.published = new Date(); + entry.contentType = "text/plain"; + entry.content = "Content " + i; + entry.repository = "Repository " + i; + entry.branch = "Branch " + i; + List tags = new ArrayList(); + for (int j = 0; j < 5; j++) { + tags.add("Tag " + j); + } + entry.tags = tags; + entries.add(entry); + } + ByteArrayOutputStream os = new ByteArrayOutputStream(); + SyndicationUtils.toRSS("http://localhost", "", "Title", "Description", + entries, os); + String feed = os.toString(); + os.close(); + assertTrue(feed.indexOf("Title") > -1); + assertTrue(feed.indexOf("Description") > -1); + } + + @Test + public void testFeedRead() throws Exception { + Set links = new HashSet(); + for (int i = 0; i < 2; i++) { + List feed = SyndicationUtils.readFeed(GitBlitSuite.url, "ticgit.git", + "master", 5, i, GitBlitSuite.account, GitBlitSuite.password.toCharArray()); + assertTrue(feed != null); + assertTrue(feed.size() > 0); + assertEquals(5, feed.size()); + for (FeedEntryModel entry : feed) { + links.add(entry.link); + } + } + // confirm we have 10 unique commits + assertEquals("Feed pagination failed", 10, links.size()); + } + + @Test + public void testSearchFeedRead() throws Exception { + List feed = SyndicationUtils + .readSearchFeed(GitBlitSuite.url, "ticgit.git", null, "test", null, 5, 0, + GitBlitSuite.account, GitBlitSuite.password.toCharArray()); + assertTrue(feed != null); + assertTrue(feed.size() > 0); + assertEquals(5, feed.size()); + feed = SyndicationUtils.readSearchFeed(GitBlitSuite.url, "ticgit.git", "master", "test", + SearchType.COMMIT, 5, 1, GitBlitSuite.account, GitBlitSuite.password.toCharArray()); + assertTrue(feed != null); + assertTrue(feed.size() > 0); + assertEquals(5, feed.size()); + } +} \ No newline at end of file diff --git a/src/test/java/com/gitblit/tests/TicgitUtilsTest.java b/src/test/java/com/gitblit/tests/TicgitUtilsTest.java new file mode 100644 index 00000000..74f9e44e --- /dev/null +++ b/src/test/java/com/gitblit/tests/TicgitUtilsTest.java @@ -0,0 +1,87 @@ +/* + * Copyright 2011 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.eclipse.jgit.lib.Repository; +import org.junit.Test; + +import com.gitblit.models.RefModel; +import com.gitblit.models.TicketModel; +import com.gitblit.models.TicketModel.Comment; +import com.gitblit.utils.TicgitUtils; + +public class TicgitUtilsTest { + + @Test + public void testTicgitBranch() throws Exception { + Repository repository = GitBlitSuite.getTicgitRepository(); + RefModel branch = TicgitUtils.getTicketsBranch(repository); + repository.close(); + assertNotNull("Ticgit branch does not exist!", branch); + + repository = GitBlitSuite.getHelloworldRepository(); + branch = TicgitUtils.getTicketsBranch(repository); + repository.close(); + assertNull("Ticgit branch exists!", branch); + } + + @Test + public void testRetrieveTickets() throws Exception { + Repository repository = GitBlitSuite.getTicgitRepository(); + List ticketsA = TicgitUtils.getTickets(repository); + List ticketsB = TicgitUtils.getTickets(repository); + repository.close(); + assertTrue("No tickets found!", ticketsA.size() > 0); + for (int i = 0; i < ticketsA.size(); i++) { + TicketModel ticketA = ticketsA.get(i); + TicketModel ticketB = ticketsB.get(i); + assertTrue("Tickets are not equal!", ticketA.equals(ticketB)); + assertFalse(ticketA.equals("")); + assertTrue(ticketA.hashCode() == ticketA.id.hashCode()); + for (int j = 0; j < ticketA.comments.size(); j++) { + Comment commentA = ticketA.comments.get(j); + Comment commentB = ticketB.comments.get(j); + assertTrue("Comments are not equal!", commentA.equals(commentB)); + assertFalse(commentA.equals("")); + assertEquals(commentA.hashCode(), commentA.text.hashCode()); + } + } + + repository = GitBlitSuite.getHelloworldRepository(); + List ticketsC = TicgitUtils.getTickets(repository); + repository.close(); + assertNull(ticketsC); + } + + @Test + public void testReadTicket() throws Exception { + Repository repository = GitBlitSuite.getTicgitRepository(); + List tickets = TicgitUtils.getTickets(repository); + TicketModel ticket = TicgitUtils + .getTicket(repository, tickets.get(tickets.size() - 1).name); + repository.close(); + assertNotNull(ticket); + assertEquals("1206206148_add-attachment-to-ticket_138", ticket.name); + } +} \ No newline at end of file diff --git a/src/test/java/com/gitblit/tests/TimeUtilsTest.java b/src/test/java/com/gitblit/tests/TimeUtilsTest.java new file mode 100644 index 00000000..f9d5d834 --- /dev/null +++ b/src/test/java/com/gitblit/tests/TimeUtilsTest.java @@ -0,0 +1,111 @@ +/* + * Copyright 2011 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Date; + +import org.junit.Test; + +import com.gitblit.utils.TimeUtils; + +public class TimeUtilsTest { + + private Date offset(long subtract) { + return new Date(System.currentTimeMillis() - subtract); + } + + @Test + public void testBasicTimeFunctions() throws Exception { + assertEquals(2, TimeUtils.minutesAgo(offset(2 * TimeUtils.MIN), false)); + assertEquals(3, TimeUtils.minutesAgo(offset((2 * TimeUtils.MIN) + (35 * 1000L)), true)); + + assertEquals(2, TimeUtils.hoursAgo(offset(2 * TimeUtils.ONEHOUR), false)); + assertEquals(3, TimeUtils.hoursAgo(offset(5 * TimeUtils.HALFHOUR), true)); + + assertEquals(4, TimeUtils.daysAgo(offset(4 * TimeUtils.ONEDAY))); + } + + @Test + public void testToday() throws Exception { + assertTrue(TimeUtils.isToday(new Date())); + } + + @Test + public void testYesterday() throws Exception { + assertTrue(TimeUtils.isYesterday(offset(TimeUtils.ONEDAY))); + } + + @Test + public void testDurations() throws Exception { + TimeUtils timeUtils = new TimeUtils(); + assertEquals("1 day", timeUtils.duration(1)); + assertEquals("5 days", timeUtils.duration(5)); + assertEquals("3 months", timeUtils.duration(75)); + assertEquals("12 months", timeUtils.duration(364)); + assertEquals("1 year", timeUtils.duration(365 + 0)); + assertEquals("1 year", timeUtils.duration(365 + 10)); + assertEquals("1 year, 1 month", timeUtils.duration(365 + 15)); + assertEquals("1 year, 1 month", timeUtils.duration(365 + 30)); + assertEquals("1 year, 1 month", timeUtils.duration(365 + 44)); + assertEquals("1 year, 2 months", timeUtils.duration(365 + 45)); + assertEquals("1 year, 2 months", timeUtils.duration(365 + 60)); + + assertEquals("2 years", timeUtils.duration(2 * 365 + 0)); + assertEquals("2 years", timeUtils.duration(2 * 365 + 10)); + assertEquals("2 years, 1 month", timeUtils.duration(2 * 365 + 15)); + assertEquals("2 years, 1 month", timeUtils.duration(2 * 365 + 30)); + assertEquals("2 years, 1 month", timeUtils.duration(2 * 365 + 44)); + assertEquals("2 years, 2 months", timeUtils.duration(2 * 365 + 45)); + assertEquals("2 years, 2 months", timeUtils.duration(2 * 365 + 60)); + } + + @Test + public void testTimeAgo() throws Exception { + // standard time ago tests + TimeUtils timeUtils = new TimeUtils(); + assertEquals("just now", timeUtils.timeAgo(offset(1 * TimeUtils.MIN))); + assertEquals("60 mins ago", timeUtils.timeAgo(offset(60 * TimeUtils.MIN))); + assertEquals("2 hours ago", timeUtils.timeAgo(offset(120 * TimeUtils.MIN))); + assertEquals("15 hours ago", timeUtils.timeAgo(offset(15 * TimeUtils.ONEHOUR))); + assertEquals("yesterday", timeUtils.timeAgo(offset(24 * TimeUtils.ONEHOUR))); + assertEquals("2 days ago", timeUtils.timeAgo(offset(2 * TimeUtils.ONEDAY))); + assertEquals("5 weeks ago", timeUtils.timeAgo(offset(35 * TimeUtils.ONEDAY))); + assertEquals("3 months ago", timeUtils.timeAgo(offset(84 * TimeUtils.ONEDAY))); + assertEquals("3 months ago", timeUtils.timeAgo(offset(95 * TimeUtils.ONEDAY))); + assertEquals("4 months ago", timeUtils.timeAgo(offset(104 * TimeUtils.ONEDAY))); + assertEquals("1 year ago", timeUtils.timeAgo(offset(365 * TimeUtils.ONEDAY))); + assertEquals("13 months ago", timeUtils.timeAgo(offset(395 * TimeUtils.ONEDAY))); + assertEquals("2 years ago", timeUtils.timeAgo(offset((2 * 365 + 30) * TimeUtils.ONEDAY))); + + // css class tests + assertEquals("age0", timeUtils.timeAgoCss(offset(1 * TimeUtils.MIN))); + assertEquals("age0", timeUtils.timeAgoCss(offset(60 * TimeUtils.MIN))); + assertEquals("age1", timeUtils.timeAgoCss(offset(120 * TimeUtils.MIN))); + assertEquals("age1", timeUtils.timeAgoCss(offset(24 * TimeUtils.ONEHOUR))); + assertEquals("age2", timeUtils.timeAgoCss(offset(2 * TimeUtils.ONEDAY))); + } + + @Test + public void testFrequency() { + assertEquals(5, TimeUtils.convertFrequencyToMinutes("2 mins")); + assertEquals(10, TimeUtils.convertFrequencyToMinutes("10 mins")); + assertEquals(600, TimeUtils.convertFrequencyToMinutes("10 hours")); + assertEquals(14400, TimeUtils.convertFrequencyToMinutes(" 10 days ")); + } +} diff --git a/src/test/java/com/gitblit/tests/UserServiceTest.java b/src/test/java/com/gitblit/tests/UserServiceTest.java new file mode 100644 index 00000000..710d1f35 --- /dev/null +++ b/src/test/java/com/gitblit/tests/UserServiceTest.java @@ -0,0 +1,245 @@ +/* + * Copyright 2011 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; + +import org.junit.Test; + +import com.gitblit.ConfigUserService; +import com.gitblit.Constants.AccessRestrictionType; +import com.gitblit.FileUserService; +import com.gitblit.IUserService; +import com.gitblit.models.RepositoryModel; +import com.gitblit.models.TeamModel; +import com.gitblit.models.UserModel; + +public class UserServiceTest { + + @Test + public void testFileUserService() throws IOException { + File file = new File("us-test.properties"); + file.delete(); + IUserService service = new FileUserService(file); + testUsers(service); + testTeams(service); + file.delete(); + } + + @Test + public void testConfigUserService() throws IOException { + File file = new File("us-test.conf"); + file.delete(); + IUserService service = new ConfigUserService(file); + testUsers(service); + testTeams(service); + file.delete(); + } + + protected void testUsers(IUserService service) { + + UserModel admin = service.getUserModel("admin"); + assertTrue(admin == null); + + // add admin and admins team + TeamModel admins = new TeamModel("admins"); + admins.mailingLists.add("admins@localhost.com"); + + admin = new UserModel("admin"); + admin.password = "password"; + admin.canAdmin = true; + admin.excludeFromFederation = true; + admin.teams.add(admins); + + service.updateUserModel(admin); + admin = null; + admins = null; + + // add new user + UserModel newUser = new UserModel("test"); + newUser.password = "testPassword"; + newUser.addRepositoryPermission("repo1"); + newUser.addRepositoryPermission("repo2"); + newUser.addRepositoryPermission("sub/repo3"); + service.updateUserModel(newUser); + + // add one more new user and then test reload of first new user + newUser = new UserModel("GARBAGE"); + newUser.password = "garbage"; + service.updateUserModel(newUser); + + // confirm all added users + assertEquals(3, service.getAllUsernames().size()); + assertTrue(service.getUserModel("garbage") != null); + assertTrue(service.getUserModel("GaRbAgE") != null); + assertTrue(service.getUserModel("GARBAGE") != null); + + // confirm reloaded test user + newUser = service.getUserModel("test"); + assertEquals("testPassword", newUser.password); + assertEquals(3, newUser.permissions.size()); + assertTrue(newUser.hasRepositoryPermission("repo1")); + assertTrue(newUser.hasRepositoryPermission("repo2")); + assertTrue(newUser.hasRepositoryPermission("sub/repo3")); + + // confirm authentication of test user + UserModel testUser = service.authenticate("test", "testPassword".toCharArray()); + assertEquals("test", testUser.username); + assertEquals("testPassword", testUser.password); + + // delete a repository role and confirm role removal from test user + service.deleteRepositoryRole("repo2"); + testUser = service.getUserModel("test"); + assertEquals(2, testUser.permissions.size()); + + // delete garbage user and confirm user count + service.deleteUser("garbage"); + assertEquals(2, service.getAllUsernames().size()); + + // rename repository and confirm role change for test user + service.renameRepositoryRole("repo1", "newrepo1"); + testUser = service.getUserModel("test"); + assertTrue(testUser.hasRepositoryPermission("newrepo1")); + } + + protected void testTeams(IUserService service) { + + // confirm we have 1 team (admins) + assertEquals(1, service.getAllTeamNames().size()); + assertEquals("admins", service.getAllTeamNames().get(0)); + + RepositoryModel newrepo1 = new RepositoryModel("newrepo1", null, null, null); + newrepo1.accessRestriction = AccessRestrictionType.VIEW; + RepositoryModel NEWREPO1 = new RepositoryModel("NEWREPO1", null, null, null); + NEWREPO1.accessRestriction = AccessRestrictionType.VIEW; + + // remove newrepo1 from test user + // now test user has no repositories + UserModel user = service.getUserModel("test"); + user.permissions.clear(); + service.updateUserModel(user); + user = service.getUserModel("test"); + assertEquals(0, user.permissions.size()); + assertFalse(user.canView(newrepo1)); + assertFalse(user.canView(NEWREPO1)); + + // create test team and add test user and newrepo1 + TeamModel team = new TeamModel("testteam"); + team.addUser("test"); + team.addRepositoryPermission(newrepo1.name); + service.updateTeamModel(team); + + // confirm 1 user and 1 repo + team = service.getTeamModel("testteam"); + assertEquals(1, team.permissions.size()); + assertEquals(1, team.users.size()); + + // confirm team membership + user = service.getUserModel("test"); + assertEquals(0, user.permissions.size()); + assertEquals(1, user.teams.size()); + + // confirm team access + assertTrue(team.hasRepositoryPermission(newrepo1.name)); + assertTrue(user.canView(newrepo1)); + assertTrue(team.hasRepositoryPermission(NEWREPO1.name)); + assertTrue(user.canView(NEWREPO1)); + + // rename the team and add new repository + RepositoryModel newrepo2 = new RepositoryModel("newrepo2", null, null, null); + newrepo2.accessRestriction = AccessRestrictionType.VIEW; + RepositoryModel NEWREPO2 = new RepositoryModel("NEWREPO2", null, null, null); + NEWREPO2.accessRestriction = AccessRestrictionType.VIEW; + + team.addRepositoryPermission(newrepo2.name); + team.name = "testteam2"; + service.updateTeamModel("testteam", team); + + team = service.getTeamModel("testteam2"); + user = service.getUserModel("test"); + + // confirm user and team can access newrepo2 + assertEquals(2, team.permissions.size()); + assertTrue(team.hasRepositoryPermission(newrepo2.name)); + assertTrue(user.canView(newrepo2)); + assertTrue(team.hasRepositoryPermission(NEWREPO2.name)); + assertTrue(user.canView(NEWREPO2)); + + // delete testteam2 + service.deleteTeam("testteam2"); + team = service.getTeamModel("testteam2"); + user = service.getUserModel("test"); + + // confirm team does not exist and user can not access newrepo1 and 2 + assertEquals(null, team); + assertFalse(user.canView(newrepo1)); + assertFalse(user.canView(newrepo2)); + + // create new team and add it to user + // this tests the inverse team creation/team addition + team = new TeamModel("testteam"); + team.addRepositoryPermission(NEWREPO1.name); + team.addRepositoryPermission(NEWREPO2.name); + user.teams.add(team); + service.updateUserModel(user); + + // confirm the inverted team addition + user = service.getUserModel("test"); + team = service.getTeamModel("testteam"); + assertTrue(user.canView(newrepo1)); + assertTrue(user.canView(newrepo2)); + assertTrue(team.hasUser("test")); + + // drop testteam from user and add nextteam to user + team = new TeamModel("nextteam"); + team.addRepositoryPermission(NEWREPO1.name); + team.addRepositoryPermission(NEWREPO2.name); + user.teams.clear(); + user.teams.add(team); + service.updateUserModel(user); + + // confirm implicit drop + user = service.getUserModel("test"); + team = service.getTeamModel("testteam"); + assertTrue(user.canView(newrepo1)); + assertTrue(user.canView(newrepo2)); + assertFalse(team.hasUser("test")); + team = service.getTeamModel("nextteam"); + assertTrue(team.hasUser("test")); + + // delete the user and confirm team no longer has user + service.deleteUser("test"); + team = service.getTeamModel("testteam"); + assertFalse(team.hasUser("test")); + + // delete both teams + service.deleteTeam("testteam"); + service.deleteTeam("nextteam"); + + // assert we still have the admins team + assertEquals(1, service.getAllTeamNames().size()); + assertEquals("admins", service.getAllTeamNames().get(0)); + + team = service.getTeamModel("admins"); + assertEquals(1, team.mailingLists.size()); + assertTrue(team.mailingLists.contains("admins@localhost.com")); + } +} \ No newline at end of file diff --git a/src/test/java/com/gitblit/tests/X509UtilsTest.java b/src/test/java/com/gitblit/tests/X509UtilsTest.java new file mode 100644 index 00000000..5d17e18d --- /dev/null +++ b/src/test/java/com/gitblit/tests/X509UtilsTest.java @@ -0,0 +1,184 @@ +/* + * Copyright 2012 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests; + +import java.io.File; +import java.io.FileInputStream; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import org.eclipse.jgit.util.FileUtils; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.gitblit.models.UserModel; +import com.gitblit.utils.HttpUtils; +import com.gitblit.utils.X509Utils; +import com.gitblit.utils.X509Utils.RevocationReason; +import com.gitblit.utils.X509Utils.X509Log; +import com.gitblit.utils.X509Utils.X509Metadata; + +/** + * Unit tests for X509 certificate generation. + * + * @author James Moger + * + */ +public class X509UtilsTest extends Assert { + + // passwords are case-sensitive and may be length-limited + // based on the JCE policy files + String caPassword = "aBcDeFg"; + File folder = new File(System.getProperty("user.dir"), "x509test"); + + X509Log log = new X509Log() { + public void log(String message) { + System.out.println(message); + } + }; + + @Before + public void prepare() throws Exception { + cleanUp(); + X509Metadata goMetadata = new X509Metadata("localhost", caPassword); + X509Utils.prepareX509Infrastructure(goMetadata, folder, log); + } + + @After + public void cleanUp() throws Exception { + if (folder.exists()) { + FileUtils.delete(folder, FileUtils.RECURSIVE); + } + } + + @Test + public void testNewCA() throws Exception { + File storeFile = new File(folder, X509Utils.CA_KEY_STORE); + X509Utils.getPrivateKey(X509Utils.CA_ALIAS, storeFile, caPassword); + X509Certificate cert = X509Utils.getCertificate(X509Utils.CA_ALIAS, storeFile, caPassword); + assertEquals("O=Gitblit,OU=Gitblit,CN=Gitblit Certificate Authority", cert.getIssuerDN().getName()); + } + + @Test + public void testCertificateUserMapping() throws Exception { + File storeFile = new File(folder, X509Utils.CA_KEY_STORE); + PrivateKey caPrivateKey = X509Utils.getPrivateKey(X509Utils.CA_ALIAS, storeFile, caPassword); + X509Certificate caCert = X509Utils.getCertificate(X509Utils.CA_ALIAS, storeFile, caPassword); + + X509Metadata userMetadata = new X509Metadata("james", "james"); + userMetadata.serverHostname = "www.myserver.com"; + userMetadata.userDisplayname = "James Moger"; + userMetadata.passwordHint = "your name"; + userMetadata.oids.put("C", "US"); + + X509Certificate cert1 = X509Utils.newClientCertificate(userMetadata, caPrivateKey, caCert, storeFile.getParentFile()); + UserModel userModel1 = HttpUtils.getUserModelFromCertificate(cert1); + assertEquals(userMetadata.commonName, userModel1.username); + assertEquals(userMetadata.emailAddress, userModel1.emailAddress); + assertEquals("C=US,O=Gitblit,OU=Gitblit,CN=james", cert1.getSubjectDN().getName()); + + + X509Certificate cert2 = X509Utils.newClientCertificate(userMetadata, caPrivateKey, caCert, storeFile.getParentFile()); + UserModel userModel2 = HttpUtils.getUserModelFromCertificate(cert2); + assertEquals(userMetadata.commonName, userModel2.username); + assertEquals(userMetadata.emailAddress, userModel2.emailAddress); + assertEquals("C=US,O=Gitblit,OU=Gitblit,CN=james", cert2.getSubjectDN().getName()); + + assertNotSame("Serial numbers are the same!", cert1.getSerialNumber().longValue(), cert2.getSerialNumber().longValue()); + } + + @Test + public void testUserBundle() throws Exception { + File storeFile = new File(folder, X509Utils.CA_KEY_STORE); + + X509Metadata userMetadata = new X509Metadata("james", "james"); + userMetadata.serverHostname = "www.myserver.com"; + userMetadata.userDisplayname = "James Moger"; + userMetadata.passwordHint = "your name"; + + File zip = X509Utils.newClientBundle(userMetadata, storeFile, caPassword, log); + assertTrue(zip.exists()); + + List expected = Arrays.asList( + userMetadata.commonName + ".pem", + userMetadata.commonName + ".p12", + userMetadata.commonName + ".cer", + "ca.cer", + "README.TXT"); + + ZipInputStream zis = new ZipInputStream(new FileInputStream(zip)); + ZipEntry entry = null; + while ((entry = zis.getNextEntry()) != null) { + assertTrue("Unexpected file: " + entry.getName(), expected.contains(entry.getName())); + } + zis.close(); + } + + @Test + public void testCertificateRevocation() throws Exception { + File storeFile = new File(folder, X509Utils.CA_KEY_STORE); + PrivateKey caPrivateKey = X509Utils.getPrivateKey(X509Utils.CA_ALIAS, storeFile, caPassword); + X509Certificate caCert = X509Utils.getCertificate(X509Utils.CA_ALIAS, storeFile, caPassword); + + X509Metadata userMetadata = new X509Metadata("james", "james"); + userMetadata.serverHostname = "www.myserver.com"; + userMetadata.userDisplayname = "James Moger"; + userMetadata.passwordHint = "your name"; + + // generate a new client certificate + X509Certificate cert1 = X509Utils.newClientCertificate(userMetadata, caPrivateKey, caCert, storeFile.getParentFile()); + + // confirm this certificate IS NOT revoked + File caRevocationList = new File(folder, X509Utils.CA_REVOCATION_LIST); + assertFalse(X509Utils.isRevoked(cert1, caRevocationList)); + + // revoke certificate and then confirm it IS revoked + X509Utils.revoke(cert1, RevocationReason.ACompromise, caRevocationList, storeFile, caPassword, log); + assertTrue(X509Utils.isRevoked(cert1, caRevocationList)); + + // generate a second certificate + X509Certificate cert2 = X509Utils.newClientCertificate(userMetadata, caPrivateKey, caCert, storeFile.getParentFile()); + + // confirm second certificate IS NOT revoked + assertTrue(X509Utils.isRevoked(cert1, caRevocationList)); + assertFalse(X509Utils.isRevoked(cert2, caRevocationList)); + + // revoke second certificate and then confirm it IS revoked + X509Utils.revoke(cert2, RevocationReason.ACompromise, caRevocationList, caPrivateKey, log); + assertTrue(X509Utils.isRevoked(cert1, caRevocationList)); + assertTrue(X509Utils.isRevoked(cert2, caRevocationList)); + + // generate a third certificate + X509Certificate cert3 = X509Utils.newClientCertificate(userMetadata, caPrivateKey, caCert, storeFile.getParentFile()); + + // confirm third certificate IS NOT revoked + assertTrue(X509Utils.isRevoked(cert1, caRevocationList)); + assertTrue(X509Utils.isRevoked(cert2, caRevocationList)); + assertFalse(X509Utils.isRevoked(cert3, caRevocationList)); + + // revoke third certificate and then confirm it IS revoked + X509Utils.revoke(cert3, RevocationReason.ACompromise, caRevocationList, caPrivateKey, log); + assertTrue(X509Utils.isRevoked(cert1, caRevocationList)); + assertTrue(X509Utils.isRevoked(cert2, caRevocationList)); + assertTrue(X509Utils.isRevoked(cert3, caRevocationList)); + } +} diff --git a/src/test/java/com/gitblit/tests/mock/MemorySettings.java b/src/test/java/com/gitblit/tests/mock/MemorySettings.java new file mode 100644 index 00000000..1b3e2382 --- /dev/null +++ b/src/test/java/com/gitblit/tests/mock/MemorySettings.java @@ -0,0 +1,50 @@ + /* + * Copyright 2012 John Crygier + * Copyright 2012 gitblit.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.tests.mock; + +import java.util.Map; +import java.util.Properties; + +import com.gitblit.IStoredSettings; + +public class MemorySettings extends IStoredSettings { + + private Map backingMap; + + public MemorySettings(Map backingMap) { + super(MemorySettings.class); + this.backingMap = backingMap; + } + + @Override + protected Properties read() { + Properties props = new Properties(); + props.putAll(backingMap); + + return props; + } + + public void put(Object key, Object value) { + backingMap.put(key.toString(), value); + } + + @Override + public boolean saveSettings(Map updatedSettings) { + return false; + } + +} diff --git a/src/test/java/com/gitblit/tests/resources/ldapUserServiceSampleData.ldif b/src/test/java/com/gitblit/tests/resources/ldapUserServiceSampleData.ldif new file mode 100644 index 00000000..df79333e --- /dev/null +++ b/src/test/java/com/gitblit/tests/resources/ldapUserServiceSampleData.ldif @@ -0,0 +1,108 @@ +dn: DC=MyDomain +dc: MyDomain +objectClass: top +objectClass: domain + +dn: OU=MyOrganization,DC=MyDomain +objectClass: top +objectClass: organizationalUnit +ou: MyOrganization + +dn: OU=UserControl,OU=MyOrganization,DC=MyDomain +objectClass: top +objectClass: organizationalUnit +ou: UserControl + +dn: OU=Groups,OU=UserControl,OU=MyOrganization,DC=MyDomain +objectClass: top +objectClass: organizationalUnit +ou: Groups + +dn: CN=Git_Admins,OU=Groups,OU=UserControl,OU=MyOrganization,DC=MyDomain +objectClass: top +objectClass: group +cn: Git_Admins +sAMAccountName: Git_Admins +member: CN=UserOne,OU=US,OU=Users,OU=UserControl,OU=MyOrganization,DC=MyDomain + +dn: CN=Git Admins,OU=Groups,OU=UserControl,OU=MyOrganization,DC=MyDomain +objectClass: top +objectClass: group +cn: Git Admins +sAMAccountName: Git_Admins_With_Space +member: CN=UserTwo,OU=US,OU=Users,OU=UserControl,OU=MyOrganization,DC=MyDomain + +dn: CN=Git_Users,OU=Groups,OU=UserControl,OU=MyOrganization,DC=MyDomain +objectClass: top +objectClass: group +cn: Git_Users +sAMAccountName: Git_Users +member: CN=UserOne,OU=US,OU=Users,OU=UserControl,OU=MyOrganization,DC=MyDomain +member: CN=UserTwo,OU=US,OU=Users,OU=UserControl,OU=MyOrganization,DC=MyDomain +member: CN=UserThree,OU=Canada,OU=Users,OU=UserControl,OU=MyOrganization,DC=MyDomain +member: CN=UserFour,OU=Canada,OU=Users,OU=UserControl,OU=MyOrganization,DC=MyDomain + +dn: OU=Users,OU=UserControl,OU=MyOrganization,DC=MyDomain +objectClass: top +objectClass: organizationalUnit +ou: Users + +dn: OU=US,OU=Users,OU=UserControl,OU=MyOrganization,DC=MyDomain +objectClass: top +objectClass: organizationalUnit +ou: US + +dn: OU=Canada,OU=Users,OU=UserControl,OU=MyOrganization,DC=MyDomain +objectClass: top +objectClass: organizationalUnit +ou: Canada + +dn: CN=UserOne,OU=US,OU=Users,OU=UserControl,OU=MyOrganization,DC=MyDomain +objectClass: user +objectClass: person +sAMAccountName: UserOne +userPassword: userOnePassword +displayName: User One +givenName: User +surname: One +personalTitle: Mr +email: userone@gitblit.com +memberOf: CN=Git_Admins,OU=Groups,OU=UserControl,OU=MyOrganization,DC=MyDomain +memberOf: CN=Git_Users,OU=Groups,OU=UserControl,OU=MyOrganization,DC=MyDomain + +dn: CN=UserTwo,OU=US,OU=Users,OU=UserControl,OU=MyOrganization,DC=MyDomain +objectClass: user +objectClass: person +sAMAccountName: UserTwo +userPassword: userTwoPassword +displayName: User Two +givenName: User +surname: Two +personalTitle: Mr +email: usertwo@gitblit.com +memberOf: CN=Git_Users,OU=Groups,OU=UserControl,OU=MyOrganization,DC=MyDomain +memberOf: CN=Git Admins,OU=Groups,OU=UserControl,OU=MyOrganization,DC=MyDomain + +dn: CN=UserThree,OU=Canada,OU=Users,OU=UserControl,OU=MyOrganization,DC=MyDomain +objectClass: user +objectClass: person +sAMAccountName: UserThree +userPassword: userThreePassword +displayName: User Three +givenName: User +surname: Three +personalTitle: Mrs +email: userthree@gitblit.com +memberOf: CN=Git_Users,OU=Groups,OU=UserControl,OU=MyOrganization,DC=MyDomain + +dn: CN=UserFour,OU=Canada,OU=Users,OU=UserControl,OU=MyOrganization,DC=MyDomain +objectClass: user +objectClass: person +sAMAccountName: UserFour +userPassword: userFourPassword +displayName: User Four +givenName: User +surname: Four +personalTitle: Miss +email: userfour@gitblit.com +memberOf: CN=Git_Users,OU=Groups,OU=UserControl,OU=MyOrganization,DC=MyDomain \ No newline at end of file diff --git a/src/test/java/de/akquinet/devops/GitBlit4UITests.java b/src/test/java/de/akquinet/devops/GitBlit4UITests.java new file mode 100644 index 00000000..130f2c96 --- /dev/null +++ b/src/test/java/de/akquinet/devops/GitBlit4UITests.java @@ -0,0 +1,25 @@ +package de.akquinet.devops; + +import java.util.concurrent.TimeUnit; + +import com.gitblit.GitBlit; + +public class GitBlit4UITests extends GitBlit { + + private boolean luceneIndexingEnabled; + + public GitBlit4UITests(boolean luceneIndexingEnabled) { + this.luceneIndexingEnabled = luceneIndexingEnabled; + } + + @Override + protected void enableLuceneIndexing() { + if (luceneIndexingEnabled) { + getScheduledExecutor().scheduleAtFixedRate(getLuceneExecutor(), 1, + 2, TimeUnit.MINUTES); + getLogger() + .info("Lucene executor is scheduled to process indexed branches every 2 minutes."); + } + } + +} diff --git a/src/test/java/de/akquinet/devops/GitBlitServer4UITests.java b/src/test/java/de/akquinet/devops/GitBlitServer4UITests.java new file mode 100644 index 00000000..2d54be2a --- /dev/null +++ b/src/test/java/de/akquinet/devops/GitBlitServer4UITests.java @@ -0,0 +1,62 @@ +package de.akquinet.devops; + +import java.util.ArrayList; +import java.util.List; + +import com.beust.jcommander.JCommander; +import com.beust.jcommander.ParameterException; +import com.gitblit.GitBlit; +import com.gitblit.GitBlitServer; + +public class GitBlitServer4UITests extends GitBlitServer { + + public static void main(String... args) { + GitBlitServer4UITests server = new GitBlitServer4UITests(); + + // filter out the baseFolder parameter + List filtered = new ArrayList(); + String folder = "data"; + for (int i = 0; i < args.length; i++) { + String arg = args[i]; + if (arg.equals("--baseFolder")) { + if (i + 1 == args.length) { + System.out.println("Invalid --baseFolder parameter!"); + System.exit(-1); + } else if (args[i + 1] != ".") { + folder = args[i + 1]; + } + i = i + 1; + } else { + filtered.add(arg); + } + } + + Params.baseFolder = folder; + Params params = new Params(); + JCommander jc = new JCommander(params); + try { + jc.parse(filtered.toArray(new String[filtered.size()])); + if (params.help) { + server.usage(jc, null); + } + } catch (ParameterException t) { + server.usage(jc, t); + } + + if (params.stop) { + server.stop(params); + } else { + server.start(params); + } + } + + private GitBlit4UITests instance; + + @Override + protected GitBlit getGitBlitInstance() { + if (instance == null) { + instance = new GitBlit4UITests(false); + } + return instance; + } +} diff --git a/src/test/java/de/akquinet/devops/GitblitRunnable.java b/src/test/java/de/akquinet/devops/GitblitRunnable.java new file mode 100644 index 00000000..66a31e3c --- /dev/null +++ b/src/test/java/de/akquinet/devops/GitblitRunnable.java @@ -0,0 +1,134 @@ +/* + * Copyright 2013 akquinet tech@spree GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.akquinet.devops; + +import java.net.InetAddress; +import java.net.ServerSocket; + +import com.gitblit.GitBlitServer; +import com.gitblit.tests.GitBlitSuite; + +/** + * This is a runnable implementation, that is used to run a gitblit server in a + * separate thread (e.g. alongside test cases) + * + * @author saheba + * + */ +public class GitblitRunnable implements Runnable { + + private int httpPort, httpsPort, shutdownPort; + private String userPropertiesPath, gitblitPropertiesPath; + private boolean startFailed = false; + + /** + * constructor with reduced set of start params + * + * @param httpPort + * @param httpsPort + * @param shutdownPort + * @param gitblitPropertiesPath + * @param userPropertiesPath + */ + public GitblitRunnable(int httpPort, int httpsPort, int shutdownPort, + String gitblitPropertiesPath, String userPropertiesPath) { + this.httpPort = httpPort; + this.httpsPort = httpsPort; + this.shutdownPort = shutdownPort; + this.userPropertiesPath = userPropertiesPath; + this.gitblitPropertiesPath = gitblitPropertiesPath; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Runnable#run() + */ + public void run() { + boolean portsFree = false; + long lastRun = -1; + while (!portsFree) { + long current = System.currentTimeMillis(); + if (lastRun == -1 || lastRun + 100 < current) { + portsFree = areAllPortsFree(new int[] { httpPort, httpsPort, + shutdownPort }, "127.0.0.1"); + } + lastRun = current; + + } + try { + GitBlitServer4UITests.main("--httpPort", "" + httpPort, "--httpsPort", "" + + httpsPort, "--shutdownPort", "" + shutdownPort, + "--repositoriesFolder", + "\"" + GitBlitSuite.REPOSITORIES.getAbsolutePath() + "\"", + "--userService", userPropertiesPath, "--settings", + gitblitPropertiesPath); + setStartFailed(false); + } catch (Exception iex) { + System.out.println("Gitblit server start failed"); + setStartFailed(true); + } + } + + /** + * Method used to ensure that all ports are free, if the runnable is used + * JUnit test classes. Be aware that JUnit's setUpClass and tearDownClass + * methods, which are executed before and after a test class (consisting of + * several test cases), may be executed parallely if they are part of a test + * suite consisting of several test classes. Therefore the run method of + * this class calls areAllPortsFree to check port availability before + * starting another gitblit instance. + * + * @param ports + * @param inetAddress + * @return + */ + public static boolean areAllPortsFree(int[] ports, String inetAddress) { + System.out + .println("\n" + + System.currentTimeMillis() + + " ----------------------------------- testing if all ports are free ..."); + String blockedPorts = ""; + for (int i = 0; i < ports.length; i++) { + ServerSocket s; + try { + s = new ServerSocket(ports[i], 1, + InetAddress.getByName(inetAddress)); + s.close(); + } catch (Exception e) { + if (!blockedPorts.equals("")) { + blockedPorts += ", "; + } + } + } + if (blockedPorts.equals("")) { + System.out + .println(" ----------------------------------- ... verified"); + return true; + } + System.out.println(" ----------------------------------- ... " + + blockedPorts + " are still blocked"); + return false; + } + + private void setStartFailed(boolean startFailed) { + this.startFailed = startFailed; + } + + public boolean isStartFailed() { + return startFailed; + } +} diff --git a/src/test/java/de/akquinet/devops/LaunchWithUITestConfig.java b/src/test/java/de/akquinet/devops/LaunchWithUITestConfig.java new file mode 100644 index 00000000..aebde9a2 --- /dev/null +++ b/src/test/java/de/akquinet/devops/LaunchWithUITestConfig.java @@ -0,0 +1,128 @@ +/* + * Copyright 2013 akquinet tech@spree GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.akquinet.devops; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; + +import junit.framework.Assert; + +import org.junit.Test; + +import com.gitblit.Constants; +import com.gitblit.GitBlitServer; +import com.gitblit.tests.GitBlitSuite; + +/** + * This test checks if it is possible to run two server instances in the same + * JVM sequentially + * + * @author saheba + * + */ +public class LaunchWithUITestConfig { + + @Test + public void testSequentialLaunchOfSeveralInstances() + throws InterruptedException { + // different ports than in testParallelLaunchOfSeveralInstances to + // ensure that both test cases do not affect each others test results + int httpPort = 9191, httpsPort = 9292, shutdownPort = 9393; + String gitblitPropertiesPath = "src/test/config/test-ui-gitblit.properties", + usersPropertiesPath = "src/test/config/test-ui-users.conf"; + + GitblitRunnable gitblitRunnable = new GitblitRunnable(httpPort, + httpsPort, shutdownPort, gitblitPropertiesPath, + usersPropertiesPath); + Thread serverThread = new Thread(gitblitRunnable); + serverThread.start(); + Thread.sleep(2000); + Assert.assertFalse(gitblitRunnable.isStartFailed()); + LaunchWithUITestConfig.shutdownGitBlitServer(shutdownPort); + + Thread.sleep(5000); + + GitblitRunnable gitblitRunnable2 = new GitblitRunnable(httpPort, + httpsPort, shutdownPort, gitblitPropertiesPath, + usersPropertiesPath); + Thread serverThread2 = new Thread(gitblitRunnable2); + serverThread2.start(); + Thread.sleep(2000); + Assert.assertFalse(gitblitRunnable2.isStartFailed()); + LaunchWithUITestConfig.shutdownGitBlitServer(shutdownPort); + } + + @Test + public void testParallelLaunchOfSeveralInstances() + throws InterruptedException { + // different ports than in testSequentialLaunchOfSeveralInstances to + // ensure that both test cases do not affect each others test results + int httpPort = 9797, httpsPort = 9898, shutdownPort = 9999; + int httpPort2 = 9494, httpsPort2 = 9595, shutdownPort2 = 9696; + String gitblitPropertiesPath = "src/test/config/test-ui-gitblit.properties", + usersPropertiesPath = "src/test/config/test-ui-users.conf"; + + GitblitRunnable gitblitRunnable = new GitblitRunnable(httpPort, + httpsPort, shutdownPort, gitblitPropertiesPath, + usersPropertiesPath); + Thread serverThread = new Thread(gitblitRunnable); + serverThread.start(); + Thread.sleep(2000); + Assert.assertFalse(gitblitRunnable.isStartFailed()); + + GitblitRunnable gitblitRunnable2 = new GitblitRunnable(httpPort2, + httpsPort2, shutdownPort2, gitblitPropertiesPath, + usersPropertiesPath); + Thread serverThread2 = new Thread(gitblitRunnable2); + serverThread2.start(); + Thread.sleep(2000); + Assert.assertFalse(gitblitRunnable2.isStartFailed()); + + LaunchWithUITestConfig.shutdownGitBlitServer(shutdownPort); + LaunchWithUITestConfig.shutdownGitBlitServer(shutdownPort2); + } + + /** + * main runs the tests without assert checks. You have to check the console + * output manually. + * + * @param args + * @throws InterruptedException + */ + public static void main(String[] args) throws InterruptedException { + new LaunchWithUITestConfig().testSequentialLaunchOfSeveralInstances(); + new LaunchWithUITestConfig().testParallelLaunchOfSeveralInstances(); + } + + private static void shutdownGitBlitServer(int shutdownPort) { + try { + Socket s = new Socket(InetAddress.getByName("127.0.0.1"), + shutdownPort); + OutputStream out = s.getOutputStream(); + System.out.println("Sending Shutdown Request to " + Constants.NAME); + out.write("\r\n".getBytes()); + out.flush(); + s.close(); + } catch (UnknownHostException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/de/akquinet/devops/ManualUITestLaunch.java b/src/test/java/de/akquinet/devops/ManualUITestLaunch.java new file mode 100644 index 00000000..809360aa --- /dev/null +++ b/src/test/java/de/akquinet/devops/ManualUITestLaunch.java @@ -0,0 +1,15 @@ +package de.akquinet.devops; + +public class ManualUITestLaunch { +public static void main(String[] args) { + int httpPort = 8080, httpsPort = 8443, shutdownPort = 8081; + String gitblitPropertiesPath = "src/test/config/test-ui-gitblit.properties", + usersPropertiesPath = "src/test/config/test-ui-users.conf"; + + GitblitRunnable gitblitRunnable = new GitblitRunnable(httpPort, + httpsPort, shutdownPort, gitblitPropertiesPath, + usersPropertiesPath); + Thread serverThread = new Thread(gitblitRunnable); + serverThread.start(); +} +} diff --git a/src/test/java/de/akquinet/devops/test/ui/TestUISuite.java b/src/test/java/de/akquinet/devops/test/ui/TestUISuite.java new file mode 100644 index 00000000..08d7a00b --- /dev/null +++ b/src/test/java/de/akquinet/devops/test/ui/TestUISuite.java @@ -0,0 +1,33 @@ +/* + * Copyright 2013 akquinet tech@spree GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.akquinet.devops.test.ui; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +import de.akquinet.devops.test.ui.cases.UI_MultiAdminSupportTest; + +/** + * the test suite including all selenium-based ui-tests. + * + * @author saheba + * + */ +@RunWith(Suite.class) +@Suite.SuiteClasses({ UI_MultiAdminSupportTest.class, UI_MultiAdminSupportTest.class }) +public class TestUISuite { + +} diff --git a/src/test/java/de/akquinet/devops/test/ui/cases/UI_MultiAdminSupportTest.java b/src/test/java/de/akquinet/devops/test/ui/cases/UI_MultiAdminSupportTest.java new file mode 100644 index 00000000..a3925719 --- /dev/null +++ b/src/test/java/de/akquinet/devops/test/ui/cases/UI_MultiAdminSupportTest.java @@ -0,0 +1,93 @@ +/* + * Copyright 2013 akquinet tech@spree GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.akquinet.devops.test.ui.cases; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import de.akquinet.devops.test.ui.generic.AbstractUITest; +import de.akquinet.devops.test.ui.view.RepoEditView; +import de.akquinet.devops.test.ui.view.RepoListView; + +/** + * tests the multi admin per repo feature. + * + * @author saheba + * + */ +public class UI_MultiAdminSupportTest extends AbstractUITest { + + String baseUrl = "https://localhost:8443"; + RepoListView view; + RepoEditView editView; + private static final String TEST_MULTI_ADMIN_SUPPORT_REPO_NAME = "testmultiadminsupport"; + private static final String TEST_MULTI_ADMIN_SUPPORT_REPO_PATH = "~repocreator/" + + TEST_MULTI_ADMIN_SUPPORT_REPO_NAME + ".git"; + private static final String TEST_MULTI_ADMIN_SUPPORT_REPO_PATH_WITHOUT_SUFFIX = "~repocreator/" + + TEST_MULTI_ADMIN_SUPPORT_REPO_NAME; + + @Before + public void before() { + System.out.println("IN BEFORE"); + this.view = new RepoListView(AbstractUITest.getDriver(), baseUrl); + this.editView = new RepoEditView(AbstractUITest.getDriver()); + AbstractUITest.getDriver().navigate().to(baseUrl); + } + + @Test + public void test_MultiAdminSelectionInStandardRepo() { + // login + view.login("repocreator", "repocreator"); + + // create new repo + view.navigateToNewRepo(1); + editView.changeName(TEST_MULTI_ADMIN_SUPPORT_REPO_PATH); + Assert.assertTrue(editView.navigateToPermissionsTab()); + + Assert.assertTrue(editView + .changeAccessRestriction(RepoEditView.RESTRICTION_AUTHENTICATED_VCP)); + Assert.assertTrue(editView + .changeAuthorizationControl(RepoEditView.AUTHCONTROL_RWALL)); + + // with a second admin + editView.addOwner("admin"); + Assert.assertTrue(editView.save()); + // user is automatically forwarded to repo list view + Assert.assertTrue(view.isEmptyRepo(TEST_MULTI_ADMIN_SUPPORT_REPO_PATH)); + Assert.assertTrue(view + .isEditableRepo(TEST_MULTI_ADMIN_SUPPORT_REPO_PATH)); + Assert.assertTrue(view + .isDeletableRepo(TEST_MULTI_ADMIN_SUPPORT_REPO_PATH_WITHOUT_SUFFIX)); + // logout repocreator + view.logout(); + + // check with admin account if second admin has the same rights + view.login("admin", "admin"); + Assert.assertTrue(view.isEmptyRepo(TEST_MULTI_ADMIN_SUPPORT_REPO_PATH)); + Assert.assertTrue(view + .isEditableRepo(TEST_MULTI_ADMIN_SUPPORT_REPO_PATH)); + Assert.assertTrue(view + .isDeletableRepo(TEST_MULTI_ADMIN_SUPPORT_REPO_PATH_WITHOUT_SUFFIX)); + // delete repo to reach state as before test execution + view.navigateToDeleteRepo(TEST_MULTI_ADMIN_SUPPORT_REPO_PATH_WITHOUT_SUFFIX); + view.acceptAlertDialog(); + view.logout(); + + Assert.assertTrue(view.isLoginPartVisible()); + } + +} diff --git a/src/test/java/de/akquinet/devops/test/ui/generic/AbstractUITest.java b/src/test/java/de/akquinet/devops/test/ui/generic/AbstractUITest.java new file mode 100644 index 00000000..bb7b3da2 --- /dev/null +++ b/src/test/java/de/akquinet/devops/test/ui/generic/AbstractUITest.java @@ -0,0 +1,96 @@ +/* + * Copyright 2013 akquinet tech@spree GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.akquinet.devops.test.ui.generic; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.firefox.FirefoxDriver; +import org.openqa.selenium.firefox.FirefoxProfile; + +import com.gitblit.GitBlitServer; + +import de.akquinet.devops.GitblitRunnable; + +/** + * This abstract class implements the setUpClass and tearDownClass for + * selenium-based UITests. They require a running gitblit server instance and a + * webdriver instance, which are managed by the setUpClass and tearDownClass + * method. Write a separate test class derived from this abstract class for each + * scenario consisting of one or more test cases, which can share the same + * server instance. + * + * @author saheba + * + */ +public abstract class AbstractUITest { + + private static Thread serverThread; + private static WebDriver driver; + + private static final int HTTP_PORT = 8080, HTTPS_PORT = 8443, + SHUTDOWN_PORT = 8081; + private static final String GITBLIT_PROPERTIES_PATH = "test-ui-gitblit.properties", + USERS_PROPERTIES_PATH = "test-ui-users.conf"; + + /** + * starts a gitblit server instance in a separate thread before test cases + * of concrete, non-abstract child-classes are executed + */ + @BeforeClass + public static void setUpClass() { + Runnable gitblitRunnable = new GitblitRunnable(HTTP_PORT, HTTPS_PORT, + SHUTDOWN_PORT, GITBLIT_PROPERTIES_PATH, USERS_PROPERTIES_PATH); + + serverThread = new Thread(gitblitRunnable); + serverThread.start(); + FirefoxProfile firefoxProfile = new FirefoxProfile(); + firefoxProfile.setPreference("startup.homepage_welcome_url", + "https://www.google.de"); + + firefoxProfile.setPreference("browser.download.folderList", 2); + firefoxProfile.setPreference( + "browser.download.manager.showWhenStarting", false); + String downloadDir = System.getProperty("java.io.tmpdir"); + firefoxProfile.setPreference("browser.download.dir", downloadDir); + firefoxProfile.setPreference("browser.helperApps.neverAsk.saveToDisk", + "text/csv,text/plain,application/zip,application/pdf"); + firefoxProfile.setPreference("browser.helperApps.alwaysAsk.force", + false); + System.out.println("Saving all attachments to: " + downloadDir); + + driver = new FirefoxDriver(firefoxProfile); + } + + /** + * stops the gitblit server instance running in a separate thread after test + * cases of concrete, non-abstract child-classes have been executed + */ + @AfterClass + public static void tearDownClass() throws InterruptedException { + driver.close(); + // Stop Gitblit + GitBlitServer.main("--stop", "--shutdownPort", "" + SHUTDOWN_PORT); + + // Wait a few seconds for it to be running completely including thread + // destruction + Thread.sleep(1000); + } + + public static WebDriver getDriver() { + return AbstractUITest.driver; + } +} diff --git a/src/test/java/de/akquinet/devops/test/ui/view/Exp.java b/src/test/java/de/akquinet/devops/test/ui/view/Exp.java new file mode 100644 index 00000000..3433bbb6 --- /dev/null +++ b/src/test/java/de/akquinet/devops/test/ui/view/Exp.java @@ -0,0 +1,45 @@ +/* + * Copyright 2013 akquinet tech@spree GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.akquinet.devops.test.ui.view; + +import java.util.List; + +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.ExpectedCondition; + +/** + * container class for selenium conditions + * + * @author saheba + * + */ +public class Exp { + public static class EditRepoViewLoaded implements ExpectedCondition { + public Boolean apply(WebDriver d) { + List findElements = d.findElements(By.partialLinkText("general")); + return findElements.size() == 1; + } + } + public static class RepoListViewLoaded implements ExpectedCondition { + public Boolean apply(WebDriver d) { + String xpath = "//img[@src=\"git-black-16x16.png\"]"; + List findElements = d.findElements(By.xpath(xpath )); + return findElements.size() == 1; + } + } +} diff --git a/src/test/java/de/akquinet/devops/test/ui/view/GitblitDashboardView.java b/src/test/java/de/akquinet/devops/test/ui/view/GitblitDashboardView.java new file mode 100644 index 00000000..0908d7c9 --- /dev/null +++ b/src/test/java/de/akquinet/devops/test/ui/view/GitblitDashboardView.java @@ -0,0 +1,100 @@ +/* + * Copyright 2013 akquinet tech@spree GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.akquinet.devops.test.ui.view; + +import java.util.List; + +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.ExpectedCondition; +import org.openqa.selenium.support.ui.WebDriverWait; + +/** + * class representing the view componenents and possible user interactions, you + * can see and do on most screens when you are logged in. + * + * @author saheba + * + */ +public class GitblitDashboardView extends GitblitPageView { + + public static final String TITLE_STARTS_WITH = "localhost"; + + public GitblitDashboardView(WebDriver driver, String baseUrl) { + super(driver, baseUrl); + } + + public boolean isLoginPartVisible() { + List found = getDriver().findElements( + By.partialLinkText("logout")); + return found == null || found.size() == 0; + } + + public void logout() { + // String pathLogout = "//a[@href =\"?" + WICKET_HREF_PAGE_PATH + // + ".LogoutPage\"]"; + // List logout = + // getDriver().findElements(By.xpath(pathLogout)); + // logout.get(0).click(); + // replaced by url call because click hangs sometimes if the clicked + // object is not a button or selenium ff driver does not notice the + // change for any other reason + getDriver().navigate().to( + getBaseUrl() + "?" + WICKET_HREF_PAGE_PATH + ".LogoutPage"); + } + + public static final String LOGIN_AREA_SELECTOR = "//span[@class = \"form-search\" ]"; + public static final String WICKET_PAGES_PACKAGE_NAME = "com.gitblit.wicket.pages"; + public static final String WICKET_HREF_PAGE_PATH = "wicket:bookmarkablePage=:" + + WICKET_PAGES_PACKAGE_NAME; + + synchronized public void waitToLoadFor(int sec) { + WebDriverWait webDriverWait = new WebDriverWait(getDriver(), sec); + webDriverWait.until(new ExpectedCondition() { + public Boolean apply(WebDriver d) { + return d.getTitle().toLowerCase() + .startsWith(GitblitDashboardView.TITLE_STARTS_WITH); + } + }); + } + + public void login(String id, String pw) { + String pathID = LOGIN_AREA_SELECTOR + "/input[@name = \"username\" ]"; + String pathPW = LOGIN_AREA_SELECTOR + "/input[@name = \"password\" ]"; + String pathSubmit = LOGIN_AREA_SELECTOR + + "/button[@type = \"submit\" ]"; + // System.out.println("DRIVER:"+getDriver()); + // List findElement = + // getDriver().findElements(By.xpath("//span[@class = \"form-search\" ]")); + // + // System.out.println("ELEM: "+findElement); + // System.out.println("SIZE: "+findElement.size()); + // System.out.println("XPath: "+pathID); + WebElement idField = getDriver().findElement(By.xpath(pathID)); + // System.out.println("IDFIELD:"+idField); + idField.sendKeys(id); + WebElement pwField = getDriver().findElement(By.xpath(pathPW)); + // System.out.println(pwField); + pwField.sendKeys(pw); + WebElement submit = getDriver().findElement(By.xpath(pathSubmit)); + submit.click(); + } + + public void acceptAlertDialog() { + getDriver().switchTo().alert().accept(); + } +} diff --git a/src/test/java/de/akquinet/devops/test/ui/view/GitblitPageView.java b/src/test/java/de/akquinet/devops/test/ui/view/GitblitPageView.java new file mode 100644 index 00000000..43716434 --- /dev/null +++ b/src/test/java/de/akquinet/devops/test/ui/view/GitblitPageView.java @@ -0,0 +1,73 @@ +/* + * Copyright 2013 akquinet tech@spree GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.akquinet.devops.test.ui.view; + +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +/** + * general basic class representing a gitblit webpage and offering basic methods + * used in selenium tests. + * + * @author saheba + * + */ +public class GitblitPageView { + private WebDriver driver; + private String baseUrl; + + public GitblitPageView(WebDriver driver, String baseUrl) { + this.driver = driver; + this.baseUrl = baseUrl; + } + + public void sleep(int miliseconds) { + try { + Thread.sleep(miliseconds); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + public WebElement getElementWithFocus() { + String elScript = "return document.activeElement;"; + + WebElement focuseedEl = (WebElement) ((JavascriptExecutor) getDriver()) + .executeScript(elScript); + return focuseedEl; + } + + public void navigateToPreviousPageOfBrowserHistory() { + driver.navigate().back(); + } + + public void setDriver(WebDriver driver) { + this.driver = driver; + } + + public WebDriver getDriver() { + return driver; + } + + public void setBaseUrl(String baseUrl) { + this.baseUrl = baseUrl; + } + + public String getBaseUrl() { + return baseUrl; + } +} diff --git a/src/test/java/de/akquinet/devops/test/ui/view/RepoEditView.java b/src/test/java/de/akquinet/devops/test/ui/view/RepoEditView.java new file mode 100644 index 00000000..a3365d1c --- /dev/null +++ b/src/test/java/de/akquinet/devops/test/ui/view/RepoEditView.java @@ -0,0 +1,158 @@ +/* + * Copyright 2013 akquinet tech@spree GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.akquinet.devops.test.ui.view; + +import java.util.List; + +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.WebDriverWait; + +/** + * class representing the tabs you can access when you edit a repo. + * + * @author saheba + * + */ +public class RepoEditView extends GitblitDashboardView { + + public static final String PERMISSION_VIEW_USERS_NAME_PREFIX = "users:"; + public static final String PERMISSION_VIEW_TEAMS_NAME_PREFIX = "teams:"; + + public static final String PERMISSION_VIEW_MUTABLE = "permissionToggleForm:showMutable"; + public static final String PERMISSION_VIEW_SPECIFIED = "permissionToggleForm:showSpecified"; + public static final String PERMISSION_VIEW_EFFECTIVE = "permissionToggleForm:showEffective"; + + public static final int RESTRICTION_ANONYMOUS_VCP = 0; + public static final int RESTRICTION_AUTHENTICATED_P = 1; + public static final int RESTRICTION_AUTHENTICATED_CP = 2; + public static final int RESTRICTION_AUTHENTICATED_VCP = 3; + + public static final int AUTHCONTROL_RWALL = 0; + public static final int AUTHOCONTROL_FINE = 1; + + public RepoEditView(WebDriver driver) { + super(driver, null); + } + + public void changeName(String newName) { + String pathName = "//input[@id = \"name\" ]"; + WebElement field = getDriver().findElement(By.xpath(pathName)); + field.clear(); + field.sendKeys(newName); + } + + public boolean navigateToPermissionsTab() { + String linkText = "access permissions"; + List found = getDriver().findElements( + By.partialLinkText(linkText)); + System.out.println("PERM TABS found =" + found.size()); + if (found != null && found.size() == 1) { + found.get(0).click(); + return true; + } + return false; + } + + private void changeOwners(String action, + String affectedSelection, String username) { + String xpath = "//select[@name=\"" + affectedSelection + + "\"]/option[@value = \"" + username + "\" ]"; + WebElement option = getDriver().findElement(By.xpath(xpath)); + option.click(); + String buttonPath = "//button[@class=\"button " + action + "\"]"; + WebElement button = getDriver().findElement(By.xpath(buttonPath)); + button.click(); + } + + public void removeOwner(String username) { + changeOwners("remove", "owners:selection", + username); + } + + public void addOwner(String username) { + changeOwners("add", "owners:choices", username); + } + + public WebElement getAccessRestrictionSelection() { + String xpath = "//select[@name =\"accessRestriction\"]"; + List found = getDriver().findElements(By.xpath(xpath)); + if (found != null && found.size() == 1) { + return found.get(0); + } + return null; + } + + public boolean changeAccessRestriction(int option) { + WebElement accessRestrictionSelection = getAccessRestrictionSelection(); + if (accessRestrictionSelection == null) { + return false; + } + accessRestrictionSelection.click(); + sleep(100); + String xpath = "//select[@name =\"accessRestriction\"]/option[@value=\"" + + option + "\"]"; + List found = getDriver().findElements(By.xpath(xpath)); + if (found == null || found.size() == 0 || found.size() > 1) { + return false; + } + found.get(0).click(); + return true; + } + + public boolean changeAuthorizationControl(int option) { + System.out.println("try to change auth control"); + String xpath = "//input[@name =\"authorizationControl\" and @value=\"" + + option + "\"]"; + List found = getDriver().findElements(By.xpath(xpath)); + System.out.println("found auth CONTROL options " + found.size()); + if (found == null || found.size() == 0 || found.size() > 1) { + return false; + } + found.get(0).click(); + return true; + } + + private boolean isPermissionViewDisabled(String prefix, String view) { + String xpath = "//[@name =\"" + prefix + view + "\"]"; + List found = getDriver().findElements(By.xpath(xpath)); + if (found == null || found.size() == 0 || found.size() > 1) { + return false; + } + String attrValue = found.get(0).getAttribute("disabled"); + return (attrValue != null) && (attrValue.equals("disabled")); + } + + public boolean isPermissionViewSectionDisabled(String prefix) { + return isPermissionViewDisabled(prefix, PERMISSION_VIEW_MUTABLE) + && isPermissionViewDisabled(prefix, PERMISSION_VIEW_SPECIFIED) + && isPermissionViewDisabled(prefix, PERMISSION_VIEW_EFFECTIVE); + } + + public boolean save() { + String xpath = "//div[@class=\"form-actions\"]/input[@name =\"" + + "save" + "\"]"; + List found = getDriver().findElements(By.xpath(xpath)); + if (found == null || found.size() == 0 || found.size() > 1) { + return false; + } + found.get(0).click(); + WebDriverWait webDriverWait = new WebDriverWait(getDriver(), 1); + webDriverWait.until(new Exp.RepoListViewLoaded()); + return true; + } +} diff --git a/src/test/java/de/akquinet/devops/test/ui/view/RepoListView.java b/src/test/java/de/akquinet/devops/test/ui/view/RepoListView.java new file mode 100644 index 00000000..6ec6203f --- /dev/null +++ b/src/test/java/de/akquinet/devops/test/ui/view/RepoListView.java @@ -0,0 +1,130 @@ +/* + * Copyright 2013 akquinet tech@spree GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.akquinet.devops.test.ui.view; + +import java.util.List; + +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.WebDriverWait; + +/** + * class representing the repo list view, which you see e.g. right after you + * logged in. + * + * @author saheba + * + */ +public class RepoListView extends GitblitDashboardView { + + public RepoListView(WebDriver driver, String baseUrl) { + super(driver, baseUrl); + } + + public boolean isEmptyRepo(String fullyQualifiedRepoName) { + String pathToLink = "//a[@href = \"?" + WICKET_HREF_PAGE_PATH + + ".EmptyRepositoryPage&r=" + fullyQualifiedRepoName + "\"]"; + List found = getDriver().findElements(By.xpath(pathToLink)); + return found != null && found.size() > 0; + } + + private String getEditRepoPath(String fullyQualifiedRepoName) { + return "//a[@href =\"?" + WICKET_HREF_PAGE_PATH + + ".EditRepositoryPage&r=" + fullyQualifiedRepoName + "\"]"; + } + + private String getDeleteRepoOnclickIdentifier( + String fullyQualifiedRepoPathAndName) { + return "var conf = confirm('Delete repository \"" + + fullyQualifiedRepoPathAndName + + "\"?'); if (!conf) return false; "; + } + + public boolean navigateToNewRepo(long waitSecToLoad) { + String pathToLink = "//a[@href =\"?" + WICKET_HREF_PAGE_PATH + + ".EditRepositoryPage\"]"; + List found = getDriver().findElements(By.xpath(pathToLink)); + if (found == null || found.size() == 0 || found.size() > 1) { + return false; + } + found.get(0).click(); + WebDriverWait webDriverWait = new WebDriverWait(getDriver(), + waitSecToLoad); + webDriverWait.until(new Exp.EditRepoViewLoaded()); + return true; + } + + private boolean checkOrDoEditRepo(String fullyQualifiedRepoName, + boolean doEdit) { + List found = getDriver().findElements( + By.xpath(getEditRepoPath(fullyQualifiedRepoName))); + if (found == null || found.size() == 0 || found.size() > 1) { + return false; + } + if (doEdit) { + found.get(0).click(); + } + return true; + } + + public boolean navigateToEditRepo(String fullyQualifiedRepoName, + int waitSecToLoad) { + boolean result = checkOrDoEditRepo(fullyQualifiedRepoName, true); + WebDriverWait webDriverWait = new WebDriverWait(getDriver(), + waitSecToLoad); + webDriverWait.until(new Exp.EditRepoViewLoaded()); + return result; + } + + public boolean isEditableRepo(String fullyQualifiedRepoName) { + return checkOrDoEditRepo(fullyQualifiedRepoName, false); + } + + private boolean checkOrDoDeleteRepo(String fullyQualifiedRepoPathAndName, + boolean doDelete) { + List found = getDriver().findElements( + By.partialLinkText("delete")); + String onclickIdentifier = getDeleteRepoOnclickIdentifier(fullyQualifiedRepoPathAndName); + WebElement result = null; + for (WebElement webElement : found) { + if (webElement.getAttribute("onclick") != null + && webElement.getAttribute("onclick").equals( + onclickIdentifier)) { + result = webElement; + break; + } + } + System.out.println("result ? " + result); + if (result == null) { + return false; + } + if (doDelete) { + System.out.println(".............. DO DELETE .... "); + result.click(); + } + return true; + } + + public boolean isDeletableRepo(String fullyQualifiedRepoPathAndName) { + return checkOrDoDeleteRepo(fullyQualifiedRepoPathAndName, false); + } + + public boolean navigateToDeleteRepo(String fullyQualifiedRepoPathAndName) { + return checkOrDoDeleteRepo(fullyQualifiedRepoPathAndName, true); + + } +} -- cgit v1.2.3