Removed a handful of samples

This commit is contained in:
Marcin Grzejszczak
2019-08-28 15:05:47 +02:00
parent d4740706f0
commit 2098e81ece
257 changed files with 163 additions and 13276 deletions

View File

@@ -17,13 +17,14 @@
package com.example.fraud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableAutoConfiguration
@ComponentScan
@SpringBootApplication
@EnableBinding({ Source.class, MyProcessor.class })
public class Application {
public static void main(String[] args) {

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* 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
*
* https://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.
*/
package com.example.fraud;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author Marcin Grzejszczak
*/
@RestController
class FooController {
@GetMapping("/foo")
void foo() {
}
}

View File

@@ -51,6 +51,16 @@ public class FraudDetectionController {
// end::initial_impl[]
}
@RequestMapping(value = "/pactfraudcheck", method = PUT)
public FraudCheckResult pactFraudCheck(@RequestBody FraudCheck fraudCheck) {
return fraudCheck(fraudCheck);
}
@RequestMapping(value = "/yamlfraudcheck", method = PUT)
public FraudCheckResult yamlFraudCheck(@RequestBody FraudCheck fraudCheck) {
return fraudCheck(fraudCheck);
}
private boolean amountGreaterThanThreshold(FraudCheck fraudCheck) {
return MAX_AMOUNT.compareTo(fraudCheck.getLoanAmount()) < 0;
}

View File

@@ -16,6 +16,7 @@
package com.example.fraud;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
@@ -56,6 +57,17 @@ class FraudNameController {
return value + " " + value2;
}
@PutMapping(value = "/yamlfrauds/name")
public NameResponse yamlCheckByName(@RequestBody NameRequest request) {
return checkByName(request);
}
@GetMapping(value = "/yamlfrauds/name")
public String yamlCheckByName(@CookieValue("name") String value,
@CookieValue("name2") String value2) {
return checkByName(value, value2);
}
}
class NameRequest {
@@ -99,3 +111,12 @@ class NameResponse {
}
}
@Component
class DefaultFraudVerifier implements FraudVerifier {
@Override
public boolean isFraudByName(String name) {
return true;
}
}

View File

@@ -16,6 +16,7 @@
package com.example.fraud;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -45,11 +46,31 @@ public class FraudStatsController {
return new Response(this.statsProvider.count(FraudType.ALL));
}
@GetMapping(value = "/pactfrauds")
public Response countAllPactFrauds() {
return countAllFrauds();
}
@GetMapping(value = "/yamlfrauds")
public Response countAllYamlFrauds() {
return countAllFrauds();
}
@GetMapping(value = "/drunks")
public Response countAllDrunks() {
return new Response(this.statsProvider.count(FraudType.DRUNKS));
}
@GetMapping(value = "/pactdrunks")
public Response countAllPactDrunks() {
return countAllDrunks();
}
@GetMapping(value = "/yamldrunks")
public Response countAllYamlDrunks() {
return countAllDrunks();
}
}
class Response {
@@ -72,3 +93,12 @@ class Response {
}
}
@Component
class DefaultStatsProvider implements StatsProvider {
@Override
public int count(FraudType fraudType) {
return 0;
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* 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
*
* https://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.
*/
package com.example.fraud;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.stereotype.Component;
@Component
class MessagePoller {
private final Source source;
MessagePoller(Source source) {
this.source = source;
}
public void poll() {
this.source.output().send(MessageBuilder
.withPayload("{\"id\":\"99\",\"temperature\":\"123.45\"}").build());
}
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* 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
*
* https://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.
*/
package com.example.fraud;
import org.springframework.cloud.stream.annotation.Output;
import org.springframework.cloud.stream.messaging.Sink;
import org.springframework.messaging.MessageChannel;
interface MyProcessor extends Sink {
String MY_OUTPUT = "my_output";
@Output("my_output")
MessageChannel output();
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* 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
*
* https://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.
*/
package com.example.fraud;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.cloud.stream.messaging.Sink;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.stereotype.Component;
@Component
class MyProcessorListener {
private static final Logger log = LoggerFactory.getLogger(MyProcessorListener.class);
private final MyProcessor processor;
private final byte[] expectedInput;
private final byte[] expectedOutput;
MyProcessorListener(MyProcessor processor) {
this.processor = processor;
this.expectedInput = forFile("/contracts/messaging/input.pdf");
this.expectedOutput = forFile("/contracts/messaging/output.pdf");
}
private byte[] forFile(String relative) {
URL resource = MyProcessorListener.class.getResource(relative);
try {
return Files.readAllBytes(new File(resource.toURI()).toPath());
}
catch (IOException | URISyntaxException ex) {
throw new IllegalStateException(ex);
}
}
@StreamListener(Sink.INPUT)
void listen(byte[] payload) {
log.info("Got the message!");
if (!Arrays.equals(payload, this.expectedInput)) {
throw new IllegalStateException("Wrong input");
}
this.processor.output()
.send(MessageBuilder.withPayload(this.expectedOutput).build());
}
}

View File

@@ -0,0 +1,6 @@
spring.cloud.stream.bindings.output.contentType=application/json
spring.cloud.stream.bindings.input.contentType=application/octet-stream
spring.cloud.stream.bindings.input.destination=bytes_input
spring.cloud.stream.bindings.my_output.contentType=application/octet-stream
spring.cloud.stream.bindings.my_output.destination=bytes_output
server.port=0

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2016-2019 the original author or authors.
*
* 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
*
* https://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.
*/
package com.example.fraud;
import io.restassured.module.mockmvc.RestAssuredMockMvc;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.contract.verifier.messaging.boot.AutoConfigureMessageVerifier;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.context.WebApplicationContext;
/**
* Base class for sensor autogenerated tests (used by Spring Cloud Contract).
*
* This bootstraps the Spring Boot application code.
*
* @author Marius Bogoevici
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class, properties = "spring.cloud.stream.bindings.output.destination=sensor-data")
@AutoConfigureMessageVerifier
public abstract class MessagingBase {
@Autowired
MessagePoller poller;
@Autowired
WebApplicationContext context;
@Before
public void setup() {
RestAssuredMockMvc.webAppContextSetup(this.context);
}
public void createSensorData() {
poller.poll();
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* 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
*
* https://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.
*/
package com.example.fraud;
import io.restassured.module.mockmvc.RestAssuredMockMvc;
import org.junit.Before;
public class PactBase {
@Before
public void setup() {
RestAssuredMockMvc.standaloneSetup(new FraudDetectionController(),
new FraudStatsController(stubbedStatsProvider()));
}
private StatsProvider stubbedStatsProvider() {
return fraudType -> {
switch (fraudType) {
case DRUNKS:
return 100;
case ALL:
return 200;
}
return 0;
};
}
public void assertThatRejectionReasonIsNull(Object rejectionReason) {
assert rejectionReason == null;
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* 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
*
* https://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.
*/
package com.example.fraud;
import io.restassured.module.mockmvc.RestAssuredMockMvc;
import org.junit.Before;
public class YmlFraudBase {
@Before
public void setup() {
RestAssuredMockMvc.standaloneSetup(new FraudDetectionController(),
new FraudStatsController(stubbedStatsProvider()));
}
private StatsProvider stubbedStatsProvider() {
return fraudType -> {
switch (fraudType) {
case DRUNKS:
return 100;
case ALL:
return 200;
}
return 0;
};
}
public void assertThatRejectionReasonIsNull(Object rejectionReason) {
assert rejectionReason == null;
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* 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
*
* https://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.
*/
package com.example.fraud;
import io.restassured.module.mockmvc.RestAssuredMockMvc;
import org.junit.Before;
public class YmlFraudnameBase {
private static final String FRAUD_NAME = "fraud";
FraudVerifier fraudVerifier = FRAUD_NAME::equals;
@Before
public void setup() {
RestAssuredMockMvc.standaloneSetup(new FraudNameController(this.fraudVerifier));
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* 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
*
* https://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.
*/
package contracts
org.springframework.cloud.contract.spec.Contract.make {
// Human readable description
description 'Should produce valid sensor data'
// Label by means of which the output message can be triggered
label 'sensor1'
// input to the contract
input {
// the contract will be triggered by a method
triggeredBy('createSensorData()')
}
// output message of the contract
outputMessage {
// destination to which the output message will be sent
sentTo 'sensor-data'
headers {
header('contentType': 'application/json')
}
// the body of the output message
body([
id : $(consumer(9), producer(regex("[0-9]+"))),
temperature: "123.45"
])
}
}

View File

@@ -0,0 +1,6 @@
description: Should return 200 for /foo
request:
url: /foo
method: GET
response:
status: 200

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* 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
*
* https://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.
*/
package contracts
import org.springframework.cloud.contract.spec.Contract
Contract.make {
label("positive")
input {
messageFrom("bytes_input")
messageBody(fileAsBytes("input.pdf"))
messageHeaders {
messagingContentType(applicationOctetStream())
}
}
outputMessage {
sentTo("bytes_output")
body(fileAsBytes("output.pdf"))
headers {
messagingContentType(applicationOctetStream())
}
}
}

View File

@@ -0,0 +1,98 @@
{
"provider": {
"name": "Provider"
},
"consumer": {
"name": "Consumer"
},
"interactions": [
{
"description": "",
"request": {
"method": "PUT",
"path": "/pactfraudcheck",
"headers": {
"Content-Type": "application/json"
},
"body": {
"clientId": "1234567890",
"loanAmount": 99999
},
"generators": {
"body": {
"$.clientId": {
"type": "Regex",
"regex": "[0-9]{10}"
}
}
},
"matchingRules": {
"header": {
"Content-Type": {
"matchers": [
{
"match": "regex",
"regex": "application/json.*"
}
],
"combine": "AND"
}
},
"body": {
"$.clientId": {
"matchers": [
{
"match": "regex",
"regex": "[0-9]{10}"
}
],
"combine": "AND"
}
}
}
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": {
"fraudCheckStatus": "FRAUD",
"rejection.reason": "Amount too high"
},
"matchingRules": {
"header": {
"Content-Type": {
"matchers": [
{
"match": "regex",
"regex": "application/json.*"
}
],
"combine": "AND"
}
},
"body": {
"$.fraudCheckStatus": {
"matchers": [
{
"match": "regex",
"regex": "FRAUD"
}
],
"combine": "AND"
}
}
}
}
}
],
"metadata": {
"pact-specification": {
"version": "3.0.0"
},
"pact-jvm": {
"version": "3.5.13"
}
}
}

View File

@@ -0,0 +1,42 @@
{
"provider": {
"name": "Provider"
},
"consumer": {
"name": "Consumer"
},
"interactions": [
{
"description": "",
"request": {
"method": "PUT",
"path": "/pactfraudcheck",
"headers": {
"Content-Type": "application/json"
},
"body": {
"clientId": "1234567890",
"loanAmount": 123.123
}
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": {
"fraudCheckStatus": "OK",
"rejection.reason": null
}
}
}
],
"metadata": {
"pact-specification": {
"version": "2.0.0"
},
"pact-jvm": {
"version": "2.4.18"
}
}
}

View File

@@ -0,0 +1,34 @@
{
"provider": {
"name": "Provider"
},
"consumer": {
"name": "Consumer"
},
"interactions": [
{
"description": "",
"request": {
"method": "GET",
"path": "/drunks"
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": {
"count": 100
}
}
}
],
"metadata": {
"pact-specification": {
"version": "2.0.0"
},
"pact-jvm": {
"version": "2.4.18"
}
}
}

View File

@@ -0,0 +1,34 @@
{
"provider": {
"name": "Provider"
},
"consumer": {
"name": "Consumer"
},
"interactions": [
{
"description": "",
"request": {
"method": "GET",
"path": "/pactfrauds"
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": {
"count": 200
}
}
}
],
"metadata": {
"pact-specification": {
"version": "2.0.0"
},
"pact-jvm": {
"version": "2.4.18"
}
}
}

View File

@@ -0,0 +1,52 @@
request: # (1)
method: PUT # (2)
url: /yamlfraudcheck # (3)
body: # (4)
"client.id": 1234567890
loanAmount: 99999
headers: # (5)
Content-Type: application/json
matchers:
body:
- path: $.['client.id'] # (6)
type: by_regex
value: "[0-9]{10}"
response: # (7)
status: 200 # (8)
body: # (9)
fraudCheckStatus: "FRAUD"
"rejection.reason": "Amount too high"
headers: # (10)
Content-Type: application/json
#From the Consumer perspective, when shooting a request in the integration test:
#
#(1) - If the consumer sends a request
#(2) - With the "PUT" method
#(3) - to the URL "/yamlfraudcheck"
#(4) - with the JSON body that
# * has a field `client.id`
# * has a field `loanAmount` that is equal to `99999`
#(5) - with header `Content-Type` equal to `application/json`
#(6) - and a `client.id` json entry matches the regular expression `[0-9]{10}`
#(7) - then the response will be sent with
#(8) - status equal `200`
#(9) - and JSON body equal to
# { "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
#(10) - with header `Content-Type` equal to `application/json`
#
#From the Producer perspective, in the autogenerated producer-side test:
#
#(1) - A request will be sent to the producer
#(2) - With the "PUT" method
#(3) - to the URL "/yamlfraudcheck"
#(4) - with the JSON body that
# * has a field `client.id` `1234567890`
# * has a field `loanAmount` that is equal to `99999`
#(5) - with header `Content-Type` equal to `application/json`
#(7) - then the test will assert if the response has been sent with
#(8) - status equal `200`
#(9) - and JSON body equal to
# { "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
#(10) - with header `Content-Type` equal to `application/json`

View File

@@ -0,0 +1,25 @@
request:
method: PUT
url: /yamlfraudcheck
body:
"client.id": 1234567890
loanAmount: 123.123
headers:
Content-Type: application/json
matchers:
body:
- path: $.['client.id']
type: by_regex
value: "[0-9]{10}"
response:
status: 200
body:
fraudCheckStatus: "OK"
"rejection.reason": null
headers:
Content-Type: application/json
matchers:
body:
- path: $.['rejection.reason']
type: by_command
value: assertThatRejectionReasonIsNull($it)

View File

@@ -0,0 +1,21 @@
---
name: "should count all frauds"
request:
method: GET
url: /yamlfrauds
response:
status: 200
body:
count: 200
headers:
Content-Type: application/json
---
request:
method: GET
url: /drunks
response:
status: 200
body:
count: 100
headers:
Content-Type: application/json

View File

@@ -0,0 +1,15 @@
# highest priority
priority: 1
request:
method: PUT
url: /yamlfrauds/name
body:
name: "fraud"
headers:
Content-Type: application/json
response:
status: 200
body:
result: "Sorry {{{ jsonpath this '$.name' }}} but you're a fraud"
headers:
Content-Type: "{{{ request.headers.Content-Type.0 }}}"

View File

@@ -0,0 +1,18 @@
request:
method: PUT
url: /yamlfrauds/name
body:
name: "non fraud"
headers:
Content-Type: application/json
matchers:
body:
- path: $.name
type: by_regex
predefined: only_alpha_unicode
response:
status: 200
body:
result: "Don't worry {{{ jsonpath this '$.name' }}} you're not a fraud"
headers:
Content-Type: "{{{ request.headers.Content-Type.0 }}}"