Skip to content
This repository has been archived by the owner on Sep 8, 2021. It is now read-only.

Commit

Permalink
Added docker based integration testing
Browse files Browse the repository at this point in the history
Signed-off-by: Andrew DeMaria <lostonamountain@gmail.com>
  • Loading branch information
muff1nman committed Oct 1, 2018
1 parent 685f4fa commit 004b8bb
Show file tree
Hide file tree
Showing 20 changed files with 781 additions and 4 deletions.
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ language: java
sudo: required
jdk:
- oraclejdk8
services:
- docker
cache:
directories:
- $HOME/.m2
Expand All @@ -13,4 +15,4 @@ before_script:
- export M2_HOME=$PWD/apache-maven-3.5.4
- export PATH=$PWD/apache-maven-3.5.4/bin:$PATH
script:
- mvn package install
- mvn verify -P integration-test
3 changes: 2 additions & 1 deletion install/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ RUN apk --no-cache add \
ttf-dejavu \
ca-certificates \
tini \
curl \
openjdk8-jre

COPY run.sh /usr/local/bin/run.sh
Expand All @@ -28,6 +29,6 @@ EXPOSE $AIRSONIC_PORT

VOLUME $AIRSONIC_DIR/data $AIRSONIC_DIR/music $AIRSONIC_DIR/playlists $AIRSONIC_DIR/podcasts

HEALTHCHECK CMD wget -q http://localhost:"$AIRSONIC_PORT""$CONTEXT_PATH"/rest/ping -O /dev/null || exit 1
HEALTHCHECK --interval=15s --timeout=3s CMD wget -q http://localhost:"$AIRSONIC_PORT""$CONTEXT_PATH"rest/ping -O /dev/null || exit 1

ENTRYPOINT ["tini", "--", "run.sh"]
205 changes: 205 additions & 0 deletions integration-test/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>
<artifactId>airsonic-integration-test</artifactId>
<name>Airsonic Integration Test</name>

<parent>
<groupId>org.airsonic.player</groupId>
<artifactId>airsonic</artifactId>
<version>10.2.0-SNAPSHOT</version>
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<cucumber.version>2.3.1</cucumber.version>
</properties>

<dependencies>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-core</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java8</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-spring</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.spotify</groupId>
<artifactId>docker-client</artifactId>
<version>8.13.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.xmlunit</groupId>
<artifactId>xmlunit-core</artifactId>
<version>2.6.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.xmlunit</groupId>
<artifactId>xmlunit-matchers</artifactId>
<version>2.6.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.airsonic.player</groupId>
<artifactId>subsonic-rest-api</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<testResources>
<testResource>
<directory>src/test/resources</directory>
<filtering>true</filtering>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>com.github.temyers</groupId>
<artifactId>cucumber-jvm-parallel-plugin</artifactId>
<version>5.0.0</version>
<executions>
<execution>
<id>generateRunners</id>
<phase>generate-test-sources</phase>
<goals>
<goal>generateRunners</goal>
</goals>
<configuration>
<featuresDirectory>src/test/resources/features</featuresDirectory>
<format>pretty</format>
<glue>org.airsonic.test.cucumber.steps</glue>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerVersion>1.8</compilerVersion>
<showWarnings>true</showWarnings>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>default-jar</id>
<phase/>
<configuration>
<finalName>unwanted</finalName>
<classifier>unwanted</classifier>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.21.0</version>
<configuration>
<parallel>all</parallel>
<threadCount>2</threadCount>
<includes>
<include>**/Parallel*IT.class</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.airsonic.test;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration
@ComponentScan("org.airsonic.test")
@PropertySource("classpath:application.properties")
public class SpringContext {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.airsonic.test.cucumber;

import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
import org.junit.runner.RunWith;

@RunWith(Cucumber.class)
@CucumberOptions(plugin = {"pretty"},
features = "classpath:features/api/stream-mp3.feature",
glue = "org.airsonic.test.cucumber.steps")
public class RunCukesTest {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.airsonic.test.cucumber.server;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.client.methods.RequestBuilder;

import java.nio.file.Path;

public interface AirsonicServer {
String getBaseUri();

void uploadToDefaultMusicFolder(Path directoryPath, String relativePath);

default void addRestParameters(RequestBuilder builder) {
builder.addParameter("c", "inttest");
builder.addParameter("v", "1.15.0");
builder.addParameter("u", "admin");
builder.addParameter("s", "int");
builder.addParameter("t", DigestUtils.md5Hex("admin" + "int"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.airsonic.test.cucumber.steps.api;

import cucumber.api.java8.En;
import org.airsonic.test.cucumber.server.AirsonicServer;
import org.apache.http.HttpEntity;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.xmlunit.builder.Input;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.xmlunit.matchers.CompareMatcher.isIdenticalTo;

public class PingStepDef implements En {

private CloseableHttpResponse response;
private CloseableHttpClient client;

public PingStepDef(AirsonicServer server) {
this.client = HttpClientBuilder.create().build();
When("^A ping request is sent$", () -> {
HttpGet httpGet = new HttpGet(server.getBaseUri() + "/rest/ping");
this.response = client.execute(httpGet);
});
Then("^A required parameter response is received$", () -> {
if(response == null) {
throw new IllegalStateException();
}
try {
StatusLine statusLine = response.getStatusLine();
assertEquals(statusLine.getStatusCode(), 200);
HttpEntity entity = response.getEntity();
String actual = EntityUtils.toString(entity);
assertThat(
actual,
isIdenticalTo(
Input.fromStream(
getClass().getResourceAsStream("/blobs/ping/missing-auth.xml")))
.ignoreWhitespace());
} finally {
response.close();
}
});
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package org.airsonic.test.cucumber.steps.api;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import cucumber.api.java8.En;
import org.airsonic.test.cucumber.server.AirsonicServer;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.junit.Assert;
import org.subsonic.restapi.Response;

import java.io.IOException;

public class ScanStepDef implements En {

private final AirsonicServer server;
private CloseableHttpResponse response;
private CloseableHttpClient client;
private ObjectMapper mapper = new ObjectMapper();

public ScanStepDef(AirsonicServer server) {
mapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS);
this.client = HttpClientBuilder.create().build();
this.server = server;

Given("a scan is done", () -> {
Assert.assertFalse(isScanning());

RequestBuilder builder = RequestBuilder.create("GET").setUri(server.getBaseUri() + "/rest/startScan");
server.addRestParameters(builder);
response = client.execute(builder.build());
System.out.println(EntityUtils.toString(response.getEntity()));
Long waitTime = 30000L;
Long sleepTime = 1000L;
while(waitTime > 0 && isScanning()) {
waitTime -= sleepTime;
Thread.sleep(sleepTime);
}

Assert.assertFalse(isScanning());
});

}

private boolean isScanning() throws IOException {
RequestBuilder builder = RequestBuilder.create("GET").setUri(server.getBaseUri() + "/rest/getScanStatus");
builder.addParameter("f", "json");
server.addRestParameters(builder);
response = client.execute(builder.build());

String responseAsString = EntityUtils.toString(response.getEntity());
JsonNode jsonNode = mapper.readTree(responseAsString).get("subsonic-response");
Response response = mapper.treeToValue(jsonNode, Response.class);
return response.getScanStatus().isScanning();
}

}
Loading

0 comments on commit 004b8bb

Please sign in to comment.