Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ body:
- Solace
- Solr
- TiDB
- Timeplus
- ToxiProxy
- Trino
- Vault
Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/enhancement.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ body:
- Solace
- Solr
- TiDB
- Timeplus
- ToxiProxy
- Trino
- Vault
Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/feature.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ body:
- Solace
- Solr
- TiDB
- Timeplus
- ToxiProxy
- Trino
- Vault
Expand Down
5 changes: 5 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,11 @@ updates:
schedule:
interval: "weekly"
open-pull-requests-limit: 10
- package-ecosystem: "gradle"
directory: "/modules/timeplus"
schedule:
interval: "weekly"
open-pull-requests-limit: 10
- package-ecosystem: "gradle"
directory: "/modules/toxiproxy"
schedule:
Expand Down
4 changes: 4 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,10 @@
- changed-files:
- any-glob-to-any-file:
- modules/tidb/**/*
"modules/timeplus":
- changed-files:
- any-glob-to-any-file:
- modules/timeplus/**/*
"modules/toxiproxy":
- changed-files:
- any-glob-to-any-file:
Expand Down
3 changes: 3 additions & 0 deletions .github/settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,9 @@ labels:
- name: modules/tidb
color: '#006b75'

- name: modules/timeplus
color: '#006b75'

- name: modules/toxiproxy
color: '#006b75'

Expand Down
4 changes: 4 additions & 0 deletions docs/modules/databases/jdbc.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ Insert `tc:` after `jdbc:` as follows. Note that the hostname, port and database

`jdbc:tc:tidb:v6.1.0:///databasename`

#### Using Timeplus

`jdbc:tc:timeplus:2.3.3:///databasename`

#### Using Trino

`jdbc:tc:trino:352://localhost/memory/default`
Expand Down
24 changes: 24 additions & 0 deletions docs/modules/databases/timeplus.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# timeplus Module
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# timeplus Module
# Timeplus Module


## Adding this module to your project dependencies

Add the following dependency to your `pom.xml`/`build.gradle` file:

=== "Gradle"
```groovy
testImplementation "org.testcontainers:timeplus:{{latest_version}}"
```

=== "Maven"
```xml
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>timeplus</artifactId>
<version>{{latest_version}}</version>
<scope>test</scope>
</dependency>
```

!!! hint
Adding this Testcontainers library JAR will not automatically add a database driver JAR to your project. You should ensure that your project also has a suitable database driver as a dependency.

10 changes: 10 additions & 0 deletions modules/timeplus/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
description = "Testcontainers :: JDBC :: Timeplus"

dependencies {
api project(':testcontainers')
api project(':jdbc')

testImplementation project(':jdbc-test')
testRuntimeOnly 'com.timeplus:timeplus-native-jdbc:2.0.1'
testImplementation 'org.assertj:assertj-core:3.25.3'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
testImplementation 'org.assertj:assertj-core:3.25.3'
testImplementation 'org.assertj:assertj-core:3.26.3'

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package org.testcontainers.timeplus;

import org.testcontainers.containers.JdbcDatabaseContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.utility.DockerImageName;

import java.time.Duration;
import java.util.HashSet;
import java.util.Set;

/**
* Testcontainers implementation for Timeplus.
*/
public class TimeplusContainer extends JdbcDatabaseContainer<TimeplusContainer> {

static final String NAME = "timeplus";

static final String DOCKER_IMAGE_NAME = "timeplus/timeplusd";

private static final DockerImageName TIMEPLUS_IMAGE_NAME = DockerImageName.parse("timeplus/timeplusd");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private static final DockerImageName TIMEPLUS_IMAGE_NAME = DockerImageName.parse("timeplus/timeplusd");
private static final DockerImageName TIMEPLUS_IMAGE_NAME = DockerImageName.parse(DOCKER_IMAGE_NAME);


private static final Integer HTTP_PORT = 3218;

private static final Integer NATIVE_PORT = 8463;

private static final String DRIVER_CLASS_NAME = "com.timeplus.jdbc.TimeplusDriver";

private static final String JDBC_URL_PREFIX = "jdbc:" + NAME + "://";

private static final String TEST_QUERY = "SELECT 1";

private String databaseName = "default";

private String username = "default";

private String password = "";

public TimeplusContainer(String dockerImageName) {
this(DockerImageName.parse(dockerImageName));
}

public TimeplusContainer(final DockerImageName dockerImageName) {
super(dockerImageName);
dockerImageName.assertCompatibleWith(TIMEPLUS_IMAGE_NAME);

addExposedPorts(HTTP_PORT, NATIVE_PORT);
waitingFor(Wait.forHttp("/timeplusd/v1/ping").forStatusCode(200).withStartupTimeout(Duration.ofMinutes(1)));
}

@Override
protected void configure() {
withEnv("TIMEPLUS_DB", this.databaseName);
withEnv("TIMEPLUS_USER", this.username);
withEnv("TIMEPLUS_PASSWORD", this.password);
}

@Override
public Set<Integer> getLivenessCheckPortNumbers() {
return new HashSet<>(getMappedPort(HTTP_PORT));
}

@Override
public String getDriverClassName() {
return DRIVER_CLASS_NAME;
}

@Override
public String getJdbcUrl() {
return (
JDBC_URL_PREFIX +
getHost() +
":" +
getMappedPort(NATIVE_PORT) +
"/" +
this.databaseName +
constructUrlParameters("?", "&")
);
}

@Override
public String getUsername() {
return username;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return username;
return this.username;

}

@Override
public String getPassword() {
return password;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return password;
return this.password;

}

@Override
public String getDatabaseName() {
return databaseName;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return databaseName;
return this.databaseName;

}

@Override
public String getTestQueryString() {
return TEST_QUERY;
}

@Override
public TimeplusContainer withUsername(String username) {
this.username = username;
return this;
}

@Override
public TimeplusContainer withPassword(String password) {
this.password = password;
return this;
}

@Override
public TimeplusContainer withDatabaseName(String databaseName) {
this.databaseName = databaseName;
return this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.testcontainers.timeplus;

import org.testcontainers.containers.JdbcDatabaseContainer;
import org.testcontainers.containers.JdbcDatabaseContainerProvider;
import org.testcontainers.utility.DockerImageName;

/**
* Factory for Timeplus containers.
*/
public class TimeplusContainerProvider extends JdbcDatabaseContainerProvider {

private static final String DEFAULT_TAG = "2.3.3";

@Override
public boolean supports(String databaseType) {
return databaseType.equals(TimeplusContainer.NAME);
}

@Override
public JdbcDatabaseContainer newInstance() {
return newInstance(DEFAULT_TAG);
}

@Override
public JdbcDatabaseContainer newInstance(String tag) {
if (tag != null) {
return new TimeplusContainer(DockerImageName.parse(TimeplusContainer.DOCKER_IMAGE_NAME).withTag(tag));
} else {
return newInstance();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
org.testcontainers.timeplus.TimeplusContainerProvider
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.testcontainers;

import org.testcontainers.utility.DockerImageName;

public interface TimeplusImages {
DockerImageName TIMEPLUS_IMAGE = DockerImageName.parse("timeplus/timeplusd:2.3.3");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.testcontainers.junit.timeplus;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.testcontainers.TimeplusImages;
import org.testcontainers.db.AbstractContainerDatabaseTest;
import org.testcontainers.timeplus.TimeplusContainer;
import org.testcontainers.utility.DockerImageName;

import java.sql.ResultSet;
import java.sql.SQLException;

import static org.assertj.core.api.Assertions.assertThat;

@RunWith(Parameterized.class)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be run without being Parameterized

public class SimpleTimeplusTest extends AbstractContainerDatabaseTest {

private final DockerImageName imageName;

public SimpleTimeplusTest(DockerImageName imageName) {
this.imageName = imageName;
}

@Parameterized.Parameters(name = "{0}")
public static Object[][] data() {
return new Object[][] { { TimeplusImages.TIMEPLUS_IMAGE } };
}

@Test
public void testSimple() throws SQLException {
try (TimeplusContainer timeplus = new TimeplusContainer(this.imageName)) {
timeplus.start();

ResultSet resultSet = performQuery(timeplus, "SELECT 1");

int resultSetInt = resultSet.getInt(1);
assertThat(resultSetInt).as("A basic SELECT query succeeds").isEqualTo(1);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package org.testcontainers.timeplus;

import org.junit.Test;
import org.testcontainers.db.AbstractContainerDatabaseTest;

import java.sql.ResultSet;
import java.sql.SQLException;

import static org.assertj.core.api.Assertions.assertThat;

public class TimeplusContainerTest extends AbstractContainerDatabaseTest {

@Test
public void testSimple() throws SQLException {
try (TimeplusContainer timeplus = new TimeplusContainer("timeplus/timeplusd:2.3.3")) {
timeplus.start();

ResultSet resultSet = performQuery(timeplus, "SELECT 1");

int resultSetInt = resultSet.getInt(1);
assertThat(resultSetInt).isEqualTo(1);
}
}

@Test
public void customCredentialsWithUrlParams() throws SQLException {
try (
TimeplusContainer timeplus = new TimeplusContainer("timeplus/timeplusd:2.3.3")
.withUsername("system")
.withPassword("sys@t+")
.withDatabaseName("system")
.withUrlParam("max_result_rows", "5")
) {
timeplus.start();

ResultSet resultSet = performQuery(
timeplus,
"SELECT value FROM system.settings where name='max_result_rows'"
);

int resultSetInt = resultSet.getInt(1);
assertThat(resultSetInt).isEqualTo(5);
}
}
}
16 changes: 16 additions & 0 deletions modules/timeplus/src/test/resources/logback-test.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<configuration>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} %-5level %logger - %msg%n</pattern>
</encoder>
</appender>

<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>

<logger name="org.testcontainers" level="INFO"/>
</configuration>