mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 21:20:45 +00:00
Add Memory backend module
This commit is contained in:
@ -0,0 +1,185 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.core.modules.backend.implementations.memory;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.CountAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.DeleteAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.UpdateAction;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for MemoryBackendModule
|
||||
*******************************************************************************/
|
||||
class MemoryBackendModuleTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@AfterEach
|
||||
void afterEach()
|
||||
{
|
||||
MemoryRecordStore.getInstance().reset();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testFullCRUD() throws QException
|
||||
{
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
QTableMetaData table = qInstance.getTable(TestUtils.TABLE_NAME_SHAPE);
|
||||
QSession session = new QSession();
|
||||
|
||||
/////////////////////////
|
||||
// do an initial count //
|
||||
/////////////////////////
|
||||
CountInput countInput = new CountInput(qInstance);
|
||||
countInput.setSession(session);
|
||||
countInput.setTableName(table.getName());
|
||||
assertEquals(0, new CountAction().execute(countInput).getCount());
|
||||
|
||||
//////////////////
|
||||
// do an insert //
|
||||
//////////////////
|
||||
InsertInput insertInput = new InsertInput(qInstance);
|
||||
insertInput.setSession(session);
|
||||
insertInput.setTableName(table.getName());
|
||||
insertInput.setRecords(List.of(
|
||||
new QRecord()
|
||||
.withTableName(table.getName())
|
||||
.withValue("name", "My Triangle")
|
||||
.withValue("type", "triangle")
|
||||
.withValue("noOfSides", 3)
|
||||
.withValue("isPolygon", true),
|
||||
new QRecord()
|
||||
.withTableName(table.getName())
|
||||
.withValue("name", "Your Square")
|
||||
.withValue("type", "square")
|
||||
.withValue("noOfSides", 4)
|
||||
.withValue("isPolygon", true),
|
||||
new QRecord()
|
||||
.withTableName(table.getName())
|
||||
.withValue("name", "Some Circle")
|
||||
.withValue("type", "circle")
|
||||
.withValue("noOfSides", null)
|
||||
.withValue("isPolygon", false)
|
||||
));
|
||||
InsertOutput insertOutput = new InsertAction().execute(insertInput);
|
||||
assertEquals(insertOutput.getRecords().size(), 3);
|
||||
assertTrue(insertOutput.getRecords().stream().allMatch(r -> r.getValue("id") != null));
|
||||
assertTrue(insertOutput.getRecords().stream().anyMatch(r -> r.getValueInteger("id").equals(1)));
|
||||
assertTrue(insertOutput.getRecords().stream().anyMatch(r -> r.getValueInteger("id").equals(2)));
|
||||
assertTrue(insertOutput.getRecords().stream().anyMatch(r -> r.getValueInteger("id").equals(3)));
|
||||
|
||||
////////////////
|
||||
// do a query //
|
||||
////////////////
|
||||
QueryInput queryInput = new QueryInput(qInstance);
|
||||
queryInput.setSession(session);
|
||||
queryInput.setTableName(table.getName());
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
assertEquals(queryOutput.getRecords().size(), 3);
|
||||
assertTrue(queryOutput.getRecords().stream().allMatch(r -> r.getValue("id") != null));
|
||||
assertTrue(queryOutput.getRecords().stream().anyMatch(r -> r.getValueInteger("id").equals(1)));
|
||||
assertTrue(queryOutput.getRecords().stream().anyMatch(r -> r.getValueInteger("id").equals(2)));
|
||||
assertTrue(queryOutput.getRecords().stream().anyMatch(r -> r.getValueInteger("id").equals(3)));
|
||||
assertTrue(queryOutput.getRecords().stream().anyMatch(r -> r.getValueString("name").equals("My Triangle")));
|
||||
assertTrue(queryOutput.getRecords().stream().anyMatch(r -> r.getValueString("name").equals("Your Square")));
|
||||
assertTrue(queryOutput.getRecords().stream().anyMatch(r -> r.getValueString("name").equals("Some Circle")));
|
||||
|
||||
assertEquals(3, new CountAction().execute(countInput).getCount());
|
||||
|
||||
//////////////////
|
||||
// do an update //
|
||||
//////////////////
|
||||
UpdateInput updateInput = new UpdateInput(qInstance);
|
||||
updateInput.setSession(session);
|
||||
updateInput.setTableName(table.getName());
|
||||
updateInput.setRecords(List.of(
|
||||
new QRecord()
|
||||
.withTableName(table.getName())
|
||||
.withValue("id", 1)
|
||||
.withValue("name", "Not My Triangle any more"),
|
||||
new QRecord()
|
||||
.withTableName(table.getName())
|
||||
.withValue("id", 3)
|
||||
.withValue("type", "ellipse")
|
||||
));
|
||||
UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
|
||||
assertEquals(updateOutput.getRecords().size(), 2);
|
||||
|
||||
queryOutput = new QueryAction().execute(queryInput);
|
||||
assertEquals(queryOutput.getRecords().size(), 3);
|
||||
assertTrue(queryOutput.getRecords().stream().noneMatch(r -> r.getValueString("name").equals("My Triangle")));
|
||||
assertTrue(queryOutput.getRecords().stream().anyMatch(r -> r.getValueString("name").equals("Not My Triangle any more")));
|
||||
assertTrue(queryOutput.getRecords().stream().anyMatch(r -> r.getValueString("type").equals("ellipse")));
|
||||
assertTrue(queryOutput.getRecords().stream().noneMatch(r -> r.getValueString("type").equals("circle")));
|
||||
|
||||
assertEquals(3, new CountAction().execute(countInput).getCount());
|
||||
|
||||
/////////////////
|
||||
// do a delete //
|
||||
/////////////////
|
||||
DeleteInput deleteInput = new DeleteInput(qInstance);
|
||||
deleteInput.setSession(session);
|
||||
deleteInput.setTableName(table.getName());
|
||||
deleteInput.setPrimaryKeys(List.of(1, 2));
|
||||
DeleteOutput deleteOutput = new DeleteAction().execute(deleteInput);
|
||||
assertEquals(deleteOutput.getDeletedRecordCount(), 2);
|
||||
|
||||
assertEquals(1, new CountAction().execute(countInput).getCount());
|
||||
|
||||
queryOutput = new QueryAction().execute(queryInput);
|
||||
assertEquals(queryOutput.getRecords().size(), 1);
|
||||
assertTrue(queryOutput.getRecords().stream().noneMatch(r -> r.getValueInteger("id").equals(1)));
|
||||
assertTrue(queryOutput.getRecords().stream().noneMatch(r -> r.getValueInteger("id").equals(2)));
|
||||
assertTrue(queryOutput.getRecords().stream().anyMatch(r -> r.getValueInteger("id").equals(3)));
|
||||
}
|
||||
|
||||
}
|
@ -26,7 +26,6 @@ import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.person.addtopeoplesage.AddAge;
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.person.addtopeoplesage.GetAgeStatistics;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
||||
import com.kingsrook.qqq.backend.core.adapters.QInstanceAdapter;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput;
|
||||
@ -52,6 +51,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||
import com.kingsrook.qqq.backend.core.modules.authentication.MockAuthenticationModule;
|
||||
import com.kingsrook.qqq.backend.core.modules.authentication.metadata.QAuthenticationMetaData;
|
||||
import com.kingsrook.qqq.backend.core.modules.backend.implementations.memory.MemoryBackendModule;
|
||||
import com.kingsrook.qqq.backend.core.modules.backend.implementations.mock.MockBackendModule;
|
||||
import com.kingsrook.qqq.backend.core.processes.implementations.etl.basic.BasicETLProcess;
|
||||
import com.kingsrook.qqq.backend.core.processes.implementations.etl.streamed.StreamedETLProcess;
|
||||
@ -65,12 +65,14 @@ import com.kingsrook.qqq.backend.core.processes.implementations.mock.MockBackend
|
||||
public class TestUtils
|
||||
{
|
||||
public static final String DEFAULT_BACKEND_NAME = "default";
|
||||
public static final String MEMORY_BACKEND_NAME = "memory";
|
||||
|
||||
public static final String APP_NAME_GREETINGS = "greetingsApp";
|
||||
public static final String APP_NAME_PEOPLE = "peopleApp";
|
||||
public static final String APP_NAME_MISCELLANEOUS = "miscellaneous";
|
||||
|
||||
public static final String TABLE_NAME_PERSON = "person";
|
||||
public static final String TABLE_NAME_SHAPE = "shape";
|
||||
|
||||
public static final String PROCESS_NAME_GREET_PEOPLE = "greet";
|
||||
public static final String PROCESS_NAME_GREET_PEOPLE_INTERACTIVE = "greetInteractive";
|
||||
@ -89,10 +91,12 @@ public class TestUtils
|
||||
QInstance qInstance = new QInstance();
|
||||
qInstance.setAuthentication(defineAuthentication());
|
||||
qInstance.addBackend(defineBackend());
|
||||
qInstance.addBackend(defineMemoryBackend());
|
||||
|
||||
qInstance.addTable(defineTablePerson());
|
||||
qInstance.addTable(definePersonFileTable());
|
||||
qInstance.addTable(defineTableIdAndNameOnly());
|
||||
qInstance.addTable(defineTableShape());
|
||||
|
||||
qInstance.addPossibleValueSource(defineStatesPossibleValueSource());
|
||||
|
||||
@ -104,8 +108,6 @@ public class TestUtils
|
||||
|
||||
defineApps(qInstance);
|
||||
|
||||
System.out.println(new QInstanceAdapter().qInstanceToJson(qInstance));
|
||||
|
||||
return (qInstance);
|
||||
}
|
||||
|
||||
@ -174,6 +176,18 @@ public class TestUtils
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Define the in-memory backend used in standard tests
|
||||
*******************************************************************************/
|
||||
public static QBackendMetaData defineMemoryBackend()
|
||||
{
|
||||
return new QBackendMetaData()
|
||||
.withName(MEMORY_BACKEND_NAME)
|
||||
.withBackendType(MemoryBackendModule.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Define the 'person' table used in standard tests.
|
||||
*******************************************************************************/
|
||||
@ -196,6 +210,27 @@ public class TestUtils
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Define the 'shape' table used in standard tests.
|
||||
*******************************************************************************/
|
||||
public static QTableMetaData defineTableShape()
|
||||
{
|
||||
return new QTableMetaData()
|
||||
.withName(TABLE_NAME_SHAPE)
|
||||
.withBackendName(MEMORY_BACKEND_NAME)
|
||||
.withPrimaryKeyField("id")
|
||||
.withField(new QFieldMetaData("id", QFieldType.INTEGER).withIsEditable(false))
|
||||
.withField(new QFieldMetaData("createDate", QFieldType.DATE_TIME).withIsEditable(false))
|
||||
.withField(new QFieldMetaData("modifyDate", QFieldType.DATE_TIME).withIsEditable(false))
|
||||
.withField(new QFieldMetaData("name", QFieldType.STRING))
|
||||
.withField(new QFieldMetaData("type", QFieldType.STRING)) // todo PVS
|
||||
.withField(new QFieldMetaData("noOfSides", QFieldType.INTEGER))
|
||||
.withField(new QFieldMetaData("isPolygon", QFieldType.BOOLEAN)) // mmm, should be derived from type, no?
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Define a 2nd version of the 'person' table for this test (pretend it's backed by a file)
|
||||
*******************************************************************************/
|
||||
|
Reference in New Issue
Block a user