Skip to content

Commit

Permalink
Add UI tests for JDBC connector
Browse files Browse the repository at this point in the history
  • Loading branch information
kaklakariada committed Oct 21, 2021
1 parent d17af39 commit 7212df1
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 47 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,59 @@
package com.exasol.tableau;

public class JdbcConnectorIT extends TableauServerUiBaseIT {
import static com.exasol.tableau.TableauServerConfiguration.EXASOL_PORT;

protected JdbcConnectorIT() {
super("Exasol JDBC by Exasol AG");
import java.util.regex.Pattern;

import org.junit.jupiter.api.Test;

import com.exasol.tableau.Workbook.Builder;

class JdbcConnectorIT extends TableauServerUiBaseIT {

@Override
protected Builder createWorkbookBuilder() {
return Workbook.builder().workbookName("Test_workbook")
.connectorName("Exasol JDBC by Exasol AG")
.hostname(DOCKER_NETWORK_ADDRESS)
.port(EXASOL.getMappedPort(EXASOL_PORT).toString())
.username(EXASOL.getUsername())
.password(EXASOL.getPassword())
.fingerprint(getActualFingerprint())
.validateServerCertificate(true)
.databaseName("EXA_DB");
}

private String getActualFingerprint() {
return extractFingerprint(EXASOL.getJdbcUrl());
}

private static String extractFingerprint(final String jdbcUrl) {
if (jdbcUrl.contains("validateservercertificate=0")) {
throw new AssertionError("Jdbc url '" + jdbcUrl + "' does not validate certificate");
}
final java.util.regex.Matcher matcher = Pattern.compile("jdbc:exa:[^/]+/([^:]+):.*").matcher(jdbcUrl);
if (!matcher.matches()) {
throw new IllegalStateException("Error extracting fingerprint from '" + jdbcUrl + "'");
}
return matcher.group(1);
}

@Test
void connectToExasolDatasourceWithoutFingerprint() {
final Workbook workbook = createWorkbookBuilder().fingerprint("").validateServerCertificate(true).build();
assertCreatingWorkbookFails(workbook, "unable to find valid certification path to requested target");
}

@Test
void connectToExasolDatasourceWrongFingerprint() {
final Workbook workbook = createWorkbookBuilder().fingerprint("wrongFingerprint")
.validateServerCertificate(true).build();
assertCreatingWorkbookFails(workbook, "Fingerprint did not match");
}

@Test
void connectToExasolDatasourceIgnoringCertificateSucceeds() {
final Workbook workbook = createWorkbookBuilder().validateServerCertificate(false).build();
assertCreatingWorkbookSucceeds(workbook);
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
package com.exasol.tableau;

import static com.exasol.tableau.TableauServerConfiguration.EXASOL_PORT;

import com.exasol.tableau.Workbook.Builder;

public class OdbcConnectorIT extends TableauServerUiBaseIT {

protected OdbcConnectorIT() {
super("Exasol ODBC by Exasol AG");
@Override
protected Builder createWorkbookBuilder() {
return Workbook.builder().workbookName("Test_workbook")
.connectorName("Exasol ODBC by Exasol AG")
.hostname(DOCKER_NETWORK_ADDRESS)
.port(EXASOL.getMappedPort(EXASOL_PORT).toString())
.username(EXASOL.getUsername())
.password(EXASOL.getPassword())
.fingerprint(null)
.validateServerCertificate(null)
.databaseName(null);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,17 @@ public Optional<String> createWorkbook(final Workbook workbook) {
this.getElement("input", "data-tb-test-id", "port-textfield-TextInput").sendKeys(workbook.getPort());
this.getElement("input", "data-tb-test-id", "username-textfield-TextInput").sendKeys(workbook.getUsername());
this.getElement("input", "data-tb-test-id", "password-textfield-TextInput").sendKeys(workbook.getPassword());
if (workbook.getDatabaseName() != null) {
this.getElement("input", "data-tb-test-id", "dbname-textfield-TextInput")
.sendKeys(workbook.getDatabaseName());
}
if (workbook.getFingerprint() != null) {
this.getElement("input", "data-tb-test-id", "v-fingerprint-textfield-TextInput")
.sendKeys(workbook.getFingerprint());
}
if ((workbook.getValidateServerCertificate() != null) && !workbook.getValidateServerCertificate()) {
this.driver.findElement(By.xpath("//div[text()='Validate Server Certificate']")).click();
}
this.getElement("button", "data-tb-test-id", "signIn-button-Button").click();
this.explicitWait(2);
return this.getElementIfExists("div", "data-tb-test-id", "modular-dialog-error-section-error")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ public class TableauServerSetUp {
.withEnv("LICENSE_KEY", TABLEAU_LICENSE_KEY) //
.withEnv("REQUESTED_LEASE_TIME", REQUESTED_LEASE_TIME_IN_SECONDS) //
.waitingFor(Wait.forLogMessage(".*INFO exited: run-tableau-server.*", 1)) //
// INFO exited: run-tableau-server (exit status 0; expected)
.withStartupTimeout(Duration.ofMinutes(40)) //
.withReuse(true);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,22 @@
import java.sql.Statement;
import java.util.List;
import java.util.Optional;
import java.util.regex.Pattern;

import org.junit.jupiter.api.*;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

import com.exasol.containers.ExasolContainer;
import com.exasol.containers.ExasolService;
import com.exasol.tableau.Workbook.Builder;
import com.github.dockerjava.api.model.*;

@Testcontainers
abstract class TableauServerUiBaseIT {

private final String connectorName;

private static final String DEFAULT_DOCKER_DB_REFERENCE = "7.1.1";
public static final String DOCKER_NETWORK_ADDRESS = "172.17.0.1";
private static TableauServerGUIGateway tableauServerGateway;
protected static TableauServerGUIGateway tableauServerGateway;

@Container
protected static final ExasolContainer<? extends ExasolContainer<?>> EXASOL = new ExasolContainer<>(
Expand All @@ -50,7 +48,7 @@ static void beforeAll() throws UnsupportedOperationException, IOException, Inter

private static void prepareExasolDatabase() {
try (final Statement statement = EXASOL.createConnection().createStatement()) {
final String sqlFile = Files.readString(Path.of("src", "test", "resources", "populate_table.sql"));
final String sqlFile = Files.readString(Path.of("src/test/resources/populate_table.sql"));
final String[] sqlCommands = sqlFile.split(";");
for (final String command : sqlCommands) {
statement.execute(command);
Expand All @@ -60,10 +58,6 @@ private static void prepareExasolDatabase() {
}
}

protected TableauServerUiBaseIT(final String connectorName) {
this.connectorName = connectorName;
}

@BeforeEach
public void beforeEach() {
tableauServerGateway = TableauServerGUIGateway.connectTo(TableauServerSetUp.getTableauServerConnectionURL());
Expand All @@ -85,38 +79,31 @@ void connectToExasolDatasource() {
}

private void createWorkbook() {
final Workbook workbook = createWorkbookWithPassword(EXASOL.getPassword());
final Optional<String> errorMessage = tableauServerGateway.createWorkbook(workbook);
assertTrue(errorMessage.isEmpty());
final Workbook workbook = createWorkbookBuilder().build();
assertCreatingWorkbookSucceeds(workbook);
}

private Workbook createWorkbookWithPassword(final String password) {
return Workbook.builder().workbookName("Test_workbook")
.connectorName(this.connectorName)
.hostname(DOCKER_NETWORK_ADDRESS)
.port(EXASOL.getMappedPort(EXASOL_PORT).toString())
.username(EXASOL.getUsername())
.password(password)
.fingerprint(extractFingerprint(EXASOL.getJdbcUrl()))
.build();
}

public static String extractFingerprint(final String jdbcUrl) {
if (jdbcUrl.contains("validateservercertificate=0")) {
throw new AssertionError("Jdbc url '" + jdbcUrl + "' does not validate certificate");
}
final java.util.regex.Matcher matcher = Pattern.compile("jdbc:exa:[^/]+/([^:]+):.*").matcher(jdbcUrl);
if (!matcher.matches()) {
throw new IllegalStateException("Error extracting fingerprint from '" + jdbcUrl + "'");
protected void assertCreatingWorkbookSucceeds(final Workbook workbook) {
final Optional<String> errorMessage = tableauServerGateway.createWorkbook(workbook);
if (errorMessage.isPresent()) {
throw new AssertionError("Expected no error but got '" + errorMessage.get() + "'");
}
return matcher.group(1);
}

protected abstract Builder createWorkbookBuilder();

@Test
void duplicateExasolDatasource() {
this.createWorkbook();
final Workbook workbook = this.createWorkbookBuilder().build();
this.assertCreatingWorkbookSucceeds(workbook);
assertDuplicateWorkbookName(workbook);
}

private void assertDuplicateWorkbookName(final Workbook workbook) {
final String expectedDbName = workbook.getDatabaseName() != null ? workbook.getDatabaseName()
: DOCKER_NETWORK_ADDRESS;
final String duplicateName = tableauServerGateway.duplicateDataSource();
assertThat(duplicateName, equalTo(DOCKER_NETWORK_ADDRESS + " (copy)"));
assertThat(duplicateName, equalTo(expectedDbName + " (copy)"));
}

@Test
Expand All @@ -132,15 +119,19 @@ void createAndRefreshExtract() {

@Test
void connectToExasolDatasourceWithWrongCredentials() {
final Workbook workbook = this.createWorkbookWithPassword("Wrong Password");
final Optional<String> errorMessage = tableauServerGateway.createWorkbook(workbook);
final Workbook workbook = this.createWorkbookBuilder().password("Wrong Password").build();
assertCreatingWorkbookFails(workbook, "authentication failed");
}

protected void assertCreatingWorkbookFails(final Workbook configuration, final String expectedErrorMessage) {
final Optional<String> errorMessage = tableauServerGateway.createWorkbook(configuration);
assertAll(() -> assertThat(errorMessage.isPresent(), equalTo(true)),
() -> assertThat(errorMessage.get(), containsString("authentication failed")));
() -> assertThat(errorMessage.get(), containsString(expectedErrorMessage)));
}

@Test
void saveWorkbook() {
final Workbook workbook = this.createWorkbookWithPassword(EXASOL.getPassword());
final Workbook workbook = this.createWorkbookBuilder().build();
tableauServerGateway.deleteWorkbookIfExists(workbook);
tableauServerGateway.createWorkbook(workbook);
tableauServerGateway.openSchema("TESTV1");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ public class Workbook {
private final String password;
private final String port;
private final String fingerprint;
private final Boolean validateServerCertificate;
private final String databaseName;

private Workbook(final Builder builder) {
this.workbookName = builder.workbookName;
Expand All @@ -17,6 +19,8 @@ private Workbook(final Builder builder) {
this.password = builder.password;
this.port = builder.port;
this.fingerprint = builder.fingerprint;
this.validateServerCertificate = builder.validateServerCertificate;
this.databaseName = builder.databaseName;
}

public String getWorkbookName() {
Expand Down Expand Up @@ -47,6 +51,14 @@ public String getFingerprint() {
return this.fingerprint;
}

public Boolean getValidateServerCertificate() {
return this.validateServerCertificate;
}

public String getDatabaseName() {
return this.databaseName;
}

public static Builder builder() {
return new Builder();
}
Expand All @@ -58,10 +70,11 @@ static class Builder {
private String username;
private String password;
private String port;
public String fingerprint;
private String fingerprint = null;
private Boolean validateServerCertificate = null;
private String databaseName = null;

private Builder() {

}

public Builder workbookName(final String name) {
Expand Down Expand Up @@ -99,6 +112,16 @@ public Builder fingerprint(final String fingerprint) {
return this;
}

public Builder validateServerCertificate(final Boolean validateServerCertificate) {
this.validateServerCertificate = validateServerCertificate;
return this;
}

public Builder databaseName(final String databaseName) {
this.databaseName = databaseName;
return this;
}

public Workbook build() {
return new Workbook(this);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
DROP SCHEMA IF EXISTS "TESTV1";
DROP SCHEMA IF EXISTS "TESTV1" CASCADE;
CREATE SCHEMA "TESTV1";
OPEN SCHEMA "TESTV1";

Expand Down

0 comments on commit 7212df1

Please sign in to comment.