.github/workflows/static.yml 0000644 00000002527 14641217650 0012167 0 ustar 00 name: Static Analysis
on:
push:
branches: [ main ]
pull_request:
jobs:
codesniffer:
name: PHP CodeSniffer
runs-on: ubuntu-20.04
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '7.4'
tools: composer:v2
coverage: none
env:
update: true
- name: Install Dependencies
uses: nick-invision/retry@v1
with:
timeout_minutes: 5
max_attempts: 5
command: composer update --no-interaction --no-progress
- name: Execute PHP CodeSniffer
run: vendor/bin/phpcs -n -q --standard=PSR12 ./src ./tests
psalm:
name: Psalm
runs-on: ubuntu-22.04
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '7.4'
tools: composer:v2
coverage: none
env:
update: true
- name: Install Dependencies
uses: nick-invision/retry@v1
with:
timeout_minutes: 5
max_attempts: 5
command: composer update --no-interaction --no-progress
- name: Execute Psalm
run: vendor/bin/psalm.phar --no-progress --output-format=github
.github/workflows/tests.yml 0000644 00000001553 14641217650 0012040 0 ustar 00 name: Tests
on:
push:
branches: [ main ]
pull_request:
jobs:
tests:
name: PHP ${{ matrix.php }}
runs-on: ubuntu-22.04
strategy:
matrix:
php: ['7.4', '8.0', '8.1', '8.2']
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
tools: composer:v2
coverage: none
env:
update: true
- name: Setup Problem Matchers
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
- name: Install Dependencies
uses: nick-invision/retry@v1
with:
timeout_minutes: 5
max_attempts: 5
command: composer update --no-interaction --no-progress
- name: Execute PHPUnit
run: vendor/bin/phpunit
.gitignore 0000644 00000000117 14641217650 0006541 0 ustar 00 .phpunit.cache
composer.lock
phpcs.xml
phpunit.xml
psalm.xml
coverage
vendor
LICENSE 0000644 00000026135 14641217650 0005566 0 ustar 00 Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
README.md 0000644 00000007677 14641217650 0006052 0 ustar 00 # PHP SDK for [CloudEvents](https://github.com/cloudevents/spec)
## Status
This SDK currently supports the following versions of CloudEvents:
- [v1.0](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md)
## Installation
Install the SDK using [Composer](https://getcomposer.org/):
```sh
$ composer require cloudevents/sdk-php
```
## Create a CloudEvent
```php
use CloudEvents\V1\CloudEvent;
use CloudEvents\V1\CloudEventImmutable;
// Immutable CloudEvent
$immutableEvent = new CloudEventImmutable(
'1n6bFxDMHZFChlI4TVI9tdzphB9',
'/examples/php-sdk',
'com.example.type',
['example' => 'first-event'],
'application/json'
);
// Mutable CloudEvent
$mutableEvent = new CloudEvent(
'1n6bFxDMHZFChlI4TVI9tdzphB9',
'/examples/php-sdk',
'com.example.type',
['example' => 'first-event'],
'application/json'
);
// Create immutable from mutable or via versa
$event = CloudEventImmutable::createFromInterface($mutableEvent);
$event = CloudEvent::createFromInterface($immutableEvent);
```
## Serialize/Deserialize a CloudEvent
```php
use CloudEvents\Serializers\JsonDeserializer;
use CloudEvents\Serializers\JsonSerializer;
// JSON serialization
$payload = JsonSerializer::create()->serializeStructured($event);
$payload = JsonSerializer::create()->serializeBatch($events);
// JSON deserialization
$event = JsonDeserializer::create()->deserializeStructured($payload);
$events = JsonDeserializer::create()->deserializeBatch($payload);
```
## Marshal/Unmarshal a CloudEvent
```php
use CloudEvents\Http\Marshaller;
use CloudEvents\Http\Unmarshaller;
// Marshal HTTP request
$request = Marshaller::createJsonMarshaller()->marshalStructuredRequest($event);
$request = Marshaller::createJsonMarshaller()->marshalBinaryRequest($event);
$request = Marshaller::createJsonMarshaller()->marshalBatchRequest($events);
// Marshal HTTP response
$request = Marshaller::createJsonMarshaller()->marshalStructuredResponse($event);
$request = Marshaller::createJsonMarshaller()->marshalBinaryResponse($event);
$request = Marshaller::createJsonMarshaller()->marshalBatchResponse($events);
// Unmarshal HTTP message
$events = Unmarshaller::createJsonUnmarshaller()->unmarshal($message);
```
## Testing
You can use `composer` to build and run test environments when contributing.
```
$ composer run -l
scripts:
lint Show all current linting errors according to PSR12
lint-fix Show and fix all current linting errors according to PSR12
sa Run the static analyzer
tests Run all tests locally
tests-build Build containers to test against supported PHP versions
tests-docker Run tests within supported PHP version containers
```
## Community
- There are bi-weekly calls immediately following the [Serverless/CloudEvents
call](https://github.com/cloudevents/spec#meeting-time) at
9am PT (US Pacific). Which means they will typically start at 10am PT, but
if the other call ends early then the SDK call will start early as well.
See the [CloudEvents meeting minutes](https://docs.google.com/document/d/1OVF68rpuPK5shIHILK9JOqlZBbfe91RNzQ7u_P7YCDE/edit#)
to determine which week will have the call.
- Slack: #cloudeventssdk channel under
[CNCF's Slack workspace](https://slack.cncf.io/).
- Email: https://lists.cncf.io/g/cncf-cloudevents-sdk
- Contact for additional information: Denis Makogon (`@denysmakogon` on slack).
Each SDK may have its own unique processes, tooling and guidelines, common
governance related material can be found in the
[CloudEvents `community`](https://github.com/cloudevents/spec#community-and-docs)
directory. In particular, in there you will find information concerning
how SDK projects are
[managed](https://github.com/cloudevents/spec/blob/main/docs/SDK-GOVERNANCE.md),
[guidelines](https://github.com/cloudevents/spec/blob/main/docs/SDK-maintainer-guidelines.md)
for how PR reviews and approval, and our
[Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md)
information.
composer.json 0000644 00000006262 14641217650 0007302 0 ustar 00 {
"name": "cloudevents/sdk-php",
"description": "CloudEvents SDK",
"type": "library",
"license": "Apache-2.0",
"support": {
"issues": "https://github.com/cloudevents/sdk-php/issues",
"source": "https://github.com/cloudevents/sdk-php"
},
"autoload": {
"psr-4": {
"CloudEvents\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"require": {
"php": "^7.4.15 || ^8.0.2",
"ext-json": "*",
"ext-pcre": "*",
"symfony/polyfill-php80": "^1.26"
},
"require-dev": {
"guzzlehttp/psr7": "^2.4.3",
"php-http/discovery": "^1.15.2",
"phpunit/phpunit": "^9.6.3 || ^10.0.12",
"psalm/phar": "5.7.6",
"psr/http-factory": "^1.0.1",
"psr/http-message": "^1.0.1",
"squizlabs/php_codesniffer": "3.7.2"
},
"suggest": {
"php-http/discovery": "Required for automatic discovery of HTTP message factories in the HTTP Marshaller.",
"psr/http-factory": "Required for use of the HTTP Marshaller.",
"psr/http-factory-implementation": "Required for use of the HTTP Marshaller.",
"psr/http-message": "Required for use of the HTTP Marshaller and Unmarshaller.",
"psr/http-message-implementation": "Required for use of the HTTP Marshaller and Unmarshaller."
},
"scripts": {
"lint": "./vendor/bin/phpcs -n --standard=PSR12 ./src ./tests",
"lint-fix": "./vendor/bin/phpcbf -n --standard=PSR12 ./src ./tests",
"tests": "./vendor/bin/phpunit",
"sa": "./vendor/bin/psalm.phar",
"tests-build": [
"DOCKER_BUILDKIT=1 docker build -t cloudevents/sdk-php:7.4-tests -f hack/7.4.Dockerfile hack",
"DOCKER_BUILDKIT=1 docker build -t cloudevents/sdk-php:8.0-tests -f hack/8.0.Dockerfile hack",
"DOCKER_BUILDKIT=1 docker build -t cloudevents/sdk-php:8.1-tests -f hack/8.1.Dockerfile hack",
"DOCKER_BUILDKIT=1 docker build -t cloudevents/sdk-php:8.2-tests -f hack/8.1.Dockerfile hack"
],
"tests-docker": [
"docker run -it -v $(pwd):/var/www cloudevents/sdk-php:7.4-tests --coverage-html=coverage",
"docker run -it -v $(pwd):/var/www cloudevents/sdk-php:8.0-tests",
"docker run -it -v $(pwd):/var/www cloudevents/sdk-php:8.1-tests",
"docker run -it -v $(pwd):/var/www cloudevents/sdk-php:8.2-tests"
]
},
"scripts-descriptions": {
"lint": "Show all current linting errors according to PSR12",
"lint-fix": "Show and fix all current linting errors according to PSR12",
"sa": "Run the static analyzer",
"tests": "Run all tests locally",
"tests-build": "Build containers to test against supported PHP versions",
"tests-docker": "Run tests within supported PHP version containers"
},
"config": {
"preferred-install": "dist",
"sort-packages": true,
"allow-plugins": {
"php-http/discovery": true
}
},
"extra": {
"branch-alias": {
"dev-main": "1.0-dev"
}
},
"minimum-stability": "dev",
"prefer-stable": true
}
hack/7.4.Dockerfile 0000644 00000002210 14641217650 0007754 0 ustar 00 FROM php:7.4-alpine
LABEL org.opencontainers.image.url="https://github.com/cloudevents/sdk-php/tree/main/hack/7.4.Dockerfile" \
org.opencontainers.image.documentation="https://github.com/cloudevents/sdk-php/tree/main/hack/README.md" \
org.opencontainers.image.source="https://github.com/cloudevents/sdk-php" \
org.opencontainers.image.vendor="CloudEvent" \
org.opencontainers.image.title="PHP 7.4" \
org.opencontainers.image.description="PHP 7.4 test environment for cloudevents/sdk-php"
COPY --chown=www-data:www-data install-composer /usr/local/bin/install-composer
RUN chmod +x /usr/local/bin/install-composer \
&& /usr/local/bin/install-composer \
&& rm /usr/local/bin/install-composer
RUN apk update \
&& apk --no-cache upgrade \
&& apk add --no-cache bash ca-certificates git libzip-dev \
&& apk add --no-cache --virtual build-deps autoconf build-base g++ \
&& pecl install pcov \
&& docker-php-ext-enable pcov \
&& apk del --purge build-deps \
&& rm -rf /var/www/html /tmp/pear \
&& chown -R www-data:www-data /var/www
WORKDIR /var/www
ENTRYPOINT ["/var/www/vendor/bin/phpunit"]
hack/8.0.Dockerfile 0000644 00000001734 14641217650 0007763 0 ustar 00 FROM php:8.0-alpine
LABEL org.opencontainers.image.url="https://github.com/cloudevents/sdk-php/tree/main/hack/8.0.Dockerfile" \
org.opencontainers.image.documentation="https://github.com/cloudevents/sdk-php/tree/main/hack/README.md" \
org.opencontainers.image.source="https://github.com/cloudevents/sdk-php" \
org.opencontainers.image.vendor="CloudEvent" \
org.opencontainers.image.title="PHP 8.0" \
org.opencontainers.image.description="PHP 8.0 test environment for cloudevents/sdk-php"
COPY --chown=www-data:www-data install-composer /usr/local/bin/install-composer
RUN chmod +x /usr/local/bin/install-composer \
&& /usr/local/bin/install-composer \
&& rm /usr/local/bin/install-composer
RUN apk update \
&& apk --no-cache upgrade \
&& apk add --no-cache bash ca-certificates git libzip-dev \
&& rm -rf /var/www/html /tmp/pear \
&& chown -R www-data:www-data /var/www
WORKDIR /var/www
ENTRYPOINT ["/var/www/vendor/bin/phpunit"]
hack/8.1.Dockerfile 0000644 00000001734 14641217650 0007764 0 ustar 00 FROM php:8.1-alpine
LABEL org.opencontainers.image.url="https://github.com/cloudevents/sdk-php/tree/main/hack/8.1.Dockerfile" \
org.opencontainers.image.documentation="https://github.com/cloudevents/sdk-php/tree/main/hack/README.md" \
org.opencontainers.image.source="https://github.com/cloudevents/sdk-php" \
org.opencontainers.image.vendor="CloudEvent" \
org.opencontainers.image.title="PHP 8.1" \
org.opencontainers.image.description="PHP 8.1 test environment for cloudevents/sdk-php"
COPY --chown=www-data:www-data install-composer /usr/local/bin/install-composer
RUN chmod +x /usr/local/bin/install-composer \
&& /usr/local/bin/install-composer \
&& rm /usr/local/bin/install-composer
RUN apk update \
&& apk --no-cache upgrade \
&& apk add --no-cache bash ca-certificates git libzip-dev \
&& rm -rf /var/www/html /tmp/pear \
&& chown -R www-data:www-data /var/www
WORKDIR /var/www
ENTRYPOINT ["/var/www/vendor/bin/phpunit"]
hack/8.2.Dockerfile 0000644 00000001734 14641217650 0007765 0 ustar 00 FROM php:8.2-alpine
LABEL org.opencontainers.image.url="https://github.com/cloudevents/sdk-php/tree/main/hack/8.2.Dockerfile" \
org.opencontainers.image.documentation="https://github.com/cloudevents/sdk-php/tree/main/hack/README.md" \
org.opencontainers.image.source="https://github.com/cloudevents/sdk-php" \
org.opencontainers.image.vendor="CloudEvent" \
org.opencontainers.image.title="PHP 8.2" \
org.opencontainers.image.description="PHP 8.2 test environment for cloudevents/sdk-php"
COPY --chown=www-data:www-data install-composer /usr/local/bin/install-composer
RUN chmod +x /usr/local/bin/install-composer \
&& /usr/local/bin/install-composer \
&& rm /usr/local/bin/install-composer
RUN apk update \
&& apk --no-cache upgrade \
&& apk add --no-cache bash ca-certificates git libzip-dev \
&& rm -rf /var/www/html /tmp/pear \
&& chown -R www-data:www-data /var/www
WORKDIR /var/www
ENTRYPOINT ["/var/www/vendor/bin/phpunit"]
hack/install-composer 0000755 00000000735 14641217650 0010706 0 ustar 00 #!/bin/sh
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === '756890a4488ce9024fc62c56153228907f1545c228516cbf63f885e036d37e9a59d27d63f46af1d4d07ee0f76181c7d3') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \
php composer-setup.php --install-dir=/usr/local/bin --filename=composer --quiet
php -r "unlink('composer-setup.php');" \
phpcs.xml.dist 0000644 00000052267 14641217650 0007367 0 ustar 00
The PSR-12 coding standard.
0
0
0
error
Method name "%s" must not be prefixed with an underscore to indicate visibility
0
0
0
0
0
0
0
phpunit.xml.dist 0000644 00000001104 14641217650 0007721 0 ustar 00
tests/Unit
src
psalm.xml.dist 0000644 00000000547 14641217650 0007360 0 ustar 00
src/CloudEventInterface.php 0000644 00000000211 14641217650 0011735 0 ustar 00 configuration = $configuration;
$this->requestFactory = $requestFactory;
$this->responseFactory = $responseFactory;
$this->streamFactory = $streamFactory;
}
public static function createJsonMarshaller(
RequestFactoryInterface $requestFactory = null,
ResponseFactoryInterface $responseFactory = null,
StreamFactoryInterface $streamFactory = null
): self {
return new self(
['serializer' => JsonSerializer::create(), 'type' => 'json'],
$requestFactory ?? Psr17FactoryDiscovery::findRequestFactory(),
$responseFactory ?? Psr17FactoryDiscovery::findResponseFactory(),
$streamFactory ?? Psr17FactoryDiscovery::findStreamFactory()
);
}
/**
* @param UriInterface|string $uri
*
* @throws UnsupportedSpecVersionException
*/
public function marshalStructuredRequest(
CloudEventInterface $cloudEvent,
string $method,
$uri
): RequestInterface {
$serialized = $this->configuration['serializer']->serializeStructured($cloudEvent);
return $this->requestFactory->createRequest($method, $uri)
->withBody($this->streamFactory->createStream($serialized))
->withHeader('Content-Type', sprintf('application/cloudevents+%s', $this->configuration['type']))
->withHeader('Content-Length', (string) strlen($serialized));
}
/**
* @param UriInterface|string $uri
*
* @throws UnsupportedSpecVersionException
*/
public function marshalBinaryRequest(
CloudEventInterface $cloudEvent,
string $method,
$uri
): RequestInterface {
$serialized = $this->configuration['serializer']->serializeBinary($cloudEvent);
$request = $this->requestFactory->createRequest($method, $uri)
->withBody($this->streamFactory->createStream($serialized['data']))
->withHeader('Content-Type', $serialized['contentType'])
->withHeader('Content-Length', (string) strlen($serialized['data']));
foreach ($serialized['attributes'] as $key => $value) {
$request = $request->withHeader(sprintf('ce-%s', $key), $value);
}
return $request;
}
/**
* @param list $cloudEvents
* @param UriInterface|string $uri
*
* @throws UnsupportedSpecVersionException
*/
public function marshalBatchRequest(
array $cloudEvents,
string $method,
$uri
): RequestInterface {
$serialized = $this->configuration['serializer']->serializeBatch($cloudEvents);
return $this->requestFactory->createRequest($method, $uri)
->withBody($this->streamFactory->createStream($serialized))
->withHeader('Content-Type', sprintf('application/cloudevents-batch+%s', $this->configuration['type']))
->withHeader('Content-Length', (string) strlen($serialized));
}
/**
* @throws UnsupportedSpecVersionException
*/
public function marshalStructuredResponse(
CloudEventInterface $cloudEvent,
int $code = 200,
string $reasonPhrase = ''
): ResponseInterface {
$serialized = $this->configuration['serializer']->serializeStructured($cloudEvent);
return $this->responseFactory->createResponse($code, $reasonPhrase)
->withBody($this->streamFactory->createStream($serialized))
->withHeader('Content-Type', sprintf('application/cloudevents+%s', $this->configuration['type']))
->withHeader('Content-Length', (string) strlen($serialized));
}
/**
* @param UriInterface|string $uri
*
* @throws UnsupportedSpecVersionException
*/
public function marshalBinaryResponse(
CloudEventInterface $cloudEvent,
int $code = 200,
string $reasonPhrase = ''
): ResponseInterface {
$serialized = $this->configuration['serializer']->serializeBinary($cloudEvent);
$response = $this->responseFactory->createResponse($code, $reasonPhrase)
->withBody($this->streamFactory->createStream($serialized['data']))
->withHeader('Content-Type', $serialized['contentType'])
->withHeader('Content-Length', (string) strlen($serialized['data']));
foreach ($serialized['attributes'] as $key => $value) {
$response = $response->withHeader(sprintf('ce-%s', $key), $value);
}
return $response;
}
/**
* @param list $cloudEvents
*
* @throws UnsupportedSpecVersionException
*/
public function marshalBatchResponse(
array $cloudEvents,
int $code = 200,
string $reasonPhrase = ''
): ResponseInterface {
$serialized = $this->configuration['serializer']->serializeBatch($cloudEvents);
return $this->responseFactory->createResponse($code, $reasonPhrase)
->withBody($this->streamFactory->createStream($serialized))
->withHeader('Content-Type', sprintf('application/cloudevents-batch+%s', $this->configuration['type']))
->withHeader('Content-Length', (string) strlen($serialized));
}
}
src/Http/MarshallerInterface.php 0000644 00000003510 14641217650 0012703 0 ustar 00 $cloudEvents
* @param UriInterface|string $uri
*
* @throws UnsupportedSpecVersionException
*/
public function marshalBatchRequest(
array $cloudEvents,
string $method,
$uri
): RequestInterface;
/**
* @throws UnsupportedSpecVersionException
*/
public function marshalStructuredResponse(
CloudEventInterface $cloudEvent,
int $code = 200,
string $reasonPhrase = ''
): ResponseInterface;
/**
* @throws UnsupportedSpecVersionException
*/
public function marshalBinaryResponse(
CloudEventInterface $cloudEvent,
int $code = 200,
string $reasonPhrase = ''
): ResponseInterface;
/**
* @param list $cloudEvents
*
* @throws UnsupportedSpecVersionException
*/
public function marshalBatchResponse(
array $cloudEvents,
int $code = 200,
string $reasonPhrase = ''
): ResponseInterface;
}
src/Http/Unmarshaller.php 0000644 00000010564 14641217650 0011434 0 ustar 00 }>
*/
private array $configuration;
/**
* @param array}> $configuration
*/
public function __construct(array $configuration)
{
$this->configuration = $configuration;
}
public static function createJsonUnmarshaller(): self
{
return new self([
'json' => ['deserializer' => JsonDeserializer::create(), 'contentTypes' => ['application/json']],
]);
}
/**
* @throws InvalidPayloadSyntaxException
* @throws UnsupportedContentTypeException
* @throws UnsupportedSpecVersionException
* @throws MissingAttributeException
*
* @return list
*/
public function unmarshal(MessageInterface $message): array
{
$contentType = strtolower(explode(';', $message->getHeader('Content-Type')[0] ?? '')[0]);
foreach ($this->configuration as $type => $entry) {
switch ($contentType) {
case sprintf('application/cloudevents+%s', $type):
return self::unmarshalStructured($message, $entry['deserializer']);
case sprintf('application/cloudevents-batch+%s', $type):
return self::unmarshalBatch($message, $entry['deserializer']);
default:
if (in_array($contentType, $entry['contentTypes'], true)) {
return self::unmarshalBinary($message, $entry['deserializer']);
}
}
}
throw new UnsupportedContentTypeException();
}
/**
* @throws InvalidPayloadSyntaxException
* @throws UnsupportedSpecVersionException
* @throws MissingAttributeException
*
* @return list
*/
private static function unmarshalStructured(
MessageInterface $message,
DeserializerInterface $deserializer
): array {
$cloudEvent = $deserializer->deserializeStructured(
(string) $message->getBody()
);
return [$cloudEvent];
}
/**
* @throws InvalidPayloadSyntaxException
* @throws UnsupportedSpecVersionException
* @throws MissingAttributeException
*
* @return list
*/
private static function unmarshalBinary(
MessageInterface $message,
DeserializerInterface $deserializer
): array {
/** @var array> */
$headers = $message->getHeaders();
/** @psalm-suppress MixedArgumentTypeCoercion */
$cloudEvent = $deserializer->deserializeBinary(
(string) $message->getBody(),
implode(', ', $message->getHeader('Content-Type')),
self::decodeAttributes($headers)
);
return [$cloudEvent];
}
/**
* @param array> $headers
*
* @return array
*/
private static function decodeAttributes(array $headers): array
{
$attributes = [];
foreach ($headers as $key => $values) {
$key = (string) $key;
/** @psalm-suppress UndefinedFunction */
if (\str_starts_with($key, 'ce-')) {
$attributes[substr($key, 3)] = implode(', ', $values);
}
}
return $attributes;
}
/**
* @throws InvalidPayloadSyntaxException
* @throws UnsupportedSpecVersionException
* @throws MissingAttributeException
*
* @return list
*/
private static function unmarshalBatch(
MessageInterface $message,
DeserializerInterface $deserializer
): array {
return $deserializer->deserializeBatch(
(string) $message->getBody()
);
}
}
src/Http/UnmarshallerInterface.php 0000644 00000001314 14641217650 0013246 0 ustar 00
*/
public function unmarshal(MessageInterface $message): array;
}
src/Serializers/DeserializerInterface.php 0000644 00000002144 14641217650 0014612 0 ustar 00
*/
public function deserializeBatch(string $payload): array;
/**
* @param array $attributes
*
* @throws InvalidPayloadSyntaxException
* @throws UnsupportedSpecVersionException
* @throws MissingAttributeException
*/
public function deserializeBinary(string $data, string $contentType, array $attributes): CloudEventInterface;
}
src/Serializers/JsonDeserializer.php 0000644 00000006010 14641217650 0013617 0 ustar 00 denormalizer = $denormalizer;
}
public static function create(): self
{
return new self(
new Denormalizer()
);
}
/**
* @throws InvalidPayloadSyntaxException
* @throws UnsupportedSpecVersionException
* @throws MissingAttributeException
*/
public function deserializeStructured(string $payload): CloudEventInterface
{
try {
/** @var mixed */
$decoded = json_decode($payload, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
throw new InvalidPayloadSyntaxException(null, 0, $e);
}
if (!is_array($decoded)) {
throw new InvalidPayloadSyntaxException();
}
return $this->denormalizer->denormalize($decoded);
}
/**
* @throws InvalidPayloadSyntaxException
* @throws UnsupportedSpecVersionException
* @throws MissingAttributeException
*
* @return list
*/
public function deserializeBatch(string $payload): array
{
try {
$decoded = json_decode($payload, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
throw new InvalidPayloadSyntaxException(null, 0, $e);
}
if (!is_array($decoded)) {
throw new InvalidPayloadSyntaxException();
}
$cloudEvents = [];
foreach ($decoded as $value) {
if (!is_array($value)) {
throw new InvalidPayloadSyntaxException();
}
$cloudEvents[] = $this->denormalizer->denormalize($value);
}
return $cloudEvents;
}
/**
* @param array $attributes
*
* @throws InvalidPayloadSyntaxException
* @throws UnsupportedSpecVersionException
* @throws MissingAttributeException
*/
public function deserializeBinary(string $data, string $contentType, array $attributes): CloudEventInterface
{
try {
/** @var mixed */
$decoded = json_decode($data, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
throw new InvalidPayloadSyntaxException(null, 0, $e);
}
return $this->denormalizer->denormalize(
array_merge(
array_map('rawurldecode', $attributes),
['data' => $decoded, 'datacontenttype' => $contentType]
)
);
}
}
src/Serializers/JsonSerializer.php 0000644 00000005724 14641217650 0013321 0 ustar 00 normalizer = $normalizer;
}
public static function create(): self
{
return new self(
new Normalizer()
);
}
/**
* @throws UnsupportedSpecVersionException
*/
public function serializeStructured(CloudEventInterface $cloudEvent): string
{
if (! $cloudEvent instanceof V1CloudEventInterface) {
throw new UnsupportedSpecVersionException();
}
$normalized = $this->normalizer->normalize($cloudEvent, false);
return json_encode($normalized);
}
/**
* @param list $cloudEvents
*
* @throws UnsupportedSpecVersionException
*/
public function serializeBatch(array $cloudEvents): string
{
$normalized = [];
foreach ($cloudEvents as $cloudEvent) {
if (! $cloudEvent instanceof V1CloudEventInterface) {
throw new UnsupportedSpecVersionException();
}
$normalized[] = $this->normalizer->normalize($cloudEvent, false);
}
return json_encode($normalized);
}
/**
* @throws UnsupportedSpecVersionException
*
* @return array{data: string, contentType: string, attributes: array}
*/
public function serializeBinary(CloudEventInterface $cloudEvent): array
{
if (! $cloudEvent instanceof V1CloudEventInterface) {
throw new UnsupportedSpecVersionException();
}
$normalized = $this->normalizer->normalize($cloudEvent, true);
/** @var string */
$data = json_encode($normalized['data']);
unset($normalized['data']);
/** @var string */
$contentType = $normalized['datacontenttype'] ?? 'application/json';
unset($normalized['datacontenttype']);
$attributes = [];
/** @var mixed $value */
foreach ($normalized as $key => $value) {
$attributes[$key] = self::encodeAttributeValue($value);
}
return [
'data' => $data,
'contentType' => $contentType,
'attributes' => $attributes,
];
}
/**
* @param mixed $value
*
* @return string
*/
private static function encodeAttributeValue($value): string
{
if ($value === true) {
return 'true';
}
if ($value === false) {
return 'false';
}
return rawurlencode((string) $value);
}
}
src/Serializers/Normalizers/V1/Denormalizer.php 0000644 00000002621 14641217650 0015575 0 ustar 00 $payload
*
* @throws InvalidAttributeException
* @throws UnsupportedSpecVersionException
* @throws MissingAttributeException
*/
public function denormalize(array $payload): CloudEventInterface
{
try {
if (($payload['specversion'] ?? null) !== CloudEventInterface::SPEC_VERSION) {
throw new UnsupportedSpecVersionException();
}
$cloudEvent = AttributeConverter::fromArray($payload);
if ($cloudEvent === null) {
throw new MissingAttributeException();
}
return $cloudEvent->withData(DataFormatter::decode($payload));
} catch (Throwable $e) {
if ($e instanceof UnsupportedSpecVersionException || $e instanceof MissingAttributeException) {
throw $e;
}
throw new InvalidAttributeException(null, 0, $e);
}
}
}
src/Serializers/Normalizers/V1/DenormalizerInterface.php 0000644 00000001126 14641217650 0017415 0 ustar 00 $payload
*
* @throws InvalidAttributeException
* @throws UnsupportedSpecVersionException
* @throws MissingAttributeException
*/
public function denormalize(array $payload): CloudEventInterface;
}
src/Serializers/Normalizers/V1/Normalizer.php 0000644 00000001104 14641217650 0015257 0 ustar 00
*/
public function normalize(CloudEventInterface $cloudEvent, bool $rawData): array
{
return array_merge(
AttributeConverter::toArray($cloudEvent),
DataFormatter::encode($cloudEvent->getData(), $rawData)
);
}
}
src/Serializers/Normalizers/V1/NormalizerInterface.php 0000644 00000000451 14641217650 0017104 0 ustar 00
*/
public function normalize(CloudEventInterface $cloudEvent, bool $rawData): array;
}
src/Serializers/SerializerInterface.php 0000644 00000001405 14641217650 0014300 0 ustar 00 $cloudEvents
*
* @throws UnsupportedSpecVersionException
*/
public function serializeBatch(array $cloudEvents): string;
/**
* @throws UnsupportedSpecVersionException
*
* @return array{data: string, contentType: string, attributes: array}
*/
public function serializeBinary(CloudEventInterface $cloudEvent): array;
}
src/Utilities/AttributeConverter.php 0000644 00000005462 14641217650 0013667 0 ustar 00
*/
public static function toArray(CloudEventInterface $cloudEvent): array
{
/** @var array */
$attributes = array_filter([
'specversion' => $cloudEvent->getSpecVersion(),
'id' => $cloudEvent->getId(),
'source' => $cloudEvent->getSource(),
'type' => $cloudEvent->getType(),
'datacontenttype' => $cloudEvent->getDataContentType(),
'dataschema' => $cloudEvent->getDataSchema(),
'subject' => $cloudEvent->getSubject(),
'time' => TimeFormatter::encode($cloudEvent->getTime()),
], fn ($attr) => $attr !== null);
return array_merge($attributes, $cloudEvent->getExtensions());
}
/**
* @param array $attributes
*/
public static function fromArray(array $attributes): ?CloudEventImmutable
{
if (!isset($attributes['id']) || !isset($attributes['source']) || !isset($attributes['type'])) {
return null;
}
/** @psalm-suppress MixedArgument */
$cloudEvent = new CloudEventImmutable(
$attributes['id'],
$attributes['source'],
$attributes['type']
);
/** @var mixed $value */
foreach ($attributes as $attribute => $value) {
switch ($attribute) {
case 'specversion':
case 'id':
case 'source':
case 'type':
case 'data':
case 'data_base64':
break;
case 'datacontenttype':
/** @psalm-suppress MixedArgument */
$cloudEvent = $cloudEvent->withDataContentType($value);
break;
case 'dataschema':
/** @psalm-suppress MixedArgument */
$cloudEvent = $cloudEvent->withDataSchema($value);
break;
case 'subject':
/** @psalm-suppress MixedArgument */
$cloudEvent = $cloudEvent->withSubject($value);
break;
case 'time':
/** @psalm-suppress MixedArgument */
$cloudEvent = $cloudEvent->withTime(TimeFormatter::decode($value));
break;
default:
/** @psalm-suppress MixedArgument */
$cloudEvent = $cloudEvent->withExtension((string) $attribute, $value);
break;
}
}
return $cloudEvent;
}
}
src/Utilities/DataFormatter.php 0000644 00000002742 14641217650 0012567 0 ustar 00 base64_encode($data)];
}
return $data !== null ? ['data' => $data] : [];
}
/**
* @return mixed
*/
public static function decode(array $data)
{
if (isset($data['data_base64'])) {
if (!is_string($data['data_base64'])) {
throw new ValueError(
\sprintf('%s(): Argument #1 ($data) contains bad data_base64 attribute content', __METHOD__)
);
}
$decoded = base64_decode($data['data_base64'], true);
if ($decoded === false) {
throw new ValueError(
\sprintf('%s(): Argument #1 ($data) contains bad data_base64 attribute content', __METHOD__)
);
}
return $decoded;
}
if (isset($data['data'])) {
return $data['data'];
}
return null;
}
/**
* @param mixed $data
*/
private static function isBinary($data): bool
{
return is_string($data) && !preg_match('//u', $data);
}
}
src/Utilities/TimeFormatter.php 0000644 00000002377 14641217650 0012620 0 ustar 00 setTimezone(new DateTimeZone(self::TIME_ZONE))->format(self::TIME_FORMAT);
}
public static function decode(?string $time): ?DateTimeImmutable
{
if ($time === null) {
return null;
}
/** @psalm-suppress UndefinedFunction */
$decoded = DateTimeImmutable::createFromFormat(
\str_contains($time, '.') ? self::RFC3339_EXTENDED_FORMAT : self::RFC3339_FORMAT,
\strtoupper($time),
new DateTimeZone(self::TIME_ZONE)
);
if ($decoded === false) {
throw new ValueError(
\sprintf('%s(): Argument #1 ($time) is not a valid RFC3339 timestamp', __METHOD__)
);
}
return $decoded;
}
}
src/V1/CloudEvent.php 0000644 00000000772 14641217650 0010416 0 ustar 00 setId($id);
return $cloudEvent;
}
public function withSource(string $source): self
{
$cloudEvent = clone $this;
$cloudEvent->setSource($source);
return $cloudEvent;
}
public function withType(string $type): self
{
$cloudEvent = clone $this;
$cloudEvent->setType($type);
return $cloudEvent;
}
/**
* @param mixed $data
*/
public function withData($data): self
{
$cloudEvent = clone $this;
$cloudEvent->setData($data);
return $cloudEvent;
}
public function withDataContentType(?string $dataContentType): self
{
$cloudEvent = clone $this;
$cloudEvent->setDataContentType($dataContentType);
return $cloudEvent;
}
public function withDataSchema(?string $dataSchema): self
{
$cloudEvent = clone $this;
$cloudEvent->setDataSchema($dataSchema);
return $cloudEvent;
}
public function withSubject(?string $subject): self
{
$cloudEvent = clone $this;
$cloudEvent->setSubject($subject);
return $cloudEvent;
}
public function withTime(?DateTimeImmutable $time): self
{
$cloudEvent = clone $this;
$cloudEvent->setTime($time);
return $cloudEvent;
}
/**
* @param array $extensions
*/
public function withExtensions(array $extensions): self
{
$cloudEvent = clone $this;
$cloudEvent->setExtensions($extensions);
return $cloudEvent;
}
/**
* @param bool|int|string|null $value
*/
public function withExtension(string $attribute, $value): self
{
$cloudEvent = clone $this;
$cloudEvent->setExtension($attribute, $value);
return $cloudEvent;
}
}
src/V1/CloudEventInterface.php 0000644 00000001432 14641217650 0012231 0 ustar 00
*/
public function getExtensions(): array;
/**
* @return bool|int|string|null
*/
public function getExtension(string $attribute);
}
src/V1/CloudEventTrait.php 0000644 00000015541 14641217650 0011422 0 ustar 00 */
private array $extensions = [];
/**
* @param mixed $data
* @param array $extensions
*/
public function __construct(
string $id,
string $source,
string $type,
$data = null,
?string $dataContentType = null,
?string $dataSchema = null,
?string $subject = null,
?DateTimeImmutable $time = null,
array $extensions = []
) {
$this->setId($id);
$this->setSource($source);
$this->setType($type);
$this->setData($data);
$this->setDataContentType($dataContentType);
$this->setDataSchema($dataSchema);
$this->setSubject($subject);
$this->setTime($time);
$this->setExtensions($extensions);
}
public static function createFromInterface(CloudEventInterface $event): self
{
return new self(
$event->getId(),
$event->getSource(),
$event->getType(),
$event->getData(),
$event->getDataContentType(),
$event->getDataSchema(),
$event->getSubject(),
$event->getTime(),
$event->getExtensions()
);
}
public function getSpecVersion(): string
{
return CloudEventInterface::SPEC_VERSION;
}
public function getId(): string
{
return $this->id;
}
private function setId(string $id): self
{
if ('' === $id) {
throw new ValueError(
\sprintf('%s(): Argument #1 ($id) must be a non-empty string, "" given', __METHOD__)
);
}
$this->id = $id;
return $this;
}
public function getSource(): string
{
return $this->source;
}
private function setSource(string $source): self
{
if ('' === $source) {
throw new ValueError(
\sprintf('%s(): Argument #1 ($source) must be a non-empty string, "" given', __METHOD__)
);
}
$this->source = $source;
return $this;
}
public function getType(): string
{
return $this->type;
}
private function setType(string $type): self
{
if ('' === $type) {
throw new ValueError(
\sprintf('%s(): Argument #1 ($type) must be a non-empty string, "" given', __METHOD__)
);
}
$this->type = $type;
return $this;
}
/**
* @return mixed
*/
public function getData()
{
return $this->data;
}
/**
* @param mixed $data
*/
private function setData($data): self
{
$this->data = $data;
return $this;
}
public function getDataContentType(): ?string
{
return $this->dataContentType;
}
private function setDataContentType(?string $dataContentType): self
{
if ($dataContentType !== null && \preg_match('#^[-\w]+/[-\w]+$#', $dataContentType) !== 1) {
throw new ValueError(
\sprintf('%s(): Argument #1 ($dataContentType) must be a valid mime-type string or null, "%s" given', __METHOD__, $dataContentType)
);
}
$this->dataContentType = $dataContentType;
return $this;
}
public function getDataSchema(): ?string
{
return $this->dataSchema;
}
private function setDataSchema(?string $dataSchema): self
{
if ('' === $dataSchema) {
throw new ValueError(
\sprintf('%s(): Argument #1 ($dataSchema) must be a non-empty string or null, "" given', __METHOD__)
);
}
$this->dataSchema = $dataSchema;
return $this;
}
public function getSubject(): ?string
{
return $this->subject;
}
private function setSubject(?string $subject): self
{
if ('' === $subject) {
throw new ValueError(
\sprintf('%s(): Argument #1 ($subject) must be a non-empty string or null, "" given', __METHOD__)
);
}
$this->subject = $subject;
return $this;
}
public function getTime(): ?DateTimeImmutable
{
return $this->time;
}
private function setTime(?DateTimeImmutable $time): self
{
$this->time = $time;
return $this;
}
/**
* @return array
*/
public function getExtensions(): array
{
return $this->extensions;
}
/**
* @return bool|int|string|null
*/
public function getExtension(string $attribute)
{
return $this->extensions[$attribute] ?? null;
}
/**
* @param array $extensions
*/
private function setExtensions(array $extensions): self
{
foreach ($extensions as $attribute => $value) {
$this->setExtension($attribute, $value);
}
return $this;
}
/**
* @param bool|int|string|null $value
*/
private function setExtension(string $attribute, $value): self
{
if (\preg_match('/^[a-z0-9]+$/', $attribute) !== 1) {
throw new ValueError(
\sprintf('%s(): Argument #1 ($attribute) must match the regex [a-z0-9]+, %s given', __METHOD__, $attribute)
);
}
/** @var list */
static $reservedAttributes = [
'specversion',
'id',
'source',
'type',
'data',
'data_base64',
'datacontenttype',
'dataschema',
'subject',
'time',
];
if (in_array($attribute, $reservedAttributes, true)) {
throw new ValueError(
\sprintf('%s(): Argument #1 ($attribute) must not be a reserved attribute, %s given', __METHOD__, $attribute)
);
}
/** @psalm-suppress UndefinedFunction */
$type = \get_debug_type($value);
$types = ['bool', 'int', 'string', 'null'];
if (!in_array($type, $types, true)) {
/** @psalm-suppress MixedArgument */
throw new TypeError(
\sprintf('%s(): Argument #2 ($value) must be of type %s, %s given', __METHOD__, implode('|', $types), $type)
);
}
if ($value === null) {
unset($this->extensions[$attribute]);
} else {
$this->extensions[$attribute] = $value;
}
return $this;
}
}
tests/Unit/Http/MarshallerTest.php 0000644 00000027176 14641217650 0013232 0 ustar 00 createStub(CloudEventInterface::class);
$event->method('getSpecVersion')->willReturn('1.0');
$event->method('getId')->willReturn('1234-1234-1234');
$event->method('getSource')->willReturn('/var/data');
$event->method('getType')->willReturn('com.example.someevent');
$event->method('getDataContentType')->willReturn('application/json');
$event->method('getDataSchema')->willReturn('com.example/schema');
$event->method('getSubject')->willReturn('larger-context');
$event->method('getTime')->willReturn(new DateTimeImmutable('2018-04-05T17:31:00Z'));
$event->method('getData')->willReturn(['key' => 'value']);
$event->method('getExtensions')->willReturn(['comacme' => 'foo']);
$request = Marshaller::createJsonMarshaller()
->marshalStructuredRequest($event, 'GET', 'https://example.com/endpoint');
self::assertSame(
"GET /endpoint HTTP/1.1\r\nHost: example.com\r\nContent-Type: application/cloudevents+json\r\nContent-Length: 266\r\n\r\n{\"specversion\":\"1.0\",\"id\":\"1234-1234-1234\",\"source\":\"\/var\/data\",\"type\":\"com.example.someevent\",\"datacontenttype\":\"application\/json\",\"dataschema\":\"com.example\/schema\",\"subject\":\"larger-context\",\"time\":\"2018-04-05T17:31:00Z\",\"comacme\":\"foo\",\"data\":{\"key\":\"value\"}}",
Message::toString($request)
);
}
public function testMarshalBinaryRequest(): void
{
/** @var CloudEventInterfaceV1|Stub $event */
$event = $this->createStub(CloudEventInterface::class);
$event->method('getSpecVersion')->willReturn('1.0');
$event->method('getId')->willReturn('1234-1234-1234');
$event->method('getSource')->willReturn('/var/data');
$event->method('getType')->willReturn('com.example.someevent');
$event->method('getDataContentType')->willReturn('application/json');
$event->method('getDataSchema')->willReturn('com.example/schema');
$event->method('getSubject')->willReturn('larger-context');
$event->method('getTime')->willReturn(new DateTimeImmutable('2018-04-05T17:31:00Z'));
$event->method('getData')->willReturn(['key' => 'value']);
$event->method('getExtensions')->willReturn(['comacme' => 'foo']);
$request = Marshaller::createJsonMarshaller()
->marshalBinaryRequest($event, 'GET', 'https://example.com/endpoint');
self::assertSame(
"GET /endpoint HTTP/1.1\r\nHost: example.com\r\nContent-Type: application/json\r\nContent-Length: 15\r\nce-specversion: 1.0\r\nce-id: 1234-1234-1234\r\nce-source: %2Fvar%2Fdata\r\nce-type: com.example.someevent\r\nce-dataschema: com.example%2Fschema\r\nce-subject: larger-context\r\nce-time: 2018-04-05T17%3A31%3A00Z\r\nce-comacme: foo\r\n\r\n{\"key\":\"value\"}",
Message::toString($request)
);
}
public function testMarshalBatchRequest(): void
{
/** @var CloudEventInterfaceV1|Stub $event */
$event1 = $this->createStub(CloudEventInterface::class);
$event1->method('getSpecVersion')->willReturn('1.0');
$event1->method('getId')->willReturn('1234-1234-1234');
$event1->method('getSource')->willReturn('/var/data');
$event1->method('getType')->willReturn('com.example.someevent');
$event1->method('getDataContentType')->willReturn('application/json');
$event1->method('getDataSchema')->willReturn('com.example/schema');
$event1->method('getSubject')->willReturn('larger-context');
$event1->method('getTime')->willReturn(new DateTimeImmutable('2018-04-05T17:31:00Z'));
$event1->method('getData')->willReturn(['key' => 'value']);
$event1->method('getExtensions')->willReturn(['comacme' => 'foo']);
/** @var CloudEventInterfaceV1|Stub $event */
$event2 = $this->createStub(CloudEventInterface::class);
$event2->method('getSpecVersion')->willReturn('1.0');
$event2->method('getId')->willReturn('1234-1234-2222');
$event2->method('getSource')->willReturn('/var/data');
$event2->method('getType')->willReturn('com.example.someevent');
$event2->method('getDataContentType')->willReturn('application/json');
$event2->method('getDataSchema')->willReturn('com.example/schema');
$event2->method('getSubject')->willReturn('larger-context');
$event2->method('getTime')->willReturn(new DateTimeImmutable('2018-04-05T17:31:00Z'));
$event2->method('getData')->willReturn(['key' => 'value']);
$event2->method('getExtensions')->willReturn(['comacme' => 'foo']);
$request = Marshaller::createJsonMarshaller()
->marshalBatchRequest([$event1, $event2], 'GET', 'https://example.com/endpoint');
self::assertSame(
"GET /endpoint HTTP/1.1\r\nHost: example.com\r\nContent-Type: application/cloudevents-batch+json\r\nContent-Length: 535\r\n\r\n[{\"specversion\":\"1.0\",\"id\":\"1234-1234-1234\",\"source\":\"\/var\/data\",\"type\":\"com.example.someevent\",\"datacontenttype\":\"application\/json\",\"dataschema\":\"com.example\/schema\",\"subject\":\"larger-context\",\"time\":\"2018-04-05T17:31:00Z\",\"comacme\":\"foo\",\"data\":{\"key\":\"value\"}},{\"specversion\":\"1.0\",\"id\":\"1234-1234-2222\",\"source\":\"\/var\/data\",\"type\":\"com.example.someevent\",\"datacontenttype\":\"application\/json\",\"dataschema\":\"com.example\/schema\",\"subject\":\"larger-context\",\"time\":\"2018-04-05T17:31:00Z\",\"comacme\":\"foo\",\"data\":{\"key\":\"value\"}}]",
Message::toString($request)
);
}
public function testMarshalStructuredResponse(): void
{
/** @var CloudEventInterfaceV1|Stub $event */
$event = $this->createStub(CloudEventInterface::class);
$event->method('getSpecVersion')->willReturn('1.0');
$event->method('getId')->willReturn('1234-1234-1234');
$event->method('getSource')->willReturn('/var/data');
$event->method('getType')->willReturn('com.example.someevent');
$event->method('getDataContentType')->willReturn('application/json');
$event->method('getDataSchema')->willReturn('com.example/schema');
$event->method('getSubject')->willReturn('larger-context');
$event->method('getTime')->willReturn(new DateTimeImmutable('2018-04-05T17:31:00Z'));
$event->method('getData')->willReturn(['key' => 'value']);
$event->method('getExtensions')->willReturn(['comacme' => 'foo']);
$response = Marshaller::createJsonMarshaller()
->marshalStructuredResponse($event);
self::assertSame(
"HTTP/1.1 200 OK\r\nContent-Type: application/cloudevents+json\r\nContent-Length: 266\r\n\r\n{\"specversion\":\"1.0\",\"id\":\"1234-1234-1234\",\"source\":\"\/var\/data\",\"type\":\"com.example.someevent\",\"datacontenttype\":\"application\/json\",\"dataschema\":\"com.example\/schema\",\"subject\":\"larger-context\",\"time\":\"2018-04-05T17:31:00Z\",\"comacme\":\"foo\",\"data\":{\"key\":\"value\"}}",
Message::toString($response)
);
}
public function testMarshalBinaryResponse(): void
{
/** @var CloudEventInterfaceV1|Stub $event */
$event = $this->createStub(CloudEventInterface::class);
$event->method('getSpecVersion')->willReturn('1.0');
$event->method('getId')->willReturn('1234-1234-1234');
$event->method('getSource')->willReturn('/var/data');
$event->method('getType')->willReturn('com.example.someevent');
$event->method('getDataContentType')->willReturn('application/json');
$event->method('getDataSchema')->willReturn('com.example/schema');
$event->method('getSubject')->willReturn('larger-context');
$event->method('getTime')->willReturn(new DateTimeImmutable('2018-04-05T17:31:00Z'));
$event->method('getData')->willReturn(['key' => 'value']);
$event->method('getExtensions')->willReturn(['comacme' => 'foo']);
$response = Marshaller::createJsonMarshaller()
->marshalBinaryResponse($event);
self::assertSame(
"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: 15\r\nce-specversion: 1.0\r\nce-id: 1234-1234-1234\r\nce-source: %2Fvar%2Fdata\r\nce-type: com.example.someevent\r\nce-dataschema: com.example%2Fschema\r\nce-subject: larger-context\r\nce-time: 2018-04-05T17%3A31%3A00Z\r\nce-comacme: foo\r\n\r\n{\"key\":\"value\"}",
Message::toString($response)
);
}
public function testMarshalBatchResponse(): void
{
/** @var CloudEventInterfaceV1|Stub $event */
$event1 = $this->createStub(CloudEventInterface::class);
$event1->method('getSpecVersion')->willReturn('1.0');
$event1->method('getId')->willReturn('1234-1234-1234');
$event1->method('getSource')->willReturn('/var/data');
$event1->method('getType')->willReturn('com.example.someevent');
$event1->method('getDataContentType')->willReturn('application/json');
$event1->method('getDataSchema')->willReturn('com.example/schema');
$event1->method('getSubject')->willReturn('larger-context');
$event1->method('getTime')->willReturn(new DateTimeImmutable('2018-04-05T17:31:00Z'));
$event1->method('getData')->willReturn(['key' => 'value']);
$event1->method('getExtensions')->willReturn(['comacme' => 'foo']);
/** @var CloudEventInterfaceV1|Stub $event */
$event2 = $this->createStub(CloudEventInterface::class);
$event2->method('getSpecVersion')->willReturn('1.0');
$event2->method('getId')->willReturn('1234-1234-2222');
$event2->method('getSource')->willReturn('/var/data');
$event2->method('getType')->willReturn('com.example.someevent');
$event2->method('getDataContentType')->willReturn('application/json');
$event2->method('getDataSchema')->willReturn('com.example/schema');
$event2->method('getSubject')->willReturn('larger-context');
$event2->method('getTime')->willReturn(new DateTimeImmutable('2018-04-05T17:31:00Z'));
$event2->method('getData')->willReturn(['key' => 'value']);
$event2->method('getExtensions')->willReturn(['comacme' => 'foo']);
$response = Marshaller::createJsonMarshaller()
->marshalBatchResponse([$event1, $event2]);
self::assertSame(
"HTTP/1.1 200 OK\r\nContent-Type: application/cloudevents-batch+json\r\nContent-Length: 535\r\n\r\n[{\"specversion\":\"1.0\",\"id\":\"1234-1234-1234\",\"source\":\"\/var\/data\",\"type\":\"com.example.someevent\",\"datacontenttype\":\"application\/json\",\"dataschema\":\"com.example\/schema\",\"subject\":\"larger-context\",\"time\":\"2018-04-05T17:31:00Z\",\"comacme\":\"foo\",\"data\":{\"key\":\"value\"}},{\"specversion\":\"1.0\",\"id\":\"1234-1234-2222\",\"source\":\"\/var\/data\",\"type\":\"com.example.someevent\",\"datacontenttype\":\"application\/json\",\"dataschema\":\"com.example\/schema\",\"subject\":\"larger-context\",\"time\":\"2018-04-05T17:31:00Z\",\"comacme\":\"foo\",\"data\":{\"key\":\"value\"}}]",
Message::toString($response)
);
}
}
tests/Unit/Http/UnmarshallerTest.php 0000644 00000031051 14641217650 0013560 0 ustar 00 unmarshal(
Message::parseRequest(
"GET /endpoint HTTP/1.1\r\nHost: example.com\r\nContent-Type: application/cloudevents+json\r\nContent-Length: 266\r\n\r\n{\"specversion\":\"1.0\",\"id\":\"1234-1234-1234\",\"source\":\"\/var\/data\",\"type\":\"com.example.someevent\",\"datacontenttype\":\"application\/json\",\"dataschema\":\"com.example\/schema\",\"subject\":\"larger-context\",\"time\":\"2018-04-05T17:31:00Z\",\"comacme\":\"foo\",\"data\":{\"key\":\"value\"}}"
)
);
self::assertCount(1, $events);
self::assertInstanceOf(CloudEventInterface::class, $events[0]);
self::assertSame('1.0', $events[0]->getSpecVersion());
self::assertSame('1234-1234-1234', $events[0]->getId());
self::assertSame('/var/data', $events[0]->getSource());
self::assertSame('com.example.someevent', $events[0]->getType());
self::assertSame('application/json', $events[0]->getDataContentType());
self::assertSame('com.example/schema', $events[0]->getDataSchema());
self::assertSame('larger-context', $events[0]->getSubject());
self::assertSame(1522949460, $events[0]->getTime()->getTimestamp());
self::assertSame(['key' => 'value'], $events[0]->getData());
self::assertSame(['comacme' => 'foo'], $events[0]->getExtensions());
}
public function testUnmarshalStructuredRequestInvalidContentType(): void
{
$this->expectException(UnsupportedContentTypeException::class);
Unmarshaller::createJsonUnmarshaller()->unmarshal(
Message::parseRequest(
"GET /endpoint HTTP/1.1\r\nHost: example.com\r\nContent-Type: application/cloudevents+xml\r\nContent-Length: 4\r\n\r\nDATA"
)
);
}
public function testUnmarshalBinaryRequest(): void
{
$events = Unmarshaller::createJsonUnmarshaller()->unmarshal(
Message::parseRequest(
"GET /endpoint HTTP/1.1\r\nHost: example.com\r\nContent-Type: application/json\r\nContent-Length: 15\r\nce-specversion: 1.0\r\nce-id: 1234-1234-1234\r\nce-source: %2Fvar%2Fdata\r\nce-type: com.example.someevent\r\nce-dataschema: com.example%2Fschema\r\nce-subject: larger-context\r\nce-time: 2018-04-05T17%3A31%3A00Z\r\nce-comacme: foo\r\n\r\n{\"key\":\"value\"}"
)
);
self::assertCount(1, $events);
self::assertInstanceOf(CloudEventInterface::class, $events[0]);
self::assertSame('1.0', $events[0]->getSpecVersion());
self::assertSame('1234-1234-1234', $events[0]->getId());
self::assertSame('/var/data', $events[0]->getSource());
self::assertSame('com.example.someevent', $events[0]->getType());
self::assertSame('application/json', $events[0]->getDataContentType());
self::assertSame('com.example/schema', $events[0]->getDataSchema());
self::assertSame('larger-context', $events[0]->getSubject());
self::assertSame(1522949460, $events[0]->getTime()->getTimestamp());
self::assertSame(['key' => 'value'], $events[0]->getData());
self::assertSame(['comacme' => 'foo'], $events[0]->getExtensions());
}
public function testUnmarshalBinaryRequestInvalidContentType(): void
{
$this->expectException(UnsupportedContentTypeException::class);
Unmarshaller::createJsonUnmarshaller()->unmarshal(
Message::parseRequest(
"GET /endpoint HTTP/1.1\r\nHost: example.com\r\nContent-Type: application/xml\r\nContent-Length: 4\r\nce-specversion: 1.0\r\nce-id: 1234-1234-1234\r\nce-source: %2Fvar%2Fdata\r\nce-type: com.example.someevent\r\nce-dataschema: com.example%2Fschema\r\nce-subject: larger-context\r\nce-time: 2018-04-05T17%3A31%3A00Z\r\nce-comacme: foo\r\n\r\nDATA"
)
);
}
public function testUnmarshalBatchRequest(): void
{
$events = Unmarshaller::createJsonUnmarshaller()->unmarshal(
Message::parseRequest(
"GET /endpoint HTTP/1.1\r\nHost: example.com\r\nContent-Type: application/cloudevents-batch+json\r\nContent-Length: 535\r\n\r\n[{\"specversion\":\"1.0\",\"id\":\"1234-1234-1234\",\"source\":\"\/var\/data\",\"type\":\"com.example.someevent\",\"datacontenttype\":\"application\/json\",\"dataschema\":\"com.example\/schema\",\"subject\":\"larger-context\",\"time\":\"2018-04-05T17:31:00Z\",\"comacme\":\"foo\",\"data\":{\"key\":\"value\"}},{\"specversion\":\"1.0\",\"id\":\"1234-1234-2222\",\"source\":\"\/var\/data\",\"type\":\"com.example.someevent\",\"datacontenttype\":\"application\/json\",\"dataschema\":\"com.example\/schema\",\"subject\":\"larger-context\",\"time\":\"2018-04-05T17:31:00Z\",\"comacme\":\"foo\",\"data\":{\"key\":\"value\"}}]"
)
);
self::assertCount(2, $events);
self::assertInstanceOf(CloudEventInterface::class, $events[0]);
self::assertSame('1.0', $events[0]->getSpecVersion());
self::assertSame('1234-1234-1234', $events[0]->getId());
self::assertSame('/var/data', $events[0]->getSource());
self::assertSame('com.example.someevent', $events[0]->getType());
self::assertSame('application/json', $events[0]->getDataContentType());
self::assertSame('com.example/schema', $events[0]->getDataSchema());
self::assertSame('larger-context', $events[0]->getSubject());
self::assertSame(1522949460, $events[0]->getTime()->getTimestamp());
self::assertSame(['key' => 'value'], $events[0]->getData());
self::assertSame(['comacme' => 'foo'], $events[0]->getExtensions());
self::assertInstanceOf(CloudEventInterface::class, $events[1]);
self::assertSame('1.0', $events[1]->getSpecVersion());
self::assertSame('1234-1234-2222', $events[1]->getId());
self::assertSame('/var/data', $events[1]->getSource());
self::assertSame('com.example.someevent', $events[1]->getType());
self::assertSame('application/json', $events[1]->getDataContentType());
self::assertSame('com.example/schema', $events[1]->getDataSchema());
self::assertSame('larger-context', $events[1]->getSubject());
self::assertSame(1522949460, $events[1]->getTime()->getTimestamp());
self::assertSame(['key' => 'value'], $events[1]->getData());
self::assertSame(['comacme' => 'foo'], $events[1]->getExtensions());
}
public function testUnmarshalStructuredResponse(): void
{
$events = Unmarshaller::createJsonUnmarshaller()->unmarshal(
Message::parseResponse(
"HTTP/1.1 200 OK\r\nContent-Type: application/cloudevents+json\r\nContent-Length: 266\r\n\r\n{\"specversion\":\"1.0\",\"id\":\"1234-1234-1234\",\"source\":\"\/var\/data\",\"type\":\"com.example.someevent\",\"datacontenttype\":\"application\/json\",\"dataschema\":\"com.example\/schema\",\"subject\":\"larger-context\",\"time\":\"2018-04-05T17:31:00Z\",\"comacme\":\"foo\",\"data\":{\"key\":\"value\"}}"
)
);
self::assertCount(1, $events);
self::assertInstanceOf(CloudEventInterface::class, $events[0]);
self::assertSame('1.0', $events[0]->getSpecVersion());
self::assertSame('1234-1234-1234', $events[0]->getId());
self::assertSame('/var/data', $events[0]->getSource());
self::assertSame('com.example.someevent', $events[0]->getType());
self::assertSame('application/json', $events[0]->getDataContentType());
self::assertSame('com.example/schema', $events[0]->getDataSchema());
self::assertSame('larger-context', $events[0]->getSubject());
self::assertSame(1522949460, $events[0]->getTime()->getTimestamp());
self::assertSame(['key' => 'value'], $events[0]->getData());
self::assertSame(['comacme' => 'foo'], $events[0]->getExtensions());
}
public function testUnmarshalStructuredResponseInvalidContentType(): void
{
$this->expectException(UnsupportedContentTypeException::class);
Unmarshaller::createJsonUnmarshaller()->unmarshal(
Message::parseResponse(
"HTTP/1.1 200 OK\r\nContent-Type: application/cloudevents+xml\r\nContent-Length: 4\r\n\r\nDATA"
)
);
}
public function testUnmarshalBinaryResponse(): void
{
$events = Unmarshaller::createJsonUnmarshaller()->unmarshal(
Message::parseResponse(
"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: 15\r\nce-specversion: 1.0\r\nce-id: 1234-1234-1234\r\nce-source: %2Fvar%2Fdata\r\nce-type: com.example.someevent\r\nce-dataschema: com.example%2Fschema\r\nce-subject: larger-context\r\nce-time: 2018-04-05T17%3A31%3A00Z\r\nce-comacme: foo\r\n\r\n{\"key\":\"value\"}"
)
);
self::assertCount(1, $events);
self::assertInstanceOf(CloudEventInterface::class, $events[0]);
self::assertSame('1.0', $events[0]->getSpecVersion());
self::assertSame('1234-1234-1234', $events[0]->getId());
self::assertSame('/var/data', $events[0]->getSource());
self::assertSame('com.example.someevent', $events[0]->getType());
self::assertSame('application/json', $events[0]->getDataContentType());
self::assertSame('com.example/schema', $events[0]->getDataSchema());
self::assertSame('larger-context', $events[0]->getSubject());
self::assertSame(1522949460, $events[0]->getTime()->getTimestamp());
self::assertSame(['key' => 'value'], $events[0]->getData());
self::assertSame(['comacme' => 'foo'], $events[0]->getExtensions());
}
public function testUnmarshalBatchResponse(): void
{
$events = Unmarshaller::createJsonUnmarshaller()->unmarshal(
Message::parseResponse(
"HTTP/1.1 200 OK\r\nContent-Type: application/cloudevents-batch+json\r\nContent-Length: 535\r\n\r\n[{\"specversion\":\"1.0\",\"id\":\"1234-1234-1234\",\"source\":\"\/var\/data\",\"type\":\"com.example.someevent\",\"datacontenttype\":\"application\/json\",\"dataschema\":\"com.example\/schema\",\"subject\":\"larger-context\",\"time\":\"2018-04-05T17:31:00Z\",\"comacme\":\"foo\",\"data\":{\"key\":\"value\"}},{\"specversion\":\"1.0\",\"id\":\"1234-1234-2222\",\"source\":\"\/var\/data\",\"type\":\"com.example.someevent\",\"datacontenttype\":\"application\/json\",\"dataschema\":\"com.example\/schema\",\"subject\":\"larger-context\",\"time\":\"2018-04-05T17:31:00Z\",\"comacme\":\"foo\",\"data\":{\"key\":\"value\"}}]"
)
);
self::assertCount(2, $events);
self::assertInstanceOf(CloudEventInterface::class, $events[0]);
self::assertSame('1.0', $events[0]->getSpecVersion());
self::assertSame('1234-1234-1234', $events[0]->getId());
self::assertSame('/var/data', $events[0]->getSource());
self::assertSame('com.example.someevent', $events[0]->getType());
self::assertSame('application/json', $events[0]->getDataContentType());
self::assertSame('com.example/schema', $events[0]->getDataSchema());
self::assertSame('larger-context', $events[0]->getSubject());
self::assertSame(1522949460, $events[0]->getTime()->getTimestamp());
self::assertSame(['key' => 'value'], $events[0]->getData());
self::assertSame(['comacme' => 'foo'], $events[0]->getExtensions());
self::assertInstanceOf(CloudEventInterface::class, $events[1]);
self::assertSame('1.0', $events[1]->getSpecVersion());
self::assertSame('1234-1234-2222', $events[1]->getId());
self::assertSame('/var/data', $events[1]->getSource());
self::assertSame('com.example.someevent', $events[1]->getType());
self::assertSame('application/json', $events[1]->getDataContentType());
self::assertSame('com.example/schema', $events[1]->getDataSchema());
self::assertSame('larger-context', $events[1]->getSubject());
self::assertSame(1522949460, $events[1]->getTime()->getTimestamp());
self::assertSame(['key' => 'value'], $events[1]->getData());
self::assertSame(['comacme' => 'foo'], $events[1]->getExtensions());
}
}
tests/Unit/Serializers/JsonDeserializerTest.php 0000644 00000024163 14641217650 0015762 0 ustar 00 createStub(DenormalizerInterface::class))
);
self::assertInstanceOf(
DeserializerInterface::class,
JsonDeserializer::create()
);
}
public function testDeserializeStructured(): void
{
$formatter = JsonDeserializer::create();
$event = $formatter->deserializeStructured(
'{"specversion":"1.0","id":"1234-1234-1234","source":"\/var\/data","type":"com.example.someevent","datacontenttype":"application\/json","dataschema":"com.example\/schema","subject":"larger-context","time":"2018-04-05T17:31:00Z","data":{"key":"value"},"comacme":"foo"}'
);
self::assertEquals('1.0', $event->getSpecVersion());
self::assertEquals('1234-1234-1234', $event->getId());
self::assertEquals('/var/data', $event->getSource());
self::assertEquals('com.example.someevent', $event->getType());
self::assertEquals('application/json', $event->getDataContentType());
self::assertEquals('com.example/schema', $event->getDataSchema());
self::assertEquals('larger-context', $event->getSubject());
self::assertEquals(new DateTimeImmutable('2018-04-05T17:31:00Z'), $event->getTime());
self::assertEquals(['key' => 'value'], $event->getData());
self::assertEquals(['comacme' => 'foo'], $event->getExtensions());
}
public function testDeserializeStructuredUnsupportedSpecVersion(): void
{
$formatter = JsonDeserializer::create();
$this->expectException(UnsupportedSpecVersionException::class);
$formatter->deserializeStructured(
'{"specversion":"0.3","id":"1234-1234-1234","source":"\/var\/data","type":"com.example.someevent","datacontenttype":"application\/json","dataschema":"com.example\/schema","subject":"larger-context","time":"2018-04-05T17:31:00Z","data":{"key":"value"},"comacme":"foo"}'
);
}
public function testDeserializeStructuredInvalidSyntax1(): void
{
$formatter = JsonDeserializer::create();
$this->expectException(InvalidPayloadSyntaxException::class);
$formatter->deserializeStructured(
'{"specversion":"1.0","id":"1234-1'
);
}
public function testDeserializeStructuredInvalidSyntax2(): void
{
$formatter = JsonDeserializer::create();
$this->expectException(InvalidPayloadSyntaxException::class);
$formatter->deserializeStructured(
'true'
);
}
public function testDeserializeStructuredInvalidId(): void
{
$formatter = JsonDeserializer::create();
$this->expectException(InvalidAttributeException::class);
$formatter->deserializeStructured(
'{"specversion":"1.0","id":123,"source":"\/var\/data","type":"com.example.someevent","datacontenttype":"application\/json","dataschema":"com.example\/schema","subject":"larger-context","time":"2018-04-05T17:31:00Z","data":{"key":"value"},"comacme":"foo"}'
);
}
public function testDeserializeBatch(): void
{
$formatter = JsonDeserializer::create();
$events = $formatter->deserializeBatch(
'[{"specversion":"1.0","id":"1234-1234-1234","source":"\/var\/data","type":"com.example.someevent","datacontenttype":"application\/json","dataschema":"com.example\/schema","subject":"larger-context","time":"2018-04-05T17:31:00Z","data":{"key":"value"},"comacme":"foo"},{"specversion":"1.0","id":"1234-1234-2222","source":"\/var\/data","type":"com.example.someevent","datacontenttype":"application\/json","dataschema":"com.example\/schema","subject":"larger-context","time":"2018-04-05T17:31:00Z","data":{"key":"value"},"comacme":"foo"}]'
);
self::assertCount(2, $events);
self::assertEquals('1.0', $events[0]->getSpecVersion());
self::assertEquals('1234-1234-1234', $events[0]->getId());
self::assertEquals('/var/data', $events[0]->getSource());
self::assertEquals('com.example.someevent', $events[0]->getType());
self::assertEquals('application/json', $events[0]->getDataContentType());
self::assertEquals('com.example/schema', $events[0]->getDataSchema());
self::assertEquals('larger-context', $events[0]->getSubject());
self::assertEquals(new DateTimeImmutable('2018-04-05T17:31:00Z'), $events[0]->getTime());
self::assertEquals(['key' => 'value'], $events[0]->getData());
self::assertEquals(['comacme' => 'foo'], $events[0]->getExtensions());
self::assertEquals('1.0', $events[1]->getSpecVersion());
self::assertEquals('1234-1234-2222', $events[1]->getId());
self::assertEquals('/var/data', $events[1]->getSource());
self::assertEquals('com.example.someevent', $events[1]->getType());
self::assertEquals('application/json', $events[1]->getDataContentType());
self::assertEquals('com.example/schema', $events[1]->getDataSchema());
self::assertEquals('larger-context', $events[1]->getSubject());
self::assertEquals(new DateTimeImmutable('2018-04-05T17:31:00Z'), $events[1]->getTime());
self::assertEquals(['key' => 'value'], $events[1]->getData());
self::assertEquals(['comacme' => 'foo'], $events[1]->getExtensions());
}
public function testDeserializeBatchUnsupportedSpecVersion(): void
{
$formatter = JsonDeserializer::create();
$this->expectException(UnsupportedSpecVersionException::class);
$formatter->deserializeBatch(
'[{"specversion":"1.0","id":"1234-1234-1234","source":"\/var\/data","type":"com.example.someevent","datacontenttype":"application\/json","dataschema":"com.example\/schema","subject":"larger-context","time":"2018-04-05T17:31:00Z","data":{"key":"value"},"comacme":"foo"},{"specversion":"0.3","id":"1234-1234-2222","source":"\/var\/data","type":"com.example.someevent","datacontenttype":"application\/json","dataschema":"com.example\/schema","subject":"larger-context","time":"2018-04-05T17:31:00Z","data":{"key":"value"},"comacme":"foo"}]'
);
}
public function testDeserializeBatchInvalidSyntax1(): void
{
$formatter = JsonDeserializer::create();
$this->expectException(InvalidPayloadSyntaxException::class);
$formatter->deserializeBatch(
'[{"specversion":"1.0","id":"1234-1'
);
}
public function testDeserializeBatchInvalidSyntax2(): void
{
$formatter = JsonDeserializer::create();
$this->expectException(InvalidPayloadSyntaxException::class);
$formatter->deserializeBatch(
'true'
);
}
public function testDeserializeBatchInvalidSyntax3(): void
{
$formatter = JsonDeserializer::create();
$this->expectException(InvalidPayloadSyntaxException::class);
$formatter->deserializeBatch(
'[true]'
);
}
public function testDeserializeBinary(): void
{
$formatter = JsonDeserializer::create();
$event = $formatter->deserializeBinary(
'{"key":"value"}',
'application/json',
[
'specversion' => '1.0',
'id' => '1234-1234-1234',
'source' => '%2Fvar%2Fdata',
'type' => 'com.example.someevent',
'dataschema' => 'com.example%2Fschema',
'subject' => 'larger-context',
'time' => '2018-04-05T17%3A31%3A00Z',
'comacme' => 'foo',
]
);
self::assertEquals('1.0', $event->getSpecVersion());
self::assertEquals('1234-1234-1234', $event->getId());
self::assertEquals('/var/data', $event->getSource());
self::assertEquals('com.example.someevent', $event->getType());
self::assertEquals('application/json', $event->getDataContentType());
self::assertEquals('com.example/schema', $event->getDataSchema());
self::assertEquals('larger-context', $event->getSubject());
self::assertEquals(new DateTimeImmutable('2018-04-05T17:31:00Z'), $event->getTime());
self::assertEquals(['key' => 'value'], $event->getData());
self::assertEquals(['comacme' => 'foo'], $event->getExtensions());
}
public function testDeserializeBinaryUnsupportedSpecVersion(): void
{
$formatter = JsonDeserializer::create();
$this->expectException(UnsupportedSpecVersionException::class);
$formatter->deserializeBinary(
'{"key":"value"}',
'application/json',
[
'specversion' => '0.3',
'id' => '1234-1234-1234',
'source' => '%2Fvar%2Fdata',
'type' => 'com.example.someevent',
'dataschema' => 'com.example%2Fschema',
'subject' => 'larger-context',
'time' => '2018-04-05T17%3A31%3A00Z',
'comacme' => 'foo',
]
);
}
public function testDeserializeBinaryInvalidSyntax1(): void
{
$formatter = JsonDeserializer::create();
$this->expectException(InvalidPayloadSyntaxException::class);
$formatter->deserializeBinary(
'{"key":"val',
'application/json',
[
'specversion' => '0.3',
'id' => '1234-1234-1234',
'source' => '%2Fvar%2Fdata',
'type' => 'com.example.someevent',
'dataschema' => 'com.example%2Fschema',
'subject' => 'larger-context',
'time' => '2018-04-05T17%3A31%3A00Z',
'comacme' => 'foo',
]
);
}
}
tests/Unit/Serializers/JsonSerializerTest.php 0000644 00000020611 14641217650 0015443 0 ustar 00 createStub(NormalizerInterface::class))
);
self::assertInstanceOf(
SerializerInterface::class,
JsonSerializer::create()
);
}
public function testSerializeStructured(): void
{
/** @var CloudEventInterfaceV1|Stub $event */
$event = $this->createStub(CloudEventInterfaceV1::class);
$event->method('getSpecVersion')->willReturn('1.0');
$event->method('getId')->willReturn('1234-1234-1234');
$event->method('getSource')->willReturn('/var/data');
$event->method('getType')->willReturn('com.example.someevent');
$event->method('getDataContentType')->willReturn('application/json');
$event->method('getDataSchema')->willReturn('com.example/schema');
$event->method('getSubject')->willReturn('larger-context');
$event->method('getTime')->willReturn(new DateTimeImmutable('2018-04-05T17:31:00Z'));
$event->method('getData')->willReturn(['key' => 'value']);
$event->method('getExtensions')->willReturn(['comacme' => 'foo']);
$formatter = JsonSerializer::create();
self::assertSame(
'{"specversion":"1.0","id":"1234-1234-1234","source":"\/var\/data","type":"com.example.someevent","datacontenttype":"application\/json","dataschema":"com.example\/schema","subject":"larger-context","time":"2018-04-05T17:31:00Z","comacme":"foo","data":{"key":"value"}}',
$formatter->serializeStructured($event)
);
}
public function testSerializeStructuredUnsupportedSpecVersion(): void
{
/** @var CloudEventInterface|Stub $event */
$event = $this->createStub(CloudEventInterface::class);
$event->method('getSpecVersion')->willReturn('0.3');
$formatter = JsonSerializer::create();
$this->expectException(UnsupportedSpecVersionException::class);
$formatter->serializeStructured($event);
}
public function testSerializeBatch(): void
{
/** @var CloudEventInterfaceV1|Stub $event1 */
$event1 = $this->createStub(CloudEventInterfaceV1::class);
$event1->method('getSpecVersion')->willReturn('1.0');
$event1->method('getId')->willReturn('1234-1234-1234');
$event1->method('getSource')->willReturn('/var/data');
$event1->method('getType')->willReturn('com.example.someevent');
$event1->method('getDataContentType')->willReturn('application/json');
$event1->method('getDataSchema')->willReturn('com.example/schema');
$event1->method('getSubject')->willReturn('larger-context');
$event1->method('getTime')->willReturn(new DateTimeImmutable('2018-04-05T17:31:00Z'));
$event1->method('getData')->willReturn(['key' => 'value']);
$event1->method('getExtensions')->willReturn(['comacme' => 'foo']);
/** @var CloudEventInterfaceV1|Stub $event2 */
$event2 = $this->createStub(CloudEventInterfaceV1::class);
$event2->method('getSpecVersion')->willReturn('1.0');
$event2->method('getId')->willReturn('1234-1234-2222');
$event2->method('getSource')->willReturn('/var/data');
$event2->method('getType')->willReturn('com.example.someevent');
$event2->method('getDataContentType')->willReturn('application/json');
$event2->method('getDataSchema')->willReturn('com.example/schema');
$event2->method('getSubject')->willReturn('larger-context');
$event2->method('getTime')->willReturn(new DateTimeImmutable('2018-04-05T17:31:00Z'));
$event2->method('getData')->willReturn(['key' => 'value']);
$event2->method('getExtensions')->willReturn(['comacme' => 'foo']);
$formatter = JsonSerializer::create();
self::assertSame(
'[{"specversion":"1.0","id":"1234-1234-1234","source":"\/var\/data","type":"com.example.someevent","datacontenttype":"application\/json","dataschema":"com.example\/schema","subject":"larger-context","time":"2018-04-05T17:31:00Z","comacme":"foo","data":{"key":"value"}},{"specversion":"1.0","id":"1234-1234-2222","source":"\/var\/data","type":"com.example.someevent","datacontenttype":"application\/json","dataschema":"com.example\/schema","subject":"larger-context","time":"2018-04-05T17:31:00Z","comacme":"foo","data":{"key":"value"}}]',
$formatter->serializeBatch([$event1, $event2])
);
}
public function testSerializeBatchUnsupportedSpecVersion(): void
{
/** @var CloudEventInterfaceV1|Stub $event1 */
$event1 = $this->createStub(CloudEventInterfaceV1::class);
$event1->method('getSpecVersion')->willReturn('1.0');
$event1->method('getId')->willReturn('1234-1234-1234');
$event1->method('getSource')->willReturn('/var/data');
$event1->method('getType')->willReturn('com.example.someevent');
$event1->method('getDataContentType')->willReturn('application/json');
$event1->method('getDataSchema')->willReturn('com.example/schema');
$event1->method('getSubject')->willReturn('larger-context');
$event1->method('getTime')->willReturn(new DateTimeImmutable('2018-04-05T17:31:00Z'));
$event1->method('getData')->willReturn(['key' => 'value']);
$event1->method('getExtensions')->willReturn(['comacme' => 'foo']);
/** @var CloudEventInterface|Stub $event */
$event2 = $this->createStub(CloudEventInterface::class);
$event2->method('getSpecVersion')->willReturn('0.3');
$formatter = JsonSerializer::create();
$this->expectException(UnsupportedSpecVersionException::class);
$formatter->serializeBatch([$event1, $event2]);
}
public function testSerializeBinary(): void
{
/** @var CloudEventInterfaceV1|Stub $event */
$event = $this->createStub(CloudEventInterfaceV1::class);
$event->method('getSpecVersion')->willReturn('1.0');
$event->method('getId')->willReturn('1234-1234-1234');
$event->method('getSource')->willReturn('/var/data');
$event->method('getType')->willReturn('com.example.someevent');
$event->method('getDataContentType')->willReturn('application/json');
$event->method('getDataSchema')->willReturn('com.example/schema');
$event->method('getSubject')->willReturn('larger-context');
$event->method('getTime')->willReturn(new DateTimeImmutable('2018-04-05T17:31:00Z'));
$event->method('getData')->willReturn(['key' => 'value']);
$event->method('getExtensions')->willReturn(['comacme' => 'foo', 'comacmen' => 123, 'comacmet' => true, 'comacmef' => false]);
$formatter = JsonSerializer::create();
self::assertSame(
[
'data' => '{"key":"value"}',
'contentType' => 'application/json',
'attributes' => [
'specversion' => '1.0',
'id' => '1234-1234-1234',
'source' => '%2Fvar%2Fdata',
'type' => 'com.example.someevent',
'dataschema' => 'com.example%2Fschema',
'subject' => 'larger-context',
'time' => '2018-04-05T17%3A31%3A00Z',
'comacme' => 'foo',
'comacmen' => '123',
'comacmet' => 'true',
'comacmef' => 'false',
],
],
$formatter->serializeBinary($event)
);
}
public function testSerializeBinaryUnsupportedSpecVersion(): void
{
/** @var CloudEventInterface|Stub $event */
$event = $this->createStub(CloudEventInterface::class);
$event->method('getSpecVersion')->willReturn('0.3');
$formatter = JsonSerializer::create();
$this->expectException(UnsupportedSpecVersionException::class);
$formatter->serializeBinary($event);
}
}
tests/Unit/Serializers/Normalizers/V1/DenormalizerTest.php 0000644 00000004731 14641217650 0017733 0 ustar 00 '1.0',
'id' => '1234-1234-1234',
'source' => '/var/data',
'type' => 'com.example.someevent',
'datacontenttype' => 'application/json',
'dataschema' => 'com.example/schema',
'subject' => 'larger-context',
'time' => '2018-04-05T17:31:00Z',
'data' => [
'key' => 'value',
],
'comacme' => 'foo',
];
$formatter = new Denormalizer();
$event = $formatter->denormalize($payload);
self::assertEquals('1.0', $event->getSpecVersion());
self::assertEquals('1234-1234-1234', $event->getId());
self::assertEquals('/var/data', $event->getSource());
self::assertEquals('com.example.someevent', $event->getType());
self::assertEquals('application/json', $event->getDataContentType());
self::assertEquals('com.example/schema', $event->getDataSchema());
self::assertEquals('larger-context', $event->getSubject());
self::assertEquals(new DateTimeImmutable('2018-04-05T17:31:00Z'), $event->getTime());
self::assertEquals(['key' => 'value'], $event->getData());
self::assertEquals(['comacme' => 'foo'], $event->getExtensions());
}
public function testDenormalizeMissingId(): void
{
$payload = [
'specversion' => '1.0',
'source' => '/var/data',
'type' => 'com.example.someevent',
'datacontenttype' => 'application/json',
'dataschema' => 'com.example/schema',
'subject' => 'larger-context',
'time' => '2018-04-05T17:31:00Z',
'data' => [
'key' => 'value',
],
'comacme' => 'foo',
];
$formatter = new Denormalizer();
$this->expectException(MissingAttributeException::class);
$formatter->denormalize($payload);
}
}
tests/Unit/Serializers/Normalizers/V1/NormalizerTest.php 0000644 00000006122 14641217650 0017416 0 ustar 00 createStub(CloudEventInterface::class);
$event->method('getSpecVersion')->willReturn('1.0');
$event->method('getId')->willReturn('1234-1234-1234');
$event->method('getSource')->willReturn('/var/data');
$event->method('getType')->willReturn('com.example.someevent');
$event->method('getDataContentType')->willReturn('application/json');
$event->method('getDataSchema')->willReturn('com.example/schema');
$event->method('getSubject')->willReturn('larger-context');
$event->method('getTime')->willReturn(new DateTimeImmutable('2018-04-05T17:31:00Z'));
$event->method('getData')->willReturn(['key' => 'value']);
$event->method('getExtensions')->willReturn(['comacme' => 'foo']);
$formatter = new Normalizer();
self::assertSame(
[
'specversion' => '1.0',
'id' => '1234-1234-1234',
'source' => '/var/data',
'type' => 'com.example.someevent',
'datacontenttype' => 'application/json',
'dataschema' => 'com.example/schema',
'subject' => 'larger-context',
'time' => '2018-04-05T17:31:00Z',
'comacme' => 'foo',
'data' => [
'key' => 'value',
],
],
$formatter->normalize($event, false)
);
}
public function testNormalizerWithUnsetAttributes(): void
{
/** @var CloudEventInterface|Stub $event */
$event = $this->createStub(CloudEventInterface::class);
$event->method('getSpecVersion')->willReturn('1.0');
$event->method('getId')->willReturn('1234-1234-1234');
$event->method('getSource')->willReturn('/var/data');
$event->method('getType')->willReturn('com.example.someevent');
$event->method('getSubject')->willReturn('larger-context');
$event->method('getTime')->willReturn(new DateTimeImmutable('2018-04-05T17:31:00Z'));
$event->method('getExtensions')->willReturn([]);
$formatter = new Normalizer();
self::assertSame(
[
'specversion' => '1.0',
'id' => '1234-1234-1234',
'source' => '/var/data',
'type' => 'com.example.someevent',
'subject' => 'larger-context',
'time' => '2018-04-05T17:31:00Z',
],
$formatter->normalize($event, false)
);
}
}
tests/Unit/Utilities/DataFormatterTest.php 0000644 00000002734 14641217650 0014722 0 ustar 00 ['foo' => 'bar']], DataFormatter::encode(['foo' => 'bar'], false));
self::assertEquals(['foo' => 'bar'], DataFormatter::decode(['data' => ['foo' => 'bar']]));
}
public function testEncodeAndDecodeBinary(): void
{
$data = random_bytes(1024);
$encoded = base64_encode($data);
self::assertEquals(['data_base64' => $encoded], DataFormatter::encode($data, false));
self::assertEquals($data, DataFormatter::decode(['data_base64' => $encoded]));
self::assertEquals(['data' => $data], DataFormatter::encode($data, true));
self::assertEquals($data, DataFormatter::decode(['data' => $data]));
}
public function testInvalidBase64Decode1(): void
{
$this->expectException(ValueError::class);
DataFormatter::decode(['data_base64' => 123]);
}
public function testInvalidBase64Decode2(): void
{
$this->expectException(ValueError::class);
DataFormatter::decode(['data_base64' => 'a']);
}
public function testEncodeAndDecodeEmpty(): void
{
self::assertEquals([], DataFormatter::encode(null, false));
self::assertEquals(null, DataFormatter::decode([]));
}
}
tests/Unit/Utilities/TimeFormatterTest.php 0000644 00000006545 14641217650 0014753 0 ustar 00 expectException(ValueError::class);
$this->expectExceptionMessage(
'CloudEvents\\Utilities\\TimeFormatter::decode(): Argument #1 ($time) is not a valid RFC3339 timestamp'
);
TimeFormatter::decode('2018asdsdsafd');
}
}
tests/Unit/V1/CloudEventImmutableTest.php 0000644 00000014723 14641217650 0014411 0 ustar 00 getEvent()->getSpecVersion());
}
public function testGetSetId(): void
{
$event = $this->getEvent();
self::assertEquals('A234-1234-1234', $event->getId());
$event = $event->withId('new-id');
self::assertEquals('new-id', $event->getId());
}
public function testGetSetSource(): void
{
$event = $this->getEvent();
self::assertEquals('https://github.com/cloudevents/spec/pull', $event->getSource());
$event = $event->withSource('new-source');
self::assertEquals('new-source', $event->getSource());
}
public function testGetSetType(): void
{
$event = $this->getEvent();
self::assertEquals('com.github.pull_request.opened', $event->getType());
$event = $event->withType('new-type');
self::assertEquals('new-type', $event->getType());
}
public function testGetSetDataContentType(): void
{
$event = $this->getEvent();
self::assertEquals('text/xml', $event->getDataContentType());
$event = $event->withDataContentType('application/json');
self::assertEquals('application/json', $event->getDataContentType());
}
public function testGetSetDataSchema(): void
{
$event = $this->getEvent();
self::assertEquals(null, $event->getDataSchema());
$event = $event->withDataSchema('new-schema');
self::assertEquals('new-schema', $event->getDataSchema());
}
public function testGetSetSubject(): void
{
$event = $this->getEvent();
self::assertEquals('123', $event->getSubject());
$event = $event->withSubject('new-subject');
self::assertEquals('new-subject', $event->getSubject());
}
public function testGetSetTime(): void
{
$event = $this->getEvent();
self::assertEquals(new \DateTimeImmutable('2018-04-05T17:31:00Z'), $event->getTime());
$event = $event->withTime(new \DateTimeImmutable('2021-01-19T17:31:00Z'));
self::assertEquals(new \DateTimeImmutable('2021-01-19T17:31:00Z'), $event->getTime());
}
public function testGetSetData(): void
{
$event = $this->getEvent();
self::assertEquals('', $event->getData());
$event = $event->withData('{"key": "value"}');
self::assertEquals('{"key": "value"}', $event->getData());
}
public function testCannotSetEmptyExtensionValueType(): void
{
$event = $this->getEvent();
$this->expectException(ValueError::class);
$event->withExtension('', '1.1');
}
public function testCannotSetInvalidExtensionAttribute(): void
{
$event = $this->getEvent();
$this->expectException(ValueError::class);
$event->withExtension('comBAD', '1.1');
}
public function testCannotSetReservedExtensionAttribute(): void
{
$event = $this->getEvent();
$this->expectException(ValueError::class);
$event->withExtension('specversion', '1.1');
}
public function testCannotSetInvalidExtensionValueType(): void
{
$event = $this->getEvent();
$this->expectException(TypeError::class);
$event->withExtension('comacme', 1.1);
}
public function testCanSetAndUnsetExtensions(): void
{
$event = $this->getEvent();
self::assertEquals([], $event->getExtensions());
self::assertNull($event->getExtension('comacme'));
self::assertNull($event->getExtension('comacme2'));
$event = $event->withExtension('comacme', 'foo');
self::assertEquals('foo', $event->getExtension('comacme'));
self::assertEquals(['comacme' => 'foo'], $event->getExtensions());
$event = $event->withExtension('comacme2', 123);
self::assertEquals(123, $event->getExtension('comacme2'));
self::assertEquals(['comacme' => 'foo', 'comacme2' => 123], $event->getExtensions());
$event = $event->withExtension('comacme', null);
self::assertNull($event->getExtension('comacme'));
self::assertEquals(['comacme2' => 123], $event->getExtensions());
$event = $event->withExtensions(['comacme' => 12345, 'comacme2' => null]);
self::assertEquals(12345, $event->getExtension('comacme'));
self::assertNull($event->getExtension('comacme2'));
self::assertEquals(['comacme' => 12345], $event->getExtensions());
}
public function testCanCreateFromInterface(): void
{
$original = $this->getEvent();
$event = CloudEventImmutable::createFromInterface($original);
self::assertInstanceOf(CloudEventImmutable::class, $original);
self::assertInstanceOf(CloudEventInterface::class, $original);
self::assertInstanceOf(CloudEventInterfaceV1::class, $original);
self::assertSame($original->getId(), $event->getId());
self::assertSame($original->getSource(), $event->getSource());
self::assertSame($original->getType(), $event->getType());
self::assertSame($original->getData(), $event->getData());
self::assertSame($original->getDataContentType(), $event->getDataContentType());
self::assertSame($original->getDataSchema(), $event->getDataSchema());
self::assertSame($original->getSubject(), $event->getSubject());
self::assertSame($original->getTime(), $event->getTime());
self::assertSame($original->getExtensions(), $event->getExtensions());
}
private function getEvent(): CloudEventImmutable
{
return new CloudEventImmutable(
'A234-1234-1234',
'https://github.com/cloudevents/spec/pull',
'com.github.pull_request.opened',
'',
'text/xml',
null,
'123',
new \DateTimeImmutable('2018-04-05T17:31:00Z')
);
}
}
tests/Unit/V1/CloudEventTest.php 0000644 00000014573 14641217650 0012554 0 ustar 00 getEvent()->getSpecVersion());
}
public function testGetSetId(): void
{
$event = $this->getEvent();
self::assertEquals('A234-1234-1234', $event->getId());
$event = $event->setId('new-id');
self::assertEquals('new-id', $event->getId());
}
public function testGetSetSource(): void
{
$event = $this->getEvent();
self::assertEquals('https://github.com/cloudevents/spec/pull', $event->getSource());
$event = $event->setSource('new-source');
self::assertEquals('new-source', $event->getSource());
}
public function testGetSetType(): void
{
$event = $this->getEvent();
self::assertEquals('com.github.pull_request.opened', $event->getType());
$event = $event->setType('new-type');
self::assertEquals('new-type', $event->getType());
}
public function testGetSetDataContentType(): void
{
$event = $this->getEvent();
self::assertEquals('text/xml', $event->getDataContentType());
$event = $event->setDataContentType('application/json');
self::assertEquals('application/json', $event->getDataContentType());
}
public function testGetSetDataSchema(): void
{
$event = $this->getEvent();
self::assertEquals(null, $event->getDataSchema());
$event = $event->setDataSchema('new-schema');
self::assertEquals('new-schema', $event->getDataSchema());
}
public function testGetSetSubject(): void
{
$event = $this->getEvent();
self::assertEquals('123', $event->getSubject());
$event = $event->setSubject('new-subject');
self::assertEquals('new-subject', $event->getSubject());
}
public function testGetSetTime(): void
{
$event = $this->getEvent();
self::assertEquals(new \DateTimeImmutable('2018-04-05T17:31:00Z'), $event->getTime());
$event = $event->setTime(new \DateTimeImmutable('2021-01-19T17:31:00Z'));
self::assertEquals(new \DateTimeImmutable('2021-01-19T17:31:00Z'), $event->getTime());
}
public function testGetSetData(): void
{
$event = $this->getEvent();
self::assertEquals('', $event->getData());
$event = $event->setData('{"key": "value"}');
self::assertEquals('{"key": "value"}', $event->getData());
}
public function testCannotSetEmptyExtensionValueType(): void
{
$event = $this->getEvent();
$this->expectException(ValueError::class);
$event->setExtension('', '1.1');
}
public function testCannotSetInvalidExtensionAttribute(): void
{
$event = $this->getEvent();
$this->expectException(ValueError::class);
$event->setExtension('comBAD', '1.1');
}
public function testCannotSetReservedExtensionAttribute(): void
{
$event = $this->getEvent();
$this->expectException(ValueError::class);
$event->setExtension('specversion', '1.1');
}
public function testCannotSetInvalidExtensionValueType(): void
{
$event = $this->getEvent();
$this->expectException(TypeError::class);
$event->setExtension('comacme', 1.1);
}
public function testCanSetAndUnsetExtensions(): void
{
$event = $this->getEvent();
self::assertEquals([], $event->getExtensions());
self::assertNull($event->getExtension('comacme'));
self::assertNull($event->getExtension('comacme2'));
$event = $event->setExtension('comacme', 'foo');
self::assertEquals('foo', $event->getExtension('comacme'));
self::assertEquals(['comacme' => 'foo'], $event->getExtensions());
$event = $event->setExtension('comacme2', 123);
self::assertEquals(123, $event->getExtension('comacme2'));
self::assertEquals(['comacme' => 'foo', 'comacme2' => 123], $event->getExtensions());
$event = $event->setExtension('comacme', null);
self::assertNull($event->getExtension('comacme'));
self::assertEquals(['comacme2' => 123], $event->getExtensions());
$event = $event->setExtensions(['comacme' => 12345, 'comacme2' => null]);
self::assertEquals(12345, $event->getExtension('comacme'));
self::assertNull($event->getExtension('comacme2'));
self::assertEquals(['comacme' => 12345], $event->getExtensions());
}
public function testCanCreateFromInterface(): void
{
$original = $this->getEvent();
$event = CloudEvent::createFromInterface($original);
self::assertInstanceOf(CloudEvent::class, $original);
self::assertInstanceOf(CloudEventInterface::class, $original);
self::assertInstanceOf(CloudEventInterfaceV1::class, $original);
self::assertSame($original->getId(), $event->getId());
self::assertSame($original->getSource(), $event->getSource());
self::assertSame($original->getType(), $event->getType());
self::assertSame($original->getData(), $event->getData());
self::assertSame($original->getDataContentType(), $event->getDataContentType());
self::assertSame($original->getDataSchema(), $event->getDataSchema());
self::assertSame($original->getSubject(), $event->getSubject());
self::assertSame($original->getTime(), $event->getTime());
self::assertSame($original->getExtensions(), $event->getExtensions());
}
private function getEvent(): CloudEvent
{
return new CloudEvent(
'A234-1234-1234',
'https://github.com/cloudevents/spec/pull',
'com.github.pull_request.opened',
'',
'text/xml',
null,
'123',
new \DateTimeImmutable('2018-04-05T17:31:00Z')
);
}
}