Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Timeplus module #8779

Merged
merged 11 commits into from
Aug 14, 2024
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> {
eddumelendez marked this conversation as resolved.
Show resolved Hide resolved

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>