Skip to content

Commit e5ed9bd

Browse files
authored
fix: new errors in conformance tests (GoogleCloudPlatform#103)
1 parent 9bdf156 commit e5ed9bd

File tree

4 files changed

+176
-10
lines changed

4 files changed

+176
-10
lines changed

src/Context.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,20 @@ class Context
2323
private $timestamp;
2424
private $eventType;
2525
private $resource;
26+
private $domain;
2627

2728
public function __construct(
2829
?string $eventId,
2930
?string $timestamp,
3031
?string $eventType,
31-
?array $resource
32+
?array $resource,
33+
?string $domain
3234
) {
3335
$this->eventId = $eventId;
3436
$this->timestamp = $timestamp;
3537
$this->eventType = $eventType;
3638
$this->resource = $resource;
39+
$this->domain = $domain;
3740
}
3841

3942
public function getEventId(): ?string
@@ -66,6 +69,11 @@ public function getResourceName(): ?string
6669
return $this->resource['name'] ?? null;
6770
}
6871

72+
public function getDomain(): ?string
73+
{
74+
return $this->domain;
75+
}
76+
6977
public static function fromArray(array $arr)
7078
{
7179
// When "resource" is defined in the root (instead of in "context") it
@@ -75,7 +83,7 @@ public static function fromArray(array $arr)
7583
}
7684

7785
$args = [];
78-
$argKeys = ['eventId', 'timestamp', 'eventType', 'resource'];
86+
$argKeys = ['eventId', 'timestamp', 'eventType', 'resource', 'domain'];
7987
foreach ($argKeys as $key) {
8088
$args[] = $arr[$key] ?? null;
8189
}

src/LegacyEventMapper.php

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class LegacyEventMapper
6969
// for the subject.
7070
private static $ceResourceRegexMap = [
7171
self::FIREBASE_CE_SERVICE => '#^(projects/[^/]+)/(events/[^/]+)$#',
72-
self::FIREBASE_DB_CE_SERVICE => '#^(projects/_/instances/[^/]+)/(refs/.+)$#',
72+
self::FIREBASE_DB_CE_SERVICE => '#^projects/_/(instances/[^/]+)/(refs/.+)$#',
7373
self::FIRESTORE_CE_SERVICE => '#^(projects/[^/]+/databases/\(default\))/(documents/.+)$#',
7474
self::STORAGE_CE_SERVICE => '#^(projects/_/buckets/[^/]+)/(objects/.+)$#',
7575
];
@@ -97,12 +97,21 @@ public function fromJsonData(array $jsonData): CloudEvent
9797
$ceService = $context->getService() ?: $this->ceService($eventType);
9898

9999
// Split the background event resource into a CloudEvent resource and subject.
100-
[$ceResource, $ceSubject] = $this->ceResourceAndSubject($ceService, $resourceName);
100+
[$ceResource, $ceSubject] = $this->ceResourceAndSubject(
101+
$ceService,
102+
$resourceName,
103+
$context->getDomain()
104+
);
101105

102106
$ceTime = $context->getTimestamp();
103107

104108
if ($ceService === self::PUBSUB_CE_SERVICE) {
105109
// Handle Pub/Sub events.
110+
if (!is_array($data)) {
111+
$data = ['data' => $data];
112+
}
113+
$data['messageId'] = $context->getEventId();
114+
$data['publishTime'] = $context->getTimestamp();
106115
$data = ['message' => $data];
107116
} elseif ($ceService === self::FIREBASE_AUTH_CE_SERVICE) {
108117
// Handle Firebase Auth events.
@@ -171,7 +180,7 @@ private function ceService(string $eventType): string
171180
return $eventType;
172181
}
173182

174-
private function ceResourceAndSubject(string $ceService, string $resource): array
183+
private function ceResourceAndSubject(string $ceService, string $resource, ?string $domain): array
175184
{
176185
if (!array_key_exists($ceService, self::$ceResourceRegexMap)) {
177186
return [$resource, null];
@@ -183,6 +192,20 @@ private function ceResourceAndSubject(string $ceService, string $resource): arra
183192
$ret === 0 ? 'Resource regex did not match' : 'Failed while matching resource regex'
184193
);
185194
}
195+
if (self::FIREBASE_DB_CE_SERVICE === $ceService) {
196+
if (null === $domain) {
197+
return [null, null];
198+
}
199+
$location = 'us-central1';
200+
if ($domain !== 'firebaseio.com') {
201+
preg_match('#^([\w-]+)\.#', $domain, $locationMatches);
202+
if (!$locationMatches) {
203+
return [null, null];
204+
}
205+
$location = $locationMatches[1];
206+
}
207+
return ["projects/_/locations/$location/$matches[1]", $matches[2]];
208+
}
186209

187210
return [$matches[1], $matches[2]];
188211
}

tests/CloudEventFunctionsWrapperTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ public function testFromLegacyEventWithContextProperty(): void
274274
[$this, 'invokeThisLegacy']
275275
);
276276
$request = new ServerRequest('GET', '/', [], json_encode([
277-
'data' => 'foo',
277+
'data' => ['data' => 'foo'],
278278
'context' => [
279279
'eventId' => '1413058901901494',
280280
'timestamp' => '2020-12-08T20:03:19.162Z',
@@ -324,7 +324,7 @@ public function testFromStructuredEventRequest(): void
324324
'dataschema' => 'type.googleapis.com/google.logging.v2.LogEntry',
325325
'subject' => 'My Subject',
326326
'time' => '2020-12-08T20:03:19.162Z',
327-
'data' => 'foo',
327+
'data' => ['data' => 'foo'],
328328
]));
329329
$cloudEventFunctionWrapper->execute($request);
330330
$this->assertTrue(self::$functionCalled);

tests/LegacyEventMapperTest.php

Lines changed: 138 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,10 @@ public function testWithContextProperty(): void
5959
$this->assertNull($cloudevent->getSubject());
6060

6161
// Verify Pub/Sub-specific data transformation.
62-
$this->assertSame(['message' => 'foo'], $cloudevent->getData());
62+
$message = $cloudevent->getData()['message'];
63+
$this->assertSame('foo', $message['data']);
64+
$this->assertSame($jsonData['context']['eventId'], $message['messageId']);
65+
$this->assertSame($jsonData['context']['timestamp'], $message['publishTime']);
6366
}
6467

6568
public function testWithoutContextProperty(): void
@@ -93,7 +96,10 @@ public function testWithoutContextProperty(): void
9396
$this->assertSame('2020-12-08T20:03:19.162Z', $cloudevent->getTime());
9497

9598
// Verify Pub/Sub-specific data transformation.
96-
$this->assertSame(['message' => 'foo'], $cloudevent->getData());
99+
$message = $cloudevent->getData()['message'];
100+
$this->assertSame('foo', $message['data']);
101+
$this->assertSame($jsonData['eventId'], $message['messageId']);
102+
$this->assertSame($jsonData['timestamp'], $message['publishTime']);
97103
}
98104

99105
public function testResourceAsString(): void
@@ -124,7 +130,10 @@ public function testResourceAsString(): void
124130
$this->assertSame('2020-12-08T20:03:19.162Z', $cloudevent->getTime());
125131

126132
// Verify Pub/Sub-specific data transformation.
127-
$this->assertSame(['message' => 'foo'], $cloudevent->getData());
133+
$message = $cloudevent->getData()['message'];
134+
$this->assertSame('foo', $message['data']);
135+
$this->assertSame($jsonData['eventId'], $message['messageId']);
136+
$this->assertSame($jsonData['timestamp'], $message['publishTime']);
128137
}
129138

130139
public function testCloudStorage(): void
@@ -211,4 +220,130 @@ public function testFirebaseAuth(): void
211220
$this->assertSame('2020-05-26T10:42:27Z', $cloudevent->getData()['metadata']['createTime']);
212221
$this->assertSame('2020-10-24T11:00:00Z', $cloudevent->getData()['metadata']['lastSignInTime']);
213222
}
223+
224+
public function testFirebaseAuthDbDelete(): void
225+
{
226+
$mapper = new LegacyEventMapper();
227+
$jsonData = [
228+
'eventType' => 'providers/google.firebase.database/eventTypes/ref.delete',
229+
'params' => [
230+
'child' => 'xyz'
231+
],
232+
'auth' => [
233+
'admin' => true
234+
],
235+
'domain' => 'europe-west1.firebasedatabase.app',
236+
'data' => [
237+
'data' => [
238+
'grandchild' => 'other changed'
239+
],
240+
'delta' => null
241+
],
242+
'resource' => 'projects/_/instances/my-project-id/refs/gcf-test/xyz',
243+
'timestamp' => '2020-05-21T11:53:45.337Z',
244+
'eventId' => 'oIcVXHEMZfhQMNs/yD4nwpuKE0s='
245+
];
246+
$cloudevent = $mapper->fromJsonData($jsonData);
247+
248+
$this->assertSame('oIcVXHEMZfhQMNs/yD4nwpuKE0s=', $cloudevent->getId());
249+
$this->assertSame(
250+
'//firebasedatabase.googleapis.com/projects/_/locations/europe-west1/instances/my-project-id',
251+
$cloudevent->getSource()
252+
);
253+
$this->assertSame('1.0', $cloudevent->getSpecVersion());
254+
$this->assertSame(
255+
'google.firebase.database.document.v1.deleted',
256+
$cloudevent->getType()
257+
);
258+
$this->assertSame('application/json', $cloudevent->getDataContentType());
259+
$this->assertNull($cloudevent->getDataSchema());
260+
$this->assertSame(
261+
'refs/gcf-test/xyz',
262+
$cloudevent->getSubject()
263+
);
264+
$this->assertSame('2020-05-21T11:53:45.337Z', $cloudevent->getTime());
265+
}
266+
267+
public function testFirebaseAuthDbDeleteWithAlternateDomain(): void
268+
{
269+
$mapper = new LegacyEventMapper();
270+
$jsonData = [
271+
'eventType' => 'providers/google.firebase.database/eventTypes/ref.delete',
272+
'params' => [
273+
'child' => 'xyz'
274+
],
275+
'auth' => [
276+
'admin' => true
277+
],
278+
'domain' => 'europe-west1.someother.app',
279+
'data' => [
280+
'data' => [
281+
'grandchild' => 'other changed'
282+
],
283+
'delta' => null
284+
],
285+
'resource' => 'projects/_/instances/my-project-id/refs/gcf-test/xyz',
286+
'timestamp' => '2020-05-21T11:53:45.337Z',
287+
'eventId' => 'oIcVXHEMZfhQMNs/yD4nwpuKE0s='
288+
];
289+
$cloudevent = $mapper->fromJsonData($jsonData);
290+
291+
$this->assertSame('oIcVXHEMZfhQMNs/yD4nwpuKE0s=', $cloudevent->getId());
292+
$this->assertSame(
293+
'//firebasedatabase.googleapis.com/projects/_/locations/europe-west1/instances/my-project-id',
294+
$cloudevent->getSource()
295+
);
296+
$this->assertSame('1.0', $cloudevent->getSpecVersion());
297+
$this->assertSame(
298+
'google.firebase.database.document.v1.deleted',
299+
$cloudevent->getType()
300+
);
301+
$this->assertSame('application/json', $cloudevent->getDataContentType());
302+
$this->assertNull($cloudevent->getDataSchema());
303+
$this->assertSame(
304+
'refs/gcf-test/xyz',
305+
$cloudevent->getSubject()
306+
);
307+
$this->assertSame('2020-05-21T11:53:45.337Z', $cloudevent->getTime());
308+
}
309+
310+
public function testFirebaseAuthDbDeleteWithInvalidDomain(): void
311+
{
312+
$mapper = new LegacyEventMapper();
313+
$jsonData = [
314+
'eventType' => 'providers/google.firebase.database/eventTypes/ref.delete',
315+
'params' => [
316+
'child' => 'xyz'
317+
],
318+
'auth' => [
319+
'admin' => true
320+
],
321+
'domain' => 'this-wont-match-regex',
322+
'data' => [
323+
'data' => [
324+
'grandchild' => 'other changed'
325+
],
326+
'delta' => null
327+
],
328+
'resource' => 'projects/_/instances/my-project-id/refs/gcf-test/xyz',
329+
'timestamp' => '2020-05-21T11:53:45.337Z',
330+
'eventId' => 'oIcVXHEMZfhQMNs/yD4nwpuKE0s='
331+
];
332+
$cloudevent = $mapper->fromJsonData($jsonData);
333+
334+
$this->assertSame('oIcVXHEMZfhQMNs/yD4nwpuKE0s=', $cloudevent->getId());
335+
$this->assertSame(
336+
'//firebasedatabase.googleapis.com/',
337+
$cloudevent->getSource()
338+
);
339+
$this->assertSame('1.0', $cloudevent->getSpecVersion());
340+
$this->assertSame(
341+
'google.firebase.database.document.v1.deleted',
342+
$cloudevent->getType()
343+
);
344+
$this->assertSame('application/json', $cloudevent->getDataContentType());
345+
$this->assertNull($cloudevent->getDataSchema());
346+
$this->assertNull($cloudevent->getSubject());
347+
$this->assertSame('2020-05-21T11:53:45.337Z', $cloudevent->getTime());
348+
}
214349
}

0 commit comments

Comments
 (0)