Skip to content

Commit a3f6160

Browse files
Merge pull request #5 from JavaWebStack/TimothyGillespie/automigrationTests
Auto Migration Tests (Part 1 - auto migration mysql types, default size setting)
2 parents 7c312d8 + 824898c commit a3f6160

File tree

12 files changed

+582
-28
lines changed

12 files changed

+582
-28
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
*.iml
22
target
3-
.idea
3+
.idea
4+
testenv.properties

src/main/java/org/javawebstack/orm/ORMConfig.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.javawebstack.orm;
22

33
import org.javawebstack.injector.Injector;
4+
import org.javawebstack.orm.exception.ORMConfigurationException;
45
import org.javawebstack.orm.mapper.DefaultMapper;
56
import org.javawebstack.orm.mapper.TypeMapper;
67

@@ -30,7 +31,10 @@ public ORMConfig setCamelToSnakeCase(boolean camelToSnakeCase) {
3031
return this;
3132
}
3233

33-
public ORMConfig setDefaultSize(int defaultSize) {
34+
public ORMConfig setDefaultSize(int defaultSize) throws ORMConfigurationException {
35+
if(defaultSize <= 0)
36+
throw new ORMConfigurationException("Default size must be positive and non-zero. If this exceptions occurs unexpectedly make sure no overflow is occurring.");
37+
3438
this.defaultSize = defaultSize;
3539
return this;
3640
}

src/test/java/org/javawebstack/orm/test/ORMTestCase.java

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,23 @@
33
import org.javawebstack.orm.ORM;
44
import org.javawebstack.orm.Repo;
55
import org.javawebstack.orm.migration.AutoMigrator;
6-
import org.javawebstack.orm.wrapper.MySQL;
7-
import org.javawebstack.orm.wrapper.SQL;
6+
import org.javawebstack.orm.test.shared.settings.MySQLConnectionContainer;
7+
import org.junit.jupiter.api.AfterAll;
8+
import org.junit.jupiter.api.BeforeEach;
89

9-
public abstract class ORMTestCase {
10+
public abstract class ORMTestCase extends MySQLConnectionContainer {
1011

11-
private static final SQL sql;
12-
13-
static {
14-
String host = System.getenv("MYSQL_HOST");
15-
String port = System.getenv("MYSQL_PORT");
16-
String name = System.getenv("MYSQL_DATABASE");
17-
String user = System.getenv("MYSQL_USERNAME");
18-
String password = System.getenv("MYSQL_PASSWORD");
19-
sql = new MySQL(
20-
host != null ? host : "localhost",
21-
port != null ? Integer.parseInt(port) : 3306,
22-
name != null ? name : "test",
23-
user != null ? user : "root",
24-
password != null ? password : ""
25-
);
26-
}
27-
28-
{
12+
@BeforeEach
13+
public void beforeEach() {
2914
reset();
3015
}
3116

32-
protected static void reset() {
17+
@AfterAll
18+
public static void finishTestClass() { reset(); }
19+
20+
public static void reset() {
3321
AutoMigrator.drop(ORM.getRepos().toArray(new Repo[0]));
3422
ORM.reset();
3523
}
3624

37-
protected static SQL sql() {
38-
return sql;
39-
}
40-
4125
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package org.javawebstack.orm.test.automigrate;
2+
3+
import org.javawebstack.orm.ORM;
4+
import org.javawebstack.orm.ORMConfig;
5+
import org.javawebstack.orm.exception.ORMConfigurationException;
6+
import org.javawebstack.orm.test.ORMTestCase;
7+
import org.javawebstack.orm.test.shared.models.Datatype;
8+
import org.javawebstack.orm.test.shared.verification.Field;
9+
import org.javawebstack.orm.test.shared.verification.IdField;
10+
import org.junit.jupiter.api.BeforeEach;
11+
import org.junit.jupiter.api.Test;
12+
13+
import java.sql.SQLException;
14+
import java.util.HashMap;
15+
import java.util.Map;
16+
17+
public class CommonTest extends ORMTestCase {
18+
19+
private static final String tableName = "datatypes";
20+
private final Map<String, String> columnDataTypeMap;
21+
22+
{
23+
columnDataTypeMap = new HashMap<>();
24+
25+
columnDataTypeMap.put("primitive_boolean", "tinyint(1)");
26+
columnDataTypeMap.put("wrapper_boolean", "tinyint(1)");
27+
28+
columnDataTypeMap.put("primitive_byte", "tinyint(4)");
29+
columnDataTypeMap.put("wrapper_byte", "tinyint(4)");
30+
31+
columnDataTypeMap.put("primitive_short", "smallint(6)");
32+
columnDataTypeMap.put("wrapper_short", "smallint(6)");
33+
34+
columnDataTypeMap.put("primitive_integer", "int(11)");
35+
columnDataTypeMap.put("wrapper_integer", "int(11)");
36+
37+
columnDataTypeMap.put("primitive_long", "bigint(20)");
38+
columnDataTypeMap.put("wrapper_long", "bigint(20)");
39+
40+
columnDataTypeMap.put("primitive_float", "float");
41+
columnDataTypeMap.put("wrapper_float", "float");
42+
43+
columnDataTypeMap.put("primitive_double", "double");
44+
columnDataTypeMap.put("wrapper_double", "double");
45+
46+
columnDataTypeMap.put("primitive_char", "char(1)");
47+
48+
columnDataTypeMap.put("wrapper_string", "varchar(255)");
49+
50+
columnDataTypeMap.put("char_array", "varchar(255)");
51+
52+
columnDataTypeMap.put("byte_array", "varbinary(255)");
53+
54+
columnDataTypeMap.put("timestamp", "timestamp");
55+
56+
columnDataTypeMap.put("date", "date");
57+
58+
columnDataTypeMap.put("uuid", "varchar(36)");
59+
60+
columnDataTypeMap.put("option_enum", "enum('OPTION1','OPTION2')");
61+
}
62+
63+
@BeforeEach
64+
public void setUp() throws ORMConfigurationException {
65+
ORMConfig config = new ORMConfig()
66+
.setDefaultSize(255);
67+
ORM.register(Datatype.class, sql(), config);
68+
ORM.autoMigrate(true);
69+
}
70+
71+
@Test
72+
public void testId() throws SQLException {
73+
IdField.assertCorrectDatabaseFormat(tableName);
74+
}
75+
76+
@Test
77+
public void testDatatypes() throws SQLException {
78+
Field checkedField;
79+
80+
for(Map.Entry<String, String> entry : columnDataTypeMap.entrySet()) {
81+
checkedField = new Field(tableName, entry.getKey());
82+
checkedField.assertType(entry.getValue());
83+
}
84+
85+
}
86+
87+
@Test
88+
public void testNullable() throws SQLException {
89+
Field checkedField;
90+
91+
for(Map.Entry<String, String> entry : columnDataTypeMap.entrySet()) {
92+
checkedField = new Field(tableName, entry.getKey());
93+
checkedField.assertNullable();
94+
}
95+
}
96+
97+
@Test
98+
public void testNotPrimaryKey() throws SQLException {
99+
Field checkedField;
100+
101+
for(Map.Entry<String, String> entry : columnDataTypeMap.entrySet()) {
102+
checkedField = new Field(tableName, entry.getKey());
103+
checkedField.assertNotPrimaryKey();
104+
}
105+
}
106+
107+
@Test
108+
public void testNotAutoIncrement() throws SQLException {
109+
Field checkedField;
110+
111+
for(Map.Entry<String, String> entry : columnDataTypeMap.entrySet()) {
112+
checkedField = new Field(tableName, entry.getKey());
113+
checkedField.assertNotAutoIncrementing();
114+
}
115+
}
116+
117+
}
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
package org.javawebstack.orm.test.automigrate;
2+
3+
import org.javawebstack.orm.Model;
4+
import org.javawebstack.orm.ORM;
5+
import org.javawebstack.orm.ORMConfig;
6+
import org.javawebstack.orm.exception.ORMConfigurationException;
7+
import org.javawebstack.orm.test.ORMTestCase;
8+
import org.javawebstack.orm.test.shared.models.Datatype;
9+
import org.javawebstack.orm.test.shared.models.JustCharArray;
10+
import org.javawebstack.orm.test.shared.models.JustString;
11+
import org.javawebstack.orm.test.shared.verification.Field;
12+
import org.junit.jupiter.api.Test;
13+
14+
import java.sql.SQLException;
15+
16+
import static org.junit.jupiter.api.Assertions.assertThrows;
17+
18+
/**
19+
* This class tests if the default size is being applied for the types:
20+
* - String
21+
* - char[]
22+
*
23+
* This class also tests that the default size is not applied to the type:
24+
* - short
25+
* - Short
26+
* - int
27+
* - Integer
28+
* - float
29+
* - Float
30+
* - double
31+
* - Double
32+
*
33+
* And covers the following error cases:
34+
* - negative default size has been set
35+
* - zero default size has been set
36+
*/
37+
public class DefaultSizeTest extends ORMTestCase {
38+
39+
// Copy from DefaultMapper:
40+
// SOURCES:
41+
// TEXT Datatypes: https://www.mysqltutorial.org/mysql-text/
42+
private static final int BYTES_OVERHEAD_VARCHAR = 4;
43+
private static final int BYTES_OVERHEAD_TINYTEXT = 1;
44+
private static final int BYTES_OVERHEAD_TEXT = 2;
45+
private static final int BYTES_OVERHEAD_MEDIUMTEXT = 3;
46+
private static final int BYTES_OVERHEAD_LONGTEXT = 4;
47+
48+
// The max sizes given in the manual are in bytes. There are overheads which need to be subtracted.
49+
// The following values assume utf8mb4 encoding which uses 4 bytes per character and
50+
// further quarters the maximum column length accordingly.
51+
private static final long MAX_SIZE_VARCHAR = (long) Math.floor((65535 - BYTES_OVERHEAD_VARCHAR) / 4.0);
52+
private static final long MAX_SIZE_MEDIUMTEXT = (long) Math.floor((16777215 - BYTES_OVERHEAD_MEDIUMTEXT) / 4.0);
53+
private static final long MAX_SIZE_LONGTEXT = (long) Math.floor((4294967295L - BYTES_OVERHEAD_LONGTEXT) / 4.0);
54+
55+
final static String tableNameString = "just_strings";
56+
final static String columnNameString = "string";
57+
58+
// Not renaming the table name as this is not focus of the test
59+
final static String tableNameCharArray = "just_char_arraies";
60+
final static String columnNameCharArray = "char_array";
61+
62+
final static String tableNameDatatype = "datatypes";
63+
64+
/*
65+
* Positive Test
66+
*/
67+
68+
// String
69+
@Test
70+
public void testStringUsesDefaultSizeChar() throws ORMConfigurationException, SQLException {
71+
setUpWithDefaultSize(JustString.class, 1);
72+
(new Field(tableNameString, columnNameString)).assertType("char(1)");
73+
}
74+
75+
@Test
76+
public void testStringUsesDefaultSizeVarchar() throws ORMConfigurationException, SQLException {
77+
int[] parameters = {2, 3, 123, 1234, 12345, (int) MAX_SIZE_VARCHAR - 1, (int) MAX_SIZE_VARCHAR};
78+
for( int singleParameter : parameters) {
79+
setUpWithDefaultSize(JustString.class, singleParameter);
80+
(new Field(tableNameString, columnNameString)).assertType(String.format("varchar(%s)", singleParameter));
81+
}
82+
}
83+
84+
@Test
85+
public void testStringUsesDefaultSizeMediumText() throws ORMConfigurationException, SQLException {
86+
int[] parameters = {(int) MAX_SIZE_VARCHAR + 1, 123456, 1234567, (int) MAX_SIZE_MEDIUMTEXT - 1};
87+
for( int singleParameter : parameters) {
88+
setUpWithDefaultSize(JustString.class, singleParameter);
89+
(new Field(tableNameString, columnNameString)).assertType("mediumtext");
90+
}
91+
}
92+
93+
@Test
94+
public void testStringUsesDefaultSizeLongText() throws ORMConfigurationException, SQLException {
95+
int[] parameters = {(int) MAX_SIZE_MEDIUMTEXT + 1, 123456789, 123467890, Integer.MAX_VALUE};
96+
for( int singleParameter : parameters) {
97+
setUpWithDefaultSize(JustString.class, singleParameter);
98+
(new Field(tableNameString, columnNameString)).assertType("longtext");
99+
}
100+
}
101+
102+
// Char Array
103+
@Test
104+
public void testCharArrayUsesDefaultSizeChar() throws ORMConfigurationException, SQLException {
105+
setUpWithDefaultSize(JustCharArray.class, 1);
106+
(new Field(tableNameCharArray, columnNameCharArray)).assertType("char(1)");
107+
}
108+
109+
@Test
110+
public void testCharArrayUsesDefaultSizeVarchar() throws ORMConfigurationException, SQLException {
111+
int[] parameters = {2, 3, 123, 1234, 12345, (int) MAX_SIZE_VARCHAR - 1, (int) MAX_SIZE_VARCHAR};
112+
for( int singleParameter : parameters) {
113+
setUpWithDefaultSize(JustCharArray.class, singleParameter);
114+
(new Field(tableNameCharArray, columnNameCharArray)).assertType(String.format("varchar(%s)", singleParameter));
115+
}
116+
}
117+
118+
@Test
119+
public void testCharArrayUsesDefaultSizeMediumText() throws ORMConfigurationException, SQLException {
120+
int[] parameters = {(int) MAX_SIZE_VARCHAR + 1, 123456, 1234567, (int) MAX_SIZE_MEDIUMTEXT - 1};
121+
for( int singleParameter : parameters) {
122+
setUpWithDefaultSize(JustCharArray.class, singleParameter);
123+
(new Field(tableNameCharArray, columnNameCharArray)).assertType("mediumtext");
124+
}
125+
}
126+
127+
@Test
128+
public void testCharArrayUsesDefaultSizeLongText() throws ORMConfigurationException, SQLException {
129+
int[] parameters = {(int) MAX_SIZE_MEDIUMTEXT + 1, 123456789, 123467890, Integer.MAX_VALUE};
130+
for( int singleParameter : parameters) {
131+
setUpWithDefaultSize(JustCharArray.class, singleParameter);
132+
(new Field(tableNameCharArray, columnNameCharArray)).assertType("longtext");
133+
}
134+
}
135+
136+
/*
137+
* Negative Tests
138+
*/
139+
140+
@Test
141+
public void testOtherDataTypesDoNotUseDefaultSize() throws ORMConfigurationException, SQLException {
142+
// smallint defaults to the size 6 the default size should therefore not be chosen as 6 or higher;
143+
setUpWithDefaultSize(Datatype.class, 5);
144+
145+
// smallint defaults to 6
146+
(new Field(tableNameDatatype, "primitive_short")).assertType("smallint(6)");
147+
(new Field(tableNameDatatype, "wrapper_short")).assertType("smallint(6)");
148+
149+
// tinyint defaults to 11
150+
(new Field(tableNameDatatype, "primitive_integer")).assertType("int(11)");
151+
(new Field(tableNameDatatype, "wrapper_integer")).assertType("int(11)");
152+
153+
// bigint defaults to 20
154+
(new Field(tableNameDatatype, "primitive_long")).assertType("bigint(20)");
155+
(new Field(tableNameDatatype, "wrapper_long")).assertType("bigint(20)");
156+
157+
(new Field(tableNameDatatype, "primitive_float")).assertType("float");
158+
(new Field(tableNameDatatype, "wrapper_float")).assertType("float");
159+
160+
(new Field(tableNameDatatype, "primitive_double")).assertType("double");
161+
(new Field(tableNameDatatype, "wrapper_double")).assertType("double");
162+
}
163+
164+
/*
165+
* Error Cases
166+
*/
167+
168+
@Test
169+
public void defaultSizeIsZero() {
170+
assertThrows(
171+
ORMConfigurationException.class,
172+
() -> new ORMConfig().setDefaultSize(0),
173+
"Registering a class with a default size of 0 must throw an ORMConfigurationException but it didn't."
174+
);
175+
}
176+
177+
@Test
178+
public void defaultSizeIsNegative() {
179+
assertThrows(
180+
ORMConfigurationException.class,
181+
() -> setUpWithDefaultSize(JustString.class, -1),
182+
"Registering a class with a negative default size must throw an ORMConfigurationException but it didn't."
183+
);
184+
}
185+
186+
187+
private void setUpWithDefaultSize(Class<? extends Model> clazz, int defaultSize) throws ORMConfigurationException {
188+
ORMConfig config = new ORMConfig()
189+
.setDefaultSize(defaultSize);
190+
ORM.register(clazz, sql(), config);
191+
ORM.autoMigrate(true);
192+
}
193+
}

0 commit comments

Comments
 (0)