diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml
new file mode 100644
index 0000000..ecbb045
--- /dev/null
+++ b/.github/workflows/e2e.yml
@@ -0,0 +1,123 @@
+# Copyright © 2023 Cask Data, Inc.
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+# http://www.apache.org/licenses/LICENSE-2.0
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+# This workflow will build a Java project with Maven
+# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
+# Note: Any changes to this workflow would be used only after merging into develop
+name: Build e2e tests
+
+on:
+ push:
+ branches: [ e2e ]
+ pull_request:
+ branches: [ e2e ]
+ types: [ opened, synchronize, reopened, labeled ]
+ workflow_dispatch:
+
+jobs:
+ build:
+ runs-on: k8s-runner-e2e
+ # We allow builds:
+ # 1) When triggered manually
+ # 2) When it's a merge into a branch
+ # 3) For PRs that are labeled as build and
+ # - It's a code change
+ # - A build label was just added
+ # A bit complex, but prevents builds when other labels are manipulated
+ if: >
+ github.event_name == 'workflow_dispatch'
+ || github.event_name == 'push'
+ || (contains(github.event.pull_request.labels.*.name, 'build')
+ && (github.event.action != 'labeled' || github.event.label.name == 'build')
+ )
+ strategy:
+ fail-fast: false
+
+ steps:
+ # Pinned 1.0.0 version
+ - uses: actions/checkout@v3
+ with:
+ path: plugin
+ submodules: 'recursive'
+ ref: ${{ github.event.workflow_run.head_sha }}
+
+ - uses: dorny/paths-filter@b2feaf19c27470162a626bd6fa8438ae5b263721
+ if: github.event_name != 'workflow_dispatch' && github.event_name != 'push'
+ id: filter
+ with:
+ working-directory: plugin
+ filters: |
+ e2e-test:
+ - '**/e2e-test/**'
+ - name: Checkout e2e test repo
+ uses: actions/checkout@v3
+ with:
+ repository: cdapio/cdap-e2e-tests
+ path: e2e
+
+ - name: Cache
+ uses: actions/cache@v3
+ with:
+ path: ~/.m2/repository
+ key: ${{ runner.os }}-maven-${{ github.workflow }}-${{ hashFiles('**/pom.xml') }}
+ restore-keys: |
+ ${{ runner.os }}-maven-${{ github.workflow }}
+ - name: Get Secrets from GCP Secret Manager
+ id: secrets
+ uses: 'google-github-actions/get-secretmanager-secrets@v0'
+ with:
+ secrets: |-
+ ORACLE_HOST:cdapio-github-builds/ORACLE_HOST
+ ORACLE_USERNAME:cdapio-github-builds/ORACLE_NORMAL_USERNAME
+ ORACLE_PASSWORD:cdapio-github-builds/ORACLE_NORMAL_PASSWORD
+ ORACLE_PORT:cdapio-github-builds/ORACLE_PORT
+ PROJECT_ID:cdapio-github-builds/PROJECT_ID_FOR_REPL
+ - name: Run required e2e tests
+ if: github.event_name != 'workflow_dispatch' && github.event_name != 'push' && steps.filter.outputs.e2e-test == 'false'
+ run: python3 e2e/src/main/scripts/run_e2e_test.py --testRunner TestRunnerRequired.java
+ env:
+ ORACLE_HOST: ${{ steps.secrets.outputs.ORACLE_HOST }}
+ ORACLE_USERNAME: ${{ steps.secrets.outputs.ORACLE_USERNAME }}
+ ORACLE_PASSWORD: ${{ steps.secrets.outputs.ORACLE_PASSWORD }}
+ ORACLE_PORT: ${{ steps.secrets.outputs.ORACLE_PORT }}
+
+
+ - name: Run all e2e tests
+ if: github.event_name == 'workflow_dispatch' || github.event_name == 'push' || steps.filter.outputs.e2e-test == 'true'
+ run: python3 e2e/src/main/scripts/run_e2e_test.py --testRunner TestRunner.java
+ env:
+ ORACLE_HOST: ${{ steps.secrets.outputs.ORACLE_HOST }}
+ ORACLE_USERNAME: ${{ steps.secrets.outputs.ORACLE_USERNAME }}
+ ORACLE_PASSWORD: ${{ steps.secrets.outputs.ORACLE_PASSWORD }}
+ ORACLE_PORT: ${{ steps.secrets.outputs.ORACLE_PORT }}
+ PROJECT_ID : ${{ steps.secrets.outputs.PROJECT_ID }}
+
+ - name: Upload report
+ uses: actions/upload-artifact@v3
+ if: always()
+ with:
+ name: Cucumber report
+ path: ./**/target/cucumber-reports
+
+ - name: Upload debug files
+ uses: actions/upload-artifact@v3
+ if: always()
+ with:
+ name: Debug files
+ path: ./**/target/e2e-debug
+
+ - name: Upload files to GCS
+ uses: google-github-actions/upload-cloud-storage@v0
+ if: always()
+ with:
+ path: ./plugin
+ destination: e2e-tests-cucumber-reports/${{ github.event.repository.name }}/${{ github.ref }}
+ glob: '**/target/cucumber-reports/**'
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index d81813d..79a519b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -153,7 +153,7 @@
org.junit.jupiter
junit-jupiter-engine
- 5.4.0
+ 5.9.1
test
@@ -385,6 +385,155 @@
+
+ e2e-tests
+
+ src/e2e-test/java
+ TestRunner.java
+
+
+
+
+ src/e2e-test/resources
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.22.0
+
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+ 3.0.0
+
+
+ org.apache.maven.surefire
+ surefire-junit47
+ 3.0.0
+
+
+
+
+ ${TEST_RUNNER}
+
+
+ classes
+ 2
+ 2
+ true
+
+
+
+ ${GOOGLE_APPLICATION_CREDENTIALS}
+
+
+ ${SERVICE_ACCOUNT_TYPE}
+
+
+ ${SERVICE_ACCOUNT_FILE_PATH}
+
+
+ ${SERVICE_ACCOUNT_JSON}
+
+
+
+
+
+
+ integration-test
+
+
+
+
+
+
+ net.masterthought
+ maven-cucumber-reporting
+ 5.5.0
+
+
+
+ execution
+ verify
+
+ generate
+
+
+ Cucumber Reports
+ target/cucumber-reports/advanced-reports
+ 1
+ false
+ ${project.build.directory}/cucumber-reports
+
+ **/*.json
+
+ ${project.build.directory}/cucumber-reports
+ true
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ 3.3.0
+
+
+ add-test-source
+ generate-test-sources
+
+ add-test-source
+
+
+
+ ${project.basedir}/${testSourceLocation}
+
+
+
+
+
+
+
+
+
+
+
+ com.google.guava
+ guava
+ 31.1-jre
+
+
+
+
+
+
+ com.oracle.database.jdbc
+ ojdbc8
+ 21.1.0.0
+ test
+
+
+ io.cdap.tests.e2e
+ cdap-e2e-framework
+ 0.3.0-SNAPSHOT
+ test
+
+
+ ch.qos.logback
+ logback-classic
+ 1.2.8
+ runtime
+
+
+
+
+
diff --git a/src/e2e-test/features/Pipeline.feature b/src/e2e-test/features/Pipeline.feature
new file mode 100644
index 0000000..f2c8547
--- /dev/null
+++ b/src/e2e-test/features/Pipeline.feature
@@ -0,0 +1,51 @@
+#
+# Copyright © 2023 Cask Data, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+#
+
+@Oracle
+Feature: Oracle - Verify Oracle source data transfer to Big Query
+ @ENV_VARIABLES
+ Scenario: To verify replication of snapshot and cdc data from Oracle to Big Query successfully with Sanity test
+ Given Open DataFusion Project with replication to configure pipeline
+ When Enter input plugin property: "name" with value: "pipelineName"
+ And Click on the Next button
+ And Select Oracle as Source
+ Then Replace input plugin property: "host" with value: "host" for Credentials and Authorization related fields
+ Then Replace input plugin property: "port" with value: "port" for Credentials and Authorization related fields
+ Then Click plugin property: "region"
+ Then Click plugin property: "regionOption"
+ Then Replace input plugin property: "user" with value: "username" for Credentials and Authorization related fields
+ Then Replace input plugin property: "password" with value: "password" for Credentials and Authorization related fields
+ Then Replace input plugin property: "sid" with value: "dataset" for Credentials and Authorization related fields
+ Then Click on the Next button
+ Then Replace input plugin property: "loadInterval" with value: "loadInterval"
+ Then Click on the Next button
+ Then Validate Source table is available and select it
+ And Click on the Next button
+ And Click on the Next button
+ And Click on the Next button
+ Then Deploy the replication pipeline
+ And Run the replication Pipeline
+ Then Open the logs
+ And Wait till pipeline is in running state and check if no errors occurred
+ Then Verify expected Oracle records in target BigQuery table
+ And Insert a record in the source table and wait for replication
+ Then Verify expected Oracle records in target BigQuery table
+ And Delete a record in the source table and wait for replication
+ Then Verify expected Oracle records in target BigQuery table
+ And Update a record in the source table and wait for replication
+ Then Verify expected Oracle records in target BigQuery table
+ And Capture raw logs
+ Then Close the pipeline logs and stop the pipeline
\ No newline at end of file
diff --git a/src/e2e-test/java/io.cdap.plugin/actions/ReplicationActions.java b/src/e2e-test/java/io.cdap.plugin/actions/ReplicationActions.java
new file mode 100644
index 0000000..e51c9be
--- /dev/null
+++ b/src/e2e-test/java/io.cdap.plugin/actions/ReplicationActions.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2023.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package io.cdap.plugin.actions;
+
+import io.cdap.e2e.pages.actions.CdfPipelineRunAction;
+import io.cdap.e2e.pages.locators.CdfPipelineRunLocators;
+import io.cdap.e2e.utils.AssertionHelper;
+import io.cdap.e2e.utils.ConstantsUtil;
+import io.cdap.e2e.utils.ElementHelper;
+import io.cdap.e2e.utils.PageHelper;
+import io.cdap.e2e.utils.PluginPropertyUtils;
+import io.cdap.e2e.utils.SeleniumDriver;
+import io.cdap.e2e.utils.SeleniumHelper;
+import io.cdap.e2e.utils.WaitHelper;
+import io.cdap.plugin.locators.ReplicationLocators;
+import io.cdap.plugin.utils.BigQuery;
+import io.cdap.plugin.utils.OracleClient;
+import io.cdap.plugin.utils.ValidationHelper;
+import org.apache.commons.lang.StringUtils;
+import org.junit.Assert;
+import stepsdesign.BeforeActions;
+
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Replication oracle Actions.
+ */
+public class ReplicationActions {
+ private static String parentWindow = StringUtils.EMPTY;
+ private static final String projectId = PluginPropertyUtils.pluginProp("projectId");
+ private static final String database = PluginPropertyUtils.pluginProp("dataset");
+ public static String tableName = PluginPropertyUtils.pluginProp("sourceTable");
+ public static String schemaName = PluginPropertyUtils.pluginProp("schema");
+ public static String datatypeValues = PluginPropertyUtils.pluginProp("datatypeValuesForInsertOperation");
+ public static String deleteCondition = PluginPropertyUtils.pluginProp("deleteRowCondition");
+ public static String updateCondition = PluginPropertyUtils.pluginProp("updateRowCondition");
+ public static String updatedValue = PluginPropertyUtils.pluginProp("updatedRow");
+
+ static {
+ SeleniumHelper.getPropertiesLocators(ReplicationLocators.class);
+ }
+ public static void clickNextButton() throws InterruptedException {
+ TimeUnit time = TimeUnit.SECONDS;
+ time.sleep(1);
+ ElementHelper.clickOnElement(ReplicationLocators.next);
+ }
+
+ public static void clickOnOraclePlugin() {
+ ElementHelper.clickOnElement(ReplicationLocators.oraclePlugin);
+ }
+
+ public static void selectTable() {
+ String table = schemaName + "." + tableName;
+ WaitHelper.waitForElementToBeDisplayed(ReplicationLocators.selectTable(table), 300);
+ AssertionHelper.verifyElementDisplayed(ReplicationLocators.selectTable(table));
+ ElementHelper.clickOnElement(ReplicationLocators.selectTable(table));
+ }
+
+ public static void deployPipeline() {
+ ElementHelper.clickOnElement(ReplicationLocators.deployPipeline);
+ }
+
+ public static void startPipeline() {
+ ElementHelper.clickIfDisplayed(ReplicationLocators.start, ConstantsUtil.DEFAULT_TIMEOUT_SECONDS);
+ }
+
+ public static void runThePipeline() {
+ startPipeline();
+ WaitHelper.waitForElementToBeDisplayed(ReplicationLocators.running);
+ }
+
+ public static void openAdvanceLogs() {
+ ReplicationLocators.logs.click();
+ parentWindow = SeleniumDriver.getDriver().getWindowHandle();
+ ArrayList tabs = new ArrayList(SeleniumDriver.getDriver().getWindowHandles());
+ SeleniumDriver.getDriver().switchTo().window(tabs.get(tabs.indexOf(parentWindow) + 1));
+ ReplicationLocators.advancedLogs.click();
+ }
+
+ public static void captureRawLog() {
+ //Capturing raw logs.
+ try {
+ String rawLogs = getRawLogs();
+ String logsSeparatorMessage = ConstantsUtil.LOGS_SEPARATOR_MESSAGE
+ .replace("MESSAGE", "DEPLOYED PIPELINE RUNTIME LOGS");
+ BeforeActions.scenario.write(rawLogs);
+ CdfPipelineRunAction.writeRawLogsToFile(BeforeActions.file, logsSeparatorMessage, rawLogs);
+ } catch (Exception e) {
+ BeforeActions.scenario.write("Exception in capturing logs : " + e);
+ }
+ }
+
+ public static String getRawLogs() {
+ CdfPipelineRunAction.viewRawLogs();
+ ArrayList tabs = new ArrayList(SeleniumDriver.getDriver().getWindowHandles());
+ PageHelper.switchToWindow(tabs.indexOf(parentWindow) + 2);
+ String logs = CdfPipelineRunLocators.logsTextbox.getText();
+ Assert.assertNotNull(logs);
+ PageHelper.closeCurrentWindow();
+ return logs;
+ }
+
+ public static void waitTillPipelineIsRunningAndCheckForErrors() throws InterruptedException {
+ //wait for datastream to startup
+ int defaultTimeout = Integer.parseInt(PluginPropertyUtils.pluginProp("pipeline-initialization"));
+ TimeUnit time = TimeUnit.SECONDS;
+ time.sleep(defaultTimeout);
+ BigQuery.waitForFlush();
+ // Checking if an error message is displayed.
+ Assert.assertFalse(ElementHelper.isElementDisplayed(ReplicationLocators.error));
+ }
+
+ public static void closeTheLogsAndClickOnStopButton() {
+ SeleniumDriver.getDriver().switchTo().window(parentWindow);
+ //Stopping the pipeline
+ ElementHelper.clickOnElement(ReplicationLocators.stop);
+ SeleniumDriver.getDriver().navigate().refresh();
+ WaitHelper.waitForElementToBeDisplayed(ReplicationLocators.stopped);
+ }
+ public static void verifyTargetBigQueryRecordMatchesExpectedOracleRecord()
+ throws IOException, InterruptedException, SQLException, ClassNotFoundException {
+ // Checking if an error message is displayed.
+ Assert.assertFalse(ElementHelper.isElementDisplayed(ReplicationLocators.error));
+
+ List