1+ package com .myorg .urs .integration ;
2+
3+ import java .util .ArrayList ;
4+ import java .util .List ;
5+ import java .util .Map ;
6+ import java .util .UUID ;
7+
8+ import org .junit .jupiter .api .AfterAll ;
9+ import org .junit .jupiter .api .Assertions ;
10+ import org .junit .jupiter .api .BeforeAll ;
11+ import org .junit .jupiter .api .Test ;
12+
13+ import software .amazon .awssdk .core .sync .RequestBody ;
14+ import software .amazon .awssdk .http .apache .ApacheHttpClient ;
15+ import software .amazon .awssdk .services .cloudformation .CloudFormationClient ;
16+ import software .amazon .awssdk .services .cloudformation .model .DescribeStacksRequest ;
17+ import software .amazon .awssdk .services .cloudformation .model .DescribeStacksResponse ;
18+ import software .amazon .awssdk .services .dynamodb .DynamoDbClient ;
19+ import software .amazon .awssdk .services .dynamodb .model .AttributeValue ;
20+ import software .amazon .awssdk .services .dynamodb .model .DeleteItemRequest ;
21+ import software .amazon .awssdk .services .dynamodb .model .DeleteItemResponse ;
22+ import software .amazon .awssdk .services .dynamodb .model .GetItemRequest ;
23+ import software .amazon .awssdk .services .dynamodb .model .GetItemResponse ;
24+ import software .amazon .awssdk .services .dynamodb .model .PutItemRequest ;
25+ import software .amazon .awssdk .services .dynamodb .model .PutItemResponse ;
26+ import software .amazon .awssdk .services .s3 .S3Client ;
27+ import software .amazon .awssdk .services .s3 .model .PutObjectRequest ;
28+ import software .amazon .awssdk .services .s3 .model .PutObjectResponse ;
29+
30+ public class TestFileProcessor {
31+
32+ private static S3Client s3Client ;
33+
34+ private static String dynamoDbTableName ;
35+
36+ private static String unicornInventoryBucket ;
37+
38+ private static String idPostfix ;
39+
40+ private static String testUnicorn ;
41+
42+ private static String testLocation ;
43+
44+ @ BeforeAll
45+ public static void runBeforeAll () {
46+ s3Client = S3Client .builder ()
47+ .httpClient (ApacheHttpClient .create ())
48+ .build ();
49+
50+ String awsSamStackName = System .getenv ("AWS_SAM_STACK_NAME" );
51+
52+ Assertions .assertNotNull (awsSamStackName );
53+
54+ DescribeStacksRequest describeStacksRequest = DescribeStacksRequest .builder ().stackName (awsSamStackName )
55+ .build ();
56+
57+ CloudFormationClient cloudFormationClient = CloudFormationClient .builder ().build ();
58+
59+ DescribeStacksResponse describeStacksResponse = cloudFormationClient .describeStacks (describeStacksRequest );
60+
61+ Assertions .assertNotNull (describeStacksResponse );
62+
63+ describeStacksResponse .stacks ().forEach (stack -> stack .outputs ().forEach (output -> {
64+ if (output .outputKey ().equals ("DynamoDBTableName" )) {
65+ dynamoDbTableName = output .outputValue ();
66+ } else if (output .outputKey ().equals ("UnicornInventoryBucket" )) {
67+ unicornInventoryBucket = output .outputValue ();
68+ }
69+ }));
70+
71+ Assertions .assertNotNull (dynamoDbTableName );
72+ Assertions .assertNotNull (unicornInventoryBucket );
73+
74+ idPostfix = "_%s" .formatted (UUID .randomUUID ().toString ());
75+ testUnicorn = "TEST_UNI%s" .formatted (idPostfix );
76+ testLocation = "TEST_LOC%s" .formatted (idPostfix );
77+ }
78+
79+ @ AfterAll
80+ public static void runAfterAll () {
81+ // Delete testUnicorn
82+ Map <String , AttributeValue > key = Map .of ("PK" , AttributeValue .builder ().s (testUnicorn ).build ());
83+
84+ GetItemRequest getItemRequest = GetItemRequest .builder ().tableName (dynamoDbTableName ).key (key ).build ();
85+
86+ DynamoDbClient dynamoDbClient = DynamoDbClient .builder ().build ();
87+
88+ GetItemResponse getItemResponse = dynamoDbClient .getItem (getItemRequest );
89+
90+ if (getItemResponse .hasItem ()) {
91+ DeleteItemRequest deleteItemRequest = DeleteItemRequest .builder ().tableName (dynamoDbTableName ).key (key )
92+ .build ();
93+
94+ DeleteItemResponse deleteItemResponse = dynamoDbClient .deleteItem (deleteItemRequest );
95+
96+ Assertions .assertNotNull (deleteItemResponse );
97+ }
98+
99+ // Update LOCATION#LIST without testLocation
100+ key = Map .of ("PK" , AttributeValue .builder ().s ("LOCATION#LIST" ).build ());
101+
102+ getItemRequest = GetItemRequest .builder ().tableName (dynamoDbTableName ).key (key ).build ();
103+
104+ dynamoDbClient = DynamoDbClient .builder ().build ();
105+
106+ getItemResponse = dynamoDbClient .getItem (getItemRequest );
107+
108+ Assertions .assertNotNull (getItemResponse );
109+
110+ List <AttributeValue > locations = getItemResponse .item ().get ("LOCATIONS" ).l ();
111+
112+ List <AttributeValue > updatedLocations = new ArrayList <>();
113+
114+ for (AttributeValue location : locations ) {
115+ if (!location .s ().equals (testLocation )) {
116+ updatedLocations .add (location );
117+ }
118+ }
119+
120+ Map <String , AttributeValue > item = Map .of ("PK" , AttributeValue .builder ().s ("LOCATION#LIST" ).build (),
121+ "LOCATIONS" , AttributeValue .builder ().l (updatedLocations ).build ());
122+
123+ PutItemRequest putItemRequest = PutItemRequest .builder ().tableName (dynamoDbTableName ).item (item ).build ();
124+
125+ PutItemResponse putItemResponse = dynamoDbClient .putItem (putItemRequest );
126+
127+ Assertions .assertNotNull (putItemResponse );
128+ }
129+
130+ @ Test
131+ public void testFileProcessorHappyPath () {
132+ Map <String , AttributeValue > key = Map .of ("PK" , AttributeValue .builder ().s (testUnicorn ).build ());
133+
134+ GetItemRequest getItemRequest = GetItemRequest .builder ().tableName (dynamoDbTableName ).key (key ).build ();
135+
136+ DynamoDbClient dynamoDbClient = DynamoDbClient .builder ().build ();
137+
138+ GetItemResponse getItemResponse = dynamoDbClient .getItem (getItemRequest );
139+
140+ Assertions .assertFalse (getItemResponse .hasItem ());
141+
142+ String testDataCsv = "\" Unicorn Name\" ,\" Unicorn Location\" \n " ;
143+ testDataCsv += "\" %s\" ,\" %s\" \n " .formatted (testUnicorn , testLocation );
144+
145+ String testDataKey = "INTEGRATION_TEST/TEST%s.test_file_processor_happy_path.csv" .formatted (idPostfix );
146+
147+ PutObjectRequest putObjectRequest = PutObjectRequest .builder ().bucket (unicornInventoryBucket )
148+ .key (testDataKey ).build ();
149+
150+ PutObjectResponse putObjectResponse = s3Client .putObject (putObjectRequest , RequestBody .fromString (testDataCsv ));
151+ Assertions .assertNotNull (putObjectResponse );
152+
153+ int pollMaxSeconds = 30 ;
154+ int pollCompleteSeconds = 0 ;
155+
156+ while (pollCompleteSeconds < pollMaxSeconds ) {
157+ getItemResponse = dynamoDbClient .getItem (getItemRequest );
158+
159+ if (getItemResponse .hasItem ()) {
160+ break ;
161+ }
162+
163+ try {
164+ Thread .sleep (1000 );
165+ } catch (InterruptedException exception ) {
166+ Assertions .fail (exception );
167+ }
168+
169+ pollCompleteSeconds ++;
170+ }
171+
172+ Assertions .assertTrue (getItemResponse .hasItem (), "Item not found after time allowed for processing." );
173+ Assertions .assertTrue ((pollCompleteSeconds <= 2 ),
174+ "Unicorns should be fast! Took too long: %d sec" .formatted (pollCompleteSeconds ));
175+ Assertions .assertEquals (getItemResponse .item ().get ("PK" ).s (), testUnicorn ,
176+ "Table PK is not set to the Unicorn Name: %s expected %s"
177+ .formatted (getItemResponse .item ().get ("PK" ).s (), testUnicorn ));
178+ Assertions .assertEquals (getItemResponse .item ().get ("LOCATION" ).s (), testLocation ,
179+ "Table LOCATION is not set to the Unicorn Location: %s expected %s"
180+ .formatted (getItemResponse .item ().get ("LOCATION" ).s (), testLocation ));
181+ }
182+
183+ }
0 commit comments