diff --git a/org.idempiere.parent/pom.xml b/org.idempiere.parent/pom.xml
index 74803cff4c..725220d4a7 100644
--- a/org.idempiere.parent/pom.xml
+++ b/org.idempiere.parent/pom.xml
@@ -396,6 +396,11 @@
maven-dependency-plugin
${maven.dependency.version}
+
+ org.eclipse.tycho
+ tycho-surefire-plugin
+ ${tycho.version}
+
diff --git a/org.idempiere.test/.classpath b/org.idempiere.test/.classpath
new file mode 100644
index 0000000000..a621c21ac5
--- /dev/null
+++ b/org.idempiere.test/.classpath
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.idempiere.test/.project b/org.idempiere.test/.project
new file mode 100644
index 0000000000..3dd557a8f9
--- /dev/null
+++ b/org.idempiere.test/.project
@@ -0,0 +1,34 @@
+
+
+ org.idempiere.test
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.pde.ManifestBuilder
+
+
+
+
+ org.eclipse.pde.SchemaBuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.eclipse.pde.PluginNature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+
+
diff --git a/org.idempiere.test/.settings/org.eclipse.core.resources.prefs b/org.idempiere.test/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000000..99f26c0203
--- /dev/null
+++ b/org.idempiere.test/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/=UTF-8
diff --git a/org.idempiere.test/.settings/org.eclipse.jdt.core.prefs b/org.idempiere.test/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000000..c9545f06a4
--- /dev/null
+++ b/org.idempiere.test/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,9 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
+org.eclipse.jdt.core.compiler.release=enabled
+org.eclipse.jdt.core.compiler.source=11
diff --git a/org.idempiere.test/.settings/org.eclipse.pde.core.prefs b/org.idempiere.test/.settings/org.eclipse.pde.core.prefs
new file mode 100644
index 0000000000..f29e940a00
--- /dev/null
+++ b/org.idempiere.test/.settings/org.eclipse.pde.core.prefs
@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+pluginProject.extensions=false
+resolve.requirebundle=false
diff --git a/org.idempiere.test/META-INF/MANIFEST.MF b/org.idempiere.test/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..a19064ea2a
--- /dev/null
+++ b/org.idempiere.test/META-INF/MANIFEST.MF
@@ -0,0 +1,21 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: iDempiere Unit Testing
+Bundle-SymbolicName: org.idempiere.test
+Bundle-Version: 7.1.0.qualifier
+Bundle-Vendor: iDempiere
+Automatic-Module-Name: org.idempiere.test
+Bundle-RequiredExecutionEnvironment: JavaSE-11
+Import-Package: org.junit.jupiter.api;version="5.6.0",
+ org.junit.jupiter.api.condition;version="5.6.0",
+ org.junit.jupiter.api.extension;version="5.6.0",
+ org.junit.jupiter.api.extension.support;version="5.6.0",
+ org.junit.jupiter.api.function;version="5.6.0",
+ org.junit.jupiter.api.io;version="5.6.0",
+ org.junit.jupiter.api.parallel;version="5.6.0",
+ org.junit.jupiter.params;version="5.6.0",
+ org.junit.jupiter.params.aggregator;version="5.6.0",
+ org.junit.jupiter.params.converter;version="5.6.0",
+ org.junit.jupiter.params.provider;version="5.6.0",
+ org.junit.jupiter.params.support;version="5.6.0"
+Require-Bundle: org.adempiere.base;bundle-version="7.1.0"
diff --git a/org.idempiere.test/build.properties b/org.idempiere.test/build.properties
new file mode 100644
index 0000000000..56d7765555
--- /dev/null
+++ b/org.idempiere.test/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = target/classes/
+bin.includes = META-INF/,\
+ .
diff --git a/org.idempiere.test/idempiere.unit.test.launch b/org.idempiere.test/idempiere.unit.test.launch
new file mode 100644
index 0000000000..c69862c945
--- /dev/null
+++ b/org.idempiere.test/idempiere.unit.test.launch
@@ -0,0 +1,568 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.idempiere.test/pom.xml b/org.idempiere.test/pom.xml
new file mode 100644
index 0000000000..432838b7ba
--- /dev/null
+++ b/org.idempiere.test/pom.xml
@@ -0,0 +1,50 @@
+
+ 4.0.0
+
+ org.idempiere
+ org.idempiere.parent
+ 7.1.0-SNAPSHOT
+ ../org.idempiere.parent/pom.xml
+
+ org.idempiere.test
+ eclipse-test-plugin
+
+ ..
+ true
+
+
+
+
+
+ org.eclipse.tycho
+ tycho-surefire-plugin
+
+
+ -DIDEMPIERE_HOME=${idempiere.home}
+
+ p2Installed
+ ${skipTests}
+
+
+
+ org.eclipse.tycho
+ target-platform-configuration
+ ${tycho.version}
+
+
+
+
+
+ p2-installable-unit
+ org.adempiere.server.product
+ 0.0.0
+
+
+
+
+
+
+
+
diff --git a/org.idempiere.test/src/org/idempiere/test/AbstractTestCase.java b/org.idempiere.test/src/org/idempiere/test/AbstractTestCase.java
new file mode 100644
index 0000000000..d4dc3ae079
--- /dev/null
+++ b/org.idempiere.test/src/org/idempiere/test/AbstractTestCase.java
@@ -0,0 +1,191 @@
+/***********************************************************************
+ * This file is part of iDempiere ERP Open Source *
+ * http://www.idempiere.org *
+ * *
+ * Copyright (C) Contributors *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software *
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
+ * MA 02110-1301, USA. *
+ * *
+ * Contributors: *
+ * - hengsin *
+ **********************************************************************/
+package org.idempiere.test;
+
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.sql.SQLException;
+import java.sql.Timestamp;
+
+import org.compiere.Adempiere;
+import org.compiere.model.MAcctSchema;
+import org.compiere.model.MClientInfo;
+import org.compiere.model.MRole;
+import org.compiere.util.Env;
+import org.compiere.util.Language;
+import org.compiere.util.Trx;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+
+/**
+ * @author hengsin
+ *
+ */
+public abstract class AbstractTestCase {
+
+ private Trx trx;
+ private LoginDetails loginDetails;
+
+ protected final int GARDEN_WORLD_CLIENT = 11;
+ protected final int GARDEN_WORLD_HQ_ORG = 11;
+ protected final int GARDEN_WORLD_ADMIN_USER = 101;
+ protected final int GARDEN_WORLD_ADMIN_ROLE = 102;
+ protected final int GARDEN_WORLD_HQ_WAREHOUSE = 103;
+
+ @BeforeAll
+ static void setup() {
+ Adempiere.startup(false);
+ }
+
+ @BeforeEach
+ protected void init() {
+ String trxName = Trx.createTrxName(getClass().getName()+"_");
+ trx = Trx.get(trxName, true);
+ trx.start();
+
+ initContext();
+ }
+
+ protected LoginDetails newLoginDetails() {
+ return new LoginDetails(GARDEN_WORLD_CLIENT, GARDEN_WORLD_HQ_ORG, GARDEN_WORLD_ADMIN_USER, GARDEN_WORLD_ADMIN_ROLE, GARDEN_WORLD_HQ_WAREHOUSE,
+ new Timestamp(System.currentTimeMillis()), Language.getLanguage("en_US"));
+ }
+
+ protected void initContext() {
+ loginDetails = newLoginDetails();
+
+ Env.setContext(Env.getCtx(), Env.AD_CLIENT_ID, loginDetails.getClientId());
+ Env.setContext(Env.getCtx(), Env.AD_ORG_ID, loginDetails.getOrganizationId());
+ Env.setContext(Env.getCtx(), Env.AD_USER_ID, loginDetails.getUserId());
+ Env.setContext(Env.getCtx(), Env.AD_ROLE_ID, loginDetails.getRoleId());
+ Env.setContext(Env.getCtx(), Env.M_WAREHOUSE_ID, loginDetails.getWarehouseId());
+ Env.setContext(Env.getCtx(), "#LanguageName", loginDetails.getLoginLanguage().getName());
+ Env.setContext(Env.getCtx(), "#Date", loginDetails.getLoginDate());
+
+ Env.verifyLanguage(Env.getCtx(), getLanguage());
+ Env.setContext(Env.getCtx(), Env.LANGUAGE, getLanguage().getAD_Language());
+ Env.setContext(Env.getCtx(), Env.LOCALE, getLanguage().getLocale().toString());
+
+ if (loginDetails.getRoleId() > 0) {
+ if (MRole.getDefault(Env.getCtx(), false).isShowAcct())
+ Env.setContext(Env.getCtx(), "#ShowAcct", "Y");
+ else
+ Env.setContext(Env.getCtx(), "#ShowAcct", "N");
+ }
+
+ /** Define AcctSchema , Currency, HasAlias **/
+ if (loginDetails.getClientId() > 0) {
+ if (MClientInfo.get(Env.getCtx(), loginDetails.getClientId()).getC_AcctSchema1_ID() > 0) {
+ MAcctSchema primary = MAcctSchema.get(Env.getCtx(), MClientInfo.get(Env.getCtx(), loginDetails.getClientId()).getC_AcctSchema1_ID());
+ Env.setContext(Env.getCtx(), "$C_AcctSchema_ID", primary.getC_AcctSchema_ID());
+ Env.setContext(Env.getCtx(), "$C_Currency_ID", primary.getC_Currency_ID());
+ Env.setContext(Env.getCtx(), "$HasAlias", primary.isHasAlias());
+ }
+
+ MAcctSchema[] ass = MAcctSchema.getClientAcctSchema(Env.getCtx(), loginDetails.getClientId());
+ if(ass != null && ass.length > 1) {
+ for(MAcctSchema as : ass) {
+ if (as.getAD_OrgOnly_ID() != 0) {
+ if (as.isSkipOrg(loginDetails.getOrganizationId())) {
+ continue;
+ } else {
+ Env.setContext(Env.getCtx(), "$C_AcctSchema_ID", as.getC_AcctSchema_ID());
+ Env.setContext(Env.getCtx(), "$C_Currency_ID", as.getC_Currency_ID());
+ Env.setContext(Env.getCtx(), "$HasAlias", as.isHasAlias());
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @AfterEach
+ protected void tearDown() {
+ if (trx != null && trx.isActive()) {
+ trx.rollback();
+ trx.close();
+ }
+ }
+
+ protected Trx getTrx() {
+ return trx;
+ }
+
+ protected void commit() {
+ if (trx != null && trx.isActive()) {
+ try {
+ trx.commit(true);
+ } catch (SQLException e) {
+ fail(e.getMessage(), e);
+ }
+ }
+ }
+
+ protected void rollback() {
+ if (trx != null && trx.isActive()) {
+ trx.rollback();
+ }
+ }
+
+ protected int getAD_Client_ID() {
+ return loginDetails.getClientId();
+ }
+
+ protected int getAD_Org_ID() {
+ return loginDetails.getOrganizationId();
+ }
+
+ protected int getAD_User_ID() {
+ return loginDetails.getUserId();
+ }
+
+ protected int getAD_Role_ID() {
+ return loginDetails.getRoleId();
+ }
+
+ protected int getM_Warehouse_ID() {
+ return loginDetails.getWarehouseId();
+ }
+
+ protected Language getLanguage() {
+ return loginDetails.getLoginLanguage();
+ }
+
+ protected Timestamp getLoginDate() {
+ return loginDetails.getLoginDate();
+ }
+
+ protected String getTrxName() {
+ return trx.getTrxName();
+ }
+
+ @AfterAll
+ static void shutdown() {
+ Adempiere.stop();
+ }
+}
diff --git a/org.idempiere.test/src/org/idempiere/test/LoginDetails.java b/org.idempiere.test/src/org/idempiere/test/LoginDetails.java
new file mode 100644
index 0000000000..8f0ad2ae29
--- /dev/null
+++ b/org.idempiere.test/src/org/idempiere/test/LoginDetails.java
@@ -0,0 +1,114 @@
+/***********************************************************************
+ * This file is part of iDempiere ERP Open Source *
+ * http://www.idempiere.org *
+ * *
+ * Copyright (C) Contributors *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software *
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
+ * MA 02110-1301, USA. *
+ * *
+ * Contributors: *
+ * - hengsin *
+ **********************************************************************/
+package org.idempiere.test;
+
+import java.sql.Timestamp;
+
+import org.compiere.util.Language;
+
+/**
+ *
+ * @author hengsin
+ *
+ */
+public class LoginDetails {
+ private int clientId;
+ private int organizationId;
+ private int userId;
+ private int roleId;
+ private int warehouseId;
+ private Timestamp loginDate;
+ private Language loginLanguage;
+
+ public LoginDetails(int clientId, int organizationId, int userId, int roleId, int warehouseId, Timestamp loginDate,
+ Language loginLanguage) {
+ super();
+ this.clientId = clientId;
+ this.organizationId = organizationId;
+ this.userId = userId;
+ this.roleId = roleId;
+ this.warehouseId = warehouseId;
+ this.loginDate = loginDate;
+ this.loginLanguage = loginLanguage;
+ }
+
+ public int getClientId() {
+ return clientId;
+ }
+
+ public void setClientId(int clientId) {
+ this.clientId = clientId;
+ }
+
+ public int getOrganizationId() {
+ return organizationId;
+ }
+
+ public void setOrganizationId(int organizationId) {
+ this.organizationId = organizationId;
+ }
+
+ public int getUserId() {
+ return userId;
+ }
+
+ public void setUserId(int userId) {
+ this.userId = userId;
+ }
+
+ public int getRoleId() {
+ return roleId;
+ }
+
+ public void setRoleId(int roleId) {
+ this.roleId = roleId;
+ }
+
+ public int getWarehouseId() {
+ return warehouseId;
+ }
+
+ public void setWarehouseId(int warehouseId) {
+ this.warehouseId = warehouseId;
+ }
+
+ public Timestamp getLoginDate() {
+ return loginDate;
+ }
+
+ public void setLoginDate(Timestamp loginDate) {
+ this.loginDate = loginDate;
+ }
+
+ public Language getLoginLanguage() {
+ return loginLanguage;
+ }
+
+ public void setLoginLanguage(Language loginLanguage) {
+ this.loginLanguage = loginLanguage;
+ }
+
+
+}
diff --git a/org.idempiere.test/src/org/idempiere/test/base/DBTest.java b/org.idempiere.test/src/org/idempiere/test/base/DBTest.java
new file mode 100644
index 0000000000..966ccb6dff
--- /dev/null
+++ b/org.idempiere.test/src/org/idempiere/test/base/DBTest.java
@@ -0,0 +1,207 @@
+/******************************************************************************
+ * Product: Adempiere ERP & CRM Smart Business Solution *
+ * Copyright (C) 2008 SC ARHIPAC SERVICE SRL. All Rights Reserved. *
+ * This program is free software; you can redistribute it and/or modify it *
+ * under the terms version 2 of the GNU General Public License as published *
+ * by the Free Software Foundation. This program is distributed in the hope *
+ * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
+ * See the GNU General Public License for more details. *
+ * You should have received a copy of the GNU General Public License along *
+ * with this program; if not, write to the Free Software Foundation, Inc., *
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
+ *****************************************************************************/
+package org.idempiere.test.base;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.math.BigDecimal;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+
+import org.adempiere.exceptions.DBException;
+import org.compiere.model.MTable;
+import org.compiere.util.DB;
+import org.compiere.util.KeyNamePair;
+import org.compiere.util.TimeUtil;
+import org.compiere.util.ValueNamePair;
+import org.idempiere.test.AbstractTestCase;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Test {@link org.compiere.util.DB} class
+ * @author Teo Sarca, www.arhipac.ro
+ * @author hengsin
+ */
+public class DBTest extends AbstractTestCase
+{
+ @Test
+ public void test_getSQLValueEx() throws Exception
+ {
+ int result = DB.getSQLValueEx(null, "SELECT 10 FROM DUAL");
+ assertEquals(10, result);
+ //
+ result = DB.getSQLValue(null, "SELECT 10 FROM AD_SYSTEM WHERE 1=2");
+ assertEquals(-1, result, "No value should be returned");
+ //
+ assertThrows(DBException.class, () -> {
+ DB.getSQLValueEx(null, "SELECT 10 FROM INEXISTENT_TABLE");
+ });
+ }
+
+ @Test
+ public void test_getSQLValue() throws Exception
+ {
+ int result = DB.getSQLValue(null, "SELECT 10 FROM DUAL");
+ assertEquals(10, result);
+ //
+ result = DB.getSQLValue(null, "SELECT 10 FROM AD_SYSTEM WHERE 1=2");
+ assertEquals(-1, result, "No value should be returned");
+ //
+ result = DB.getSQLValue(null, "SELECT 10 FROM INEXISTENT_TABLE");
+ assertEquals(-1, result, "Error should be signaled");
+ }
+
+ @Test
+ public void test_getSQLValueBDEx() throws Exception
+ {
+ BigDecimal result = DB.getSQLValueBDEx(null, "SELECT 10 FROM DUAL");
+ assertEquals(BigDecimal.TEN, result);
+ //
+ result = DB.getSQLValueBD(null, "SELECT 10 FROM AD_SYSTEM WHERE 1=2");
+ assertNull(result, "No value should be returned");
+ //
+ assertThrows(DBException.class, () -> {
+ DB.getSQLValueBDEx(null, "SELECT 10 FROM INEXISTENT_TABLE");
+ });
+ }
+
+ @Test
+ public void test_getSQLValueBD() throws Exception
+ {
+ BigDecimal result = DB.getSQLValueBD(null, "SELECT 10 FROM DUAL");
+ assertEquals(BigDecimal.TEN, result);
+ //
+ result = DB.getSQLValueBD(null, "SELECT 10 FROM AD_SYSTEM WHERE 1=2");
+ assertNull(result, "No value should be returned");
+ //
+ result = DB.getSQLValueBD(null, "SELECT 10 FROM INEXISTENT_TABLE");
+ assertNull(result, "Error should be signaled");
+ }
+
+ @Test
+ public void test_getSQLValueStringEx() throws Exception
+ {
+ String result = DB.getSQLValueStringEx(null, "SELECT 'string' FROM DUAL");
+ assertEquals("string", result);
+ //
+ result = DB.getSQLValueStringEx(null, "SELECT 10 FROM AD_SYSTEM WHERE 1=2");
+ assertNull(result, "No value should be returned");
+ //
+ assertThrows(DBException.class, () -> {
+ DB.getSQLValueStringEx(null, "SELECT 'string' FROM INEXISTENT_TABLE");
+ });
+ }
+
+ @Test
+ public void test_getSQLValueString() throws Exception
+ {
+ String result = DB.getSQLValueString(null, "SELECT 'string' FROM DUAL");
+ assertEquals("string", result);
+ //
+ result = DB.getSQLValueString(null, "SELECT 'string' FROM AD_SYSTEM WHERE 1=2");
+ assertNull(result, "No value should be returned");
+ //
+ result = DB.getSQLValueString(null, "SELECT 'string' FROM INEXISTENT_TABLE");
+ assertNull(result, "Error should be signaled");
+ }
+
+ @Test
+ public void test_getSQLValueTSEx() throws Exception
+ {
+ final Timestamp target = TimeUtil.getDay(2008, 01, 01);
+ //
+ Timestamp result = DB.getSQLValueTSEx(null, "SELECT TO_DATE('2008-01-01','YYYY-MM-DD') FROM AD_SYSTEM");
+ assertEquals(target, result);
+ //
+ result = DB.getSQLValueTSEx(null, "SELECT TO_DATE('2008-01-01','YYYY-MM-DD') FROM AD_SYSTEM WHERE 1=2");
+ assertNull(result, "No value should be returned");
+ //
+ assertThrows(DBException.class, () -> {
+ DB.getSQLValueTSEx(null, "SELECT TO_DATE('2008-01-01','YYYY-MM-DD') FROM INEXISTENT_TABLE");
+ });
+ }
+
+ @Test
+ public void test_getSQLValueTS() throws Exception
+ {
+ final Timestamp target = TimeUtil.getDay(2008, 01, 01);
+ //
+ Timestamp result = DB.getSQLValueTS(null, "SELECT TO_DATE('2008-01-01','YYYY-MM-DD') FROM DUAL");
+ assertEquals(target, result);
+ //
+ result = DB.getSQLValueTS(null, "SELECT TO_DATE('2008-01-01','YYYY-MM-DD') FROM AD_SYSTEM WHERE 1=2");
+ assertNull(result, "No value should be returned");
+ //
+ result = DB.getSQLValueTS(null, "SELECT TO_DATE('2008-01-01','YYYY-MM-DD') FROM INEXISTENT_TABLE");
+ assertNull(result, "Error should be signaled");
+ }
+
+ @Test
+ public void test_getValueNamePairs() throws Exception
+ {
+ ArrayList