Skip to content

Commit aeefbfd

Browse files
authored
feat(functions): helloworld storage initial commit (GoogleCloudPlatform#1213)
1 parent a25f2b8 commit aeefbfd

File tree

9 files changed

+586
-3
lines changed

9 files changed

+586
-3
lines changed

functions/helloworld_http/test/SampleUnitTest.php renamed to functions/helloworld_http/SampleUnitTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
// [START functions_http_unit_test]
1919

20-
namespace Google\Cloud\Samples\Functions\HelloworldHttp\Test;
20+
namespace Google\Cloud\Samples\Functions\HelloworldHttp;
2121

2222
use GuzzleHttp\Psr7\ServerRequest;
2323
use PHPUnit\Framework\TestCase;
@@ -31,7 +31,7 @@ class SampleUnitTest extends TestCase
3131
{
3232
public static function setUpBeforeClass(): void
3333
{
34-
require_once __DIR__ . '/../index.php';
34+
require_once __DIR__ . '/index.php';
3535
}
3636

3737
public function testFunction(): void

functions/helloworld_http/phpunit.xml.dist

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
<phpunit bootstrap="../../testing/bootstrap.php" convertWarningsToExceptions="false">
1818
<testsuites>
1919
<testsuite name="Cloud Functions Hello World HTTP Test Suite">
20-
<directory>testdirectory>
20+
<directory>.directory>
21+
<exclude>vendorexclude>
2122
testsuite>
2223
testsuites>
2324
<logging>
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
2+
/**
3+
* Copyright 2020 Google LLC.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the 'License');
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an 'AS IS' BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
declare(strict_types=1);
19+
20+
// [START functions_storage_integration_test]
21+
22+
namespace Google\Cloud\Samples\Functions\HelloworldStorage;
23+
24+
use Google\CloudFunctions\CloudEvent;
25+
use GuzzleHttp\Client;
26+
use PHPUnit\Framework\TestCase;
27+
use Symfony\Component\Process\Process;
28+
use Symfony\Component\Process\PhpExecutableFinder;
29+
30+
/**
31+
* Class SampleIntegrationTest.
32+
*
33+
* Integration tests for the 'Helloworld Storage' Cloud Function.
34+
*/
35+
class SampleIntegrationTest extends TestCase
36+
{
37+
/** @var Process */
38+
private static $process;
39+
40+
/** @var Client */
41+
private static $client;
42+
43+
public function dataProvider()
44+
{
45+
return [
46+
[
47+
'cloudevent' => [
48+
'id' => uniqid(),
49+
'source' => 'storage.googleapis.com',
50+
'specversion' => '1.0',
51+
'type' => 'google.cloud.storage.object.v1.finalized',
52+
],
53+
'data' => [
54+
'bucket' => 'some-bucket',
55+
'metageneration' => '1',
56+
'name' => 'folder/friendly.txt',
57+
'timeCreated' => '2020-04-23T07:38:57.230Z',
58+
'updated' => '2020-04-23T07:38:57.230Z',
59+
],
60+
'statusCode' => '200',
61+
],
62+
];
63+
}
64+
65+
/**
66+
* @dataProvider dataProvider
67+
*/
68+
public function testHelloGCS(array $cloudevent, array $data, string $statusCode): void
69+
{
70+
// Prepare the HTTP headers for a CloudEvent.
71+
$cloudEventHeaders = [];
72+
foreach ($cloudevent as $key => $value) {
73+
$cloudEventHeaders['ce-' . $key] = $value;
74+
}
75+
76+
// Send an HTTP request using CloudEvent metadata.
77+
$resp = self::$client->post('/', [
78+
'body' => json_encode($data),
79+
'headers' => $cloudEventHeaders + [
80+
// Instruct the function framework to parse the body as JSON.
81+
'content-type' => 'application/json'
82+
],
83+
]);
84+
85+
// The Cloud Function logs all data to stderr.
86+
$actual = self::$process->getIncrementalErrorOutput();
87+
88+
// Confirm the status code.
89+
$this->assertEquals($statusCode, $resp->getStatusCode());
90+
91+
// Verify the CloudEvent and data properties are logged by the function.
92+
foreach ($data as $property => $value) {
93+
$this->assertContains($value, $actual);
94+
}
95+
$this->assertContains($cloudevent['id'], $actual);
96+
$this->assertContains($cloudevent['type'], $actual);
97+
}
98+
99+
/**
100+
* Start a local PHP server running the Functions Framework.
101+
*
102+
* @beforeClass
103+
*/
104+
public static function startFunctionFramework(): void
105+
{
106+
$port = getenv('PORT') ?: '8080';
107+
$php = (new PhpExecutableFinder())->find();
108+
$uri = 'localhost:' . $port;
109+
110+
// https://symfony.com/doc/current/components/process.html#usage
111+
self::$process = new Process([$php, '-S', $uri, 'vendor/bin/router.php'], null, [
112+
'FUNCTION_SIGNATURE_TYPE' => 'cloudevent',
113+
'FUNCTION_TARGET' => 'helloGCS',
114+
]);
115+
self::$process->start();
116+
117+
// Initialize an HTTP client to drive requests.
118+
self::$client = new Client(['base_uri' => 'http://' . $uri]);
119+
120+
// Short delay to ensure PHP server is ready.
121+
sleep(1);
122+
}
123+
124+
/**
125+
* Stop the local PHP server.
126+
*
127+
* @afterClass
128+
*/
129+
public static function stopFunctionFramework(): void
130+
{
131+
if (!self::$process->isRunning()) {
132+
echo self::$process->getErrorOutput();
133+
throw new RuntimeException('Function Framework PHP process not running by end of test');
134+
}
135+
self::$process->stop(3, SIGTERM);
136+
}
137+
}
138+
139+
// [END functions_storage_integration_test]
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
2+
/**
3+
* Copyright 2020 Google LLC.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the 'License');
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an 'AS IS' BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
declare(strict_types=1);
19+
20+
// [START functions_storage_unit_test]
21+
22+
namespace Google\Cloud\Samples\Functions\HelloworldStorage\Test;
23+
24+
use Google\CloudFunctions\CloudEvent;
25+
use PHPUnit\Framework\TestCase;
26+
27+
/**
28+
* Class SampleUnitTest.
29+
*
30+
* Unit test for 'Helloworld Storage' Cloud Function.
31+
*/
32+
class SampleUnitTest extends TestCase
33+
{
34+
/**
35+
* Include the Cloud Function code before running any tests.
36+
*
37+
* @see https://phpunit.readthedocs.io/en/latest/fixtures.html
38+
*/
39+
public static function setUpBeforeClass(): void
40+
{
41+
require_once __DIR__ . '/index.php';
42+
}
43+
44+
public function dataProvider()
45+
{
46+
return [
47+
[
48+
'cloudevent' => CloudEvent::fromArray([
49+
'id' => uniqid(),
50+
'source' => 'storage.googleapis.com',
51+
'specversion' => '1.0',
52+
'type' => 'google.cloud.storage.object.v1.finalized',
53+
'data' => [
54+
'bucket' => 'some-bucket',
55+
'metageneration' => '1',
56+
'name' => 'folder/friendly.txt',
57+
'timeCreated' => '2020-04-23T07:38:57.230Z',
58+
'updated' => '2020-04-23T07:38:57.230Z',
59+
],
60+
]),
61+
'statusCode' => '200',
62+
],
63+
];
64+
}
65+
66+
/**
67+
* @dataProvider dataProvider
68+
*/
69+
public function testFunction(CloudEvent $cloudevent, string $statusCode): void
70+
{
71+
// Capture function output by overriding the function's logging behavior.
72+
// The 'LOGGER_OUTPUT' environment variable must be used in your function:
73+
//
74+
// $log = fopen(getenv('LOGGER_OUTPUT') ?: 'php://stderr', 'wb');
75+
// fwrite($log, 'Log Entry');
76+
putenv('LOGGER_OUTPUT=php://output');
77+
helloGCS($cloudevent);
78+
// Provided by PHPUnit\Framework\TestCase.
79+
$actual = $this->getActualOutput();
80+
81+
// Test output includes the properties provided in the CloudEvent.
82+
foreach ($cloudevent->getData() as $property => $value) {
83+
$this->assertContains($value, $actual);
84+
}
85+
$this->assertContains($cloudevent->getId(), $actual);
86+
$this->assertContains($cloudevent->getType(), $actual);
87+
}
88+
}
89+
90+
// [END functions_storage_unit_test]
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"require": {
3+
"google/cloud-functions-framework": "^0.7.1"
4+
},
5+
"scripts": {
6+
"start": [
7+
"Composer\\Config::disableProcessTimeout",
8+
"FUNCTION_SIGNATURE_TYPE=cloudevent FUNCTION_TARGET=helloGCS php -S localhost:${PORT:-8080} vendor/bin/router.php"
9+
]
10+
},
11+
"require-dev": {
12+
"google/cloud-storage": "^1.23",
13+
"google/cloud-logging": "^1.21"
14+
}
15+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
2+
/**
3+
* Copyright 2020 Google LLC.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
// [START functions_helloworld_storage]
19+
20+
use Google\CloudFunctions\CloudEvent;
21+
22+
function helloGCS(CloudEvent $cloudevent)
23+
{
24+
$log = fopen(getenv('LOGGER_OUTPUT') ?: 'php://stderr', 'wb');
25+
$data = $cloudevent->getData();
26+
fwrite($log, "Event: " . $cloudevent->getId() . PHP_EOL);
27+
fwrite($log, "Event Type: " . $cloudevent->getType() . PHP_EOL);
28+
fwrite($log, "Bucket: " . $data['bucket'] . PHP_EOL);
29+
fwrite($log, "File: " . $data['name'] . PHP_EOL);
30+
fwrite($log, "Metageneration: " . $data['metageneration'] . PHP_EOL);
31+
fwrite($log, "Created: " . $data['timeCreated'] . PHP_EOL);
32+
fwrite($log, "Updated: " . $data['updated'] . PHP_EOL);
33+
}
34+
35+
// [END functions_helloworld_storage]
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
xml version="1.0" encoding="UTF-8"?>
2+
17+
<phpunit bootstrap="../../testing/bootstrap.php" convertWarningsToExceptions="false">
18+
<testsuites>
19+
<testsuite name="Cloud Functions Hello Cloud Storage Test Suite">
20+
<directory>.directory>
21+
<exclude>vendorexclude>
22+
testsuite>
23+
testsuites>
24+
<logging>
25+
<log type="coverage-clover" target="build/logs/clover.xml"/>
26+
logging>
27+
<filter>
28+
<whitelist>
29+
<directory suffix=".php">.directory>
30+
<exclude>
31+
<directory>./vendordirectory>
32+
exclude>
33+
whitelist>
34+
filter>
35+
phpunit>

0 commit comments

Comments
 (0)