mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 21:20:45 +00:00
Moving qqq-backend-core into its own subdir
This commit is contained in:
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* 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.actions.async;
|
||||
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for AsyncJobManager
|
||||
*******************************************************************************/
|
||||
class AsyncJobManagerTest
|
||||
{
|
||||
public static final int ANSWER = 42;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testCompletesInTime() throws JobGoingAsyncException, QException
|
||||
{
|
||||
AsyncJobManager asyncJobManager = new AsyncJobManager();
|
||||
Integer answer = asyncJobManager.startJob(5, TimeUnit.SECONDS, (callback) ->
|
||||
{
|
||||
return (ANSWER);
|
||||
});
|
||||
assertEquals(ANSWER, answer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testJobGoesAsync()
|
||||
{
|
||||
assertThrows(JobGoingAsyncException.class, () ->
|
||||
{
|
||||
AsyncJobManager asyncJobManager = new AsyncJobManager();
|
||||
asyncJobManager.startJob(1, TimeUnit.MICROSECONDS, (callback) ->
|
||||
{
|
||||
Thread.sleep(1_000);
|
||||
return (ANSWER);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testJobThatThrowsBeforeTimeout()
|
||||
{
|
||||
assertThrows(QException.class, () ->
|
||||
{
|
||||
AsyncJobManager asyncJobManager = new AsyncJobManager();
|
||||
asyncJobManager.startJob(1, TimeUnit.SECONDS, (callback) ->
|
||||
{
|
||||
throw (new IllegalArgumentException("I must throw."));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testJobThatThrowsAfterTimeout() throws QException, InterruptedException
|
||||
{
|
||||
String message = "I must throw.";
|
||||
AsyncJobManager asyncJobManager = new AsyncJobManager();
|
||||
try
|
||||
{
|
||||
asyncJobManager.startJob(1, TimeUnit.MILLISECONDS, (callback) ->
|
||||
{
|
||||
Thread.sleep(50);
|
||||
throw (new IllegalArgumentException(message));
|
||||
});
|
||||
fail("We should catch a JobGoingAsyncException");
|
||||
}
|
||||
catch(JobGoingAsyncException jgae)
|
||||
{
|
||||
Thread.sleep(100);
|
||||
Optional<AsyncJobStatus> jobStatus = asyncJobManager.getJobStatus(jgae.getJobUUID());
|
||||
assertEquals(AsyncJobState.ERROR, jobStatus.get().getState());
|
||||
assertNotNull(jobStatus.get().getCaughtException());
|
||||
assertEquals(message, jobStatus.get().getCaughtException().getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testGettingStatusOfAsyncJob() throws InterruptedException, QException
|
||||
{
|
||||
AsyncJobManager asyncJobManager = new AsyncJobManager();
|
||||
String preMessage = "Going to sleep";
|
||||
String postMessage = "Waking up";
|
||||
try
|
||||
{
|
||||
asyncJobManager.startJob(50, TimeUnit.MILLISECONDS, (callback) ->
|
||||
{
|
||||
callback.updateStatus(preMessage);
|
||||
callback.updateStatus(0, 1);
|
||||
Thread.sleep(100);
|
||||
callback.updateStatus(postMessage, 1, 1);
|
||||
return (ANSWER);
|
||||
});
|
||||
fail("We should catch a JobGoingAsyncException");
|
||||
}
|
||||
catch(JobGoingAsyncException jgae)
|
||||
{
|
||||
assertNotNull(jgae.getJobUUID());
|
||||
Optional<AsyncJobStatus> jobStatus = asyncJobManager.getJobStatus(jgae.getJobUUID());
|
||||
|
||||
assertEquals(AsyncJobState.RUNNING, jobStatus.get().getState());
|
||||
assertEquals(preMessage, jobStatus.get().getMessage());
|
||||
assertEquals(0, jobStatus.get().getCurrent());
|
||||
assertEquals(1, jobStatus.get().getTotal());
|
||||
|
||||
Thread.sleep(200);
|
||||
jobStatus = asyncJobManager.getJobStatus(jgae.getJobUUID());
|
||||
assertEquals(AsyncJobState.COMPLETE, jobStatus.get().getState());
|
||||
assertEquals(postMessage, jobStatus.get().getMessage());
|
||||
assertEquals(1, jobStatus.get().getCurrent());
|
||||
assertEquals(1, jobStatus.get().getTotal());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.actions.metadata;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataOutput;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for MetaDataAction
|
||||
**
|
||||
*******************************************************************************/
|
||||
class MetaDataActionTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test() throws QException
|
||||
{
|
||||
MetaDataInput request = new MetaDataInput(TestUtils.defineInstance());
|
||||
request.setSession(TestUtils.getMockSession());
|
||||
MetaDataOutput result = new MetaDataAction().execute(request);
|
||||
assertNotNull(result);
|
||||
assertNotNull(result.getTables());
|
||||
assertNotNull(result.getTables().get("person"));
|
||||
assertEquals("person", result.getTables().get("person").getName());
|
||||
assertEquals("Person", result.getTables().get("person").getLabel());
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.actions.metadata;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QNotFoundException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.ProcessMetaDataInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.ProcessMetaDataOutput;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for ProcessMetaDataAction
|
||||
**
|
||||
*******************************************************************************/
|
||||
class ProcessMetaDataActionTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
** Test basic success case.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test() throws QException
|
||||
{
|
||||
ProcessMetaDataInput request = new ProcessMetaDataInput(TestUtils.defineInstance());
|
||||
request.setSession(TestUtils.getMockSession());
|
||||
request.setProcessName(TestUtils.PROCESS_NAME_GREET_PEOPLE_INTERACTIVE);
|
||||
ProcessMetaDataOutput result = new ProcessMetaDataAction().execute(request);
|
||||
assertNotNull(result);
|
||||
assertNotNull(result.getProcess());
|
||||
assertEquals("greetInteractive", result.getProcess().getName());
|
||||
assertEquals("Greet Interactive", result.getProcess().getLabel());
|
||||
assertEquals(2, result.getProcess().getFrontendSteps().size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test exception is thrown for the "not-found" case.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_notFound()
|
||||
{
|
||||
assertThrows(QNotFoundException.class, () -> {
|
||||
ProcessMetaDataInput request = new ProcessMetaDataInput(TestUtils.defineInstance());
|
||||
request.setSession(TestUtils.getMockSession());
|
||||
request.setProcessName("willNotBeFound");
|
||||
new ProcessMetaDataAction().execute(request);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.actions.metadata;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.TableMetaDataInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.TableMetaDataOutput;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for TableMetaDataAction
|
||||
**
|
||||
*******************************************************************************/
|
||||
class TableMetaDataActionTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
** Test basic success case.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test() throws QException
|
||||
{
|
||||
TableMetaDataInput request = new TableMetaDataInput(TestUtils.defineInstance());
|
||||
request.setSession(TestUtils.getMockSession());
|
||||
request.setTableName("person");
|
||||
TableMetaDataOutput result = new TableMetaDataAction().execute(request);
|
||||
assertNotNull(result);
|
||||
assertNotNull(result.getTable());
|
||||
assertEquals("person", result.getTable().getName());
|
||||
assertEquals("Person", result.getTable().getLabel());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test exeption is thrown for the "not-found" case.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_notFound()
|
||||
{
|
||||
assertThrows(QUserFacingException.class, () -> {
|
||||
TableMetaDataInput request = new TableMetaDataInput(TestUtils.defineInstance());
|
||||
request.setSession(TestUtils.getMockSession());
|
||||
request.setTableName("willNotBeFound");
|
||||
new TableMetaDataAction().execute(request);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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.actions.processes;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public class RunBackendStepActionTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test() throws QException
|
||||
{
|
||||
TestCallback callback = new TestCallback();
|
||||
RunBackendStepInput request = new RunBackendStepInput(TestUtils.defineInstance());
|
||||
request.setSession(TestUtils.getMockSession());
|
||||
request.setProcessName("greet");
|
||||
request.setStepName("prepare");
|
||||
request.setCallback(callback);
|
||||
RunBackendStepOutput result = new RunBackendStepAction().execute(request);
|
||||
assertNotNull(result);
|
||||
assertTrue(result.getRecords().stream().allMatch(r -> r.getValues().containsKey("mockValue")), "records should have a mock value");
|
||||
assertTrue(result.getValues().containsKey("mockValue"), "result object should have a mock value");
|
||||
assertEquals("ABC", result.getValues().get("greetingPrefix"), "result object should have value from our callback");
|
||||
assertTrue(callback.wasCalledForQueryFilter, "callback was used for query filter");
|
||||
assertTrue(callback.wasCalledForFieldValues, "callback was used for field values");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static class TestCallback implements QProcessCallback
|
||||
{
|
||||
private boolean wasCalledForQueryFilter = false;
|
||||
private boolean wasCalledForFieldValues = false;
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Override
|
||||
public QQueryFilter getQueryFilter()
|
||||
{
|
||||
wasCalledForQueryFilter = true;
|
||||
return (new QQueryFilter());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Override
|
||||
public Map<String, Serializable> getFieldValues(List<QFieldMetaData> fields)
|
||||
{
|
||||
wasCalledForFieldValues = true;
|
||||
Map<String, Serializable> rs = new HashMap<>();
|
||||
for(QFieldMetaData field : fields)
|
||||
{
|
||||
rs.put(field.getName(), switch(field.getType())
|
||||
{
|
||||
case STRING -> "ABC";
|
||||
case INTEGER -> 42;
|
||||
case DECIMAL -> new BigDecimal("47");
|
||||
case DATE, DATE_TIME -> null;
|
||||
case TEXT -> """
|
||||
ABC
|
||||
XYZ""";
|
||||
case HTML -> "<b>Oh my</b>";
|
||||
case PASSWORD -> "myPa**word";
|
||||
case BLOB -> new byte[] { 1, 2, 3, 4 };
|
||||
});
|
||||
}
|
||||
return (rs);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,290 @@
|
||||
/*
|
||||
* 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.actions.processes;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.processes.implementations.mock.MockBackendStep;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.ProcessState;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendStepMetaData;
|
||||
import com.kingsrook.qqq.backend.core.state.StateType;
|
||||
import com.kingsrook.qqq.backend.core.state.UUIDAndTypeStateKey;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public class RunProcessTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test() throws QException
|
||||
{
|
||||
TestCallback callback = new TestCallback();
|
||||
RunProcessInput request = new RunProcessInput(TestUtils.defineInstance());
|
||||
request.setSession(TestUtils.getMockSession());
|
||||
request.setProcessName("addToPeoplesAge");
|
||||
request.setCallback(callback);
|
||||
RunProcessOutput result = new RunProcessAction().execute(request);
|
||||
assertNotNull(result);
|
||||
assertTrue(result.getRecords().stream().allMatch(r -> r.getValues().containsKey("age")), "records should have a value set by the process");
|
||||
assertTrue(result.getValues().containsKey("maxAge"), "process result object should have a value set by the first function in the process");
|
||||
assertTrue(result.getValues().containsKey("totalYearsAdded"), "process result object should have a value set by the second function in the process");
|
||||
assertTrue(callback.wasCalledForQueryFilter, "callback was used for query filter");
|
||||
assertTrue(callback.wasCalledForFieldValues, "callback was used for field values");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testBreakOnFrontendSteps() throws QException
|
||||
{
|
||||
TestCallback callback = new TestCallback();
|
||||
QInstance instance = TestUtils.defineInstance();
|
||||
RunProcessInput request = new RunProcessInput(instance);
|
||||
String processName = TestUtils.PROCESS_NAME_GREET_PEOPLE_INTERACTIVE;
|
||||
|
||||
request.setSession(TestUtils.getMockSession());
|
||||
request.setProcessName(processName);
|
||||
request.setFrontendStepBehavior(RunProcessInput.FrontendStepBehavior.BREAK);
|
||||
request.setCallback(callback);
|
||||
RunProcessOutput result0 = new RunProcessAction().execute(request);
|
||||
|
||||
assertNotNull(result0);
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// make sure we were told that we broke at a (frontend) step //
|
||||
///////////////////////////////////////////////////////////////
|
||||
Optional<String> breakingAtStep0 = result0.getProcessState().getNextStepName();
|
||||
assertTrue(breakingAtStep0.isPresent());
|
||||
assertInstanceOf(QFrontendStepMetaData.class, instance.getProcessStep(processName, breakingAtStep0.get()));
|
||||
assertNull(result0.getValues().get(MockBackendStep.FIELD_MOCK_VALUE));
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// now run again, proceeding from this step //
|
||||
//////////////////////////////////////////////
|
||||
request.setStartAfterStep(breakingAtStep0.get());
|
||||
RunProcessOutput result1 = new RunProcessAction().execute(request);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// make sure we were told that we broke at the next frontend step //
|
||||
////////////////////////////////////////////////////////////////////
|
||||
Optional<String> breakingAtStep1 = result1.getProcessState().getNextStepName();
|
||||
assertTrue(breakingAtStep1.isPresent());
|
||||
assertInstanceOf(QFrontendStepMetaData.class, instance.getProcessStep(processName, breakingAtStep1.get()));
|
||||
assertNotEquals(breakingAtStep0.get(), breakingAtStep1.get());
|
||||
assertEquals(MockBackendStep.MOCK_VALUE, result1.getValues().get(MockBackendStep.FIELD_MOCK_VALUE));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testSkipFrontendSteps() throws QException
|
||||
{
|
||||
TestCallback callback = new TestCallback();
|
||||
QInstance instance = TestUtils.defineInstance();
|
||||
RunProcessInput request = new RunProcessInput(instance);
|
||||
String processName = TestUtils.PROCESS_NAME_GREET_PEOPLE_INTERACTIVE;
|
||||
|
||||
request.setSession(TestUtils.getMockSession());
|
||||
request.setProcessName(processName);
|
||||
request.setFrontendStepBehavior(RunProcessInput.FrontendStepBehavior.SKIP);
|
||||
request.setCallback(callback);
|
||||
|
||||
RunProcessOutput runProcessOutput = new RunProcessAction().execute(request);
|
||||
assertTrue(runProcessOutput.getException().isEmpty());
|
||||
assertEquals(MockBackendStep.MOCK_VALUE, runProcessOutput.getValues().get(MockBackendStep.FIELD_MOCK_VALUE));
|
||||
assertTrue(runProcessOutput.getProcessState().getNextStepName().isEmpty());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testFailOnFrontendSteps()
|
||||
{
|
||||
TestCallback callback = new TestCallback();
|
||||
QInstance instance = TestUtils.defineInstance();
|
||||
RunProcessInput request = new RunProcessInput(instance);
|
||||
String processName = TestUtils.PROCESS_NAME_GREET_PEOPLE_INTERACTIVE;
|
||||
|
||||
request.setSession(TestUtils.getMockSession());
|
||||
request.setProcessName(processName);
|
||||
request.setFrontendStepBehavior(RunProcessInput.FrontendStepBehavior.FAIL);
|
||||
request.setCallback(callback);
|
||||
|
||||
try
|
||||
{
|
||||
new RunProcessAction().execute(request);
|
||||
fail("This should have thrown...");
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
assertTrue(e.getMessage().contains("fail on frontend steps"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testPrimeProcessRequestNewProcess() throws QException
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// this is a flow where it's a new process - so, we should create a new state //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
RunProcessInput runProcessInput = new RunProcessInput();
|
||||
UUIDAndTypeStateKey stateKey = new UUIDAndTypeStateKey(UUID.randomUUID(), StateType.PROCESS_STATUS);
|
||||
ProcessState processState = new RunProcessAction().primeProcessState(runProcessInput, stateKey);
|
||||
assertNotNull(processState);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testPrimeProcessRequestAttemptToContinueButStateNotFound() throws QException
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// this is a flow where it's a continue, but we don't have a state stored, so it should throw //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
RunProcessInput runProcessInput = new RunProcessInput();
|
||||
runProcessInput.setStartAfterStep("setupStep");
|
||||
UUIDAndTypeStateKey stateKey = new UUIDAndTypeStateKey(UUID.randomUUID(), StateType.PROCESS_STATUS);
|
||||
|
||||
assertThrows(QException.class, () ->
|
||||
{
|
||||
new RunProcessAction().primeProcessState(runProcessInput, stateKey);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testPrimeProcessRequestAttemptToContinueAndStateIsFound() throws QException
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// this is a flow where it's a continue, but we don't have a state stored, so it should throw //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
RunProcessInput runProcessInput = new RunProcessInput();
|
||||
runProcessInput.setStartAfterStep("setupStep");
|
||||
runProcessInput.addValue("foo", "bar");
|
||||
runProcessInput.addValue("alpha", "beta");
|
||||
UUIDAndTypeStateKey stateKey = new UUIDAndTypeStateKey(UUID.randomUUID(), StateType.PROCESS_STATUS);
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// simulate the state being previously stored //
|
||||
////////////////////////////////////////////////
|
||||
ProcessState oldProcessState = new ProcessState();
|
||||
oldProcessState.getValues().put("key", "myValue");
|
||||
oldProcessState.getValues().put("foo", "fubu");
|
||||
RunProcessAction.getStateProvider().put(stateKey, oldProcessState);
|
||||
|
||||
ProcessState primedProcessState = new RunProcessAction().primeProcessState(runProcessInput, stateKey);
|
||||
assertEquals("myValue", primedProcessState.getValues().get("key"));
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// make sure values that were in the original request trump values that had been in state. //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
assertEquals("bar", primedProcessState.getValues().get("foo"));
|
||||
assertEquals("beta", primedProcessState.getValues().get("alpha"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static class TestCallback implements QProcessCallback
|
||||
{
|
||||
private boolean wasCalledForQueryFilter = false;
|
||||
private boolean wasCalledForFieldValues = false;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Override
|
||||
public QQueryFilter getQueryFilter()
|
||||
{
|
||||
wasCalledForQueryFilter = true;
|
||||
return (new QQueryFilter());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Override
|
||||
public Map<String, Serializable> getFieldValues(List<QFieldMetaData> fields)
|
||||
{
|
||||
wasCalledForFieldValues = true;
|
||||
Map<String, Serializable> rs = new HashMap<>();
|
||||
if(fields.stream().anyMatch(f -> f.getName().equals("yearsToAdd")))
|
||||
{
|
||||
rs.put("yearsToAdd", 42);
|
||||
}
|
||||
return (rs);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.actions.processes.person.addtopeoplesage;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public class AddAge implements BackendStep
|
||||
{
|
||||
@Override
|
||||
public void run(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput)
|
||||
{
|
||||
int totalYearsAdded = 0;
|
||||
Integer yearsToAdd = runBackendStepInput.getValueInteger("yearsToAdd");
|
||||
for(QRecord record : runBackendStepInput.getRecords())
|
||||
{
|
||||
Integer age = record.getValueInteger("age");
|
||||
age += yearsToAdd;
|
||||
totalYearsAdded += yearsToAdd;
|
||||
record.setValue("age", age);
|
||||
}
|
||||
runBackendStepOutput.addValue("totalYearsAdded", totalYearsAdded);
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.actions.processes.person.addtopeoplesage;
|
||||
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.Period;
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public class GetAgeStatistics implements BackendStep
|
||||
{
|
||||
@Override
|
||||
public void run(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput)
|
||||
{
|
||||
Integer min = null;
|
||||
Integer max = null;
|
||||
LocalDate now = LocalDate.now();
|
||||
for(QRecord record : runBackendStepInput.getRecords())
|
||||
{
|
||||
LocalDate birthDate = record.getValueLocalDate("birthDate");
|
||||
Period until = birthDate.until(now);
|
||||
int age = until.getYears();
|
||||
record.setValue("age", age);
|
||||
System.out.println(birthDate + " -> " + age);
|
||||
min = (min == null || age < min) ? age : min;
|
||||
max = (max == null || age > max) ? age : max;
|
||||
}
|
||||
|
||||
runBackendStepOutput.addValue("minAge", min);
|
||||
runBackendStepOutput.addValue("maxAge", max);
|
||||
}
|
||||
}
|
@ -0,0 +1,213 @@
|
||||
/*
|
||||
* 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.actions.reporting;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for the ReportAction
|
||||
*******************************************************************************/
|
||||
class ReportActionTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testCSV() throws Exception
|
||||
{
|
||||
int recordCount = 1000;
|
||||
String filename = "/tmp/ReportActionTest.csv";
|
||||
|
||||
runReport(recordCount, filename, ReportFormat.CSV, false);
|
||||
|
||||
File file = new File(filename);
|
||||
List<String> fileLines = FileUtils.readLines(file, StandardCharsets.UTF_8.name());
|
||||
assertEquals(recordCount + 1, fileLines.size());
|
||||
assertTrue(file.delete());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** This test runs for more records, to stress more of the pipe-filling and
|
||||
** other bits of the ReportAction.
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testBigger() throws Exception
|
||||
{
|
||||
// int recordCount = 2_000_000; // to really stress locally, use this.
|
||||
int recordCount = 200_000;
|
||||
String filename = "/tmp/ReportActionTest.csv";
|
||||
|
||||
runReport(recordCount, filename, ReportFormat.CSV, false);
|
||||
|
||||
File file = new File(filename);
|
||||
List<String> fileLines = FileUtils.readLines(file, StandardCharsets.UTF_8.name());
|
||||
assertEquals(recordCount + 1, fileLines.size());
|
||||
assertTrue(file.delete());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testExcel() throws Exception
|
||||
{
|
||||
int recordCount = 1000;
|
||||
String filename = "/tmp/ReportActionTest.xlsx";
|
||||
|
||||
runReport(recordCount, filename, ReportFormat.XLSX, true);
|
||||
|
||||
File file = new File(filename);
|
||||
|
||||
assertTrue(file.delete());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private void runReport(int recordCount, String filename, ReportFormat reportFormat, boolean specifyFields) throws IOException, QException
|
||||
{
|
||||
try(FileOutputStream outputStream = new FileOutputStream(filename))
|
||||
{
|
||||
ReportInput reportInput = new ReportInput(TestUtils.defineInstance(), TestUtils.getMockSession());
|
||||
reportInput.setTableName("person");
|
||||
QTableMetaData table = reportInput.getTable();
|
||||
|
||||
reportInput.setReportFormat(reportFormat);
|
||||
reportInput.setReportOutputStream(outputStream);
|
||||
reportInput.setQueryFilter(new QQueryFilter());
|
||||
reportInput.setLimit(recordCount);
|
||||
|
||||
if(specifyFields)
|
||||
{
|
||||
reportInput.setFieldNames(table.getFields().values().stream().map(QFieldMetaData::getName).collect(Collectors.toList()));
|
||||
}
|
||||
ReportOutput reportOutput = new ReportAction().execute(reportInput);
|
||||
assertNotNull(reportOutput);
|
||||
assertEquals(recordCount, reportOutput.getRecordCount());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testBadFieldNames()
|
||||
{
|
||||
ReportInput reportInput = new ReportInput(TestUtils.defineInstance(), TestUtils.getMockSession());
|
||||
reportInput.setTableName("person");
|
||||
reportInput.setFieldNames(List.of("Foo", "Bar", "Baz"));
|
||||
assertThrows(QUserFacingException.class, () ->
|
||||
{
|
||||
new ReportAction().execute(reportInput);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testPreExecuteCount() throws QException
|
||||
{
|
||||
ReportInput reportInput = new ReportInput(TestUtils.defineInstance(), TestUtils.getMockSession());
|
||||
reportInput.setTableName("person");
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// use xlsx, which has a max-rows limit, to verify that code runs, but doesn't throw when there aren't too many rows //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
reportInput.setReportFormat(ReportFormat.XLSX);
|
||||
|
||||
new ReportAction().preExecute(reportInput);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// nothing to assert - but if preExecute throws, then the test will fail. //
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testTooManyColumns() throws QException
|
||||
{
|
||||
QTableMetaData wideTable = new QTableMetaData()
|
||||
.withName("wide")
|
||||
.withBackendName(TestUtils.DEFAULT_BACKEND_NAME);
|
||||
for(int i = 0; i < ReportFormat.XLSX.getMaxCols() + 1; i++)
|
||||
{
|
||||
wideTable.addField(new QFieldMetaData("field" + i, QFieldType.STRING));
|
||||
}
|
||||
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
qInstance.addTable(wideTable);
|
||||
|
||||
ReportInput reportInput = new ReportInput(qInstance, TestUtils.getMockSession());
|
||||
reportInput.setTableName("wide");
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// use xlsx, which has a max-cols limit, to verify that code. //
|
||||
////////////////////////////////////////////////////////////////
|
||||
reportInput.setReportFormat(ReportFormat.XLSX);
|
||||
|
||||
assertThrows(QUserFacingException.class, () ->
|
||||
{
|
||||
new ReportAction().preExecute(reportInput);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.actions.tables;
|
||||
|
||||
|
||||
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.count.CountOutput;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for CountAction
|
||||
**
|
||||
*******************************************************************************/
|
||||
class CountActionTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
** At the core level, there isn't much that can be asserted, as it uses the
|
||||
** mock implementation - just confirming that all of the "wiring" works.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test() throws QException
|
||||
{
|
||||
CountInput request = new CountInput(TestUtils.defineInstance());
|
||||
request.setSession(TestUtils.getMockSession());
|
||||
request.setTableName("person");
|
||||
CountOutput result = new CountAction().execute(request);
|
||||
assertNotNull(result);
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.actions.tables;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
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.query.QQueryFilter;
|
||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for DeleteAction
|
||||
**
|
||||
*******************************************************************************/
|
||||
class DeleteActionTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
** At the core level, there isn't much that can be asserted, as it uses the
|
||||
** mock implementation - just confirming that all of the "wiring" works.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test() throws QException
|
||||
{
|
||||
DeleteInput request = new DeleteInput(TestUtils.defineInstance());
|
||||
request.setSession(TestUtils.getMockSession());
|
||||
request.setTableName("person");
|
||||
request.setPrimaryKeys(List.of(1, 2));
|
||||
DeleteOutput result = new DeleteAction().execute(request);
|
||||
assertNotNull(result);
|
||||
assertEquals(2, result.getDeletedRecordCount());
|
||||
assertTrue(CollectionUtils.nullSafeIsEmpty(result.getRecordsWithErrors()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testErrorIfBothPrimaryKeysAndFilter()
|
||||
{
|
||||
DeleteInput request = new DeleteInput(TestUtils.defineInstance());
|
||||
request.setSession(TestUtils.getMockSession());
|
||||
request.setTableName("person");
|
||||
request.setPrimaryKeys(List.of(1, 2));
|
||||
request.setQueryFilter(new QQueryFilter());
|
||||
|
||||
assertThrows(QException.class, () ->
|
||||
{
|
||||
new DeleteAction().execute(request);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.actions.tables;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
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.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for InsertAction
|
||||
**
|
||||
*******************************************************************************/
|
||||
class InsertActionTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
** At the core level, there isn't much that can be asserted, as it uses the
|
||||
** mock implementation - just confirming that all of the "wiring" works.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test() throws QException
|
||||
{
|
||||
InsertInput request = new InsertInput(TestUtils.defineInstance());
|
||||
request.setSession(TestUtils.getMockSession());
|
||||
request.setTableName("person");
|
||||
List<QRecord> records =new ArrayList<>();
|
||||
QRecord record = new QRecord();
|
||||
record.setValue("firstName", "James");
|
||||
records.add(record);
|
||||
request.setRecords(records);
|
||||
InsertOutput result = new InsertAction().execute(request);
|
||||
assertNotNull(result);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.actions.tables;
|
||||
|
||||
|
||||
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;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for QueryAction
|
||||
**
|
||||
*******************************************************************************/
|
||||
class QueryActionTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
** At the core level, there isn't much that can be asserted, as it uses the
|
||||
** mock implementation - just confirming that all of the "wiring" works.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test() throws QException
|
||||
{
|
||||
QueryInput request = new QueryInput(TestUtils.defineInstance());
|
||||
request.setSession(TestUtils.getMockSession());
|
||||
request.setTableName("person");
|
||||
QueryOutput result = new QueryAction().execute(request);
|
||||
assertNotNull(result);
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.actions.tables;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
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.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for UpdateAction
|
||||
**
|
||||
*******************************************************************************/
|
||||
class UpdateActionTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
** At the core level, there isn't much that can be asserted, as it uses the
|
||||
** mock implementation - just confirming that all of the "wiring" works.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test() throws QException
|
||||
{
|
||||
UpdateInput request = new UpdateInput(TestUtils.defineInstance());
|
||||
request.setSession(TestUtils.getMockSession());
|
||||
request.setTableName("person");
|
||||
List<QRecord> records =new ArrayList<>();
|
||||
QRecord record = new QRecord();
|
||||
record.setValue("id", "47");
|
||||
record.setValue("firstName", "James");
|
||||
records.add(record);
|
||||
request.setRecords(records);
|
||||
UpdateOutput result = new UpdateAction().execute(request);
|
||||
assertNotNull(result);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,284 @@
|
||||
/*
|
||||
* 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.adapters;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.shared.mapping.QIndexBasedFieldMapping;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.shared.mapping.QKeyBasedFieldMapping;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for CsvToQRecordAdapter
|
||||
**
|
||||
*******************************************************************************/
|
||||
class CsvToQRecordAdapterTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_buildRecordsFromCsv_nullInput()
|
||||
{
|
||||
testExpectedToThrow(null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_buildRecordsFromCsv_emptyStringInput()
|
||||
{
|
||||
testExpectedToThrow("");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private void testExpectedToThrow(String csv)
|
||||
{
|
||||
try
|
||||
{
|
||||
CsvToQRecordAdapter csvToQRecordAdapter = new CsvToQRecordAdapter();
|
||||
List<QRecord> qRecords = csvToQRecordAdapter.buildRecordsFromCsv(csv, TestUtils.defineTablePerson(), null);
|
||||
System.out.println(qRecords);
|
||||
}
|
||||
catch(IllegalArgumentException iae)
|
||||
{
|
||||
System.out.println("Threw expected exception");
|
||||
return;
|
||||
}
|
||||
|
||||
fail("Didn't throw expected exception");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_buildRecordsFromCsv_emptyList()
|
||||
{
|
||||
CsvToQRecordAdapter csvToQRecordAdapter = new CsvToQRecordAdapter();
|
||||
List<QRecord> qRecords = csvToQRecordAdapter.buildRecordsFromCsv(getPersonCsvHeader(), TestUtils.defineTablePerson(), null);
|
||||
assertNotNull(qRecords);
|
||||
assertTrue(qRecords.isEmpty());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private String getPersonCsvHeader()
|
||||
{
|
||||
return ("""
|
||||
"id","createDate","modifyDate","firstName","lastName","birthDate","email"\r
|
||||
""");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private String getPersonCsvRow2()
|
||||
{
|
||||
return ("""
|
||||
"0","2021-10-26 14:39:37","2021-10-26 14:39:37","Jane","Doe","1981-01-01","john@doe.com"\r
|
||||
""");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private String getPersonCsvRow1()
|
||||
{
|
||||
return ("""
|
||||
"0","2021-10-26 14:39:37","2021-10-26 14:39:37","John","Doe","1980-01-01","john@doe.com"\r
|
||||
""");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_buildRecordsFromCsv_oneRowStandardHeaderNoMapping()
|
||||
{
|
||||
CsvToQRecordAdapter csvToQRecordAdapter = new CsvToQRecordAdapter();
|
||||
List<QRecord> qRecords = csvToQRecordAdapter.buildRecordsFromCsv(getPersonCsvHeader() + getPersonCsvRow1(), TestUtils.defineTablePerson(), null);
|
||||
assertNotNull(qRecords);
|
||||
assertEquals(1, qRecords.size());
|
||||
QRecord qRecord = qRecords.get(0);
|
||||
assertEquals("John", qRecord.getValue("firstName"));
|
||||
assertEquals("1980-01-01", qRecord.getValue("birthDate"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_buildRecordsFromCsv_twoRowsStandardHeaderNoMapping()
|
||||
{
|
||||
CsvToQRecordAdapter csvToQRecordAdapter = new CsvToQRecordAdapter();
|
||||
List<QRecord> qRecords = csvToQRecordAdapter.buildRecordsFromCsv(getPersonCsvHeader() + getPersonCsvRow1() + getPersonCsvRow2(), TestUtils.defineTablePerson(), null);
|
||||
assertNotNull(qRecords);
|
||||
assertEquals(2, qRecords.size());
|
||||
QRecord qRecord1 = qRecords.get(0);
|
||||
assertEquals("John", qRecord1.getValue("firstName"));
|
||||
assertEquals("1980-01-01", qRecord1.getValue("birthDate"));
|
||||
QRecord qRecord2 = qRecords.get(1);
|
||||
assertEquals("Jane", qRecord2.getValue("firstName"));
|
||||
assertEquals("1981-01-01", qRecord2.getValue("birthDate"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_buildRecordsFromCsv_oneRowCustomKeyBasedMapping()
|
||||
{
|
||||
String csvCustomHeader = """
|
||||
"id","created","modified","first","last","birthday","email"\r
|
||||
""";
|
||||
|
||||
QKeyBasedFieldMapping mapping = new QKeyBasedFieldMapping()
|
||||
.withMapping("id", "id")
|
||||
.withMapping("createDate", "created")
|
||||
.withMapping("modifyDate", "modified")
|
||||
.withMapping("firstName", "first")
|
||||
.withMapping("lastName", "last")
|
||||
.withMapping("birthDate", "birthday")
|
||||
.withMapping("email", "email");
|
||||
|
||||
CsvToQRecordAdapter csvToQRecordAdapter = new CsvToQRecordAdapter();
|
||||
List<QRecord> qRecords = csvToQRecordAdapter.buildRecordsFromCsv(csvCustomHeader + getPersonCsvRow1(), TestUtils.defineTablePerson(), mapping);
|
||||
assertNotNull(qRecords);
|
||||
assertEquals(1, qRecords.size());
|
||||
QRecord qRecord = qRecords.get(0);
|
||||
assertEquals("John", qRecord.getValue("firstName"));
|
||||
assertEquals("1980-01-01", qRecord.getValue("birthDate"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_buildRecordsFromCsv_twoRowsCustomIndexBasedMapping()
|
||||
{
|
||||
int index = 1;
|
||||
QIndexBasedFieldMapping mapping = new QIndexBasedFieldMapping()
|
||||
.withMapping("id", index++)
|
||||
.withMapping("createDate", index++)
|
||||
.withMapping("modifyDate", index++)
|
||||
.withMapping("firstName", index++)
|
||||
.withMapping("lastName", index++)
|
||||
.withMapping("birthDate", index++)
|
||||
.withMapping("email", index++);
|
||||
|
||||
CsvToQRecordAdapter csvToQRecordAdapter = new CsvToQRecordAdapter();
|
||||
List<QRecord> qRecords = csvToQRecordAdapter.buildRecordsFromCsv(getPersonCsvRow1() + getPersonCsvRow2(), TestUtils.defineTablePerson(), mapping);
|
||||
assertNotNull(qRecords);
|
||||
assertEquals(2, qRecords.size());
|
||||
QRecord qRecord1 = qRecords.get(0);
|
||||
assertEquals("John", qRecord1.getValue("firstName"));
|
||||
assertEquals("1980-01-01", qRecord1.getValue("birthDate"));
|
||||
QRecord qRecord2 = qRecords.get(1);
|
||||
assertEquals("Jane", qRecord2.getValue("firstName"));
|
||||
assertEquals("1981-01-01", qRecord2.getValue("birthDate"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** In this test - we've got CSV data with duplicated header names.
|
||||
** In our mapping, we're seeing the suffixes of " 2" and " 3" addd to those
|
||||
** header names on the RHS.
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_duplicatedColumnHeaders()
|
||||
{
|
||||
QKeyBasedFieldMapping mapping = new QKeyBasedFieldMapping()
|
||||
.withMapping("id", "id")
|
||||
.withMapping("createDate", "date")
|
||||
.withMapping("modifyDate", "date 2")
|
||||
.withMapping("firstName", "name")
|
||||
.withMapping("lastName", "name 2")
|
||||
.withMapping("birthDate", "date 3")
|
||||
.withMapping("email", "email");
|
||||
|
||||
CsvToQRecordAdapter csvToQRecordAdapter = new CsvToQRecordAdapter();
|
||||
List<QRecord> qRecords = csvToQRecordAdapter.buildRecordsFromCsv("""
|
||||
id,date,date,name,name,date,email
|
||||
1,2022-06-26,2022-06-26,John,Doe,1980-01-01,john@kingsrook.com
|
||||
""", TestUtils.defineTablePerson(), mapping);
|
||||
assertNotNull(qRecords);
|
||||
assertEquals(1, qRecords.size());
|
||||
QRecord qRecord1 = qRecords.get(0);
|
||||
assertEquals("John", qRecord1.getValue("firstName"));
|
||||
assertEquals("Doe", qRecord1.getValue("lastName"));
|
||||
assertEquals("1980-01-01", qRecord1.getValue("birthDate"));
|
||||
assertEquals("2022-06-26", qRecord1.getValue("createDate"));
|
||||
assertEquals("2022-06-26", qRecord1.getValue("modifyDate"));
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testMakeHeadersUnique()
|
||||
{
|
||||
CsvToQRecordAdapter csvToQRecordAdapter = new CsvToQRecordAdapter();
|
||||
Assertions.assertEquals(List.of("A", "B", "C"), csvToQRecordAdapter.makeHeadersUnique(List.of("A", "B", "C")));
|
||||
Assertions.assertEquals(List.of("A", "B", "C", "C 2", "C 3"), csvToQRecordAdapter.makeHeadersUnique(List.of("A", "B", "C", "C", "C")));
|
||||
Assertions.assertEquals(List.of("C", "A", "C 2", "B", "C 3"), csvToQRecordAdapter.makeHeadersUnique(List.of("C", "A", "C", "B", "C")));
|
||||
Assertions.assertEquals(List.of("A", "B", "C", "C 2", "C 3"), csvToQRecordAdapter.makeHeadersUnique(List.of("A", "B", "C", "C 2", "C")));
|
||||
Assertions.assertEquals(List.of("A", "B", "C", "C 2", "C 3"), csvToQRecordAdapter.makeHeadersUnique(List.of("A", "B", "C", "C 2", "C 3")));
|
||||
// todo - this is what the method header comment means when it says we don't handle all cases well...
|
||||
// Assertions.assertEquals(List.of("A", "B", "C", "C 2", "C 3"), csvToQRecordAdapter.makeHeadersUnique(List.of("A", "B", "C 2", "C", "C 3")));
|
||||
}
|
||||
}
|
@ -0,0 +1,209 @@
|
||||
/*
|
||||
* 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.adapters;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.model.actions.shared.mapping.AbstractQFieldMapping;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.shared.mapping.QIndexBasedFieldMapping;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.shared.mapping.QKeyBasedFieldMapping;
|
||||
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for JsonToQFieldMappingAdapter
|
||||
**
|
||||
*******************************************************************************/
|
||||
class JsonToQFieldMappingAdapterTest
|
||||
{
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_buildMappingFromJson_nullInput()
|
||||
{
|
||||
testExpectedToThrow(null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_buildMappingFromJson_emptyStringInput()
|
||||
{
|
||||
testExpectedToThrow("");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_buildMappingFromJson_malformedJsonInput()
|
||||
{
|
||||
testExpectedToThrow("{foo=bar}");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_buildMappingFromJson_validKeyBasedInput()
|
||||
{
|
||||
JsonToQFieldMappingAdapter jsonToQFieldMappingAdapter = new JsonToQFieldMappingAdapter();
|
||||
AbstractQFieldMapping<String> mapping = (QKeyBasedFieldMapping) jsonToQFieldMappingAdapter.buildMappingFromJson("""
|
||||
{
|
||||
"Field1": "source1",
|
||||
"Field2": "source2",
|
||||
}
|
||||
""");
|
||||
System.out.println(mapping);
|
||||
assertNotNull(mapping);
|
||||
|
||||
assertEquals("source1", mapping.getFieldSource("Field1"));
|
||||
assertEquals("source2", mapping.getFieldSource("Field2"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_buildMappingFromJson_validIndexBasedInput()
|
||||
{
|
||||
JsonToQFieldMappingAdapter jsonToQFieldMappingAdapter = new JsonToQFieldMappingAdapter();
|
||||
AbstractQFieldMapping<Integer> mapping = (QIndexBasedFieldMapping) jsonToQFieldMappingAdapter.buildMappingFromJson("""
|
||||
{
|
||||
"Field1": 1,
|
||||
"Field2": 2,
|
||||
}
|
||||
""");
|
||||
System.out.println(mapping);
|
||||
assertNotNull(mapping);
|
||||
|
||||
assertEquals(1, mapping.getFieldSource("Field1"));
|
||||
assertEquals(2, mapping.getFieldSource("Field2"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_buildMappingFromJson_unsupportedTypeForSource()
|
||||
{
|
||||
testExpectedToThrow("""
|
||||
{
|
||||
"Field1": [1, 2],
|
||||
"Field2": {"A": "B"}
|
||||
}
|
||||
""");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_deserializeSerializedQKeyBasedFieldMapping()
|
||||
{
|
||||
QIndexBasedFieldMapping original = new QIndexBasedFieldMapping()
|
||||
.withMapping("foo", 0)
|
||||
.withMapping("bar", 1);
|
||||
String json = JsonUtils.toJson(original);
|
||||
AbstractQFieldMapping<?> deserialized = new JsonToQFieldMappingAdapter().buildMappingFromJson(json);
|
||||
Assertions.assertThat(deserialized).usingRecursiveComparison().isEqualTo(original);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_deserializeSerializedQIndexBasedFieldMapping()
|
||||
{
|
||||
QKeyBasedFieldMapping original = new QKeyBasedFieldMapping()
|
||||
.withMapping("foo", "Fu")
|
||||
.withMapping("bar", "Bahr");
|
||||
String json = JsonUtils.toJson(original);
|
||||
AbstractQFieldMapping<?> deserialized = new JsonToQFieldMappingAdapter().buildMappingFromJson(json);
|
||||
Assertions.assertThat(deserialized).usingRecursiveComparison().isEqualTo(original);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_buildMappingFromJson_emptyMapping()
|
||||
{
|
||||
testExpectedToThrow("{}");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_buildMappingFromJson_inputJsonList()
|
||||
{
|
||||
testExpectedToThrow("[]");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private void testExpectedToThrow(String json)
|
||||
{
|
||||
try
|
||||
{
|
||||
JsonToQFieldMappingAdapter jsonToQFieldMappingAdapter = new JsonToQFieldMappingAdapter();
|
||||
AbstractQFieldMapping<?> mapping = jsonToQFieldMappingAdapter.buildMappingFromJson(json);
|
||||
System.out.println(mapping);
|
||||
}
|
||||
catch(IllegalArgumentException iae)
|
||||
{
|
||||
System.out.println("Threw expected exception");
|
||||
return;
|
||||
}
|
||||
|
||||
fail("Didn't throw expected exception");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* 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.adapters;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for JsonToQRecordAdapter
|
||||
**
|
||||
*******************************************************************************/
|
||||
class JsonToQRecordAdapterTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_buildRecordsFromJson_nullInput()
|
||||
{
|
||||
testExpectedToThrow(null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_buildRecordsFromJson_emptyStringInput()
|
||||
{
|
||||
testExpectedToThrow("");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_buildRecordsFromJson_inputDoesntLookLikeJson()
|
||||
{
|
||||
testExpectedToThrow("<HTML>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_buildRecordsFromJson_inputLooksLikeJsonButIsMalformed()
|
||||
{
|
||||
testExpectedToThrow("{json=not}");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private void testExpectedToThrow(String json)
|
||||
{
|
||||
try
|
||||
{
|
||||
JsonToQRecordAdapter jsonToQRecordAdapter = new JsonToQRecordAdapter();
|
||||
List<QRecord> qRecords = jsonToQRecordAdapter.buildRecordsFromJson(json, TestUtils.defineTablePerson(), null);
|
||||
System.out.println(qRecords);
|
||||
}
|
||||
catch(IllegalArgumentException iae)
|
||||
{
|
||||
System.out.println("Threw expected exception");
|
||||
return;
|
||||
}
|
||||
|
||||
fail("Didn't throw expected exception");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_buildRecordsFromJson_emptyList()
|
||||
{
|
||||
JsonToQRecordAdapter jsonToQRecordAdapter = new JsonToQRecordAdapter();
|
||||
List<QRecord> qRecords = jsonToQRecordAdapter.buildRecordsFromJson("[]", TestUtils.defineTablePerson(), null);
|
||||
assertNotNull(qRecords);
|
||||
assertTrue(qRecords.isEmpty());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_buildRecordsFromJson_inputObject()
|
||||
{
|
||||
JsonToQRecordAdapter jsonToQRecordAdapter = new JsonToQRecordAdapter();
|
||||
List<QRecord> qRecords = jsonToQRecordAdapter.buildRecordsFromJson("""
|
||||
{
|
||||
"firstName":"Joe",
|
||||
"lastName":"Dimagio"
|
||||
}
|
||||
""", TestUtils.defineTablePerson(), null);
|
||||
assertNotNull(qRecords);
|
||||
assertEquals(1, qRecords.size());
|
||||
assertEquals("Joe", qRecords.get(0).getValue("firstName"));
|
||||
assertEquals("Dimagio", qRecords.get(0).getValue("lastName"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_buildRecordsFromJson_inputList()
|
||||
{
|
||||
JsonToQRecordAdapter jsonToQRecordAdapter = new JsonToQRecordAdapter();
|
||||
List<QRecord> qRecords = jsonToQRecordAdapter.buildRecordsFromJson("""
|
||||
[
|
||||
{ "firstName":"Tyler", "lastName":"Samples" },
|
||||
{ "firstName":"Tim", "lastName":"Chamberlain" }
|
||||
]
|
||||
""", TestUtils.defineTablePerson(), null);
|
||||
assertNotNull(qRecords);
|
||||
assertEquals(2, qRecords.size());
|
||||
assertEquals("Tyler", qRecords.get(0).getValue("firstName"));
|
||||
assertEquals("Samples", qRecords.get(0).getValue("lastName"));
|
||||
assertEquals("Tim", qRecords.get(1).getValue("firstName"));
|
||||
assertEquals("Chamberlain", qRecords.get(1).getValue("lastName"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_buildRecordsFromJson_inputListWithNonObjectMembers()
|
||||
{
|
||||
testExpectedToThrow("[ 1701 ]");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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.adapters;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
class QInstanceAdapterTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void qInstanceToJson()
|
||||
{
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
String json = new QInstanceAdapter().qInstanceToJson(qInstance);
|
||||
System.out.println(json);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void qInstanceToJsonIncludingBackend()
|
||||
{
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
String json = new QInstanceAdapter().qInstanceToJsonIncludingBackend(qInstance);
|
||||
System.out.println(json);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
@Disabled("Pending custom deserializer on QStepMetaData")
|
||||
void jsonToQInstance() throws IOException
|
||||
{
|
||||
String json = FileUtils.readFileToString(new File("src/test/resources/personQInstance.json"));
|
||||
QInstance qInstance = new QInstanceAdapter().jsonToQInstance(json);
|
||||
System.out.println(qInstance);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
@Disabled("Pending custom deserializer on QStepMetaData")
|
||||
void jsonToQInstanceIncludingBackend() throws IOException
|
||||
{
|
||||
String json = FileUtils.readFileToString(new File("src/test/resources/personQInstanceIncludingBackend.json"));
|
||||
QInstance qInstance = new QInstanceAdapter().jsonToQInstanceIncludingBackends(json);
|
||||
System.out.println(qInstance);
|
||||
assertNotNull(qInstance.getBackends());
|
||||
assertTrue(qInstance.getBackends().size() > 0);
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.instances;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||
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.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for QInstanceEnricher
|
||||
**
|
||||
*******************************************************************************/
|
||||
class QInstanceEnricherTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
** Test that a table missing a label gets the default label applied (name w/ UC-first).
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_nullTableLabelComesFromName()
|
||||
{
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
QTableMetaData personTable = qInstance.getTable("person");
|
||||
personTable.setLabel(null);
|
||||
assertNull(personTable.getLabel());
|
||||
new QInstanceEnricher().enrich(qInstance);
|
||||
assertEquals("Person", personTable.getLabel());
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test that a table missing a label and a name doesn't NPE, but just keeps
|
||||
** the name & label both null.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_nullNameGivesNullLabel()
|
||||
{
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
QTableMetaData personTable = qInstance.getTable("person");
|
||||
personTable.setLabel(null);
|
||||
personTable.setName(null);
|
||||
assertNull(personTable.getLabel());
|
||||
assertNull(personTable.getName());
|
||||
new QInstanceEnricher().enrich(qInstance);
|
||||
assertNull(personTable.getLabel());
|
||||
assertNull(personTable.getName());
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test that a field missing a label gets the default label applied (name w/ UC-first)
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_nullFieldLabelComesFromName()
|
||||
{
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
QFieldMetaData idField = qInstance.getTable("person").getField("id");
|
||||
idField.setLabel(null);
|
||||
assertNull(idField.getLabel());
|
||||
new QInstanceEnricher().enrich(qInstance);
|
||||
assertEquals("Id", idField.getLabel());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,277 @@
|
||||
/*
|
||||
* 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.instances;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QInstanceValidationException;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for QInstanceValidator.
|
||||
**
|
||||
*******************************************************************************/
|
||||
class QInstanceValidatorTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
** Test a valid instance - should just pass
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_validatePass() throws QInstanceValidationException
|
||||
{
|
||||
new QInstanceValidator().validate(TestUtils.defineInstance());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test an instance with null backends - should throw.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_validateNullBackends()
|
||||
{
|
||||
try
|
||||
{
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
qInstance.setBackends(null);
|
||||
new QInstanceValidator().validate(qInstance);
|
||||
fail("Should have thrown validationException");
|
||||
}
|
||||
catch(QInstanceValidationException e)
|
||||
{
|
||||
assertReason("At least 1 backend must be defined", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test an instance with empty map of backends - should throw.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_validateEmptyBackends()
|
||||
{
|
||||
try
|
||||
{
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
qInstance.setBackends(new HashMap<>());
|
||||
new QInstanceValidator().validate(qInstance);
|
||||
fail("Should have thrown validationException");
|
||||
}
|
||||
catch(QInstanceValidationException e)
|
||||
{
|
||||
assertReason("At least 1 backend must be defined", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test an instance with null tables - should throw.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_validateNullTables()
|
||||
{
|
||||
try
|
||||
{
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
qInstance.setTables(null);
|
||||
new QInstanceValidator().validate(qInstance);
|
||||
fail("Should have thrown validationException");
|
||||
}
|
||||
catch(QInstanceValidationException e)
|
||||
{
|
||||
assertReason("At least 1 table must be defined", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test an instance with empty map of tables - should throw.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_validateEmptyTables()
|
||||
{
|
||||
try
|
||||
{
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
qInstance.setTables(new HashMap<>());
|
||||
new QInstanceValidator().validate(qInstance);
|
||||
fail("Should have thrown validationException");
|
||||
}
|
||||
catch(QInstanceValidationException e)
|
||||
{
|
||||
assertReason("At least 1 table must be defined", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test an instance where a table and a backend each have a name attribute that
|
||||
** doesn't match the key that those objects have in the instance's maps - should throw.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_validateInconsistentNames()
|
||||
{
|
||||
try
|
||||
{
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
qInstance.getTable("person").setName("notPerson");
|
||||
qInstance.getBackend("default").setName("notDefault");
|
||||
new QInstanceValidator().validate(qInstance);
|
||||
fail("Should have thrown validationException");
|
||||
}
|
||||
catch(QInstanceValidationException e)
|
||||
{
|
||||
assertReason("Inconsistent naming for table", e);
|
||||
assertReason("Inconsistent naming for backend", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test that if a table has a null backend, that it fails.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_validateTableWithoutBackend()
|
||||
{
|
||||
try
|
||||
{
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
qInstance.getTable("person").setBackendName(null);
|
||||
new QInstanceValidator().validate(qInstance);
|
||||
fail("Should have thrown validationException");
|
||||
}
|
||||
catch(QInstanceValidationException e)
|
||||
{
|
||||
assertReason("Missing backend name for table", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test that if a table specifies a backend that doesn't exist, that it fails.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_validateTableWithMissingBackend()
|
||||
{
|
||||
try
|
||||
{
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
qInstance.getTable("person").setBackendName("notARealBackend");
|
||||
new QInstanceValidator().validate(qInstance);
|
||||
fail("Should have thrown validationException");
|
||||
}
|
||||
catch(QInstanceValidationException e)
|
||||
{
|
||||
assertReason("Unrecognized backend", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test that a table with no fields fails.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_validateTableWithNoFields()
|
||||
{
|
||||
try
|
||||
{
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
qInstance.getTable("person").setFields(null);
|
||||
new QInstanceValidator().validate(qInstance);
|
||||
fail("Should have thrown validationException");
|
||||
}
|
||||
catch(QInstanceValidationException e)
|
||||
{
|
||||
assertReason("At least 1 field", e);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
qInstance.getTable("person").setFields(new HashMap<>());
|
||||
new QInstanceValidator().validate(qInstance);
|
||||
fail("Should have thrown validationException");
|
||||
}
|
||||
catch(QInstanceValidationException e)
|
||||
{
|
||||
assertReason("At least 1 field", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test that if a field specifies a backend that doesn't exist, that it fails.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_validateFieldWithMissingPossibleValueSource()
|
||||
{
|
||||
try
|
||||
{
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
qInstance.getTable("person").getField("homeState").setPossibleValueSourceName("not a real possible value source");
|
||||
new QInstanceValidator().validate(qInstance);
|
||||
fail("Should have thrown validationException");
|
||||
}
|
||||
catch(QInstanceValidationException e)
|
||||
{
|
||||
assertReason("Unrecognized possibleValueSourceName", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** utility method for asserting that a specific reason string is found within
|
||||
** the list of reasons in the QInstanceValidationException.
|
||||
**
|
||||
*******************************************************************************/
|
||||
private void assertReason(String reason, QInstanceValidationException e)
|
||||
{
|
||||
assertNotNull(e.getReasons());
|
||||
assertTrue(e.getReasons().stream().anyMatch(s -> s.contains(reason)));
|
||||
}
|
||||
}
|
@ -0,0 +1,281 @@
|
||||
/*
|
||||
* 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.instances;
|
||||
|
||||
|
||||
import java.util.Map;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for QSecretReader
|
||||
*******************************************************************************/
|
||||
class QMetaDataVariableInterpreterTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@BeforeEach
|
||||
public void beforeEach()
|
||||
{
|
||||
System.setProperty("username", "joe");
|
||||
System.setProperty("password", "b1d3n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@AfterEach
|
||||
public void afterEach()
|
||||
{
|
||||
System.clearProperty("username");
|
||||
System.clearProperty("password");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testInterpretObject() throws QException
|
||||
{
|
||||
GoodTestClass goodTestClass = new GoodTestClass();
|
||||
goodTestClass.setUsername("${prop.username}");
|
||||
goodTestClass.setPassword("${prop.password}");
|
||||
|
||||
new QMetaDataVariableInterpreter().interpretObject(goodTestClass);
|
||||
|
||||
assertEquals("joe", goodTestClass.getUsername());
|
||||
assertEquals("b1d3n", goodTestClass.getPassword());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testBadAnnotatedObjects()
|
||||
{
|
||||
assertThrows(QException.class, () -> new QMetaDataVariableInterpreter().interpretObject(new BadTestClassAnnotatedInteger()));
|
||||
assertThrows(QException.class, () -> new QMetaDataVariableInterpreter().interpretObject(new BadTestClassNoGetter()));
|
||||
assertThrows(QException.class, () -> new QMetaDataVariableInterpreter().interpretObject(new BadTestClassNoSetter()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testInterpretFromEnvironment()
|
||||
{
|
||||
QMetaDataVariableInterpreter secretReader = new QMetaDataVariableInterpreter();
|
||||
String key = "CUSTOM_PROPERTY";
|
||||
String value = "ABCD-9876";
|
||||
secretReader.setCustomEnvironment(Map.of(key, value));
|
||||
|
||||
assertNull(secretReader.interpret(null));
|
||||
assertEquals("foo", secretReader.interpret("foo"));
|
||||
assertNull(secretReader.interpret("${env.NOT-" + key + "}"));
|
||||
assertEquals(value, secretReader.interpret("${env." + key + "}"));
|
||||
assertEquals("${env.NOT-" + key, secretReader.interpret("${env.NOT-" + key));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testInterpretFromProperties()
|
||||
{
|
||||
QMetaDataVariableInterpreter secretReader = new QMetaDataVariableInterpreter();
|
||||
String key = "MY_PROPERTY";
|
||||
String value = "WXYZ-6789";
|
||||
System.setProperty(key, value);
|
||||
|
||||
assertNull(secretReader.interpret(null));
|
||||
assertEquals("foo", secretReader.interpret("foo"));
|
||||
assertNull(secretReader.interpret("${prop.NOT-" + key + "}"));
|
||||
assertEquals(value, secretReader.interpret("${prop." + key + "}"));
|
||||
assertEquals("${prop.NOT-" + key, secretReader.interpret("${prop.NOT-" + key));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testInterpretLiterals()
|
||||
{
|
||||
QMetaDataVariableInterpreter secretReader = new QMetaDataVariableInterpreter();
|
||||
assertEquals("${env.X}", secretReader.interpret("${literal.${env.X}}"));
|
||||
assertEquals("${prop.X}", secretReader.interpret("${literal.${prop.X}}"));
|
||||
assertEquals("${literal.X}", secretReader.interpret("${literal.${literal.X}}"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@InterpretableFields(fieldNames = { "username", "password" })
|
||||
public static class GoodTestClass
|
||||
{
|
||||
private String username;
|
||||
private String password;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for username
|
||||
**
|
||||
*******************************************************************************/
|
||||
public String getUsername()
|
||||
{
|
||||
return username;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for username
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setUsername(String username)
|
||||
{
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for password
|
||||
**
|
||||
*******************************************************************************/
|
||||
public String getPassword()
|
||||
{
|
||||
return password;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for password
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setPassword(String password)
|
||||
{
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@InterpretableFields(fieldNames = { "port" })
|
||||
public static class BadTestClassAnnotatedInteger
|
||||
{
|
||||
private Integer port;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for port
|
||||
**
|
||||
*******************************************************************************/
|
||||
public Integer getPort()
|
||||
{
|
||||
return port;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for port
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setPort(Integer port)
|
||||
{
|
||||
this.port = port;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@InterpretableFields(fieldNames = { "foo" })
|
||||
public static class BadTestClassNoGetter
|
||||
{
|
||||
private String foo;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for foo
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setFoo(String foo)
|
||||
{
|
||||
this.foo = foo;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@InterpretableFields(fieldNames = { "foo" })
|
||||
public static class BadTestClassNoSetter
|
||||
{
|
||||
private String foo;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for foo
|
||||
**
|
||||
*******************************************************************************/
|
||||
public String getFoo()
|
||||
{
|
||||
return foo;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* 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.model.data;
|
||||
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.data.testentities.Item;
|
||||
import com.kingsrook.qqq.backend.core.model.data.testentities.ItemWithPrimitives;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
class QRecordEntityTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testItemToQRecord() throws QException
|
||||
{
|
||||
Item item = new Item();
|
||||
item.setSku("ABC-123");
|
||||
item.setDescription("My Item");
|
||||
item.setQuantity(47);
|
||||
item.setPrice(new BigDecimal("3.50"));
|
||||
item.setFeatured(true);
|
||||
|
||||
QRecord qRecord = item.toQRecord();
|
||||
assertEquals("ABC-123", qRecord.getValueString("sku"));
|
||||
assertEquals("My Item", qRecord.getValueString("description"));
|
||||
assertEquals(47, qRecord.getValueInteger("quantity"));
|
||||
assertEquals(new BigDecimal("3.50"), qRecord.getValueBigDecimal("price"));
|
||||
assertTrue(qRecord.getValueBoolean("featured"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testQRecordToItem() throws QException
|
||||
{
|
||||
QRecord qRecord = new QRecord()
|
||||
.withValue("sku", "WXYZ-9876")
|
||||
.withValue("description", "Items are cool")
|
||||
.withValue("quantity", 42)
|
||||
.withValue("price", new BigDecimal("3.50"))
|
||||
.withValue("featured", false);
|
||||
|
||||
Item item = qRecord.toEntity(Item.class);
|
||||
assertEquals("WXYZ-9876", item.getSku());
|
||||
assertEquals("Items are cool", item.getDescription());
|
||||
assertEquals(42, item.getQuantity());
|
||||
assertEquals(new BigDecimal("3.50"), item.getPrice());
|
||||
assertFalse(item.getFeatured());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testItemWithPrimitivesToQRecord() throws QException
|
||||
{
|
||||
ItemWithPrimitives item = new ItemWithPrimitives();
|
||||
item.setSku("ABC-123");
|
||||
item.setDescription(null);
|
||||
item.setQuantity(47);
|
||||
item.setPrice(new BigDecimal("3.50"));
|
||||
item.setFeatured(true);
|
||||
|
||||
QRecord qRecord = item.toQRecord();
|
||||
assertEquals("ABC-123", qRecord.getValueString("sku"));
|
||||
assertNull(qRecord.getValueString("description"));
|
||||
assertEquals(47, qRecord.getValueInteger("quantity"));
|
||||
assertEquals(new BigDecimal("3.50"), qRecord.getValueBigDecimal("price"));
|
||||
assertTrue(qRecord.getValueBoolean("featured"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testQRecordToItemWithPrimitives() throws QException
|
||||
{
|
||||
QRecord qRecord = new QRecord()
|
||||
.withValue("sku", "WXYZ-9876")
|
||||
.withValue("description", null)
|
||||
.withValue("quantity", 42)
|
||||
.withValue("price", new BigDecimal("3.50"))
|
||||
.withValue("featured", false);
|
||||
|
||||
ItemWithPrimitives item = qRecord.toEntity(ItemWithPrimitives.class);
|
||||
assertEquals("WXYZ-9876", item.getSku());
|
||||
assertNull(item.getDescription());
|
||||
assertEquals(42, item.getQuantity());
|
||||
assertEquals(new BigDecimal("3.50"), item.getPrice());
|
||||
assertFalse(item.getFeatured());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testQRecordWithAllStringValuesToItem() throws QException
|
||||
{
|
||||
QRecord qRecord = new QRecord()
|
||||
.withValue("sku", "WXYZ-9876")
|
||||
.withValue("description", "Items are cool")
|
||||
.withValue("quantity", "42")
|
||||
.withValue("price", "3.50")
|
||||
.withValue("featured", "false");
|
||||
|
||||
Item item = qRecord.toEntity(Item.class);
|
||||
assertEquals("WXYZ-9876", item.getSku());
|
||||
assertEquals("Items are cool", item.getDescription());
|
||||
assertEquals(42, item.getQuantity());
|
||||
assertEquals(new BigDecimal("3.50"), item.getPrice());
|
||||
assertFalse(item.getFeatured());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||
@Test
|
||||
void testQTableConstructionFromEntity() throws QException
|
||||
{
|
||||
QTableMetaData qTableMetaData = new QTableMetaData()
|
||||
.withField(new QFieldMetaData(Item::getSku))
|
||||
.withField(new QFieldMetaData(Item::getDescription))
|
||||
.withField(new QFieldMetaData(Item::getQuantity));
|
||||
|
||||
assertEquals(QFieldType.STRING, qTableMetaData.getField("sku").getType());
|
||||
assertEquals(QFieldType.INTEGER, qTableMetaData.getField("quantity").getType());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||
@Test
|
||||
void testQTableConstructionWithPrimitives() throws QException
|
||||
{
|
||||
QTableMetaData qTableMetaData = new QTableMetaData()
|
||||
.withField(new QFieldMetaData(ItemWithPrimitives::getSku))
|
||||
.withField(new QFieldMetaData(ItemWithPrimitives::getDescription))
|
||||
.withField(new QFieldMetaData(ItemWithPrimitives::getQuantity));
|
||||
|
||||
assertEquals(QFieldType.STRING, qTableMetaData.getField("sku").getType());
|
||||
assertEquals(QFieldType.INTEGER, qTableMetaData.getField("quantity").getType());
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 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.model.data.testentities;
|
||||
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecordEntity;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Sample of an entity that can be converted to & from a QRecord
|
||||
*******************************************************************************/
|
||||
public class Item extends QRecordEntity
|
||||
{
|
||||
private String sku;
|
||||
private String description;
|
||||
private Integer quantity;
|
||||
private BigDecimal price;
|
||||
private Boolean featured;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for sku
|
||||
**
|
||||
*******************************************************************************/
|
||||
public String getSku()
|
||||
{
|
||||
return sku;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for sku
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setSku(String sku)
|
||||
{
|
||||
this.sku = sku;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for description
|
||||
**
|
||||
*******************************************************************************/
|
||||
public String getDescription()
|
||||
{
|
||||
return description;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for description
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setDescription(String description)
|
||||
{
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for quantity
|
||||
**
|
||||
*******************************************************************************/
|
||||
public Integer getQuantity()
|
||||
{
|
||||
return quantity;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for quantity
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setQuantity(Integer quantity)
|
||||
{
|
||||
this.quantity = quantity;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for price
|
||||
**
|
||||
*******************************************************************************/
|
||||
public BigDecimal getPrice()
|
||||
{
|
||||
return price;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for price
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setPrice(BigDecimal price)
|
||||
{
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for featured
|
||||
**
|
||||
*******************************************************************************/
|
||||
public Boolean getFeatured()
|
||||
{
|
||||
return featured;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for featured
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setFeatured(Boolean featured)
|
||||
{
|
||||
this.featured = featured;
|
||||
}
|
||||
}
|
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 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.model.data.testentities;
|
||||
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecordEntity;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Sample of an entity that can be converted to & from a QRecord
|
||||
*******************************************************************************/
|
||||
public class ItemWithPrimitives extends QRecordEntity
|
||||
{
|
||||
private String sku;
|
||||
private String description;
|
||||
private int quantity;
|
||||
private BigDecimal price;
|
||||
private boolean featured;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for sku
|
||||
**
|
||||
*******************************************************************************/
|
||||
public String getSku()
|
||||
{
|
||||
return sku;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for sku
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setSku(String sku)
|
||||
{
|
||||
this.sku = sku;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for description
|
||||
**
|
||||
*******************************************************************************/
|
||||
public String getDescription()
|
||||
{
|
||||
return description;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for description
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setDescription(String description)
|
||||
{
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for quantity
|
||||
**
|
||||
*******************************************************************************/
|
||||
public int getQuantity()
|
||||
{
|
||||
return quantity;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for quantity
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setQuantity(int quantity)
|
||||
{
|
||||
this.quantity = quantity;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for price
|
||||
**
|
||||
*******************************************************************************/
|
||||
public BigDecimal getPrice()
|
||||
{
|
||||
return price;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for price
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setPrice(BigDecimal price)
|
||||
{
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for featured
|
||||
**
|
||||
*******************************************************************************/
|
||||
public boolean getFeatured()
|
||||
{
|
||||
return featured;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for featured
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setFeatured(boolean featured)
|
||||
{
|
||||
this.featured = featured;
|
||||
}
|
||||
}
|
@ -0,0 +1,223 @@
|
||||
/*
|
||||
* 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.authentication;
|
||||
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QAuthenticationException;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||
import com.kingsrook.qqq.backend.core.modules.authentication.metadata.Auth0AuthenticationMetaData;
|
||||
import com.kingsrook.qqq.backend.core.modules.authentication.metadata.QAuthenticationMetaData;
|
||||
import com.kingsrook.qqq.backend.core.state.InMemoryStateProvider;
|
||||
import com.kingsrook.qqq.backend.core.state.StateProviderInterface;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static com.kingsrook.qqq.backend.core.modules.authentication.Auth0AuthenticationModule.AUTH0_ID_TOKEN_KEY;
|
||||
import static com.kingsrook.qqq.backend.core.modules.authentication.Auth0AuthenticationModule.COULD_NOT_DECODE_ERROR;
|
||||
import static com.kingsrook.qqq.backend.core.modules.authentication.Auth0AuthenticationModule.EXPIRED_TOKEN_ERROR;
|
||||
import static com.kingsrook.qqq.backend.core.modules.authentication.Auth0AuthenticationModule.INVALID_TOKEN_ERROR;
|
||||
import static com.kingsrook.qqq.backend.core.modules.authentication.Auth0AuthenticationModule.TOKEN_NOT_PROVIDED_ERROR;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for the FullyAnonymousAuthenticationModule
|
||||
*******************************************************************************/
|
||||
public class Auth0AuthenticationModuleTest
|
||||
{
|
||||
private static final String VALID_TOKEN = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IllrY2FkWTA0Q3RFVUFxQUdLNTk3ayJ9.eyJnaXZlbl9uYW1lIjoiVGltIiwiZmFtaWx5X25hbWUiOiJDaGFtYmVybGFpbiIsIm5pY2tuYW1lIjoidGltLmNoYW1iZXJsYWluIiwibmFtZSI6IlRpbSBDaGFtYmVybGFpbiIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS0vQUZkWnVjcXVSaUFvTzk1RG9URklnbUtseVA1akVBVnZmWXFnS0lHTkVubzE9czk2LWMiLCJsb2NhbGUiOiJlbiIsInVwZGF0ZWRfYXQiOiIyMDIyLTA3LTE5VDE2OjI0OjQ1LjgyMloiLCJlbWFpbCI6InRpbS5jaGFtYmVybGFpbkBraW5nc3Jvb2suY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlzcyI6Imh0dHBzOi8va2luZ3Nyb29rLnVzLmF1dGgwLmNvbS8iLCJzdWIiOiJnb29nbGUtb2F1dGgyfDEwODk2NDEyNjE3MjY1NzAzNDg2NyIsImF1ZCI6InNwQ1NtczAzcHpVZGRYN1BocHN4ZDlUd2FLMDlZZmNxIiwiaWF0IjoxNjU4MjQ3OTAyLCJleHAiOjE2NTgyODM5MDIsIm5vbmNlIjoiZUhOdFMxbEtUR2N5ZG5KS1VVY3RkRTFVT0ZKNmJFNUxVVkEwZEdsRGVXOXZkVkl4UW41eVRrUlJlZz09In0.hib7JR8NDU2kx8Fj1bnzo3IUuabE6Hb-Z7HHZAJPQuF_Zdg3L1KDypn6SY7HAd_dsz2N8RkXfvQto-Y2g2ukuz7FxzNFgcVL99cyEO3YqmyCa6JTOTCrxdeaIE8QZpCEKvC28oeJBv0wO1Dwc--OVJMsK2vSzyxj1WNok64YYjWKLL4c0dFf-nj0KWFr1IU-tMiyWLDDiJw2Sa8M4YxXZYqdlkgNmrBPExgcm9l9SiT2l3Ts3Sgc_IyMVyMrnV8XX50EWdsm6vuCOSUcqf0XhjDQ7urZveoVwVLnYq3GcLhVBcy1Hr9RL8zPdPynOzsbX6uCww2Esrv6iwWrgQ5zBA";
|
||||
private static final String INVALID_TOKEN = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IllrY2FkWTA0Q3RFVUFxQUdLNTk3ayJ9.eyJnaXZlbl9uYW1lIjoiVGltIiwiZmFtaWx5X25hbWUiOiJDaGFtYmVybGFpbiIsIm5pY2tuYW1lIjoidGltLmNoYW1iZXJsYWluIiwibmFtZSI6IlRpbSBDaGFtYmVybGFpbiIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS0vQUZkWnVjcXVSaUFvTzk1RG9URklnbUtseVA1akVBVnZmWXFnS0lHTkVubzE9czk2LWMiLCJsb2NhbGUiOiJlbiIsInVwZGF0ZWRfYXQiOiIyMDIyLTA3LTE5VDE2OjI0OjQ1LjgyMloiLCJlbWFpbCI6InRpbS5jaGFtYmVybGFpbkBraW5nc3Jvb2suY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlzcyI6Imh0dHBzOi8va2luZ3Nyb29rLnVzLmF1dGgwLmNvbS8iLCJzdWIiOiJnb29nbGUtb2F1dGgyfDEwODk2NDEyNjE3MjY1NzAzNDg2NyIsImF1ZCI6InNwQ1NtczAzcHpVZGRYN1BocHN4ZDlUd2FLMDlZZmNxIiwiaWF0IjoxNjU4MjQ3OTAyLCJleHAiOjE2NTgyODM5MDIsIm5vbmNlIjoiZUhOdFMxbEtUR2N5ZG5KS1VVY3RkRTFVT0ZKNmJFNUxVVkEwZEdsRGVXOXZkVkl4UW41eVRrUlJlZz09In0.hib7JR8NDU2kx8Fj1bnzo3IUuabE6Hb-Z7HHZAJPQuF_Zdg3L1KDypn6SY7HAd_dsz2N8RkXfvQto-Y2g2ukuz7FxzNFgcVL99cyEO3YqmyCa6JTOTCrxdeaIE8QZpCEKvC28oeJBv0wO1Dwc--OVJMsK2vSzyxj1WNok64YYjWKLL4c0dFf-nj0KWFr1IU-tMiyWLDDiJw2Sa8M4YxXZYqdlkgNmrBPExgcm9l9SiT2l3Ts3Sgc_IyMVyMrnV8XX50EWdsm6vuCOSUcqf0XhjDQ7urZveoVwVLnYq3GcLhVBcy1Hr9RL8zPdPynOzsbX6uCww2Esrv6iwWrgQ5zBA-thismakesinvalid";
|
||||
private static final String EXPIRED_TOKEN = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IllrY2FkWTA0Q3RFVUFxQUdLNTk3ayJ9.eyJnaXZlbl9uYW1lIjoiVGltIiwiZmFtaWx5X25hbWUiOiJDaGFtYmVybGFpbiIsIm5pY2tuYW1lIjoidGltLmNoYW1iZXJsYWluIiwibmFtZSI6IlRpbSBDaGFtYmVybGFpbiIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS0vQUZkWnVjcXVSaUFvTzk1RG9URklnbUtseVA1akVBVnZmWXFnS0lHTkVubzE9czk2LWMiLCJsb2NhbGUiOiJlbiIsInVwZGF0ZWRfYXQiOiIyMDIyLTA3LTE4VDIxOjM4OjE1LjM4NloiLCJlbWFpbCI6InRpbS5jaGFtYmVybGFpbkBraW5nc3Jvb2suY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlzcyI6Imh0dHBzOi8va2luZ3Nyb29rLnVzLmF1dGgwLmNvbS8iLCJzdWIiOiJnb29nbGUtb2F1dGgyfDEwODk2NDEyNjE3MjY1NzAzNDg2NyIsImF1ZCI6InNwQ1NtczAzcHpVZGRYN1BocHN4ZDlUd2FLMDlZZmNxIiwiaWF0IjoxNjU4MTgwNDc3LCJleHAiOjE2NTgyMTY0NzcsIm5vbmNlIjoiVkZkQlYzWmplR2hvY1cwMk9WZEtabHBLU0c1K1ZXbElhMEV3VkZaeFpVdEJVMDErZUZaT1RtMTNiZz09In0.fU7EwUgNrupOPz_PX_aQKON2xG1-LWD85xVo1Bn41WNEek-iMyJoch8l6NUihi7Bou14BoOfeWIG_sMqsLHqI2Pk7el7l1kigsjURx0wpiXadBt8piMxdIlxdToZEMuZCBzg7eJvXh4sM8tlV5cm0gPa6FT9Ih3VGJajNlXi5BcYS_JRpIvFvHn8-Bxj4KiAlZ5XPPkopjnDgP8kFfc4cMn_nxDkqWYlhj-5TaGW2xCLC9Qr_9UNxX0fm-CkKjYs3Z5ezbiXNkc-bxrCYvxeBeDPf8-T3EqrxCRVqCZSJ85BHdOc_E7UZC_g8bNj0umoplGwlCbzO4XIuOO-KlIaOg";
|
||||
private static final String UNDECODABLE_TOKEN = "UNDECODABLE";
|
||||
|
||||
public static final String AUTH0_BASE_URL = "https://kingsrook.us.auth0.com/";
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test a valid token where 'now' is set to a time that would be valid for it
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testLastTimeChecked() throws QAuthenticationException
|
||||
{
|
||||
//////////////////////////////////////////////////////////
|
||||
// Tuesday, July 19, 2022 12:40:27.299 PM GMT-05:00 DST //
|
||||
//////////////////////////////////////////////////////////
|
||||
Instant now = Instant.now();
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// put the 'now' from the past into the state provider //
|
||||
/////////////////////////////////////////////////////////
|
||||
StateProviderInterface spi = InMemoryStateProvider.getInstance();
|
||||
Auth0AuthenticationModule.Auth0StateKey key = new Auth0AuthenticationModule.Auth0StateKey(VALID_TOKEN);
|
||||
spi.put(key, now);
|
||||
|
||||
//////////////////////
|
||||
// build up session //
|
||||
//////////////////////
|
||||
QSession session = new QSession();
|
||||
session.setIdReference(VALID_TOKEN);
|
||||
|
||||
Auth0AuthenticationModule auth0AuthenticationModule = new Auth0AuthenticationModule();
|
||||
assertEquals(true, auth0AuthenticationModule.isSessionValid(session), "Session should return as still valid.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test failure case, token is invalid
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testInvalidToken()
|
||||
{
|
||||
Map<String, String> context = new HashMap<>();
|
||||
context.put(AUTH0_ID_TOKEN_KEY, INVALID_TOKEN);
|
||||
|
||||
try
|
||||
{
|
||||
Auth0AuthenticationModule auth0AuthenticationModule = new Auth0AuthenticationModule();
|
||||
auth0AuthenticationModule.createSession(getQInstance(), context);
|
||||
fail("Should never get here");
|
||||
}
|
||||
catch(QAuthenticationException qae)
|
||||
{
|
||||
assertThat(qae.getMessage()).contains(INVALID_TOKEN_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test failure case, token cant be decoded
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testUndecodableToken()
|
||||
{
|
||||
Map<String, String> context = new HashMap<>();
|
||||
context.put(AUTH0_ID_TOKEN_KEY, UNDECODABLE_TOKEN);
|
||||
|
||||
try
|
||||
{
|
||||
Auth0AuthenticationModule auth0AuthenticationModule = new Auth0AuthenticationModule();
|
||||
auth0AuthenticationModule.createSession(getQInstance(), context);
|
||||
fail("Should never get here");
|
||||
}
|
||||
catch(QAuthenticationException qae)
|
||||
{
|
||||
assertThat(qae.getMessage()).contains(COULD_NOT_DECODE_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test failure case, token is expired
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testProperlyFormattedButExpiredToken()
|
||||
{
|
||||
Map<String, String> context = new HashMap<>();
|
||||
context.put(AUTH0_ID_TOKEN_KEY, EXPIRED_TOKEN);
|
||||
|
||||
try
|
||||
{
|
||||
Auth0AuthenticationModule auth0AuthenticationModule = new Auth0AuthenticationModule();
|
||||
auth0AuthenticationModule.createSession(getQInstance(), context);
|
||||
fail("Should never get here");
|
||||
}
|
||||
catch(QAuthenticationException qae)
|
||||
{
|
||||
assertThat(qae.getMessage()).contains(EXPIRED_TOKEN_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test failure case, empty context
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testEmptyContext()
|
||||
{
|
||||
try
|
||||
{
|
||||
Auth0AuthenticationModule auth0AuthenticationModule = new Auth0AuthenticationModule();
|
||||
auth0AuthenticationModule.createSession(getQInstance(), new HashMap<>());
|
||||
fail("Should never get here");
|
||||
}
|
||||
catch(QAuthenticationException qae)
|
||||
{
|
||||
assertThat(qae.getMessage()).contains(TOKEN_NOT_PROVIDED_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test failure case, null token
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testNullToken()
|
||||
{
|
||||
Map<String, String> context = new HashMap<>();
|
||||
context.put(AUTH0_ID_TOKEN_KEY, null);
|
||||
|
||||
try
|
||||
{
|
||||
Auth0AuthenticationModule auth0AuthenticationModule = new Auth0AuthenticationModule();
|
||||
auth0AuthenticationModule.createSession(getQInstance(), context);
|
||||
fail("Should never get here");
|
||||
}
|
||||
catch(QAuthenticationException qae)
|
||||
{
|
||||
assertThat(qae.getMessage()).contains(TOKEN_NOT_PROVIDED_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** utility method to prime a qInstance for auth0 tests
|
||||
**
|
||||
*******************************************************************************/
|
||||
private QInstance getQInstance()
|
||||
{
|
||||
QAuthenticationMetaData authenticationMetaData = new Auth0AuthenticationMetaData()
|
||||
.withBaseUrl(AUTH0_BASE_URL)
|
||||
.withName("auth0");
|
||||
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
qInstance.setAuthentication(authenticationMetaData);
|
||||
return (qInstance);
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.authentication;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for the FullyAnonymousAuthenticationModule
|
||||
*******************************************************************************/
|
||||
public class FullyAnonymousAuthenticationModuleTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test()
|
||||
{
|
||||
FullyAnonymousAuthenticationModule fullyAnonymousAuthenticationModule = new FullyAnonymousAuthenticationModule();
|
||||
|
||||
QSession session = fullyAnonymousAuthenticationModule.createSession(null, null);
|
||||
|
||||
assertNotNull(session, "Session should not be null");
|
||||
assertNotNull(session.getIdReference(), "Session id ref should not be null");
|
||||
assertNotNull(session.getUser(), "Session User should not be null");
|
||||
assertNotNull(session.getUser().getIdReference(), "Session User id ref should not be null");
|
||||
assertTrue(fullyAnonymousAuthenticationModule.isSessionValid(session), "Any session should be valid");
|
||||
assertFalse(fullyAnonymousAuthenticationModule.isSessionValid(null), "null should be not valid");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.authentication;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QModuleDispatchException;
|
||||
import com.kingsrook.qqq.backend.core.modules.authentication.metadata.QAuthenticationMetaData;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for QModuleDispatcher
|
||||
**
|
||||
*******************************************************************************/
|
||||
class QAuthenticationModuleDispatcherTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
** Test success case - a valid backend.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_getQAuthenticationModule() throws QModuleDispatchException
|
||||
{
|
||||
QAuthenticationModuleInterface mock = new QAuthenticationModuleDispatcher().getQModule(TestUtils.defineAuthentication());
|
||||
assertNotNull(mock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test success case - a valid backend.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_getQAuthenticationModuleByType_valid() throws QModuleDispatchException
|
||||
{
|
||||
QAuthenticationModuleInterface mock = new QAuthenticationModuleDispatcher().getQModule("mock");
|
||||
assertNotNull(mock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test failure case, a backend name that doesn't exist
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_getQAuthenticationModule_typeNotFound()
|
||||
{
|
||||
assertThrows(QModuleDispatchException.class, () ->
|
||||
{
|
||||
new QAuthenticationModuleDispatcher().getQModule("aTypeThatWontExist");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test failure case, null argument
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_getQAuthenticationModule_nullArgument()
|
||||
{
|
||||
assertThrows(QModuleDispatchException.class, () ->
|
||||
{
|
||||
new QAuthenticationModuleDispatcher().getQModule((QAuthenticationMetaData) null);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QModuleDispatchException;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
|
||||
import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleDispatcher;
|
||||
import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleInterface;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for QModuleDispatcher
|
||||
**
|
||||
*******************************************************************************/
|
||||
class QBackendModuleDispatcherTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
** Test success case - a valid backend.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_getQModule_valid() throws QModuleDispatchException
|
||||
{
|
||||
QBackendModuleInterface qModule = new QBackendModuleDispatcher().getQBackendModule(TestUtils.defineBackend());
|
||||
assertNotNull(qModule);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test failure case, a backend name that doesn't exist
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_getQModule_typeNotFound()
|
||||
{
|
||||
assertThrows(QModuleDispatchException.class, () ->
|
||||
{
|
||||
QBackendMetaData qBackendMetaData = TestUtils.defineBackend();
|
||||
qBackendMetaData.setBackendType("aTypeThatWontEverExist");
|
||||
new QBackendModuleDispatcher().getQBackendModule(qBackendMetaData);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.processes.implementations.bulk.delete;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for BulkDeleteStoreStep
|
||||
*******************************************************************************/
|
||||
class BulkDeleteStoreStepTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testWithoutFilter() throws QException
|
||||
{
|
||||
RunBackendStepInput stepInput = new RunBackendStepInput(TestUtils.defineInstance());
|
||||
stepInput.setSession(TestUtils.getMockSession());
|
||||
stepInput.setTableName(TestUtils.defineTablePerson().getName());
|
||||
stepInput.setRecords(TestUtils.queryTable(TestUtils.defineTablePerson().getName()));
|
||||
|
||||
RunBackendStepOutput stepOutput = new RunBackendStepOutput();
|
||||
new BulkDeleteStoreStep().run(stepInput, stepOutput);
|
||||
assertEquals(0, stepOutput.getValueInteger(BulkDeleteStoreStep.ERROR_COUNT));
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testWithFilter() throws QException
|
||||
{
|
||||
RunBackendStepInput stepInput = new RunBackendStepInput(TestUtils.defineInstance());
|
||||
stepInput.setSession(TestUtils.getMockSession());
|
||||
stepInput.setTableName(TestUtils.defineTablePerson().getName());
|
||||
stepInput.addValue("queryFilterJSON", JsonUtils.toJson(new QQueryFilter()));
|
||||
|
||||
RunBackendStepOutput stepOutput = new RunBackendStepOutput();
|
||||
new BulkDeleteStoreStep().run(stepInput, stepOutput);
|
||||
assertEquals(0, stepOutput.getValueInteger(BulkDeleteStoreStep.ERROR_COUNT));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.processes.implementations.bulk.edit;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for BulkEditReceiveValuesStep
|
||||
*******************************************************************************/
|
||||
class BulkEditReceiveValuesStepTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test() throws QException
|
||||
{
|
||||
RunBackendStepInput stepInput = new RunBackendStepInput(TestUtils.defineInstance());
|
||||
stepInput.setSession(TestUtils.getMockSession());
|
||||
stepInput.setTableName(TestUtils.defineTablePerson().getName());
|
||||
stepInput.addValue(BulkEditReceiveValuesStep.FIELD_ENABLED_FIELDS, "firstName,email,birthDate");
|
||||
stepInput.addValue("firstName", "Johnny");
|
||||
stepInput.addValue("email", null);
|
||||
stepInput.addValue("birthDate", "1909-01-09");
|
||||
List<QRecord> records = TestUtils.queryTable(TestUtils.defineTablePerson().getName());
|
||||
stepInput.setRecords(records);
|
||||
|
||||
RunBackendStepOutput stepOutput = new RunBackendStepOutput();
|
||||
new BulkEditReceiveValuesStep().run(stepInput, stepOutput);
|
||||
|
||||
String valuesBeingUpdated = stepOutput.getValueString(BulkEditReceiveValuesStep.FIELD_VALUES_BEING_UPDATED);
|
||||
assertThat(valuesBeingUpdated).matches("(?s).*First Name.*Johnny.*");
|
||||
assertThat(valuesBeingUpdated).matches("(?s).*Email will be cleared.*");
|
||||
assertThat(valuesBeingUpdated).matches("(?s).*Birth Date.*1909-01-09.*");
|
||||
|
||||
int count = 0;
|
||||
for(QRecord record : stepOutput.getRecords())
|
||||
{
|
||||
assertEquals("Johnny", record.getValueString("firstName"));
|
||||
assertNull(record.getValue("email"));
|
||||
// todo value utils needed in getValueDate... assertEquals(LocalDate.of(1909, 1, 9), record.getValueDate("birthDate"));
|
||||
count++;
|
||||
}
|
||||
assertEquals(records.size(), count);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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.processes.implementations.bulk.edit;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for BulkEditStoreRecordsStep
|
||||
*******************************************************************************/
|
||||
class BulkEditStoreRecordsStepTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test() throws QException
|
||||
{
|
||||
RunBackendStepInput stepInput = new RunBackendStepInput(TestUtils.defineInstance());
|
||||
stepInput.setSession(TestUtils.getMockSession());
|
||||
stepInput.setTableName(TestUtils.defineTablePerson().getName());
|
||||
stepInput.addValue(BulkEditReceiveValuesStep.FIELD_ENABLED_FIELDS, "firstName,email,birthDate");
|
||||
stepInput.addValue("firstName", "Johnny");
|
||||
stepInput.addValue("email", null);
|
||||
stepInput.addValue("birthDate", "1909-01-09");
|
||||
List<QRecord> records = TestUtils.queryTable(TestUtils.defineTablePerson().getName());
|
||||
stepInput.setRecords(records);
|
||||
|
||||
RunBackendStepOutput stepOutput = new RunBackendStepOutput();
|
||||
new BulkEditStoreRecordsStep().run(stepInput, stepOutput);
|
||||
|
||||
assertRecordValues(stepOutput.getRecords());
|
||||
|
||||
// re-fetch the records, make sure they are updated.
|
||||
// but since Mock backend doesn't actually update them, we can't do this..
|
||||
// todo - implement an in-memory backend, that would do this.
|
||||
// List<QRecord> updatedRecords = TestUtils.queryTable(TestUtils.defineTablePerson().getName());
|
||||
// assertRecordValues(updatedRecords);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private void assertRecordValues(List<QRecord> records)
|
||||
{
|
||||
for(QRecord record : records)
|
||||
{
|
||||
assertEquals("Johnny", record.getValueString("firstName"));
|
||||
assertNull(record.getValue("email"));
|
||||
// todo value utils needed in getValueDate... assertEquals(LocalDate.of(1909, 1, 9), record.getValueDate("birthDate"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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.processes.implementations.bulk.insert;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.QUploadedFile;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.state.StateType;
|
||||
import com.kingsrook.qqq.backend.core.state.TempFileStateProvider;
|
||||
import com.kingsrook.qqq.backend.core.state.UUIDAndTypeStateKey;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for BulkInsertReceiveFileStep
|
||||
*******************************************************************************/
|
||||
class BulkInsertReceiveFileStepTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test() throws QException
|
||||
{
|
||||
////////////////////////////////////////////////////////////////
|
||||
// create an uploaded file, similar to how an http server may //
|
||||
////////////////////////////////////////////////////////////////
|
||||
QUploadedFile qUploadedFile = new QUploadedFile();
|
||||
qUploadedFile.setBytes((TestUtils.getPersonCsvHeaderUsingLabels() + TestUtils.getPersonCsvRow1() + TestUtils.getPersonCsvRow2()).getBytes());
|
||||
qUploadedFile.setFilename("test.csv");
|
||||
UUIDAndTypeStateKey key = new UUIDAndTypeStateKey(StateType.UPLOADED_FILE);
|
||||
TempFileStateProvider.getInstance().put(key, qUploadedFile);
|
||||
|
||||
////////////////////////////
|
||||
// setup and run the step //
|
||||
////////////////////////////
|
||||
RunBackendStepInput stepInput = new RunBackendStepInput(TestUtils.defineInstance());
|
||||
stepInput.setSession(TestUtils.getMockSession());
|
||||
stepInput.setTableName(TestUtils.defineTablePerson().getName());
|
||||
stepInput.addValue(QUploadedFile.DEFAULT_UPLOADED_FILE_FIELD_NAME, key);
|
||||
|
||||
RunBackendStepOutput stepOutput = new RunBackendStepOutput();
|
||||
new BulkInsertReceiveFileStep().run(stepInput, stepOutput);
|
||||
|
||||
List<QRecord> records = stepOutput.getRecords();
|
||||
assertEquals(2, records.size());
|
||||
assertEquals("John", records.get(0).getValueString("firstName"));
|
||||
assertEquals("Jane", records.get(1).getValueString("firstName"));
|
||||
assertNull(records.get(0).getValue("id"));
|
||||
assertNull(records.get(1).getValue("id"));
|
||||
|
||||
assertEquals(2, stepOutput.getValueInteger("noOfFileRows"));
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testBadFileType() throws QException
|
||||
{
|
||||
////////////////////////////////////////////////////////////////
|
||||
// create an uploaded file, similar to how an http server may //
|
||||
////////////////////////////////////////////////////////////////
|
||||
QUploadedFile qUploadedFile = new QUploadedFile();
|
||||
qUploadedFile.setBytes((TestUtils.getPersonCsvHeaderUsingLabels() + TestUtils.getPersonCsvRow1() + TestUtils.getPersonCsvRow2()).getBytes()); // todo - this is NOT excel content...
|
||||
qUploadedFile.setFilename("test.xslx");
|
||||
UUIDAndTypeStateKey key = new UUIDAndTypeStateKey(StateType.UPLOADED_FILE);
|
||||
TempFileStateProvider.getInstance().put(key, qUploadedFile);
|
||||
|
||||
////////////////////////////
|
||||
// setup and run the step //
|
||||
////////////////////////////
|
||||
RunBackendStepInput stepInput = new RunBackendStepInput(TestUtils.defineInstance());
|
||||
stepInput.setSession(TestUtils.getMockSession());
|
||||
stepInput.setTableName(TestUtils.defineTablePerson().getName());
|
||||
stepInput.addValue(QUploadedFile.DEFAULT_UPLOADED_FILE_FIELD_NAME, key);
|
||||
|
||||
RunBackendStepOutput stepOutput = new RunBackendStepOutput();
|
||||
|
||||
assertThrows(QUserFacingException.class, () ->
|
||||
{
|
||||
new BulkInsertReceiveFileStep().run(stepInput, stepOutput);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.processes.implementations.bulk.insert;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.QUploadedFile;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.state.StateType;
|
||||
import com.kingsrook.qqq.backend.core.state.TempFileStateProvider;
|
||||
import com.kingsrook.qqq.backend.core.state.UUIDAndTypeStateKey;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for BulkInsertStoreRecordsStep
|
||||
*******************************************************************************/
|
||||
class BulkInsertStoreRecordsStepTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test() throws QException
|
||||
{
|
||||
////////////////////////////////////////////////////////////////
|
||||
// create an uploaded file, similar to how an http server may //
|
||||
////////////////////////////////////////////////////////////////
|
||||
QUploadedFile qUploadedFile = new QUploadedFile();
|
||||
qUploadedFile.setBytes((TestUtils.getPersonCsvHeaderUsingLabels() + TestUtils.getPersonCsvRow1() + TestUtils.getPersonCsvRow2()).getBytes());
|
||||
qUploadedFile.setFilename("test.csv");
|
||||
UUIDAndTypeStateKey key = new UUIDAndTypeStateKey(StateType.UPLOADED_FILE);
|
||||
TempFileStateProvider.getInstance().put(key, qUploadedFile);
|
||||
|
||||
////////////////////////////
|
||||
// setup and run the step //
|
||||
////////////////////////////
|
||||
RunBackendStepInput stepInput = new RunBackendStepInput(TestUtils.defineInstance());
|
||||
stepInput.setSession(TestUtils.getMockSession());
|
||||
stepInput.setTableName(TestUtils.defineTablePerson().getName());
|
||||
stepInput.addValue(QUploadedFile.DEFAULT_UPLOADED_FILE_FIELD_NAME, key);
|
||||
|
||||
RunBackendStepOutput stepOutput = new RunBackendStepOutput();
|
||||
new BulkInsertStoreRecordsStep().run(stepInput, stepOutput);
|
||||
|
||||
List<QRecord> records = stepOutput.getRecords();
|
||||
assertEquals(2, records.size());
|
||||
assertEquals("John", records.get(0).getValueString("firstName"));
|
||||
assertEquals("Jane", records.get(1).getValueString("firstName"));
|
||||
assertNotNull(records.get(0).getValue("id"));
|
||||
assertNotNull(records.get(1).getValue("id"));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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.processes.implementations.etl.basic;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.RunProcessAction;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.shared.mapping.QKeyBasedFieldMapping;
|
||||
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for BasicETLProcess
|
||||
*******************************************************************************/
|
||||
class BasicETLProcessTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
** Simplest happy path
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test() throws QException
|
||||
{
|
||||
RunProcessInput request = new RunProcessInput(TestUtils.defineInstance());
|
||||
request.setSession(TestUtils.getMockSession());
|
||||
request.setProcessName(BasicETLProcess.PROCESS_NAME);
|
||||
request.addValue(BasicETLProcess.FIELD_SOURCE_TABLE, TestUtils.defineTablePerson().getName());
|
||||
request.addValue(BasicETLProcess.FIELD_DESTINATION_TABLE, TestUtils.definePersonFileTable().getName());
|
||||
request.addValue(BasicETLProcess.FIELD_MAPPING_JSON, "");
|
||||
|
||||
RunProcessOutput result = new RunProcessAction().execute(request);
|
||||
assertNotNull(result);
|
||||
assertTrue(result.getRecords().stream().allMatch(r -> r.getValues().containsKey("id")), "records should have an id, set by the process");
|
||||
assertTrue(result.getException().isEmpty());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Basic example of doing a mapping transformation
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testMappingTransformation() throws QException
|
||||
{
|
||||
RunProcessInput request = new RunProcessInput(TestUtils.defineInstance());
|
||||
request.setSession(TestUtils.getMockSession());
|
||||
request.setProcessName(BasicETLProcess.PROCESS_NAME);
|
||||
request.addValue(BasicETLProcess.FIELD_SOURCE_TABLE, TestUtils.definePersonFileTable().getName());
|
||||
request.addValue(BasicETLProcess.FIELD_DESTINATION_TABLE, TestUtils.defineTableIdAndNameOnly().getName());
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
// define our mapping from destination-table field names to source-table field names //
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
QKeyBasedFieldMapping mapping = new QKeyBasedFieldMapping().withMapping("name", "firstName");
|
||||
// request.addValue(BasicETLProcess.FIELD_MAPPING_JSON, JsonUtils.toJson(mapping.getMapping()));
|
||||
request.addValue(BasicETLProcess.FIELD_MAPPING_JSON, JsonUtils.toJson(mapping));
|
||||
|
||||
RunProcessOutput result = new RunProcessAction().execute(request);
|
||||
assertNotNull(result);
|
||||
assertTrue(result.getRecords().stream().allMatch(r -> r.getValues().containsKey("id")), "records should have an id, set by the process");
|
||||
assertTrue(result.getException().isEmpty());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.processes.implementations.etl.basic;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for BasicETLTransformFunction
|
||||
*******************************************************************************/
|
||||
class BasicETLTransformFunctionTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
** Test the removeNonNumericValuesFromMappedRecords function
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testRemoveNonNumericValuesFromMappedRecords()
|
||||
{
|
||||
assertNull(doRemoveNonNumericValuesFromMappedRecords(QFieldType.INTEGER, null));
|
||||
assertNull(doRemoveNonNumericValuesFromMappedRecords(QFieldType.INTEGER, "foo"));
|
||||
assertNull(doRemoveNonNumericValuesFromMappedRecords(QFieldType.INTEGER, "1foo"));
|
||||
assertEquals("1", doRemoveNonNumericValuesFromMappedRecords(QFieldType.INTEGER, "1"));
|
||||
assertEquals("1000", doRemoveNonNumericValuesFromMappedRecords(QFieldType.INTEGER, "1,000"));
|
||||
assertEquals("1000000", doRemoveNonNumericValuesFromMappedRecords(QFieldType.INTEGER, "1,000,000"));
|
||||
|
||||
assertNull(doRemoveNonNumericValuesFromMappedRecords(QFieldType.DECIMAL, null));
|
||||
assertNull(doRemoveNonNumericValuesFromMappedRecords(QFieldType.DECIMAL, "foo"));
|
||||
assertNull(doRemoveNonNumericValuesFromMappedRecords(QFieldType.DECIMAL, "1foo"));
|
||||
assertEquals("1", doRemoveNonNumericValuesFromMappedRecords(QFieldType.DECIMAL, "1"));
|
||||
assertEquals("1000", doRemoveNonNumericValuesFromMappedRecords(QFieldType.DECIMAL, "1,000"));
|
||||
assertEquals("1.0", doRemoveNonNumericValuesFromMappedRecords(QFieldType.DECIMAL, "1.0"));
|
||||
assertEquals("1000.00", doRemoveNonNumericValuesFromMappedRecords(QFieldType.DECIMAL, "1,000.00"));
|
||||
assertEquals("1000000", doRemoveNonNumericValuesFromMappedRecords(QFieldType.DECIMAL, "1,000,000"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
private String doRemoveNonNumericValuesFromMappedRecords(QFieldType fieldType, String inputValue)
|
||||
{
|
||||
String field = "field";
|
||||
QTableMetaData table = new QTableMetaData()
|
||||
.withField(new QFieldMetaData(field, fieldType));
|
||||
|
||||
List<QRecord> records = List.of(new QRecord().withValue(field, inputValue));
|
||||
new BasicETLTransformFunction().removeNonNumericValuesFromMappedRecords(table, records);
|
||||
return (records.get(0).getValueString(field));
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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.state;
|
||||
|
||||
|
||||
import java.util.UUID;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for InMemoryStateProvider
|
||||
*******************************************************************************/
|
||||
public class InMemoryStateProviderTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testStateNotFound()
|
||||
{
|
||||
InMemoryStateProvider stateProvider = InMemoryStateProvider.getInstance();
|
||||
UUIDAndTypeStateKey key = new UUIDAndTypeStateKey(StateType.PROCESS_STATUS);
|
||||
|
||||
Assertions.assertTrue(stateProvider.get(QRecord.class, key).isEmpty(), "Key not found in state should return empty");
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testSimpleStateFound()
|
||||
{
|
||||
InMemoryStateProvider stateProvider = InMemoryStateProvider.getInstance();
|
||||
UUIDAndTypeStateKey key = new UUIDAndTypeStateKey(StateType.PROCESS_STATUS);
|
||||
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
QRecord qRecord = new QRecord().withValue("uuid", uuid);
|
||||
stateProvider.put(key, qRecord);
|
||||
|
||||
QRecord qRecordFromState = stateProvider.get(QRecord.class, key).get();
|
||||
Assertions.assertEquals(uuid, qRecordFromState.getValueString("uuid"), "Should read value from state persistence");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testWrongTypeOnGet()
|
||||
{
|
||||
InMemoryStateProvider stateProvider = InMemoryStateProvider.getInstance();
|
||||
UUIDAndTypeStateKey key = new UUIDAndTypeStateKey(StateType.PROCESS_STATUS);
|
||||
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
QRecord qRecord = new QRecord().withValue("uuid", uuid);
|
||||
stateProvider.put(key, qRecord);
|
||||
|
||||
Assertions.assertThrows(Exception.class, () ->
|
||||
{
|
||||
stateProvider.get(QTableMetaData.class, key);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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.state;
|
||||
|
||||
|
||||
import java.util.UUID;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for TempFileStateProvider
|
||||
*******************************************************************************/
|
||||
public class TempFileStateProviderTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testStateNotFound()
|
||||
{
|
||||
TempFileStateProvider stateProvider = TempFileStateProvider.getInstance();
|
||||
UUIDAndTypeStateKey key = new UUIDAndTypeStateKey(StateType.PROCESS_STATUS);
|
||||
|
||||
Assertions.assertTrue(stateProvider.get(QRecord.class, key).isEmpty(), "Key not found in state should return empty");
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testSimpleStateFound()
|
||||
{
|
||||
TempFileStateProvider stateProvider = TempFileStateProvider.getInstance();
|
||||
UUIDAndTypeStateKey key = new UUIDAndTypeStateKey(StateType.PROCESS_STATUS);
|
||||
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
QRecord qRecord = new QRecord().withValue("uuid", uuid);
|
||||
stateProvider.put(key, qRecord);
|
||||
|
||||
QRecord qRecordFromState = stateProvider.get(QRecord.class, key).get();
|
||||
Assertions.assertEquals(uuid, qRecordFromState.getValueString("uuid"), "Should read value from state persistence");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testWrongTypeOnGet()
|
||||
{
|
||||
TempFileStateProvider stateProvider = TempFileStateProvider.getInstance();
|
||||
UUIDAndTypeStateKey key = new UUIDAndTypeStateKey(StateType.PROCESS_STATUS);
|
||||
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
QRecord qRecord = new QRecord().withValue("uuid", uuid);
|
||||
stateProvider.put(key, qRecord);
|
||||
|
||||
Assertions.assertThrows(Exception.class, () ->
|
||||
{
|
||||
stateProvider.get(QTableMetaData.class, key);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,501 @@
|
||||
/*
|
||||
* 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.utils;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for CollectionUtils
|
||||
**
|
||||
*******************************************************************************/
|
||||
class CollectionUtilsTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_nullSafeIsEmpty_Map()
|
||||
{
|
||||
assertTrue(CollectionUtils.nullSafeIsEmpty(Collections.emptyMap()));
|
||||
assertTrue(CollectionUtils.nullSafeIsEmpty(new HashMap<>()));
|
||||
assertTrue(CollectionUtils.nullSafeIsEmpty((Map<?, ?>) null));
|
||||
Map<String, Integer> myMap = new HashMap<>();
|
||||
assertTrue(CollectionUtils.nullSafeIsEmpty(myMap));
|
||||
myMap.put("A", 1);
|
||||
assertFalse(CollectionUtils.nullSafeIsEmpty(myMap));
|
||||
myMap.clear();
|
||||
assertTrue(CollectionUtils.nullSafeIsEmpty(myMap));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_nullSafeIsEmpty_Collection()
|
||||
{
|
||||
assertTrue(CollectionUtils.nullSafeIsEmpty(Collections.emptyList()));
|
||||
assertTrue(CollectionUtils.nullSafeIsEmpty(new ArrayList<>()));
|
||||
assertTrue(CollectionUtils.nullSafeIsEmpty((List<?>) null));
|
||||
List<String> myList = new ArrayList<>();
|
||||
assertTrue(CollectionUtils.nullSafeIsEmpty(myList));
|
||||
myList.add("A");
|
||||
assertFalse(CollectionUtils.nullSafeIsEmpty(myList));
|
||||
myList.clear();
|
||||
assertTrue(CollectionUtils.nullSafeIsEmpty(myList));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_nullSafeHasContents_Map()
|
||||
{
|
||||
assertFalse(CollectionUtils.nullSafeHasContents(Collections.emptyMap()));
|
||||
assertFalse(CollectionUtils.nullSafeHasContents(new HashMap<>()));
|
||||
assertFalse(CollectionUtils.nullSafeHasContents((Map<?, ?>) null));
|
||||
Map<String, Integer> myMap = new HashMap<>();
|
||||
assertFalse(CollectionUtils.nullSafeHasContents(myMap));
|
||||
myMap.put("A", 1);
|
||||
assertTrue(CollectionUtils.nullSafeHasContents(myMap));
|
||||
myMap.clear();
|
||||
assertFalse(CollectionUtils.nullSafeHasContents(myMap));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_nullSafeHasContents_Collection()
|
||||
{
|
||||
assertFalse(CollectionUtils.nullSafeHasContents(Collections.emptyList()));
|
||||
assertFalse(CollectionUtils.nullSafeHasContents(new ArrayList<>()));
|
||||
assertFalse(CollectionUtils.nullSafeHasContents((List<?>) null));
|
||||
List<String> myList = new ArrayList<>();
|
||||
assertFalse(CollectionUtils.nullSafeHasContents(myList));
|
||||
myList.add("A");
|
||||
assertTrue(CollectionUtils.nullSafeHasContents(myList));
|
||||
myList.clear();
|
||||
assertFalse(CollectionUtils.nullSafeHasContents(myList));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_nullSafeSize_Map()
|
||||
{
|
||||
assertEquals(0, CollectionUtils.nullSafeSize(Collections.emptyMap()));
|
||||
assertEquals(0, CollectionUtils.nullSafeSize(new HashMap<>()));
|
||||
assertEquals(0, CollectionUtils.nullSafeSize((Map<?, ?>) null));
|
||||
Map<String, Integer> myMap = new HashMap<>();
|
||||
assertEquals(0, CollectionUtils.nullSafeSize(myMap));
|
||||
myMap.put("A", 1);
|
||||
assertEquals(1, CollectionUtils.nullSafeSize(myMap));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_nullSafeSize_Collection()
|
||||
{
|
||||
assertEquals(0, CollectionUtils.nullSafeSize(Collections.emptyList()));
|
||||
assertEquals(0, CollectionUtils.nullSafeSize(new ArrayList<>()));
|
||||
assertEquals(0, CollectionUtils.nullSafeSize((List<?>) null));
|
||||
List<String> myList = new ArrayList<>();
|
||||
assertEquals(0, CollectionUtils.nullSafeSize(myList));
|
||||
myList.add("A");
|
||||
assertEquals(1, CollectionUtils.nullSafeSize(myList));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@Test
|
||||
void test_addAllToMap()
|
||||
{
|
||||
Map<String, Integer> to = new HashMap<>();
|
||||
Map<String, Integer> from = new HashMap<>();
|
||||
|
||||
assertThrows(NullPointerException.class, () -> CollectionUtils.addAllToMap(null, null));
|
||||
assertThrows(NullPointerException.class, () -> CollectionUtils.addAllToMap(to, null));
|
||||
|
||||
// this case does not currently throw - capture that fact here in case we change it.
|
||||
CollectionUtils.addAllToMap(null, from);
|
||||
|
||||
CollectionUtils.addAllToMap(to, from);
|
||||
assertEquals(0, to.size());
|
||||
|
||||
from.put("A", 1);
|
||||
CollectionUtils.addAllToMap(to, from);
|
||||
assertEquals(1, to.size());
|
||||
assertEquals(1, to.get("A"));
|
||||
|
||||
from.put("B", 2);
|
||||
CollectionUtils.addAllToMap(to, from);
|
||||
assertEquals(2, to.size());
|
||||
assertEquals(1, to.get("A"));
|
||||
assertEquals(2, to.get("B"));
|
||||
|
||||
from.put("B", 3);
|
||||
CollectionUtils.addAllToMap(to, from);
|
||||
assertEquals(2, to.size());
|
||||
assertEquals(1, to.get("A"));
|
||||
assertEquals(3, to.get("B"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_listToMap()
|
||||
{
|
||||
assertNull(CollectionUtils.listToMap(null, null));
|
||||
|
||||
List<String> myList = new ArrayList<>();
|
||||
myList.add("Apple");
|
||||
myList.add("Banana");
|
||||
assertThrows(NullPointerException.class, () -> CollectionUtils.listToMap(myList, null));
|
||||
|
||||
Map<String, String> myMap = CollectionUtils.listToMap(myList, first());
|
||||
assertEquals(2, myMap.size());
|
||||
assertEquals("Apple", myMap.get("A"));
|
||||
assertEquals("Banana", myMap.get("B"));
|
||||
|
||||
// confirm what a clobbered key does
|
||||
myList.add("Airplane");
|
||||
myMap = CollectionUtils.listToMap(myList, first());
|
||||
assertEquals(2, myMap.size());
|
||||
assertEquals("Airplane", myMap.get("A"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_listToMap_valueFunction()
|
||||
{
|
||||
assertNull(CollectionUtils.listToMap(null, null, null));
|
||||
|
||||
List<String> myList = new ArrayList<>();
|
||||
myList.add("Apple");
|
||||
myList.add("Banana");
|
||||
assertThrows(NullPointerException.class, () -> CollectionUtils.listToMap(myList, null, null));
|
||||
|
||||
Map<String, String> myMap = CollectionUtils.listToMap(myList, first(), rest());
|
||||
assertEquals(2, myMap.size());
|
||||
assertEquals("pple", myMap.get("A"));
|
||||
assertEquals("anana", myMap.get("B"));
|
||||
|
||||
// confirm what a clobbered key does
|
||||
myList.add("Airplane");
|
||||
myMap = CollectionUtils.listToMap(myList, first(), rest());
|
||||
assertEquals(2, myMap.size());
|
||||
assertEquals("irplane", myMap.get("A"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_listToListingHash()
|
||||
{
|
||||
assertNull(CollectionUtils.listToListingHash(null, null));
|
||||
|
||||
List<String> myList = new ArrayList<>();
|
||||
myList.add("Apple");
|
||||
myList.add("Banana");
|
||||
assertThrows(NullPointerException.class, () -> CollectionUtils.listToListingHash(myList, null));
|
||||
|
||||
ListingHash<String, String> myListingHash = CollectionUtils.listToListingHash(myList, first());
|
||||
assertEquals(2, myListingHash.size());
|
||||
assertEquals(1, myListingHash.get("A").size());
|
||||
assertEquals("Apple", myListingHash.get("A").get(0));
|
||||
assertEquals(1, myListingHash.get("B").size());
|
||||
assertEquals("Banana", myListingHash.get("B").get(0));
|
||||
|
||||
myList.add("Airplane");
|
||||
myListingHash = CollectionUtils.listToListingHash(myList, first());
|
||||
assertEquals(2, myListingHash.size());
|
||||
assertEquals(2, myListingHash.get("A").size());
|
||||
assertEquals("Apple", myListingHash.get("A").get(0));
|
||||
assertEquals("Airplane", myListingHash.get("A").get(1));
|
||||
assertEquals(1, myListingHash.get("B").size());
|
||||
assertEquals("Banana", myListingHash.get("B").get(0));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_listToListingHash_valueFunction()
|
||||
{
|
||||
assertNull(CollectionUtils.listToListingHash(null, null, null));
|
||||
|
||||
List<String> myList = new ArrayList<>();
|
||||
myList.add("Apple");
|
||||
myList.add("Banana");
|
||||
assertThrows(NullPointerException.class, () -> CollectionUtils.listToListingHash(myList, null, null));
|
||||
|
||||
ListingHash<String, String> myListingHash = CollectionUtils.listToListingHash(myList, first(), rest());
|
||||
assertEquals(2, myListingHash.size());
|
||||
assertEquals(1, myListingHash.get("A").size());
|
||||
assertEquals("pple", myListingHash.get("A").get(0));
|
||||
assertEquals(1, myListingHash.get("B").size());
|
||||
assertEquals("anana", myListingHash.get("B").get(0));
|
||||
|
||||
myList.add("Airplane");
|
||||
myListingHash = CollectionUtils.listToListingHash(myList, first(), rest());
|
||||
assertEquals(2, myListingHash.size());
|
||||
assertEquals(2, myListingHash.get("A").size());
|
||||
assertEquals("pple", myListingHash.get("A").get(0));
|
||||
assertEquals("irplane", myListingHash.get("A").get(1));
|
||||
assertEquals(1, myListingHash.get("B").size());
|
||||
assertEquals("anana", myListingHash.get("B").get(0));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_listTo2LevelMap()
|
||||
{
|
||||
assertNull(CollectionUtils.listTo2LevelMap(null, null, null));
|
||||
|
||||
List<String> myList = new ArrayList<>();
|
||||
myList.add("Apple");
|
||||
myList.add("Banana");
|
||||
myList.add("Airplane");
|
||||
assertThrows(NullPointerException.class, () -> CollectionUtils.listTo2LevelMap(myList, null, null));
|
||||
assertThrows(NullPointerException.class, () -> CollectionUtils.listTo2LevelMap(myList, first(), null));
|
||||
assertThrows(NullPointerException.class, () -> CollectionUtils.listTo2LevelMap(myList, null, second()));
|
||||
|
||||
Map<String, Map<String, String>> myMap = CollectionUtils.listTo2LevelMap(myList, first(), second());
|
||||
assertEquals(2, myMap.size());
|
||||
assertEquals(2, myMap.get("A").size());
|
||||
assertEquals("Apple", myMap.get("A").get("p"));
|
||||
assertEquals("Airplane", myMap.get("A").get("i"));
|
||||
assertEquals(1, myMap.get("B").size());
|
||||
assertEquals("Banana", myMap.get("B").get("a"));
|
||||
|
||||
// demonstrate clobbering behavior
|
||||
myList.add("Ape");
|
||||
myMap = CollectionUtils.listTo2LevelMap(myList, first(), second());
|
||||
assertEquals(2, myMap.get("A").size());
|
||||
assertEquals("Ape", myMap.get("A").get("p"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** helper method to get rest of string (unsafely)
|
||||
*******************************************************************************/
|
||||
private Function<String, String> rest()
|
||||
{
|
||||
return s -> s.substring(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** helper method to get first char of string (unsafely)
|
||||
*******************************************************************************/
|
||||
private Function<String, String> first()
|
||||
{
|
||||
return s -> s.substring(0, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** helper method to get second char of string (unsafely)
|
||||
*******************************************************************************/
|
||||
private Function<String, String> second()
|
||||
{
|
||||
return s -> s.substring(1, 2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_getPages()
|
||||
{
|
||||
List<List<Integer>> pages = CollectionUtils.getPages(null, 5);
|
||||
assertEquals(0, pages.size());
|
||||
|
||||
pages = CollectionUtils.getPages(Collections.emptyList(), 5);
|
||||
assertEquals(0, pages.size());
|
||||
|
||||
pages = CollectionUtils.getPages(List.of(1, 2, 3), 5);
|
||||
assertEquals(1, pages.size());
|
||||
assertEquals(3, pages.get(0).size());
|
||||
|
||||
pages = CollectionUtils.getPages(List.of(1, 2, 3, 4, 5), 5);
|
||||
assertEquals(1, pages.size());
|
||||
assertEquals(5, pages.get(0).size());
|
||||
|
||||
pages = CollectionUtils.getPages(List.of(1, 2, 3, 4, 5, 6, 7), 5);
|
||||
assertEquals(2, pages.size());
|
||||
assertEquals(5, pages.get(0).size());
|
||||
assertEquals(2, pages.get(1).size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_getQuestionMarks()
|
||||
{
|
||||
assertEquals("", CollectionUtils.getQuestionMarks(null));
|
||||
assertEquals("", CollectionUtils.getQuestionMarks(Collections.emptyList()));
|
||||
assertEquals("?", CollectionUtils.getQuestionMarks(List.of(1)));
|
||||
assertEquals("?,?,?", CollectionUtils.getQuestionMarks(List.of(1, 2, 3)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_safelyGetPage()
|
||||
{
|
||||
List<Integer> empty = Collections.emptyList();
|
||||
List<Integer> list = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
|
||||
|
||||
/////////////////////
|
||||
// null list input //
|
||||
/////////////////////
|
||||
assertNull(CollectionUtils.safelyGetPage(null, null, null));
|
||||
assertNull(CollectionUtils.safelyGetPage(null, 1, 1));
|
||||
assertNull(CollectionUtils.safelyGetPage(null, null, 1));
|
||||
assertNull(CollectionUtils.safelyGetPage(null, 1, null));
|
||||
|
||||
//////////////////////
|
||||
// empty list input //
|
||||
//////////////////////
|
||||
assertEquals(empty, CollectionUtils.safelyGetPage(empty, null, null));
|
||||
assertEquals(empty, CollectionUtils.safelyGetPage(empty, 1, 1));
|
||||
assertEquals(empty, CollectionUtils.safelyGetPage(empty, null, 1));
|
||||
assertEquals(empty, CollectionUtils.safelyGetPage(empty, 1, null));
|
||||
|
||||
////////////////////////////////////////
|
||||
// cases that give back the full list //
|
||||
////////////////////////////////////////
|
||||
assertEquals(list, CollectionUtils.safelyGetPage(list, null, null));
|
||||
assertEquals(list, CollectionUtils.safelyGetPage(list, 0, null));
|
||||
|
||||
///////////////////
|
||||
// empty outputs //
|
||||
///////////////////
|
||||
assertEquals(empty, CollectionUtils.safelyGetPage(list, 0, 0));
|
||||
assertEquals(empty, CollectionUtils.safelyGetPage(list, 10, 1));
|
||||
assertEquals(empty, CollectionUtils.safelyGetPage(list, 20, 10));
|
||||
|
||||
///////////////////////
|
||||
// illegal arguments //
|
||||
///////////////////////
|
||||
assertThrows(IllegalArgumentException.class, () -> CollectionUtils.safelyGetPage(list, -1, 1));
|
||||
assertThrows(IllegalArgumentException.class, () -> CollectionUtils.safelyGetPage(list, 1, -1));
|
||||
assertThrows(IllegalArgumentException.class, () -> CollectionUtils.safelyGetPage(list, -1, -1));
|
||||
assertThrows(IllegalArgumentException.class, () -> CollectionUtils.safelyGetPage(null, -1, -1));
|
||||
|
||||
/////////////////////////////
|
||||
// normal kinds of outputs //
|
||||
/////////////////////////////
|
||||
assertEquals(List.of(1), CollectionUtils.safelyGetPage(list, null, 1));
|
||||
assertEquals(List.of(1), CollectionUtils.safelyGetPage(list, 0, 1));
|
||||
assertEquals(List.of(2), CollectionUtils.safelyGetPage(list, 1, 1));
|
||||
assertEquals(List.of(2, 3), CollectionUtils.safelyGetPage(list, 1, 2));
|
||||
assertEquals(List.of(2, 3, 4), CollectionUtils.safelyGetPage(list, 1, 3));
|
||||
assertEquals(List.of(9), CollectionUtils.safelyGetPage(list, 8, 1));
|
||||
assertEquals(List.of(9, 10), CollectionUtils.safelyGetPage(list, 8, 2));
|
||||
assertEquals(List.of(9, 10), CollectionUtils.safelyGetPage(list, 8, 10));
|
||||
assertEquals(List.of(10), CollectionUtils.safelyGetPage(list, 9, 1));
|
||||
assertEquals(List.of(10), CollectionUtils.safelyGetPage(list, 9, 2));
|
||||
assertEquals(List.of(10), CollectionUtils.safelyGetPage(list, 9, 10));
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// make sure scrolling through pages works as expected //
|
||||
/////////////////////////////////////////////////////////
|
||||
int skip = 0;
|
||||
int limit = 3;
|
||||
int pageCount = 0;
|
||||
List<Integer> accumulator = new ArrayList<>();
|
||||
while (true)
|
||||
{
|
||||
List<Integer> nextPage = CollectionUtils.safelyGetPage(list, skip, limit);
|
||||
if (nextPage.isEmpty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
accumulator.addAll(nextPage);
|
||||
skip += limit;
|
||||
pageCount++;
|
||||
}
|
||||
assertEquals(4, pageCount);
|
||||
assertEquals(list, accumulator);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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.utils;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for ExceptionUtils
|
||||
**
|
||||
*******************************************************************************/
|
||||
class ExceptionUtilsTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testFindClassInRootChain()
|
||||
{
|
||||
assertNull(ExceptionUtils.findClassInRootChain(null, QUserFacingException.class));
|
||||
|
||||
QUserFacingException target = new QUserFacingException("target");
|
||||
assertSame(target, ExceptionUtils.findClassInRootChain(target, QUserFacingException.class));
|
||||
assertSame(target, ExceptionUtils.findClassInRootChain(new QException("decoy", target), QUserFacingException.class));
|
||||
assertNull(ExceptionUtils.findClassInRootChain(new QException("decoy", target), IllegalArgumentException.class));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testGetRootException()
|
||||
{
|
||||
assertNull(ExceptionUtils.getRootException(null));
|
||||
|
||||
Exception root = new Exception("root");
|
||||
assertSame(root, ExceptionUtils.getRootException(root));
|
||||
|
||||
Exception container = new Exception("container", root);
|
||||
assertSame(root, ExceptionUtils.getRootException(container));
|
||||
|
||||
Exception middle = new Exception("middle", root);
|
||||
Exception top = new Exception("top", middle);
|
||||
assertSame(root, ExceptionUtils.getRootException(top));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// without the code that checks for loops, these next two checks cause infinite loops //
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
MyException selfCaused = new MyException("selfCaused");
|
||||
selfCaused.setCause(selfCaused);
|
||||
assertSame(selfCaused, ExceptionUtils.getRootException(selfCaused));
|
||||
|
||||
MyException cycle1 = new MyException("cycle1");
|
||||
MyException cycle2 = new MyException("cycle2");
|
||||
cycle1.setCause(cycle2);
|
||||
cycle2.setCause(cycle1);
|
||||
assertSame(cycle1, ExceptionUtils.getRootException(cycle1));
|
||||
assertSame(cycle2, ExceptionUtils.getRootException(cycle2));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Test exception class - lets you set the cause, easier to create a loop.
|
||||
*******************************************************************************/
|
||||
public class MyException extends Exception
|
||||
{
|
||||
private Throwable myCause = null;
|
||||
|
||||
|
||||
|
||||
public MyException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public MyException(Throwable cause)
|
||||
{
|
||||
super(cause);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void setCause(Throwable cause)
|
||||
{
|
||||
myCause = cause;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public synchronized Throwable getCause()
|
||||
{
|
||||
return (myCause);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,296 @@
|
||||
/*
|
||||
* 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.utils;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterOrderBy;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for JsonUtils.
|
||||
**
|
||||
*******************************************************************************/
|
||||
class JsonUtilsTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_toJsonQRecordInput()
|
||||
{
|
||||
QRecord qRecord = getQRecord();
|
||||
String json = JsonUtils.toJson(qRecord);
|
||||
assertEquals("""
|
||||
{"tableName":"foo","values":{"foo":"Foo","bar":3.14159}}""", json);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static class LooksLikeAnEntityButJustThrowsInItsGetterMethod
|
||||
{
|
||||
public String getValue()
|
||||
{
|
||||
throw new IllegalStateException("Test");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_toJsonNull()
|
||||
{
|
||||
assertThrowsExactly(IllegalArgumentException.class,
|
||||
() -> JsonUtils.toJson(new LooksLikeAnEntityButJustThrowsInItsGetterMethod()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_toPrettyJsonNull()
|
||||
{
|
||||
assertThrowsExactly(IllegalArgumentException.class,
|
||||
() -> JsonUtils.toPrettyJson(new LooksLikeAnEntityButJustThrowsInItsGetterMethod()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_toPrettyJsonQRecordInput()
|
||||
{
|
||||
QRecord qRecord = getQRecord();
|
||||
String json = JsonUtils.toPrettyJson(qRecord);
|
||||
// todo assertEquals("{\"tableName\":\"foo\",\"primaryKey\":1,\"values\":{\"foo\":\"Foo\",\"bar\":3.14159}}", json);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_toJSONObject()
|
||||
{
|
||||
JSONObject jsonObject = JsonUtils.toJSONObject("""
|
||||
{
|
||||
"Foo": "Bar",
|
||||
"Baz": [1, 2, 3]
|
||||
}
|
||||
""");
|
||||
assertNotNull(jsonObject);
|
||||
assertTrue(jsonObject.has("Foo"));
|
||||
assertEquals("Bar", jsonObject.getString("Foo"));
|
||||
assertTrue(jsonObject.has("Baz"));
|
||||
assertEquals(3, jsonObject.getJSONArray("Baz").length());
|
||||
assertEquals(1, jsonObject.getJSONArray("Baz").get(0));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_toJSONObject_malformed()
|
||||
{
|
||||
// todo - what do we want to throw here?
|
||||
assertThrows(JSONException.class, () ->
|
||||
{
|
||||
JsonUtils.toJSONObject("""
|
||||
{
|
||||
"Foo": "Bar",
|
||||
""");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_toJSONObjectNonJsonObject()
|
||||
{
|
||||
try
|
||||
{
|
||||
JsonUtils.toJSONObject("");
|
||||
}
|
||||
catch(JSONException je)
|
||||
{
|
||||
System.out.println("Caught Expected exception");
|
||||
return;
|
||||
}
|
||||
|
||||
fail("Did not catch expected exception");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_toJSONArray()
|
||||
{
|
||||
JSONArray jsonArray = JsonUtils.toJSONArray("""
|
||||
[
|
||||
{"Foo": "Bar"},
|
||||
{"Baz": [1, 2, 3]}
|
||||
]
|
||||
""");
|
||||
assertNotNull(jsonArray);
|
||||
assertEquals(2, jsonArray.length());
|
||||
assertTrue(jsonArray.getJSONObject(0).has("Foo"));
|
||||
assertEquals("Bar", jsonArray.getJSONObject(0).getString("Foo"));
|
||||
assertTrue(jsonArray.getJSONObject(1).has("Baz"));
|
||||
assertEquals(3, jsonArray.getJSONObject(1).getJSONArray("Baz").length());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private QRecord getQRecord()
|
||||
{
|
||||
QRecord qRecord = new QRecord();
|
||||
qRecord.setTableName("foo");
|
||||
qRecord.setValue("id", 1);
|
||||
Map<String, Serializable> values = new LinkedHashMap<>();
|
||||
qRecord.setValues(values);
|
||||
values.put("foo", "Foo");
|
||||
values.put("bar", new BigDecimal("3.14159"));
|
||||
return qRecord;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_toJsonNullInput()
|
||||
{
|
||||
String json = JsonUtils.toJson(null);
|
||||
assertEquals("null", json);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_looksLikeObject()
|
||||
{
|
||||
assertFalse(JsonUtils.looksLikeObject(""));
|
||||
assertFalse(JsonUtils.looksLikeObject(null));
|
||||
assertFalse(JsonUtils.looksLikeObject("json"));
|
||||
assertFalse(JsonUtils.looksLikeObject("[]"));
|
||||
assertTrue(JsonUtils.looksLikeObject("{}"));
|
||||
assertTrue(JsonUtils.looksLikeObject(" {}"));
|
||||
assertTrue(JsonUtils.looksLikeObject("\n\n\n{}"));
|
||||
assertTrue(JsonUtils.looksLikeObject("\n{\n[]\n}\n"));
|
||||
assertTrue(JsonUtils.looksLikeObject("\n\n\n { \n}\n\n\n"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_looksLikeArray()
|
||||
{
|
||||
assertFalse(JsonUtils.looksLikeArray(""));
|
||||
assertFalse(JsonUtils.looksLikeArray(null));
|
||||
assertFalse(JsonUtils.looksLikeArray("json"));
|
||||
assertFalse(JsonUtils.looksLikeArray("{json[]}"));
|
||||
assertFalse(JsonUtils.looksLikeArray("{}"));
|
||||
assertTrue(JsonUtils.looksLikeArray("[]"));
|
||||
assertTrue(JsonUtils.looksLikeArray(" []"));
|
||||
assertTrue(JsonUtils.looksLikeArray("\n\n\n[]"));
|
||||
assertTrue(JsonUtils.looksLikeArray("\n[\n{}\n}\n"));
|
||||
assertTrue(JsonUtils.looksLikeArray("\n\n\n [ \n]\n\n\n"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_toObject() throws IOException
|
||||
{
|
||||
String json = JsonUtils.toJson(new QQueryFilter()
|
||||
.withCriteria(new QFilterCriteria().withFieldName("id").withOperator(QCriteriaOperator.EQUALS).withValues(List.of(1)))
|
||||
.withCriteria(new QFilterCriteria().withFieldName("name").withOperator(QCriteriaOperator.IN).withValues(List.of("Darin", "James")))
|
||||
.withOrderBy(new QFilterOrderBy().withFieldName("age").withIsAscending(true)));
|
||||
|
||||
System.out.println(json);
|
||||
|
||||
QQueryFilter qQueryFilter = JsonUtils.toObject(json, QQueryFilter.class);
|
||||
assertEquals(2, qQueryFilter.getCriteria().size());
|
||||
assertEquals("id", qQueryFilter.getCriteria().get(0).getFieldName());
|
||||
assertEquals(QCriteriaOperator.EQUALS, qQueryFilter.getCriteria().get(0).getOperator());
|
||||
assertEquals(List.of(1), qQueryFilter.getCriteria().get(0).getValues());
|
||||
assertEquals("name", qQueryFilter.getCriteria().get(1).getFieldName());
|
||||
assertEquals(QCriteriaOperator.IN, qQueryFilter.getCriteria().get(1).getOperator());
|
||||
assertEquals(List.of("Darin", "James"), qQueryFilter.getCriteria().get(1).getValues());
|
||||
assertEquals(1, qQueryFilter.getOrderBys().size());
|
||||
assertEquals("age", qQueryFilter.getOrderBys().get(0).getFieldName());
|
||||
assertTrue(qQueryFilter.getOrderBys().get(0).getIsAscending());
|
||||
}
|
||||
}
|
@ -0,0 +1,354 @@
|
||||
/*
|
||||
* 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.utils;
|
||||
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for ListingHash
|
||||
**
|
||||
*******************************************************************************/
|
||||
class ListingHashTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private ListingHash<String, String> makeDefaultTestListingHash()
|
||||
{
|
||||
ListingHash<String, String> listingHash = new ListingHash<>();
|
||||
listingHash.add("A", "Apple");
|
||||
listingHash.add("A", "Acorn");
|
||||
listingHash.add("B", "Ball");
|
||||
return listingHash;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_add()
|
||||
{
|
||||
ListingHash<String, String> listingHash = makeDefaultTestListingHash();
|
||||
assertEquals(2, listingHash.size());
|
||||
assertEquals(2, listingHash.get("A").size());
|
||||
assertEquals(1, listingHash.get("B").size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_addAllCollectionKeyFunction()
|
||||
{
|
||||
ListingHash<String, String> listingHash = new ListingHash<>();
|
||||
listingHash.addAll(Set.of("Apple", "Acorn", "Ball"), (s -> s.substring(0, 1)));
|
||||
assertEquals(2, listingHash.size());
|
||||
assertEquals(2, listingHash.get("A").size());
|
||||
assertEquals(1, listingHash.get("B").size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_addAllListingHash()
|
||||
{
|
||||
ListingHash<String, String> source = makeDefaultTestListingHash();
|
||||
|
||||
ListingHash<String, String> listingHash = new ListingHash<>();
|
||||
source.add("A", "Arrow");
|
||||
source.add("C", "Car");
|
||||
listingHash.addAll(source);
|
||||
|
||||
assertEquals(3, listingHash.size());
|
||||
assertEquals(3, listingHash.get("A").size());
|
||||
assertEquals(1, listingHash.get("B").size());
|
||||
assertEquals(1, listingHash.get("C").size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_addAllKeyCollection()
|
||||
{
|
||||
ListingHash<String, String> listingHash = new ListingHash<>();
|
||||
listingHash.add("A", "Arrow");
|
||||
listingHash.addAll("A", Set.of("Apple", "Acorn"));
|
||||
listingHash.addAll("B", Set.of("Ball"));
|
||||
assertEquals(2, listingHash.size());
|
||||
assertEquals(3, listingHash.get("A").size());
|
||||
assertEquals(1, listingHash.get("B").size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_clear()
|
||||
{
|
||||
ListingHash<String, String> listingHash = makeDefaultTestListingHash();
|
||||
listingHash.clear();
|
||||
assertEquals(0, listingHash.size());
|
||||
assertFalse(listingHash.containsKey("A"));
|
||||
assertFalse(listingHash.containsKey("B"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_containsKey()
|
||||
{
|
||||
ListingHash<String, String> listingHash = makeDefaultTestListingHash();
|
||||
assertTrue(listingHash.containsKey("A"));
|
||||
assertTrue(listingHash.containsKey("B"));
|
||||
assertFalse(listingHash.containsKey("C"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_containsValue()
|
||||
{
|
||||
ListingHash<String, String> listingHash = makeDefaultTestListingHash();
|
||||
assertTrue(listingHash.containsValue(List.of("Apple", "Acorn")));
|
||||
assertFalse(listingHash.containsValue("Apple"));
|
||||
assertFalse(listingHash.containsValue(List.of("Apple")));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_entrySet()
|
||||
{
|
||||
ListingHash<String, String> listingHash = makeDefaultTestListingHash();
|
||||
Set<Map.Entry<String, List<String>>> entrySet = listingHash.entrySet();
|
||||
assertEquals(2, entrySet.size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@SuppressWarnings({ "SimplifiableAssertion", "EqualsWithItself" })
|
||||
@Test
|
||||
void test_equals()
|
||||
{
|
||||
ListingHash<String, String> listingHash1 = makeDefaultTestListingHash();
|
||||
ListingHash<String, String> listingHash2 = makeDefaultTestListingHash();
|
||||
assertTrue(listingHash1.equals(listingHash2));
|
||||
assertTrue(listingHash1.equals(listingHash1));
|
||||
assertFalse(listingHash1.equals(new ListingHash<>()));
|
||||
assertFalse(new ListingHash<>().equals(listingHash1));
|
||||
listingHash2.add("C", "Car");
|
||||
assertFalse(listingHash1.equals(listingHash2));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_get()
|
||||
{
|
||||
ListingHash<String, String> listingHash = makeDefaultTestListingHash();
|
||||
List<String> aList = listingHash.get("A");
|
||||
assertEquals(2, aList.size());
|
||||
assertEquals("Apple", aList.get(0));
|
||||
assertEquals("Acorn", aList.get(1));
|
||||
List<String> bList = listingHash.get("B");
|
||||
assertEquals(1, bList.size());
|
||||
assertEquals("Ball", bList.get(0));
|
||||
assertNull(listingHash.get("C"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_hashCode()
|
||||
{
|
||||
ListingHash<String, String> listingHash1 = makeDefaultTestListingHash();
|
||||
ListingHash<String, String> listingHash2 = makeDefaultTestListingHash();
|
||||
assertEquals(listingHash1.hashCode(), listingHash2.hashCode());
|
||||
assertEquals(listingHash1.hashCode(), listingHash1.hashCode());
|
||||
assertNotEquals(listingHash1.hashCode(), new ListingHash<>().hashCode());
|
||||
listingHash2.add("C", "Car");
|
||||
assertNotEquals(listingHash1.hashCode(), listingHash2.hashCode());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_isEmpty()
|
||||
{
|
||||
assertTrue(new ListingHash<>().isEmpty());
|
||||
ListingHash<String, String> listingHash = makeDefaultTestListingHash();
|
||||
assertFalse(listingHash.isEmpty());
|
||||
listingHash.clear();
|
||||
assertTrue(listingHash.isEmpty());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_keySet()
|
||||
{
|
||||
ListingHash<String, String> listingHash = makeDefaultTestListingHash();
|
||||
Set<String> keySet = listingHash.keySet();
|
||||
assertEquals(2, keySet.size());
|
||||
assertTrue(keySet.contains("A"));
|
||||
assertTrue(keySet.contains("B"));
|
||||
assertFalse(keySet.contains("C"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_put()
|
||||
{
|
||||
ListingHash<String, String> listingHash = makeDefaultTestListingHash();
|
||||
listingHash.put("A", List.of("Android"));
|
||||
assertEquals(2, listingHash.size());
|
||||
assertEquals(1, listingHash.get("A").size());
|
||||
assertEquals("Android", listingHash.get("A").get(0));
|
||||
listingHash.put("C", List.of("Car"));
|
||||
assertEquals(3, listingHash.size());
|
||||
assertEquals(1, listingHash.get("C").size());
|
||||
assertEquals("Car", listingHash.get("C").get(0));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_putAll()
|
||||
{
|
||||
ListingHash<String, String> listingHash = makeDefaultTestListingHash();
|
||||
listingHash.putAll(Map.of("C", List.of("Car"), "D", List.of("Dog", "Door")));
|
||||
assertEquals(4, listingHash.size());
|
||||
assertEquals(2, listingHash.get("A").size());
|
||||
assertEquals("Apple", listingHash.get("A").get(0));
|
||||
assertEquals("Acorn", listingHash.get("A").get(1));
|
||||
assertEquals(1, listingHash.get("C").size());
|
||||
assertEquals("Car", listingHash.get("C").get(0));
|
||||
assertEquals(2, listingHash.get("D").size());
|
||||
assertEquals("Dog", listingHash.get("D").get(0));
|
||||
assertEquals("Door", listingHash.get("D").get(1));
|
||||
|
||||
listingHash.putAll(Map.of("A", List.of("Android")));
|
||||
assertEquals(4, listingHash.size());
|
||||
assertEquals(1, listingHash.get("A").size());
|
||||
assertEquals("Android", listingHash.get("A").get(0));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_remove()
|
||||
{
|
||||
ListingHash<String, String> listingHash = makeDefaultTestListingHash();
|
||||
listingHash.remove("A");
|
||||
assertEquals(1, listingHash.size());
|
||||
assertFalse(listingHash.containsKey("A"));
|
||||
listingHash.remove("B");
|
||||
assertEquals(0, listingHash.size());
|
||||
listingHash.remove("B");
|
||||
listingHash.remove("C");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_size()
|
||||
{
|
||||
ListingHash<String, String> listingHash = makeDefaultTestListingHash();
|
||||
assertEquals(2, listingHash.size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_values()
|
||||
{
|
||||
ListingHash<String, String> listingHash = makeDefaultTestListingHash();
|
||||
Collection<List<String>> values = listingHash.values();
|
||||
assertEquals(2, values.size());
|
||||
assertTrue(values.contains(List.of("Apple", "Acorn")));
|
||||
assertTrue(values.contains(List.of("Ball")));
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.utils;
|
||||
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for SleepUtils
|
||||
*******************************************************************************/
|
||||
class SleepUtilsTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testSleep()
|
||||
{
|
||||
long start = System.currentTimeMillis();
|
||||
SleepUtils.sleep(10, TimeUnit.MILLISECONDS);
|
||||
long end = System.currentTimeMillis();
|
||||
long sleptFor = end - start;
|
||||
System.out.println("Slept for: " + sleptFor);
|
||||
assertTrue(sleptFor >= 10);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,249 @@
|
||||
/*
|
||||
* 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.utils;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for StringUtils
|
||||
**
|
||||
*******************************************************************************/
|
||||
class StringUtilsTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_hasContent()
|
||||
{
|
||||
assertFalse(StringUtils.hasContent(""));
|
||||
assertFalse(StringUtils.hasContent(" "));
|
||||
assertFalse(StringUtils.hasContent(" \n "));
|
||||
assertFalse(StringUtils.hasContent(null));
|
||||
assertTrue(StringUtils.hasContent("a"));
|
||||
assertTrue(StringUtils.hasContent(" a "));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_nvlString()
|
||||
{
|
||||
assertEquals("foo", StringUtils.nvl("foo", "bar"));
|
||||
assertEquals("bar", StringUtils.nvl(null, "bar"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_nvlObject()
|
||||
{
|
||||
assertEquals("1701", StringUtils.nvl(1701, "bar"));
|
||||
assertEquals("bar", StringUtils.nvl((Integer) null, "bar"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_allCapsToMixedCase()
|
||||
{
|
||||
assertNull(StringUtils.allCapsToMixedCase(null));
|
||||
assertEquals("Foo", StringUtils.allCapsToMixedCase("FOO"));
|
||||
assertEquals("Foo Bar", StringUtils.allCapsToMixedCase("FOO BAR"));
|
||||
assertEquals("Foo bar", StringUtils.allCapsToMixedCase("FOO bar"));
|
||||
assertEquals("Foo bar", StringUtils.allCapsToMixedCase("FOo bar"));
|
||||
assertEquals("Foo Bar", StringUtils.allCapsToMixedCase("FOo BAr"));
|
||||
assertEquals("foo bar", StringUtils.allCapsToMixedCase("foo bar"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_safeTruncate2()
|
||||
{
|
||||
assertNull(StringUtils.safeTruncate(null, 5));
|
||||
assertEquals("123", StringUtils.safeTruncate("123", 5));
|
||||
assertEquals("12345", StringUtils.safeTruncate("1234567", 5));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_safeTruncate3()
|
||||
{
|
||||
assertNull(StringUtils.safeTruncate(null, 5, "..."));
|
||||
assertEquals("123", StringUtils.safeTruncate("123", 5, "..."));
|
||||
assertEquals("12345", StringUtils.safeTruncate("12345", 5, "..."));
|
||||
assertEquals("12...", StringUtils.safeTruncate("123456", 5, "..."));
|
||||
assertEquals("12...", StringUtils.safeTruncate("1234567890", 5, "..."));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_safeTrim()
|
||||
{
|
||||
assertNull(StringUtils.safeTrim(null));
|
||||
assertEquals("foo", StringUtils.safeTrim("foo "));
|
||||
assertEquals("foo", StringUtils.safeTrim(" foo "));
|
||||
assertEquals("foo", StringUtils.safeTrim(" foo"));
|
||||
assertEquals("foo", StringUtils.safeTrim(" foo \n "));
|
||||
assertEquals("foo", StringUtils.safeTrim("\nfoo \r \n "));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_join()
|
||||
{
|
||||
assertNull(StringUtils.join(",", null));
|
||||
assertEquals("1", StringUtils.join(",", List.of(1)));
|
||||
assertEquals("", StringUtils.join(",", List.of()));
|
||||
assertEquals("1,2,3", StringUtils.join(",", List.of(1, 2, 3)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_joinWithCommasAndAnd()
|
||||
{
|
||||
assertNull(StringUtils.joinWithCommasAndAnd(null));
|
||||
assertEquals("", StringUtils.joinWithCommasAndAnd(List.of()));
|
||||
assertEquals("A", StringUtils.joinWithCommasAndAnd(List.of("A")));
|
||||
assertEquals("A and B", StringUtils.joinWithCommasAndAnd(List.of("A", "B")));
|
||||
assertEquals("A, B, and C", StringUtils.joinWithCommasAndAnd(List.of("A", "B", "C")));
|
||||
assertEquals("A, B, C, and D", StringUtils.joinWithCommasAndAnd(List.of("A", "B", "C", "D")));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_ltrim()
|
||||
{
|
||||
assertEquals("", StringUtils.ltrim(null));
|
||||
assertEquals("123", StringUtils.ltrim("123"));
|
||||
assertEquals("123", StringUtils.ltrim(" 123"));
|
||||
assertEquals("123", StringUtils.ltrim(" 123"));
|
||||
assertEquals("123", StringUtils.ltrim(" \n\n 123"));
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_rtrim()
|
||||
{
|
||||
assertEquals("", StringUtils.rtrim(null));
|
||||
assertEquals("123", StringUtils.rtrim("123"));
|
||||
assertEquals("123", StringUtils.rtrim("123 "));
|
||||
assertEquals("123", StringUtils.rtrim("123 "));
|
||||
assertEquals("123", StringUtils.rtrim("123 \n\n "));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_pluralCollection()
|
||||
{
|
||||
assertEquals("s", StringUtils.plural(List.of()));
|
||||
assertEquals("", StringUtils.plural(List.of(1)));
|
||||
assertEquals("s", StringUtils.plural(List.of(1, 2)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_pluralInteger()
|
||||
{
|
||||
assertEquals("s", StringUtils.plural(0));
|
||||
assertEquals("", StringUtils.plural(1));
|
||||
assertEquals("s", StringUtils.plural(2));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_pluralCollectionStringString()
|
||||
{
|
||||
assertEquals("es", StringUtils.plural(List.of(), "", "es"));
|
||||
assertEquals("", StringUtils.plural(List.of(1), "", "es"));
|
||||
assertEquals("es", StringUtils.plural(List.of(1, 2), "", "es"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test_pluralIntegerStringString()
|
||||
{
|
||||
assertEquals("es", StringUtils.plural(0, "", "es"));
|
||||
assertEquals("", StringUtils.plural(1, "", "es"));
|
||||
assertEquals("es", StringUtils.plural(2, "", "es"));
|
||||
}
|
||||
}
|
@ -0,0 +1,378 @@
|
||||
/*
|
||||
* 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.utils;
|
||||
|
||||
|
||||
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;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QAuthenticationType;
|
||||
import com.kingsrook.qqq.backend.core.processes.implementations.mock.MockBackendStep;
|
||||
import com.kingsrook.qqq.backend.core.modules.authentication.metadata.QAuthenticationMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeType;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeUsage;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||
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.metadata.possiblevalues.QPossibleValueSource;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSourceType;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendStepMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionInputMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionOutputMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QRecordListMetaData;
|
||||
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.backend.implementations.mock.MockBackendModule;
|
||||
import com.kingsrook.qqq.backend.core.processes.implementations.etl.basic.BasicETLProcess;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Utility class for backend-core test classes
|
||||
**
|
||||
*******************************************************************************/
|
||||
public class TestUtils
|
||||
{
|
||||
public static String DEFAULT_BACKEND_NAME = "default";
|
||||
public static String PROCESS_NAME_GREET_PEOPLE = "greet";
|
||||
public static String PROCESS_NAME_GREET_PEOPLE_INTERACTIVE = "greetInteractive";
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Define the instance used in standard tests.
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static QInstance defineInstance()
|
||||
{
|
||||
QInstance qInstance = new QInstance();
|
||||
qInstance.setAuthentication(defineAuthentication());
|
||||
qInstance.addBackend(defineBackend());
|
||||
qInstance.addTable(defineTablePerson());
|
||||
qInstance.addTable(definePersonFileTable());
|
||||
qInstance.addTable(defineTableIdAndNameOnly());
|
||||
qInstance.addPossibleValueSource(defineStatesPossibleValueSource());
|
||||
qInstance.addProcess(defineProcessGreetPeople());
|
||||
qInstance.addProcess(defineProcessGreetPeopleInteractive());
|
||||
qInstance.addProcess(defineProcessAddToPeoplesAge());
|
||||
qInstance.addProcess(new BasicETLProcess().defineProcessMetaData());
|
||||
|
||||
System.out.println(new QInstanceAdapter().qInstanceToJson(qInstance));
|
||||
|
||||
return (qInstance);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Define the "states" possible value source used in standard tests
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static QPossibleValueSource<String> defineStatesPossibleValueSource()
|
||||
{
|
||||
return new QPossibleValueSource<String>()
|
||||
.withName("state")
|
||||
.withType(QPossibleValueSourceType.ENUM)
|
||||
.withEnumValues(List.of("IL", "MO"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Define the authentication used in standard tests - using 'mock' type.
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static QAuthenticationMetaData defineAuthentication()
|
||||
{
|
||||
return new QAuthenticationMetaData()
|
||||
.withName("mock")
|
||||
.withType(QAuthenticationType.MOCK);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Define the backend used in standard tests - using 'mock' type.
|
||||
*******************************************************************************/
|
||||
public static QBackendMetaData defineBackend()
|
||||
{
|
||||
return new QBackendMetaData()
|
||||
.withName(DEFAULT_BACKEND_NAME)
|
||||
.withBackendType(MockBackendModule.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Define the 'person' table used in standard tests.
|
||||
*******************************************************************************/
|
||||
public static QTableMetaData defineTablePerson()
|
||||
{
|
||||
return new QTableMetaData()
|
||||
.withName("person")
|
||||
.withLabel("Person")
|
||||
.withBackendName(DEFAULT_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("firstName", QFieldType.STRING))
|
||||
.withField(new QFieldMetaData("lastName", QFieldType.STRING))
|
||||
.withField(new QFieldMetaData("birthDate", QFieldType.DATE))
|
||||
.withField(new QFieldMetaData("email", QFieldType.STRING))
|
||||
.withField(new QFieldMetaData("homeState", QFieldType.STRING).withPossibleValueSourceName("state"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Define a 2nd version of the 'person' table for this test (pretend it's backed by a file)
|
||||
*******************************************************************************/
|
||||
public static QTableMetaData definePersonFileTable()
|
||||
{
|
||||
return (new QTableMetaData()
|
||||
.withName("personFile")
|
||||
.withLabel("Person File")
|
||||
.withBackendName(DEFAULT_BACKEND_NAME)
|
||||
.withPrimaryKeyField("id")
|
||||
.withFields(TestUtils.defineTablePerson().getFields()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Define simple table with just an id and name
|
||||
*******************************************************************************/
|
||||
public static QTableMetaData defineTableIdAndNameOnly()
|
||||
{
|
||||
return new QTableMetaData()
|
||||
.withName("idAndNameOnly")
|
||||
.withLabel("Id and Name Only")
|
||||
.withBackendName(DEFAULT_BACKEND_NAME)
|
||||
.withPrimaryKeyField("id")
|
||||
.withField(new QFieldMetaData("id", QFieldType.INTEGER))
|
||||
.withField(new QFieldMetaData("name", QFieldType.STRING));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Define the 'greet people' process
|
||||
*******************************************************************************/
|
||||
private static QProcessMetaData defineProcessGreetPeople()
|
||||
{
|
||||
return new QProcessMetaData()
|
||||
.withName(PROCESS_NAME_GREET_PEOPLE)
|
||||
.withTableName("person")
|
||||
.addStep(new QBackendStepMetaData()
|
||||
.withName("prepare")
|
||||
.withCode(new QCodeReference()
|
||||
.withName(MockBackendStep.class.getName())
|
||||
.withCodeType(QCodeType.JAVA)
|
||||
.withCodeUsage(QCodeUsage.BACKEND_STEP)) // todo - needed, or implied in this context?
|
||||
.withInputData(new QFunctionInputMetaData()
|
||||
.withRecordListMetaData(new QRecordListMetaData().withTableName("person"))
|
||||
.withFieldList(List.of(
|
||||
new QFieldMetaData("greetingPrefix", QFieldType.STRING),
|
||||
new QFieldMetaData("greetingSuffix", QFieldType.STRING)
|
||||
)))
|
||||
.withOutputMetaData(new QFunctionOutputMetaData()
|
||||
.withRecordListMetaData(new QRecordListMetaData()
|
||||
.withTableName("person")
|
||||
.addField(new QFieldMetaData("fullGreeting", QFieldType.STRING))
|
||||
)
|
||||
.withFieldList(List.of(new QFieldMetaData("outputMessage", QFieldType.STRING))))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Define an interactive version of the 'greet people' process
|
||||
*******************************************************************************/
|
||||
private static QProcessMetaData defineProcessGreetPeopleInteractive()
|
||||
{
|
||||
return new QProcessMetaData()
|
||||
.withName(PROCESS_NAME_GREET_PEOPLE_INTERACTIVE)
|
||||
.withTableName("person")
|
||||
|
||||
.addStep(new QFrontendStepMetaData()
|
||||
.withName("setup")
|
||||
.withFormField(new QFieldMetaData("greetingPrefix", QFieldType.STRING))
|
||||
.withFormField(new QFieldMetaData("greetingSuffix", QFieldType.STRING))
|
||||
)
|
||||
|
||||
.addStep(new QBackendStepMetaData()
|
||||
.withName("doWork")
|
||||
.withCode(new QCodeReference()
|
||||
.withName(MockBackendStep.class.getName())
|
||||
.withCodeType(QCodeType.JAVA)
|
||||
.withCodeUsage(QCodeUsage.BACKEND_STEP)) // todo - needed, or implied in this context?
|
||||
.withInputData(new QFunctionInputMetaData()
|
||||
.withRecordListMetaData(new QRecordListMetaData().withTableName("person"))
|
||||
.withFieldList(List.of(
|
||||
new QFieldMetaData("greetingPrefix", QFieldType.STRING),
|
||||
new QFieldMetaData("greetingSuffix", QFieldType.STRING)
|
||||
)))
|
||||
.withOutputMetaData(new QFunctionOutputMetaData()
|
||||
.withRecordListMetaData(new QRecordListMetaData()
|
||||
.withTableName("person")
|
||||
.addField(new QFieldMetaData("fullGreeting", QFieldType.STRING))
|
||||
)
|
||||
.withFieldList(List.of(new QFieldMetaData("outputMessage", QFieldType.STRING))))
|
||||
)
|
||||
|
||||
.addStep(new QFrontendStepMetaData()
|
||||
.withName("results")
|
||||
.withFormField(new QFieldMetaData("outputMessage", QFieldType.STRING))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Define the "add to people's age" process
|
||||
**
|
||||
** Works on a list of rows from the person table.
|
||||
** - first function reports the current min & max age for all input rows.
|
||||
** - user is then prompted for how much they want to add to everyone.
|
||||
** - then the second function adds that value to their age, and shows the results.
|
||||
*******************************************************************************/
|
||||
private static QProcessMetaData defineProcessAddToPeoplesAge()
|
||||
{
|
||||
return new QProcessMetaData()
|
||||
.withName("addToPeoplesAge")
|
||||
.withTableName("person")
|
||||
.addStep(new QBackendStepMetaData()
|
||||
.withName("getAgeStatistics")
|
||||
.withCode(new QCodeReference()
|
||||
.withName(GetAgeStatistics.class.getName())
|
||||
.withCodeType(QCodeType.JAVA)
|
||||
.withCodeUsage(QCodeUsage.BACKEND_STEP))
|
||||
.withInputData(new QFunctionInputMetaData()
|
||||
.withRecordListMetaData(new QRecordListMetaData().withTableName("person")))
|
||||
.withOutputMetaData(new QFunctionOutputMetaData()
|
||||
.withRecordListMetaData(new QRecordListMetaData()
|
||||
.withTableName("person")
|
||||
.addField(new QFieldMetaData("age", QFieldType.INTEGER)))
|
||||
.withFieldList(List.of(
|
||||
new QFieldMetaData("minAge", QFieldType.INTEGER),
|
||||
new QFieldMetaData("maxAge", QFieldType.INTEGER)))))
|
||||
.addStep(new QBackendStepMetaData()
|
||||
.withName("addAge")
|
||||
.withCode(new QCodeReference()
|
||||
.withName(AddAge.class.getName())
|
||||
.withCodeType(QCodeType.JAVA)
|
||||
.withCodeUsage(QCodeUsage.BACKEND_STEP))
|
||||
.withInputData(new QFunctionInputMetaData()
|
||||
.withFieldList(List.of(new QFieldMetaData("yearsToAdd", QFieldType.INTEGER))))
|
||||
.withOutputMetaData(new QFunctionOutputMetaData()
|
||||
.withRecordListMetaData(new QRecordListMetaData()
|
||||
.withTableName("person")
|
||||
.addField(new QFieldMetaData("newAge", QFieldType.INTEGER)))));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static QSession getMockSession()
|
||||
{
|
||||
MockAuthenticationModule mockAuthenticationModule = new MockAuthenticationModule();
|
||||
return (mockAuthenticationModule.createSession(null, null));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static List<QRecord> queryTable(String tableName) throws QException
|
||||
{
|
||||
QueryInput queryInput = new QueryInput(TestUtils.defineInstance());
|
||||
queryInput.setSession(TestUtils.getMockSession());
|
||||
queryInput.setTableName(tableName);
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
return (queryOutput.getRecords());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static String getPersonCsvHeader()
|
||||
{
|
||||
return ("""
|
||||
"id","createDate","modifyDate","firstName","lastName","birthDate","email"
|
||||
""");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static String getPersonCsvHeaderUsingLabels()
|
||||
{
|
||||
return ("""
|
||||
"Id","Create Date","Modify Date","First Name","Last Name","Birth Date","Email"
|
||||
""");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static String getPersonCsvRow1()
|
||||
{
|
||||
return ("""
|
||||
"0","2021-10-26 14:39:37","2021-10-26 14:39:37","John","Doe","1980-01-01","john@doe.com"
|
||||
""");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static String getPersonCsvRow2()
|
||||
{
|
||||
return ("""
|
||||
"0","2021-10-26 14:39:37","2021-10-26 14:39:37","Jane","Doe","1981-01-01","john@doe.com"
|
||||
""");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* 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.utils;
|
||||
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QValueException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for ValueUtils
|
||||
*******************************************************************************/
|
||||
class ValueUtilsTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testGetValueAsString() throws QValueException
|
||||
{
|
||||
assertNull(ValueUtils.getValueAsString(null));
|
||||
assertEquals("", ValueUtils.getValueAsString(""));
|
||||
assertEquals(" ", ValueUtils.getValueAsString(" "));
|
||||
assertEquals("A", ValueUtils.getValueAsString("A"));
|
||||
assertEquals("1", ValueUtils.getValueAsString("1"));
|
||||
assertEquals("1", ValueUtils.getValueAsString(1));
|
||||
assertEquals("1", ValueUtils.getValueAsString(1));
|
||||
assertEquals("1.10", ValueUtils.getValueAsString(new BigDecimal("1.10")));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testGetValueAsBoolean() throws QValueException
|
||||
{
|
||||
assertNull(ValueUtils.getValueAsBoolean(null));
|
||||
assertTrue(ValueUtils.getValueAsBoolean("true"));
|
||||
assertTrue(ValueUtils.getValueAsBoolean("True"));
|
||||
assertTrue(ValueUtils.getValueAsBoolean("TRUE"));
|
||||
assertFalse(ValueUtils.getValueAsBoolean("false"));
|
||||
assertFalse(ValueUtils.getValueAsBoolean("yes"));
|
||||
assertFalse(ValueUtils.getValueAsBoolean("t"));
|
||||
assertFalse(ValueUtils.getValueAsBoolean(new Object()));
|
||||
assertFalse(ValueUtils.getValueAsBoolean(1));
|
||||
assertTrue(ValueUtils.getValueAsBoolean(new Object()
|
||||
{
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return ("true");
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testGetValueAsInteger() throws QValueException
|
||||
{
|
||||
assertNull(ValueUtils.getValueAsInteger(null));
|
||||
assertNull(ValueUtils.getValueAsInteger(""));
|
||||
assertNull(ValueUtils.getValueAsInteger(" "));
|
||||
assertEquals(1, ValueUtils.getValueAsInteger(1));
|
||||
assertEquals(1, ValueUtils.getValueAsInteger("1"));
|
||||
assertEquals(1_000, ValueUtils.getValueAsInteger("1,000"));
|
||||
assertEquals(1_000_000, ValueUtils.getValueAsInteger("1,000,000"));
|
||||
assertEquals(1, ValueUtils.getValueAsInteger(new BigDecimal(1)));
|
||||
assertEquals(1, ValueUtils.getValueAsInteger(new BigDecimal("1.00")));
|
||||
assertEquals(-1, ValueUtils.getValueAsInteger("-1.00"));
|
||||
assertEquals(1_000, ValueUtils.getValueAsInteger("1,000.00"));
|
||||
assertEquals(1_000, ValueUtils.getValueAsInteger(1000L));
|
||||
assertEquals(1, ValueUtils.getValueAsInteger(1.0F));
|
||||
assertEquals(1, ValueUtils.getValueAsInteger(1.0D));
|
||||
|
||||
assertThrows(QValueException.class, () -> ValueUtils.getValueAsInteger("a"));
|
||||
assertThrows(QValueException.class, () -> ValueUtils.getValueAsInteger("a,b"));
|
||||
assertThrows(QValueException.class, () -> ValueUtils.getValueAsInteger(new Object()));
|
||||
assertThrows(QValueException.class, () -> ValueUtils.getValueAsInteger(1_000_000_000_000L));
|
||||
assertThrows(QValueException.class, () -> ValueUtils.getValueAsInteger(1.1F));
|
||||
assertThrows(QValueException.class, () -> ValueUtils.getValueAsInteger(1.1D));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testGetValueAsBigDecimal() throws QValueException
|
||||
{
|
||||
assertNull(ValueUtils.getValueAsBigDecimal(null));
|
||||
assertNull(ValueUtils.getValueAsBigDecimal(""));
|
||||
assertNull(ValueUtils.getValueAsBigDecimal(" "));
|
||||
assertEquals(new BigDecimal("1"), ValueUtils.getValueAsBigDecimal(1));
|
||||
assertEquals(new BigDecimal("1"), ValueUtils.getValueAsBigDecimal("1"));
|
||||
assertEquals(new BigDecimal("1000"), ValueUtils.getValueAsBigDecimal("1,000"));
|
||||
assertEquals(new BigDecimal("1000000"), ValueUtils.getValueAsBigDecimal("1,000,000"));
|
||||
assertEquals(new BigDecimal("1"), ValueUtils.getValueAsBigDecimal(new BigDecimal(1)));
|
||||
assertEquals(new BigDecimal("1.00"), ValueUtils.getValueAsBigDecimal(new BigDecimal("1.00")));
|
||||
assertEquals(new BigDecimal("-1.00"), ValueUtils.getValueAsBigDecimal("-1.00"));
|
||||
assertEquals(new BigDecimal("1000.00"), ValueUtils.getValueAsBigDecimal("1,000.00"));
|
||||
assertEquals(new BigDecimal("1000"), ValueUtils.getValueAsBigDecimal(1000L));
|
||||
assertEquals(new BigDecimal("1"), ValueUtils.getValueAsBigDecimal(1.0F));
|
||||
assertEquals(new BigDecimal("1"), ValueUtils.getValueAsBigDecimal(1.0D));
|
||||
assertEquals(new BigDecimal("1000000000000"), ValueUtils.getValueAsBigDecimal(1_000_000_000_000L));
|
||||
assertEquals(0, new BigDecimal("1.1").compareTo(ValueUtils.getValueAsBigDecimal(1.1F).round(MathContext.DECIMAL32)));
|
||||
assertEquals(0, new BigDecimal("1.1").compareTo(ValueUtils.getValueAsBigDecimal(1.1D).round(MathContext.DECIMAL64)));
|
||||
|
||||
assertThrows(QValueException.class, () -> ValueUtils.getValueAsBigDecimal("a"));
|
||||
assertThrows(QValueException.class, () -> ValueUtils.getValueAsBigDecimal("a,b"));
|
||||
assertThrows(QValueException.class, () -> ValueUtils.getValueAsBigDecimal(new Object()));
|
||||
}
|
||||
|
||||
}
|
156
qqq-backend-core/src/test/resources/personQInstance.json
Normal file
156
qqq-backend-core/src/test/resources/personQInstance.json
Normal file
@ -0,0 +1,156 @@
|
||||
{
|
||||
"authentication": {
|
||||
"name": "mock",
|
||||
"type": "mock",
|
||||
"values": null
|
||||
},
|
||||
"tables": {
|
||||
"person": {
|
||||
"name": "person",
|
||||
"label": "Person",
|
||||
"backendName": "default",
|
||||
"primaryKeyField": "id",
|
||||
"fields": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"label": null,
|
||||
"backendName": null,
|
||||
"type": "INTEGER",
|
||||
"possibleValueSourceName": null
|
||||
},
|
||||
"createDate": {
|
||||
"name": "createDate",
|
||||
"label": null,
|
||||
"backendName": null,
|
||||
"type": "DATE_TIME",
|
||||
"possibleValueSourceName": null
|
||||
},
|
||||
"modifyDate": {
|
||||
"name": "modifyDate",
|
||||
"label": null,
|
||||
"backendName": null,
|
||||
"type": "DATE_TIME",
|
||||
"possibleValueSourceName": null
|
||||
},
|
||||
"firstName": {
|
||||
"name": "firstName",
|
||||
"label": null,
|
||||
"backendName": null,
|
||||
"type": "STRING",
|
||||
"possibleValueSourceName": null
|
||||
},
|
||||
"lastName": {
|
||||
"name": "lastName",
|
||||
"label": null,
|
||||
"backendName": null,
|
||||
"type": "STRING",
|
||||
"possibleValueSourceName": null
|
||||
},
|
||||
"birthDate": {
|
||||
"name": "birthDate",
|
||||
"label": null,
|
||||
"backendName": null,
|
||||
"type": "DATE",
|
||||
"possibleValueSourceName": null
|
||||
},
|
||||
"email": {
|
||||
"name": "email",
|
||||
"label": null,
|
||||
"backendName": null,
|
||||
"type": "STRING",
|
||||
"possibleValueSourceName": null
|
||||
},
|
||||
"homeState": {
|
||||
"name": "homeState",
|
||||
"label": null,
|
||||
"backendName": null,
|
||||
"type": "STRING",
|
||||
"possibleValueSourceName": "state"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"possibleValueSources": {
|
||||
"state": {
|
||||
"name": "state",
|
||||
"type": "ENUM",
|
||||
"enumValues": [
|
||||
"IL",
|
||||
"MO"
|
||||
]
|
||||
}
|
||||
},
|
||||
"processes": {
|
||||
"greet": {
|
||||
"name": "greet",
|
||||
"tableName": "person",
|
||||
"stepList": [
|
||||
{
|
||||
"name": "prepare",
|
||||
"label": null,
|
||||
"inputMetaData": {
|
||||
"recordListMetaData": {
|
||||
"tableName": "person",
|
||||
"fields": null
|
||||
},
|
||||
"fieldList": [
|
||||
{
|
||||
"name": "greetingPrefix",
|
||||
"label": null,
|
||||
"backendName": null,
|
||||
"type": "STRING",
|
||||
"possibleValueSourceName": null
|
||||
},
|
||||
{
|
||||
"name": "greetingSuffix",
|
||||
"label": null,
|
||||
"backendName": null,
|
||||
"type": "STRING",
|
||||
"possibleValueSourceName": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"outputMetaData": {
|
||||
"recordListMetaData": {
|
||||
"tableName": "person",
|
||||
"fields": {
|
||||
"fullGreeting": {
|
||||
"name": "fullGreeting",
|
||||
"label": null,
|
||||
"backendName": null,
|
||||
"type": "STRING",
|
||||
"possibleValueSourceName": null
|
||||
}
|
||||
}
|
||||
},
|
||||
"fieldList": [
|
||||
{
|
||||
"name": "outputMessage",
|
||||
"label": null,
|
||||
"backendName": null,
|
||||
"type": "STRING",
|
||||
"possibleValueSourceName": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"code": {
|
||||
"name": "com.kingsrook.qqq.backend.core.interfaces.mock.MockFunctionBody",
|
||||
"codeType": "JAVA",
|
||||
"codeUsage": "FUNCTION"
|
||||
},
|
||||
"outputView": {
|
||||
"messageField": "outputMessage",
|
||||
"recordListView": {
|
||||
"fieldNames": [
|
||||
"id",
|
||||
"firstName",
|
||||
"lastName",
|
||||
"fullGreeting"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,162 @@
|
||||
{
|
||||
"tables": {
|
||||
"person": {
|
||||
"primaryKeyField": "id",
|
||||
"name": "person",
|
||||
"backendName": "default",
|
||||
"label": "Person",
|
||||
"fields": {
|
||||
"firstName": {
|
||||
"name": "firstName",
|
||||
"backendName": null,
|
||||
"label": null,
|
||||
"type": "STRING",
|
||||
"possibleValueSourceName": null
|
||||
},
|
||||
"lastName": {
|
||||
"name": "lastName",
|
||||
"backendName": null,
|
||||
"label": null,
|
||||
"type": "STRING",
|
||||
"possibleValueSourceName": null
|
||||
},
|
||||
"modifyDate": {
|
||||
"name": "modifyDate",
|
||||
"backendName": null,
|
||||
"label": null,
|
||||
"type": "DATE_TIME",
|
||||
"possibleValueSourceName": null
|
||||
},
|
||||
"homeState": {
|
||||
"name": "homeState",
|
||||
"backendName": null,
|
||||
"label": null,
|
||||
"type": "STRING",
|
||||
"possibleValueSourceName": "state"
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"backendName": null,
|
||||
"label": null,
|
||||
"type": "INTEGER",
|
||||
"possibleValueSourceName": null
|
||||
},
|
||||
"birthDate": {
|
||||
"name": "birthDate",
|
||||
"backendName": null,
|
||||
"label": null,
|
||||
"type": "DATE",
|
||||
"possibleValueSourceName": null
|
||||
},
|
||||
"email": {
|
||||
"name": "email",
|
||||
"backendName": null,
|
||||
"label": null,
|
||||
"type": "STRING",
|
||||
"possibleValueSourceName": null
|
||||
},
|
||||
"createDate": {
|
||||
"name": "createDate",
|
||||
"backendName": null,
|
||||
"label": null,
|
||||
"type": "DATE_TIME",
|
||||
"possibleValueSourceName": null
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"processes": {
|
||||
"greet": {
|
||||
"functionList": [
|
||||
{
|
||||
"code": {
|
||||
"codeUsage": "FUNCTION",
|
||||
"codeType": "JAVA",
|
||||
"name": "com.kingsrook.qqq.backend.core.interfaces.mock.MockFunctionBody"
|
||||
},
|
||||
"inputMetaData": {
|
||||
"recordListMetaData": {
|
||||
"fields": null,
|
||||
"tableName": "person"
|
||||
},
|
||||
"fieldList": [
|
||||
{
|
||||
"name": "greetingPrefix",
|
||||
"backendName": null,
|
||||
"label": null,
|
||||
"type": "STRING",
|
||||
"possibleValueSourceName": null
|
||||
},
|
||||
{
|
||||
"name": "greetingSuffix",
|
||||
"backendName": null,
|
||||
"label": null,
|
||||
"type": "STRING",
|
||||
"possibleValueSourceName": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"outputMetaData": {
|
||||
"recordListMetaData": {
|
||||
"fields": {
|
||||
"fullGreeting": {
|
||||
"name": "fullGreeting",
|
||||
"backendName": null,
|
||||
"label": null,
|
||||
"type": "STRING",
|
||||
"possibleValueSourceName": null
|
||||
}
|
||||
},
|
||||
"tableName": "person"
|
||||
},
|
||||
"fieldList": [
|
||||
{
|
||||
"name": "outputMessage",
|
||||
"backendName": null,
|
||||
"label": null,
|
||||
"type": "STRING",
|
||||
"possibleValueSourceName": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"outputView": {
|
||||
"messageField": "outputMessage",
|
||||
"recordListView": {
|
||||
"fieldNames": [
|
||||
"id",
|
||||
"firstName",
|
||||
"lastName",
|
||||
"fullGreeting"
|
||||
]
|
||||
}
|
||||
},
|
||||
"name": "prepare",
|
||||
"label": null
|
||||
}
|
||||
],
|
||||
"name": "greet",
|
||||
"tableName": "person"
|
||||
}
|
||||
},
|
||||
"possibleValueSources": {
|
||||
"state": {
|
||||
"name": "state",
|
||||
"type": "ENUM",
|
||||
"enumValues": [
|
||||
"IL",
|
||||
"MO"
|
||||
]
|
||||
}
|
||||
},
|
||||
"backends": {
|
||||
"default": {
|
||||
"name": "default",
|
||||
"backendType": "mock"
|
||||
}
|
||||
},
|
||||
"authentication": {
|
||||
"values": null,
|
||||
"name": "mock",
|
||||
"type": "mock"
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user