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

Issue 25184 adding systemtable resource #25470

Merged
merged 23 commits into from
Jul 24, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
528 changes: 528 additions & 0 deletions dotCMS/src/curl-test/SystemTable.postman_collection.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.dotcms.enterprise.LicenseUtil;
import com.dotcms.enterprise.license.LicenseLevel;
import com.dotcms.repackage.net.sf.hibernate.HibernateException;
import com.dotcms.util.ReturnableDelegate;
import com.dotcms.util.VoidDelegate;
import com.dotmarketing.beans.Host;
import com.dotmarketing.business.APILocator;
Expand All @@ -28,7 +29,6 @@
import java.io.File;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.io.FileUtils;
import org.junit.After;
Expand Down Expand Up @@ -259,4 +259,20 @@ protected void initConnection() {
DbConnectionFactory.closeSilently(); // start always we a new one
}
}
}

/**
* Wrap the Delegate into a method db read method, that will close the connection at the end
* @param supplier
* @return
* @param <T>
* @throws Throwable
*/
protected <T> T wrapOnReadOnlyConn(final ReturnableDelegate<T> supplier) throws Throwable {

try {
return supplier.execute();
} finally {
DbConnectionFactory.closeSilently();
}
}
}
6 changes: 6 additions & 0 deletions dotCMS/src/integration-test/java/com/dotcms/MainSuite2b.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import com.dotcms.auth.providers.saml.v1.DotSamlResourceTest;
import com.dotcms.auth.providers.saml.v1.SAMLHelperTest;
import com.dotcms.bayesian.BayesianAPIImplIT;
import com.dotcms.business.SystemAPITest;
import com.dotcms.business.SystemTableFactoryTest;
import com.dotcms.cache.lettuce.DotObjectCodecTest;
import com.dotcms.cache.lettuce.LettuceCacheTest;
import com.dotcms.cache.lettuce.RedisClientTest;
Expand Down Expand Up @@ -141,6 +143,7 @@
import com.dotmarketing.startup.runonce.Task230110MakeSomeSystemFieldsRemovableByBaseTypeTest;
import com.dotmarketing.startup.runonce.Task230328AddMarkedForDeletionColumnTest;
import com.dotmarketing.startup.runonce.Task230426AlterVarcharLengthOfLockedByColTest;
import com.dotmarketing.startup.runonce.Task230707CreateSystemTableTest;
import com.dotmarketing.startup.runonce.Task230701AddHashIndicesToWorkflowTablesTest;
import com.dotmarketing.startup.runonce.Task230713IncreaseDisabledWysiwygColumnSizeTest;
import com.dotmarketing.util.MaintenanceUtilTest;
Expand Down Expand Up @@ -308,6 +311,9 @@
CMSUrlUtilTest.class,
AssetPathResolverImplIntegrationTest.class,
WebAssetHelperIntegrationTest.class,
SystemTableFactoryTest.class,
Task230707CreateSystemTableTest.class,
SystemAPITest.class,
Task230701AddHashIndicesToWorkflowTablesTest.class,
Task230713IncreaseDisabledWysiwygColumnSizeTest.class
})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package com.dotcms.business;

import com.dotcms.IntegrationTestBase;
import com.dotcms.exception.ExceptionUtil;
import com.dotcms.util.IntegrationTestInitService;
import com.dotmarketing.business.APILocator;
import com.dotmarketing.db.LocalTransaction;
import com.dotmarketing.exception.DoesNotExistException;
import com.dotmarketing.exception.DotDuplicateDataException;
import com.dotmarketing.util.Logger;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import java.util.Map;
import java.util.Optional;

/**
* Test for the {@link SystemAPI}
* @author jsanca
*/
public class SystemAPITest extends IntegrationTestBase {

@BeforeClass
public static void prepare () throws Exception {

//Setting web app environment
IntegrationTestInitService.getInstance().init();
}

/**
* Method to test: test CRUD operations of {@link SystemTable}
* Given Scenario: Creates a key/value, query it, update it and delete it
* ExpectedResult: All operations should be successful
* @throws Throwable
*/
@Test
public void test_crud_success () throws Throwable {

final String key1 = "akey1";
final String value1 = "value1";
final String value2 = "value2";

final SystemTable systemTable = APILocator.getSystemAPI().getSystemTable();

if (null != systemTable) {

// SAVE + FIND
LocalTransaction.wrap(()->systemTable.set(key1, value1));
final Optional<String> value1FromDB = wrapOnReadOnlyConn(()->systemTable.get(key1));
Assert.assertTrue("Should return something", value1FromDB.isPresent());
Assert.assertEquals(
"The value previous added should be the same of the value recovery from the db with the key: " + key1,
value1, value1FromDB.get());

// UPDATE + FIND
LocalTransaction.wrap(()->systemTable.set(key1, value2));
final Optional<String> value2FromDB = wrapOnReadOnlyConn(()->systemTable.get(key1));
Assert.assertEquals(
"The value previous added should be the same of the value recovery from the db with the key: " + key1,
value2, value2FromDB.get());

// DELETE + FIND
LocalTransaction.wrap(()->systemTable.delete(key1));
final Optional<String> value3FromDB = wrapOnReadOnlyConn(()->systemTable.get(key1));
Assert.assertFalse("Should not return something", value3FromDB.isPresent());
}
}


/**
* Method to test: test double save constraint {@link SystemTable#save(String, String)}
* Given Scenario: Creates a key/value twice
* ExpectedResult: Should throw an exception b/c the key already exist
* @throws Throwable
*/
@Test()
public void test_double_insert () throws Throwable {

final String key1 = "akey13";
final String value1 = "value1";

final SystemTable systemTable = APILocator.getSystemAPI().getSystemTable();

if (null != systemTable) {

// SAVE + FIND
LocalTransaction.wrap(()->systemTable.set(key1, value1));
final Optional<String> value1FromDB = wrapOnReadOnlyConn(()->systemTable.get(key1));
Assert.assertTrue("Should return something", value1FromDB.isPresent());
Assert.assertEquals(
"The value previous added should be the same of the value recovery from the db with the key: " + key1,
value1, value1FromDB.get());

// this should throw an exception since the key1 already exist.
LocalTransaction.wrap(() -> systemTable.set(key1, value1));
final Optional<String> value2FromDB = wrapOnReadOnlyConn(()->systemTable.get(key1));
Assert.assertTrue("Should return something", value2FromDB.isPresent());
Assert.assertEquals(
"The value previous added should be the same of the value recovery from the db with the key: " + key1,
value1, value2FromDB.get());
}
}


/**
* Method to test: test find all {@link SystemTable#all()}
* Given Scenario: Creates a couple key/value
* ExpectedResult: Should retrieve both keys
* @throws Throwable
*/
@Test()
public void test_find_all () throws Throwable {

final String key1 = "akey11";
final String value1 = "value11";
final String key2 = "akey22";
final String value2 = "value22";

final SystemTable systemTable = APILocator.getSystemAPI().getSystemTable();

if (null != systemTable) {

try {
// SAVE + FIND
LocalTransaction.wrap(() -> systemTable.set(key1, value1));
LocalTransaction.wrap(() -> systemTable.set(key2, value2));
final Map<String, String> value1FromDB = wrapOnReadOnlyConn(() -> systemTable.all());
Assert.assertTrue("Should has key1", value1FromDB.containsKey(key1));
Assert.assertTrue("Should has key2", value1FromDB.containsKey(key2));
Assert.assertEquals(
"The value previous added should be the same of the value recovery from the db with the key: " + key1,
value1, value1FromDB.get(key1));
Assert.assertEquals(
"The value previous added should be the same of the value recovery from the db with the key: " + key2,
value2, value1FromDB.get(key2));
} finally {
try {
LocalTransaction.wrap(() -> systemTable.delete(key1));
LocalTransaction.wrap(() -> systemTable.delete(key2));
} catch (Throwable e) {
Logger.debug(this, e.getMessage());
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package com.dotcms.business;

import com.dotcms.IntegrationTestBase;
import com.dotcms.util.IntegrationTestInitService;
import com.dotmarketing.business.APILocator;
import com.dotmarketing.business.CacheLocator;
import com.dotmarketing.business.DotCacheAdministrator;
import com.dotmarketing.business.FactoryLocator;
import com.dotmarketing.db.LocalTransaction;
import com.dotmarketing.exception.DoesNotExistException;
import com.dotmarketing.exception.DotDuplicateDataException;
import com.dotmarketing.util.Logger;
import com.liferay.portal.model.User;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import java.util.Map;
import java.util.Optional;

/**
* Test for the {@link SystemTableFactory}
* @author jsanca
*/
public class SystemTableFactoryTest extends IntegrationTestBase {

private static DotCacheAdministrator cache;
private static User systemUser;

@BeforeClass
public static void prepare () throws Exception {

//Setting web app environment
IntegrationTestInitService.getInstance().init();

cache = CacheLocator.getCacheAdministrator();

//Setting the test user
systemUser = APILocator.getUserAPI().getSystemUser();
}

/**
* Method to test: test CRUD operations of {@link SystemTableFactory}
* Given Scenario: Creates a key/value, query it, update it and delete it
* ExpectedResult: All operations should be successful
* @throws Throwable
*/
@Test
public void test_crud_success () throws Throwable {

final String key1 = "key1";
final String value1 = "value1";
final String value2 = "value2";

final SystemTableFactory systemTableFactory = FactoryLocator.getSystemTableFactory();

if (null != systemTableFactory) {

systemTableFactory.clearCache();
// SAVE + FIND
LocalTransaction.wrap(()->systemTableFactory.saveOrUpdate(key1, value1));
final Optional<String> value1FromDB = wrapOnReadOnlyConn(()->systemTableFactory.find(key1));
Assert.assertTrue("Should return something", value1FromDB.isPresent());
Assert.assertEquals(
"The value previous added should be the same of the value recovery from the db with the key: " + key1,
value1, value1FromDB.get());

// UPDATE + FIND
LocalTransaction.wrap(()->systemTableFactory.saveOrUpdate(key1, value2));
final Optional<String> value2FromDB = wrapOnReadOnlyConn(()->systemTableFactory.find(key1));
Assert.assertEquals(
"The value previous added should be the same of the value recovery from the db with the key: " + key1,
value2, value2FromDB.get());

// DELETE + FIND
LocalTransaction.wrap(()->systemTableFactory.delete(key1));
final Optional<String> value3FromDB = wrapOnReadOnlyConn(()->systemTableFactory.find(key1));
Assert.assertFalse("Should not return something", value3FromDB.isPresent());
}
}


/**
* Method to test: test double save constraint {@link SystemTableFactory#save(String, String)}
* Given Scenario: Creates a key/value twice
* ExpectedResult: Should throw an exception b/c the key already exist
* @throws Throwable
*/
@Test()
public void test_double_insert () throws Throwable {

final String key1 = "key13";
final String value1 = "value1";

final SystemTableFactory systemTableFactory = FactoryLocator.getSystemTableFactory();

if (null != systemTableFactory) {

systemTableFactory.clearCache();
// SAVE + FIND
LocalTransaction.wrap(()->systemTableFactory.saveOrUpdate(key1, value1));
final Optional<String> value1FromDB = wrapOnReadOnlyConn(()->systemTableFactory.find(key1));
Assert.assertTrue("Should return something", value1FromDB.isPresent());
Assert.assertEquals(
"The value previous added should be the same of the value recovery from the db with the key: " + key1,
value1, value1FromDB.get());

// this should be an update
LocalTransaction.wrap(()->systemTableFactory.saveOrUpdate(key1, value1));
final Optional<String> value2FromDB = wrapOnReadOnlyConn(()->systemTableFactory.find(key1));
Assert.assertTrue("Should return something", value2FromDB.isPresent());
Assert.assertEquals(
"The value previous added should be the same of the value recovery from the db with the key: " + key1,
value1, value2FromDB.get());

}
}


/**
* Method to test: test find all {@link SystemTableFactory#findAll()}
* Given Scenario: Creates a couple key/value
* ExpectedResult: Should retrieve both keys
* @throws Throwable
*/
@Test()
public void test_find_all () throws Throwable {

final String key1 = "key11";
final String value1 = "value11";
final String key2 = "key22";
final String value2 = "value22";

final SystemTableFactory systemTableFactory = FactoryLocator.getSystemTableFactory();

if (null != systemTableFactory) {

try {
systemTableFactory.clearCache();
// SAVE + FIND
LocalTransaction.wrap(() -> systemTableFactory.saveOrUpdate(key1, value1));
LocalTransaction.wrap(() -> systemTableFactory.saveOrUpdate(key2, value2));
final Map<String, String> value1FromDB = wrapOnReadOnlyConn(() -> systemTableFactory.findAll());
Assert.assertTrue("Should has key1", value1FromDB.containsKey(key1));
Assert.assertTrue("Should has key2", value1FromDB.containsKey(key2));
Assert.assertEquals(
"The value previous added should be the same of the value recovery from the db with the key: " + key1,
value1, value1FromDB.get(key1));
Assert.assertEquals(
"The value previous added should be the same of the value recovery from the db with the key: " + key2,
value2, value1FromDB.get(key2));
} finally {
try {
LocalTransaction.wrap(() -> systemTableFactory.delete(key1));
LocalTransaction.wrap(() -> systemTableFactory.delete(key2));
} catch (Throwable e) {
Logger.debug(this, e.getMessage());
}
}
}
}
}
Loading