1
+ package com .github .wassertim .dynamodb .toolkit .integration ;
2
+
3
+ import org .junit .jupiter .api .Test ;
4
+ import org .junit .jupiter .api .DisplayName ;
5
+ import static org .assertj .core .api .Assertions .*;
6
+
7
+ import java .io .IOException ;
8
+ import java .nio .file .Files ;
9
+ import java .nio .file .Path ;
10
+ import java .util .List ;
11
+ import java .util .regex .Pattern ;
12
+
13
+ /**
14
+ * Validation tests for JavaPoet-generated code quality and performance.
15
+ */
16
+ public class JavaPoetValidationTest {
17
+
18
+ @ Test
19
+ @ DisplayName ("Validate TestUserMapper code quality" )
20
+ void validateTestUserMapperQuality () throws IOException {
21
+ Path mapperPath = Path .of ("target/generated-sources/annotations/com/github/wassertim/dynamodb/toolkit/mappers/TestUserMapper.java" );
22
+
23
+ assertThat (mapperPath ).exists ();
24
+
25
+ String content = Files .readString (mapperPath );
26
+
27
+ // Validate JavaPoet-generated characteristics
28
+ assertThat (content )
29
+ .contains ("@ApplicationScoped" )
30
+ .contains ("public class TestUserMapper" )
31
+ .contains ("toDynamoDbAttributeValue(TestUser testUser)" )
32
+ .contains ("fromDynamoDbAttributeValue(AttributeValue attributeValue)" )
33
+ .contains ("fromDynamoDbItem(Map<String, AttributeValue> item)" )
34
+ .contains ("fromDynamoDbItems(List<Map<String, AttributeValue>> items)" )
35
+ .contains ("toDynamoDbItem(TestUser object)" )
36
+ .contains ("toDynamoDbItems(List<TestUser> objects)" );
37
+
38
+ // Validate clean code structure (no string concatenation artifacts)
39
+ assertThat (content )
40
+ .doesNotContain ("\\ n" ) // No escaped newlines
41
+ .doesNotContain ("+ \" " ) // No string concatenation patterns
42
+ .doesNotContain ("writer.println" ); // No PrintWriter artifacts
43
+
44
+ // Validate proper JavaDoc
45
+ assertThat (content )
46
+ .contains ("/**" )
47
+ .contains ("Generated DynamoDB mapper for TestUser" )
48
+ .contains ("Generated at:" )
49
+ .contains ("@param" )
50
+ .contains ("@return" );
51
+ }
52
+
53
+ @ Test
54
+ @ DisplayName ("Validate TestUserFields code quality" )
55
+ void validateTestUserFieldsQuality () throws IOException {
56
+ Path fieldsPath = Path .of ("target/generated-sources/annotations/com/github/wassertim/dynamodb/toolkit/fields/TestUserFields.java" );
57
+
58
+ assertThat (fieldsPath ).exists ();
59
+
60
+ String content = Files .readString (fieldsPath );
61
+
62
+ // Validate field constants structure
63
+ assertThat (content )
64
+ .contains ("public final class TestUserFields" )
65
+ .contains ("public static final String userId = \" userId\" " )
66
+ .contains ("public static final String email = \" email\" " )
67
+ .contains ("private TestUserFields()" )
68
+ .contains ("Utility class - prevent instantiation" );
69
+
70
+ // Validate proper JavaDoc for each field
71
+ assertThat (content )
72
+ .contains ("Field name constant for 'userId' field" )
73
+ .contains ("Field name constant for 'email' field" );
74
+ }
75
+
76
+ @ Test
77
+ @ DisplayName ("Validate TableNameResolver code quality" )
78
+ void validateTableNameResolverQuality () throws IOException {
79
+ Path resolverPath = Path .of ("target/generated-sources/annotations/com/github/wassertim/infrastructure/TableNameResolver.java" );
80
+
81
+ assertThat (resolverPath ).exists ();
82
+
83
+ String content = Files .readString (resolverPath );
84
+
85
+ // Validate modern switch expression syntax
86
+ assertThat (content )
87
+ .contains ("return switch (entityClass.getName())" )
88
+ .contains ("case \" com.github.wassertim.dynamodb.toolkit.integration.entities.TestUser\" -> \" test-users\" " )
89
+ .contains ("default -> throw new IllegalArgumentException" )
90
+ .doesNotContain ("break;" ); // No old-style switch
91
+
92
+ // Validate proper error handling
93
+ assertThat (content )
94
+ .contains ("Unknown @Table annotated class:" )
95
+ .contains ("Known tables:" );
96
+ }
97
+
98
+ @ Test
99
+ @ DisplayName ("Measure code generation performance metrics" )
100
+ void measureCodeGenerationMetrics () throws IOException {
101
+ // Analyze generated mapper file
102
+ Path mapperPath = Path .of ("target/generated-sources/annotations/com/github/wassertim/dynamodb/toolkit/mappers/TestUserMapper.java" );
103
+ String mapperContent = Files .readString (mapperPath );
104
+
105
+ // Count lines of code (excluding empty lines and comments)
106
+ long mapperLoc = mapperContent .lines ()
107
+ .filter (line -> !line .trim ().isEmpty ())
108
+ .filter (line -> !line .trim ().startsWith ("//" ))
109
+ .filter (line -> !line .trim ().startsWith ("*" ))
110
+ .filter (line -> !line .trim ().startsWith ("/**" ))
111
+ .filter (line -> !line .trim ().equals ("*/" ))
112
+ .count ();
113
+
114
+ // Generated mapper should be reasonably sized (not too bloated)
115
+ assertThat (mapperLoc ).describedAs ("Mapper lines of code" ).isBetween (150L , 300L );
116
+
117
+ // Count import statements
118
+ long importCount = mapperContent .lines ()
119
+ .filter (line -> line .startsWith ("import " ))
120
+ .count ();
121
+
122
+ // JavaPoet should optimize imports
123
+ assertThat (importCount ).describedAs ("Import count" ).isLessThan (15 );
124
+
125
+ // Verify method count
126
+ long methodCount = Pattern .compile ("public .* \\ w+\\ (.*\\ ) \\ {" )
127
+ .matcher (mapperContent )
128
+ .results ()
129
+ .count ();
130
+
131
+ // Should have core methods + convenience methods
132
+ assertThat (methodCount ).describedAs ("Method count" ).isEqualTo (6 ); // 2 core + 4 convenience
133
+ }
134
+
135
+ @ Test
136
+ @ DisplayName ("Validate code consistency and formatting" )
137
+ void validateCodeConsistency () throws IOException {
138
+ Path mapperPath = Path .of ("target/generated-sources/annotations/com/github/wassertim/dynamodb/toolkit/mappers/TestUserMapper.java" );
139
+ String content = Files .readString (mapperPath );
140
+
141
+ String [] lines = content .split ("\n " );
142
+
143
+ // Validate 4-space indentation
144
+ boolean hasProperIndentation = false ;
145
+ for (String line : lines ) {
146
+ if (line .startsWith (" " ) && !line .startsWith (" " )) {
147
+ hasProperIndentation = true ;
148
+ break ;
149
+ }
150
+ }
151
+ assertThat (hasProperIndentation ).describedAs ("Should have 4-space indentation" ).isTrue ();
152
+
153
+ // Validate consistent null handling
154
+ assertThat (content )
155
+ .contains ("== null" )
156
+ .contains ("!= null" )
157
+ .contains ("if (" );
158
+
159
+ // Validate consistent naming patterns
160
+ assertThat (content )
161
+ .contains ("toDynamoDbAttributeValue" )
162
+ .contains ("fromDynamoDbAttributeValue" )
163
+ .contains ("toDynamoDbItem" )
164
+ .contains ("fromDynamoDbItem" );
165
+ }
166
+
167
+ @ Test
168
+ @ DisplayName ("Performance: Verify compilation speed impact" )
169
+ void verifyCompilationPerformance () {
170
+ // This test validates that the JavaPoet migration doesn't negatively impact compilation performance
171
+ // by checking that annotation processing completes in reasonable time
172
+
173
+ long startTime = System .currentTimeMillis ();
174
+
175
+ // The fact that this test is running means compilation succeeded
176
+ // Check that we're within reasonable bounds
177
+ long elapsedTime = System .currentTimeMillis () - startTime ;
178
+
179
+ // Should be near-instantaneous for validation
180
+ assertThat (elapsedTime ).describedAs ("Test execution time" ).isLessThan (1000 );
181
+ }
182
+
183
+ @ Test
184
+ @ DisplayName ("Memory efficiency: Validate generated code size" )
185
+ void validateGeneratedCodeSize () throws IOException {
186
+ // Check that generated files are not unnecessarily large
187
+ Path mapperPath = Path .of ("target/generated-sources/annotations/com/github/wassertim/dynamodb/toolkit/mappers/TestUserMapper.java" );
188
+ Path fieldsPath = Path .of ("target/generated-sources/annotations/com/github/wassertim/dynamodb/toolkit/fields/TestUserFields.java" );
189
+
190
+ long mapperSize = Files .size (mapperPath );
191
+ long fieldsSize = Files .size (fieldsPath );
192
+
193
+ // Generated files should be reasonably sized (not bloated)
194
+ assertThat (mapperSize ).describedAs ("Mapper file size" ).isBetween (5000L , 15000L ); // 5-15KB
195
+ assertThat (fieldsSize ).describedAs ("Fields file size" ).isBetween (1000L , 5000L ); // 1-5KB
196
+ }
197
+ }
0 commit comments