Skip to content

Commit 883f7af

Browse files
Add more tests on the data of translated CloudEvents. (GoogleCloudPlatform#62)
* Add more tests on the data of translated CloudEvents. These tests check what is in the `data` field of the CloudEvents that we translate from legacy events. For now they are not all that useful, because that field is basically just a copy of the JSON payload of the legacy event. But we do rearrange things slightly for PubSub events, and we are likely to do so for Firebase events too in the future. Furthermore, if we eventually have a library of classes representing the various event payloads, then we can use that library instead of working with the JSON directly. That is what google-cloudevents-dotnet does, for example.
1 parent fe091a5 commit 883f7af

File tree

3 files changed

+219
-0
lines changed

3 files changed

+219
-0
lines changed

invoker/core/src/test/java/com/google/cloud/functions/invoker/GcfEventsTest.java

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
import java.io.StringReader;
2929
import java.time.OffsetDateTime;
3030
import java.time.ZoneOffset;
31+
import java.util.Base64;
32+
import java.util.List;
33+
import java.util.Map;
3134
import org.junit.Ignore;
3235
import org.junit.Rule;
3336
import org.junit.Test;
@@ -87,6 +90,118 @@ public void checkAllProperties() throws IOException {
8790
assertThat(cloudEvent.getDataSchema()).isNull();
8891
}
8992

93+
// The next set of tests checks the result of using Gson to deserialize the JSON "data" field of the
94+
// CloudEvent that we get from converting a legacy event. For the most part we're not testing much here,
95+
// since the "data" field is essentially copied from the input legacy event. In some cases we adjust it,
96+
// though.
97+
// Later, when we have support for handling these types properly in Java, we can change the tests to use
98+
// that. See https://github.com/googleapis/google-cloudevents-java
99+
100+
@Test
101+
public void storageData() throws IOException {
102+
Event legacyEvent = legacyEventForResource("storage.json");
103+
CloudEvent cloudEvent = GcfEvents.convertToCloudEvent(legacyEvent);
104+
Map<String, Object> data = cloudEventDataJson(cloudEvent);
105+
assertThat(data).containsAtLeast(
106+
"bucket", "some-bucket",
107+
"timeCreated", "2020-04-23T07:38:57.230Z",
108+
"generation", "1587627537231057",
109+
"metageneration", "1",
110+
"size", "352");
111+
}
112+
113+
@Test
114+
public void firestoreSimpleData() throws IOException {
115+
Event legacyEvent = legacyEventForResource("firestore_simple.json");
116+
CloudEvent cloudEvent = GcfEvents.convertToCloudEvent(legacyEvent);
117+
Map<String, Object> data = cloudEventDataJson(cloudEvent);
118+
Map<String, Object> expectedValue = Map.of(
119+
"name", "projects/project-id/databases/(default)/documents/gcf-test/2Vm2mI1d0wIaK2Waj5to",
120+
"createTime", "2020-04-23T09:58:53.211035Z",
121+
"updateTime", "2020-04-23T12:00:27.247187Z",
122+
"fields", Map.of(
123+
"another test", Map.of("stringValue", "asd"),
124+
"count", Map.of("integerValue", "4"),
125+
"foo", Map.of("stringValue", "bar")));
126+
Map<String, Object> expectedOldValue = Map.of(
127+
"name", "projects/project-id/databases/(default)/documents/gcf-test/2Vm2mI1d0wIaK2Waj5to",
128+
"createTime", "2020-04-23T09:58:53.211035Z",
129+
"updateTime", "2020-04-23T12:00:27.247187Z",
130+
"fields", Map.of(
131+
"another test", Map.of("stringValue", "asd"),
132+
"count", Map.of("integerValue", "3"),
133+
"foo", Map.of("stringValue", "bar")));
134+
assertThat(data).containsAtLeast(
135+
"value", expectedValue,
136+
"oldValue", expectedOldValue,
137+
"updateMask", Map.of("fieldPaths", List.of("count")));
138+
}
139+
140+
@Test
141+
public void firestoreComplexData() throws IOException {
142+
Event legacyEvent = legacyEventForResource("firestore_complex.json");
143+
CloudEvent cloudEvent = GcfEvents.convertToCloudEvent(legacyEvent);
144+
Map<String, Object> data = cloudEventDataJson(cloudEvent);
145+
Map<?, ?> value = (Map<?, ?>) data.get("value");
146+
Map<?, ?> fields = (Map<?, ?>) value.get("fields");
147+
Map<String, Object> expectedFields = Map.of(
148+
"arrayValue", Map.of("arrayValue",
149+
Map.of("values",
150+
List.of(Map.of("integerValue", "1"), Map.of("integerValue", "2")))),
151+
"booleanValue", Map.of("booleanValue", true),
152+
"geoPointValue", Map.of("geoPointValue", Map.of("latitude", 51.4543, "longitude", -0.9781)),
153+
"intValue", Map.of("integerValue", "50"),
154+
"doubleValue", Map.of("doubleValue", 5.5),
155+
"nullValue", Map.of(),
156+
"referenceValue", Map.of("referenceValue",
157+
"projects/project-id/databases/(default)/documents/foo/bar/baz/qux"),
158+
"stringValue", Map.of("stringValue", "text"),
159+
"timestampValue", Map.of("timestampValue", "2020-04-23T14:23:53.241Z"),
160+
"mapValue", Map.of("mapValue",
161+
Map.of("fields",
162+
Map.of("field1", Map.of("stringValue", "x"),
163+
"field2", Map.of("arrayValue",
164+
Map.of("values",
165+
List.of(Map.of("stringValue", "x"), Map.of("integerValue", "1")))))))
166+
);
167+
assertThat(fields).containsExactlyEntriesIn(expectedFields);
168+
}
169+
170+
@Test
171+
public void pubSubTextData() throws IOException {
172+
Event legacyEvent = legacyEventForResource("pubsub_text.json");
173+
CloudEvent cloudEvent = GcfEvents.convertToCloudEvent(legacyEvent);
174+
Map<String, Object> data = cloudEventDataJson(cloudEvent);
175+
176+
Map<?, ?> message = (Map<?, ?>) data.get("message");
177+
assertThat(message).isNotNull();
178+
assertThat(message).containsKey("data");
179+
// Later we should provide support for doing this more simply and test that:
180+
String base64 = (String) message.get("data");
181+
byte[] bytes = Base64.getDecoder().decode(base64);
182+
String text = new String(bytes, UTF_8);
183+
assertThat(text).isEqualTo("test message 3");
184+
185+
assertThat(message).containsEntry("attributes", Map.of("attr1", "attr1-value"));
186+
}
187+
188+
@Test
189+
public void pubSubBinaryData() throws IOException {
190+
Event legacyEvent = legacyEventForResource("pubsub_binary.json");
191+
CloudEvent cloudEvent = GcfEvents.convertToCloudEvent(legacyEvent);
192+
Map<String, Object> data = cloudEventDataJson(cloudEvent);
193+
194+
Map<?, ?> message = (Map<?, ?>) data.get("message");
195+
assertThat(message).isNotNull();
196+
assertThat(message).containsKey("data");
197+
// Later we should provide support for doing this more simply and test that:
198+
String base64 = (String) message.get("data");
199+
byte[] bytes = Base64.getDecoder().decode(base64);
200+
assertThat(bytes).isEqualTo(new byte[] {1, 2, 3, 4});
201+
202+
assertThat(message).doesNotContainKey("attributes");
203+
}
204+
90205
// Checks that a PubSub event correctly gets its payload wrapped in a "message" dictionary.
91206
@Test
92207
public void pubSubWrapping() throws IOException {
@@ -119,4 +234,11 @@ private Event legacyEventForResource(String resourceName) throws IOException {
119234
return BackgroundFunctionExecutor.parseLegacyEvent(new StringReader(legacyEventString));
120235
}
121236
}
237+
238+
private static Map<String, Object> cloudEventDataJson(CloudEvent cloudEvent) {
239+
String data = new String(cloudEvent.getData(), UTF_8);
240+
@SuppressWarnings("unchecked")
241+
Map<String, Object> map = new Gson().fromJson(data, Map.class);
242+
return map;
243+
}
122244
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
{
2+
"data": {
3+
"oldValue": {},
4+
"updateMask": {},
5+
"value": {
6+
"createTime": "2020-04-23T14:25:05.349632Z",
7+
"fields": {
8+
"arrayValue": {
9+
"arrayValue": {
10+
"values": [
11+
{
12+
"integerValue": "1"
13+
},
14+
{
15+
"integerValue": "2"
16+
}
17+
]
18+
}
19+
},
20+
"booleanValue": {
21+
"booleanValue": true
22+
},
23+
"doubleValue": {
24+
"doubleValue": 5.5
25+
},
26+
"geoPointValue": {
27+
"geoPointValue": {
28+
"latitude": 51.4543,
29+
"longitude": -0.9781
30+
}
31+
},
32+
"intValue": {
33+
"integerValue": "50"
34+
},
35+
"mapValue": {
36+
"mapValue": {
37+
"fields": {
38+
"field1": {
39+
"stringValue": "x"
40+
},
41+
"field2": {
42+
"arrayValue": {
43+
"values": [
44+
{
45+
"stringValue": "x"
46+
},
47+
{
48+
"integerValue": "1"
49+
}
50+
]
51+
}
52+
}
53+
}
54+
}
55+
},
56+
"nullValue": {
57+
"nullValue": null
58+
},
59+
"referenceValue": {
60+
"referenceValue": "projects/project-id/databases/(default)/documents/foo/bar/baz/qux"
61+
},
62+
"stringValue": {
63+
"stringValue": "text"
64+
},
65+
"timestampValue": {
66+
"timestampValue": "2020-04-23T14:23:53.241Z"
67+
}
68+
},
69+
"name": "projects/project-id/databases/(default)/documents/gcf-test/IH75dRdeYJKd4uuQiqch",
70+
"updateTime": "2020-04-23T14:25:05.349632Z"
71+
}
72+
},
73+
"eventId": "9babded5-e5f2-41af-a46a-06ba6bd84739-0",
74+
"eventType": "providers/cloud.firestore/eventTypes/document.write",
75+
"notSupported": {},
76+
"params": {
77+
"doc": "IH75dRdeYJKd4uuQiqch"
78+
},
79+
"resource": "projects/project-id/databases/(default)/documents/gcf-test/IH75dRdeYJKd4uuQiqch",
80+
"timestamp": "2020-04-23T14:25:05.349632Z"
81+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"context": {
3+
"eventId":"1144231683168617",
4+
"timestamp":"2020-05-06T07:33:34.556Z",
5+
"eventType":"google.pubsub.topic.publish",
6+
"resource":{
7+
"service":"pubsub.googleapis.com",
8+
"name":"projects/sample-project/topics/gcf-test",
9+
"type":"type.googleapis.com/google.pubsub.v1.PubsubMessage"
10+
}
11+
},
12+
"data": {
13+
"@type": "type.googleapis.com/google.pubsub.v1.PubsubMessage",
14+
"data": "AQIDBA=="
15+
}
16+
}

0 commit comments

Comments
 (0)