Skip to content

Commit d88a28f

Browse files
authored
Merge pull request #33 from sparkoo/integration-tests
e2e tests
2 parents c73e2d2 + 2788805 commit d88a28f

27 files changed

+711
-62
lines changed

.mvn/wrapper/maven-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.0/apache-maven-3.5.0-bin.zip
1+
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ language: java
22
jdk:
33
- oraclejdk8
44
sudo: false
5-
script: ./mvnw clean verify cobertura:cobertura
5+
script: ./mvnw clean verify cobertura:cobertura-integration-test
66

77
after_success:
88
- bash <(curl -s https://codecov.io/bash)

pom.xml

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,24 @@
99
<packaging>jar</packaging>
1010

1111
<name>boxitory</name>
12-
<description>Demo project for Spring Boot</description>
12+
<description>Vagrant box repository</description>
13+
<url>https://github.com/sparkoo/boxitory</url>
14+
<developers>
15+
<developer>
16+
<name>sparkoo</name>
17+
<url>https://github.com/sparkoo</url>
18+
</developer>
19+
</developers>
20+
<contributors>
21+
<contributor>
22+
<name>D3ryk</name>
23+
<url>https://github.com/D3ryk</url>
24+
</contributor>
25+
</contributors>
26+
<organization>
27+
<name>sparkoo</name>
28+
<url>https://github.com/sparkoo</url>
29+
</organization>
1330

1431
<parent>
1532
<groupId>org.springframework.boot</groupId>
@@ -107,11 +124,36 @@
107124
<instrumentation>
108125
<ignoreTrivial>true</ignoreTrivial>
109126
</instrumentation>
110-
<check />
127+
<check/>
111128
</configuration>
112129
</plugin>
130+
<plugin>
131+
<groupId>org.apache.maven.plugins</groupId>
132+
<artifactId>maven-surefire-plugin</artifactId>
133+
<version>2.20</version>
134+
<configuration>
135+
<excludedGroups>e2e</excludedGroups>
136+
</configuration>
137+
</plugin>
138+
<plugin>
139+
<groupId>org.apache.maven.plugins</groupId>
140+
<artifactId>maven-failsafe-plugin</artifactId>
141+
<version>2.18.1</version>
142+
<configuration>
143+
<groups>e2e</groups>
144+
<includes>
145+
<include>**/*Test.java</include>
146+
</includes>
147+
</configuration>
148+
<executions>
149+
<execution>
150+
<goals>
151+
<goal>integration-test</goal>
152+
<goal>verify</goal>
153+
</goals>
154+
</execution>
155+
</executions>
156+
</plugin>
113157
</plugins>
114158
</build>
115-
116-
117159
</project>

src/main/java/cz/sparko/boxitory/conf/NotFoundException.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
package cz.sparko.boxitory.conf;
22

33
import org.springframework.http.HttpStatus;
4-
import org.springframework.web.bind.annotation.ResponseStatus;
4+
import org.springframework.web.client.HttpClientErrorException;
55

6-
@ResponseStatus(value = HttpStatus.NOT_FOUND)
7-
public class NotFoundException extends RuntimeException {
6+
public class NotFoundException extends HttpClientErrorException {
87
public NotFoundException(String message) {
9-
super(message);
8+
super(HttpStatus.NOT_FOUND, message);
109
}
1110

1211
public static NotFoundException boxNotFound(String boxName) {

src/main/java/cz/sparko/boxitory/controller/BoxController.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import cz.sparko.boxitory.service.BoxRepository;
77
import org.springframework.beans.factory.annotation.Autowired;
88
import org.springframework.http.HttpStatus;
9+
import org.springframework.http.ResponseEntity;
910
import org.springframework.stereotype.Controller;
1011
import org.springframework.ui.Model;
1112
import org.springframework.web.bind.annotation.ExceptionHandler;
@@ -50,9 +51,13 @@ public String latestBoxVersion(@PathVariable String boxName) {
5051
}
5152

5253
@ExceptionHandler
53-
@ResponseBody
54-
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
55-
public String handleException(Exception e) {
56-
return e.getMessage();
54+
public ResponseEntity<String> handleException(Exception e) {
55+
final HttpStatus status;
56+
if (e instanceof NotFoundException) {
57+
status = HttpStatus.NOT_FOUND;
58+
} else {
59+
status = HttpStatus.INTERNAL_SERVER_ERROR;
60+
}
61+
return new ResponseEntity<>(e.getMessage(), status);
5762
}
5863
}

src/main/java/cz/sparko/boxitory/service/HashService.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,19 @@ public interface HashService {
55
String getChecksum(String box);
66

77
enum HashAlgorithm {
8-
MD5("MD5", ".md5"),
9-
SHA1("SHA-1", ".sha1"),
10-
SHA256("SHA-256", ".sha256"),
11-
DISABLED("", ".noop");
8+
MD5("MD5", ".md5", "md5"),
9+
SHA1("SHA-1", ".sha1", "sha1"),
10+
SHA256("SHA-256", ".sha256", "sha256"),
11+
DISABLED("", ".noop", "");
1212

1313
private final String messageDigestName;
1414
private final String fileExtension;
15+
private final String vagrantInterfaceName;
1516

16-
HashAlgorithm(String messageDigestName, String fileExtension) {
17+
HashAlgorithm(String messageDigestName, String fileExtension, String vagrantInterfaceName) {
1718
this.messageDigestName = messageDigestName;
1819
this.fileExtension = fileExtension;
20+
this.vagrantInterfaceName = vagrantInterfaceName;
1921
}
2022

2123
public String getMessageDigestName() {
@@ -25,5 +27,9 @@ public String getMessageDigestName() {
2527
public String getFileExtension() {
2628
return fileExtension;
2729
}
30+
31+
public String getVagrantInterfaceName() {
32+
return vagrantInterfaceName;
33+
}
2834
}
2935
}

src/main/java/cz/sparko/boxitory/service/filesystem/FilesystemDigestHashService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public FilesystemDigestHashService(MessageDigest messageDigest, HashAlgorithm ha
7474

7575
@Override
7676
public String getHashType() {
77-
return messageDigest.getAlgorithm().replaceAll("-", "").toLowerCase();
77+
return hashAlgorithm.getVagrantInterfaceName();
7878
}
7979

8080
@Override

src/main/resources/banner.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
_ _ _
2+
| | (_) | ${AnsiColor.YELLOW}${application.formatted-version}${AnsiStyle.NORMAL}
3+
| |__ _____ ___| |_ ___ _ __ _ _
4+
| '_ \ / _ \ \/ / | __/ _ \| '__| | | |
5+
| |_) | (_) > <| | || (_) | | | |_| |
6+
|_.__/ \___/_/\_\_|\__\___/|_| \__, |
7+
__/ |
8+
|___/

src/test/java/cz/sparko/boxitory/service/FilesystemDescriptionProviderTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public class FilesystemDescriptionProviderTest {
2828
private DescriptionProvider descriptionProvider;
2929

3030
@BeforeClass
31-
public void setUp() throws IOException {
31+
public void setUp() {
3232
testAppProperties = new AppProperties();
3333
testAppProperties.setHome(TEST_HOME);
3434
testAppProperties.setHost_prefix(TEST_BOX_PREFIX);
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package cz.sparko.boxitory.test.e2e;
2+
3+
import cz.sparko.boxitory.App;
4+
import cz.sparko.boxitory.conf.AppProperties;
5+
import cz.sparko.boxitory.controller.BoxController;
6+
import org.apache.commons.io.FileUtils;
7+
import org.springframework.beans.factory.annotation.Autowired;
8+
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
9+
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
10+
import org.springframework.context.annotation.Bean;
11+
import org.springframework.context.annotation.Configuration;
12+
import org.springframework.test.context.ContextConfiguration;
13+
import org.springframework.test.context.TestPropertySource;
14+
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
15+
import org.springframework.test.web.servlet.MockMvc;
16+
import org.testng.annotations.AfterMethod;
17+
import org.testng.annotations.BeforeMethod;
18+
import org.testng.annotations.Test;
19+
20+
import java.io.File;
21+
import java.io.IOException;
22+
23+
@ContextConfiguration(classes = App.class)
24+
@WebMvcTest(controllers = BoxController.class)
25+
@AutoConfigureMockMvc(secure = false)
26+
@TestPropertySource(locations = "classpath:test.properties")
27+
@Test(groups = "e2e")
28+
public abstract class AbstractIntegrationTest extends AbstractTestNGSpringContextTests {
29+
public static final String UTF8_CHARSET = ";charset=UTF-8";
30+
31+
@Autowired
32+
public AppProperties appProperties;
33+
34+
@Autowired
35+
public MockMvc mockMvc;
36+
37+
@BeforeMethod
38+
public void setUp() throws IOException {
39+
createFolderStructure();
40+
}
41+
42+
@AfterMethod
43+
public void tearDown() throws IOException {
44+
destroyFolderStructure();
45+
}
46+
47+
public void createRepositoryDir() {
48+
new File(appProperties.getHome()).mkdir();
49+
}
50+
51+
public void createFolderStructure() throws IOException {
52+
createRepositoryDir();
53+
}
54+
55+
public void destroyFolderStructure() throws IOException {
56+
FileUtils.deleteDirectory(new File(appProperties.getHome()));
57+
}
58+
59+
@Configuration
60+
static class TestConfig {
61+
@Bean
62+
public AppProperties appProperties() {
63+
return new AppProperties();
64+
}
65+
}
66+
67+
public File createDirInRepository(String vmName) {
68+
File vmDir = new File(appProperties.getHome() + File.separator + vmName);
69+
vmDir.mkdir();
70+
return vmDir;
71+
}
72+
73+
public File createFile(String filePath) throws IOException {
74+
File testFile = new File(filePath);
75+
testFile.createNewFile();
76+
return testFile;
77+
}
78+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package cz.sparko.boxitory.test.e2e;
2+
3+
import org.springframework.test.context.TestPropertySource;
4+
import org.testng.annotations.Test;
5+
6+
import java.io.File;
7+
import java.io.FileWriter;
8+
import java.io.IOException;
9+
10+
import static org.hamcrest.Matchers.is;
11+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
12+
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
13+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
14+
import static org.testng.Assert.assertFalse;
15+
16+
@TestPropertySource(properties = {
17+
"box.checksum=md5",
18+
"box.checksum_persist=false"
19+
})
20+
public class DontPersistChecksumTest extends AbstractIntegrationTest {
21+
private static final String VM = "vm";
22+
private static final String BOX = "vm_1_vb.box";
23+
private static final String CHECKSUM_FILE = "vm_1_vb.box.md5";
24+
25+
private File vmDir;
26+
27+
@Override
28+
public void createFolderStructure() throws IOException {
29+
super.createFolderStructure();
30+
vmDir = createDirInRepository(VM);
31+
File box = createFile(vmDir.getPath() + File.separator + BOX);
32+
try (FileWriter fw = new FileWriter(box)) {
33+
fw.write("blabol");
34+
}
35+
}
36+
37+
@Test
38+
public void givenMd5WithPersist_whenGetBox_thenFileWithChecksumIsStored() throws Exception {
39+
File checksumFile = new File(vmDir + File.separator + CHECKSUM_FILE);
40+
assertFalse(checksumFile.exists());
41+
42+
mockMvc.perform(get("/" + VM))
43+
.andDo(print())
44+
.andExpect(jsonPath("$.versions[0].providers[0].checksum", is("f34835fa588de624b2782bd5307c344c")));
45+
46+
assertFalse(checksumFile.exists());
47+
}
48+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package cz.sparko.boxitory.test.e2e;
2+
3+
import org.springframework.test.context.TestPropertySource;
4+
import org.testng.annotations.Test;
5+
6+
import java.io.File;
7+
import java.io.IOException;
8+
9+
import static org.hamcrest.Matchers.containsString;
10+
import static org.hamcrest.Matchers.hasSize;
11+
import static org.hamcrest.Matchers.is;
12+
import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8;
13+
import static org.springframework.http.MediaType.TEXT_HTML;
14+
import static org.springframework.http.MediaType.TEXT_PLAIN;
15+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
16+
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
17+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
18+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
19+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
20+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
21+
22+
@TestPropertySource(properties = {"box.sort_desc=true"})
23+
public class MultiProviderTest extends AbstractIntegrationTest {
24+
25+
private final String VM = "vm";
26+
private final String VM_1_VBOX = VM + "_1_virtualbox.box";
27+
private final String VM_2_VBOX = VM + "_2_virtualbox.box";
28+
private final String VM_2_LVIRT = VM + "_2_libvirt.box";
29+
30+
@Override
31+
public void createFolderStructure() throws IOException {
32+
createRepositoryDir();
33+
File vmDir = createDirInRepository(VM);
34+
createFile(vmDir.getPath() + File.separator + VM_1_VBOX);
35+
createFile(vmDir.getPath() + File.separator + VM_2_VBOX);
36+
createFile(vmDir.getPath() + File.separator + VM_2_LVIRT);
37+
}
38+
39+
@Test
40+
public void givenMultiProviders_whenIndex_thenReturnListWithVm() throws Exception {
41+
mockMvc.perform(get("/"))
42+
.andDo(print())
43+
.andExpect(status().isOk())
44+
.andExpect(content().contentType(TEXT_HTML + UTF8_CHARSET))
45+
.andExpect(view().name("index"))
46+
.andExpect(content().string(containsString(VM)));
47+
}
48+
49+
@Test
50+
public void givenMultiProviders_whenBox_thenReturnListOfVmVersions() throws Exception {
51+
mockMvc.perform(get("/vm"))
52+
.andDo(print())
53+
.andExpect(status().isOk())
54+
.andExpect(content().contentType(APPLICATION_JSON_UTF8))
55+
.andExpect(jsonPath("$.name", is(VM)))
56+
.andExpect(jsonPath("$.description", is(VM)))
57+
.andExpect(jsonPath("$.versions", hasSize(2)))
58+
.andExpect(jsonPath("$.versions[0].version", is("2")))
59+
.andExpect(jsonPath("$.versions[0].providers", hasSize(2)))
60+
.andExpect(jsonPath("$.versions[0].providers[?(@.name == \'libvirt\' && " +
61+
"@.url =~ /.*" + appProperties.getHost_prefix() + ".*/i && " +
62+
"@.url =~ /.*" + VM_2_LVIRT + ".*/i)]").exists())
63+
.andExpect(jsonPath("$.versions[0].providers[?(@.name == \'virtualbox\' && " +
64+
"@.url =~ /.*" + appProperties.getHost_prefix() + ".*/i && " +
65+
"@.url =~ /.*" + VM_2_VBOX + ".*/i)]").exists())
66+
.andExpect(jsonPath("$.versions[1].version", is("1")))
67+
.andExpect(jsonPath("$.versions[1].providers", hasSize(1)))
68+
.andExpect(jsonPath("$.versions[1].providers[0].name", is("virtualbox")))
69+
.andExpect(jsonPath("$.versions[1].providers[0].url", containsString(appProperties.getHost_prefix())))
70+
.andExpect(jsonPath("$.versions[1].providers[0].url", containsString(VM_1_VBOX)));
71+
}
72+
73+
@Test
74+
public void givenMultiProviders_whenLatestVersion_thenReturnLatestVersionNumber() throws Exception {
75+
mockMvc.perform(get("/vm/latestVersion"))
76+
.andDo(print())
77+
.andExpect(status().isOk())
78+
.andExpect(content().contentType(TEXT_PLAIN + UTF8_CHARSET))
79+
.andExpect(content().string("2"));
80+
}
81+
}

0 commit comments

Comments
 (0)