Add Smoke Tests for a client/server Function execution use case, configured with SBDG auto-configuration on the client-side and SDG Function annotation config on the server-side.
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
# This file is generated by the 'io.freefair.lombok' Gradle plugin
|
||||
config.stopBubbling = true
|
||||
@@ -0,0 +1,21 @@
|
||||
plugins {
|
||||
id "io.freefair.lombok" version "4.1.2"
|
||||
}
|
||||
|
||||
apply plugin: 'io.spring.convention.spring-test'
|
||||
|
||||
description = "Smoke Tests asserting the proper execution of an Apache Geode Function using Spring Data for Apache Geode Function annotation support in a Spring Boot context."
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation project(':spring-geode-starter')
|
||||
|
||||
implementation "org.assertj:assertj-core"
|
||||
implementation "org.projectlombok:lombok"
|
||||
|
||||
testImplementation project(':spring-geode-starter-test')
|
||||
|
||||
testImplementation('org.springframework.boot:spring-boot-starter-test') {
|
||||
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 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 example.app.petclinic.function;
|
||||
|
||||
import org.springframework.data.gemfire.function.annotation.FunctionId;
|
||||
import org.springframework.data.gemfire.function.annotation.OnRegion;
|
||||
|
||||
import example.app.petclinic.model.Pet;
|
||||
|
||||
/**
|
||||
* Function interface declaring all {@link Pet} services administered by the Pet Clinic.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see example.app.petclinic.model.Pet
|
||||
* @since 1.2.1
|
||||
*/
|
||||
@OnRegion(region = "Pets")
|
||||
public interface PetServiceFunctionExecutions {
|
||||
|
||||
@FunctionId(("AdministerPetVaccinations"))
|
||||
void administerPetVaccinations();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 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 example.app.petclinic.model;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.gemfire.mapping.annotation.Region;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* Abstract Data Type (ADT) modeling a pet.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.annotation.Id
|
||||
* @see org.springframework.data.gemfire.mapping.annotation.Region
|
||||
* @since 1.2.1
|
||||
*/
|
||||
@Region("Pets")
|
||||
@ToString(of = "name")
|
||||
@EqualsAndHashCode(of = "name")
|
||||
@RequiredArgsConstructor(staticName = "newPet")
|
||||
@SuppressWarnings("unused")
|
||||
public class Pet {
|
||||
|
||||
@Getter
|
||||
private LocalDateTime vaccinationDateTime;
|
||||
|
||||
@Id @NonNull @Getter
|
||||
private String name;
|
||||
|
||||
@Getter
|
||||
private Type petType;
|
||||
|
||||
public Pet as(Type petType) {
|
||||
this.petType = petType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void vaccinate() {
|
||||
this.vaccinationDateTime = LocalDateTime.now();
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
CAT,
|
||||
DOG,
|
||||
RABBIT,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 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 example.app.petclinic.repo;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
import example.app.petclinic.model.Pet;
|
||||
|
||||
/**
|
||||
* Data Access Object (DAO) containing basic CRUD and simple Query data access operations on {@link Pet} objects.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.repository.CrudRepository
|
||||
* @see example.app.petclinic.model.Pet
|
||||
* @since 1.2.1
|
||||
*/
|
||||
public interface PetRepository extends CrudRepository<Pet, String> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright 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 example.app.petclinic;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.execute.Function;
|
||||
import org.apache.geode.cache.execute.FunctionContext;
|
||||
import org.apache.geode.cache.execute.RegionFunctionContext;
|
||||
|
||||
import org.apache.shiro.util.CollectionUtils;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.data.gemfire.config.annotation.CacheServerApplication;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableEntityDefinedRegions;
|
||||
import org.springframework.data.gemfire.config.annotation.EnablePdx;
|
||||
import org.springframework.data.gemfire.config.annotation.PeerCacheApplication;
|
||||
import org.springframework.data.gemfire.function.annotation.GemfireFunction;
|
||||
import org.springframework.data.gemfire.function.config.EnableGemfireFunctions;
|
||||
import org.springframework.data.gemfire.tests.integration.ForkingClientServerIntegrationTestsSupport;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import example.app.petclinic.function.PetServiceFunctionExecutions;
|
||||
import example.app.petclinic.model.Pet;
|
||||
import example.app.petclinic.repo.PetRepository;
|
||||
|
||||
/**
|
||||
* Smoke Tests asserting the proper injection and execution of an Apache Geode {@link Function} using Spring Data
|
||||
* for Apache Geode {@link Function} annotation support in a Spring (Boot) context.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.apache.geode.cache.execute.Function
|
||||
* @see org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
* @see org.springframework.boot.test.context.SpringBootTest
|
||||
* @see org.springframework.context.annotation.AnnotationConfigApplicationContext
|
||||
* @see org.springframework.context.annotation.Bean
|
||||
* @see org.springframework.context.annotation.Profile
|
||||
* @see org.springframework.data.gemfire.config.annotation.CacheServerApplication
|
||||
* @see org.springframework.data.gemfire.config.annotation.PeerCacheApplication
|
||||
* @see org.springframework.data.gemfire.tests.integration.ForkingClientServerIntegrationTestsSupport
|
||||
* @see org.springframework.test.context.ActiveProfiles
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @see PetServiceFunctionExecutions
|
||||
* @see example.app.petclinic.model.Pet
|
||||
* @see example.app.petclinic.repo.PetRepository
|
||||
* @since 1.2.1
|
||||
*/
|
||||
@ActiveProfiles("petclinic-client-function-execution")
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
|
||||
@SuppressWarnings("unused")
|
||||
public class PetClinicApplicationSmokeTests extends ForkingClientServerIntegrationTestsSupport {
|
||||
|
||||
@BeforeClass
|
||||
public static void startGeodeServer() throws Exception {
|
||||
startGemFireServer(GeodeServerTestConfiguration.class,
|
||||
"-Dspring.profiles.active=petclinic-server-function-execution");
|
||||
}
|
||||
|
||||
private Pet castle = Pet.newPet("Castle").as(Pet.Type.CAT);
|
||||
private Pet cocoa = Pet.newPet("Cocoa").as(Pet.Type.CAT);
|
||||
private Pet maha = Pet.newPet("Maha").as(Pet.Type.DOG);
|
||||
private Pet mittens = Pet.newPet("Mittens").as(Pet.Type.CAT);
|
||||
|
||||
private Set<Pet> pets = CollectionUtils.asSet(castle, cocoa, maha, mittens);
|
||||
|
||||
@Autowired
|
||||
private PetRepository petRepository;
|
||||
|
||||
@Autowired
|
||||
private PetServiceFunctionExecutions petServiceFunctions;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
|
||||
assertThat(this.petRepository.count()).isEqualTo(0);
|
||||
|
||||
this.pets.forEach(pet -> assertThat(pet.getVaccinationDateTime()).isNull());
|
||||
this.petRepository.saveAll(this.pets);
|
||||
|
||||
assertThat(this.petRepository.count()).isEqualTo(this.pets.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void administerPetVaccinationsIsSuccessful() {
|
||||
|
||||
LocalDateTime beforeVaccinations = LocalDateTime.now();
|
||||
|
||||
this.petServiceFunctions.administerPetVaccinations();
|
||||
|
||||
LocalDateTime afterVaccinations = LocalDateTime.now();
|
||||
|
||||
this.petRepository.findAll().forEach(pet -> {
|
||||
|
||||
assertThat(pet.getVaccinationDateTime())
|
||||
.describedAs("Vaccinations [%s] for [%s] was not correct", pet.getVaccinationDateTime(), pet)
|
||||
.isAfterOrEqualTo(beforeVaccinations);
|
||||
|
||||
assertThat(pet.getVaccinationDateTime()).isBeforeOrEqualTo(afterVaccinations);
|
||||
});
|
||||
}
|
||||
|
||||
@Profile("petclinic-client-function-execution")
|
||||
@EnableEntityDefinedRegions(basePackageClasses = Pet.class)
|
||||
@SpringBootApplication(scanBasePackageClasses = PetClinicApplicationSmokeTests.class)
|
||||
static class GeodeClientTestConfiguration { }
|
||||
|
||||
@Profile("petclinic-peer-function-execution")
|
||||
@PeerCacheApplication(name = "PetClinicApplicationSmokeTests")
|
||||
@EnableEntityDefinedRegions(basePackageClasses = Pet.class)
|
||||
@SpringBootApplication(scanBasePackageClasses = PetClinicApplicationSmokeTests.class)
|
||||
static class GeodePeerTestConfiguration { }
|
||||
|
||||
@Profile("petclinic-server-function-execution")
|
||||
@CacheServerApplication(name = "PetClinicApplicationSmokeTestsServer")
|
||||
@EnableEntityDefinedRegions(basePackageClasses = Pet.class)
|
||||
@EnableGemfireFunctions
|
||||
@EnablePdx
|
||||
static class GeodeServerTestConfiguration {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
AnnotationConfigApplicationContext applicationContext =
|
||||
new AnnotationConfigApplicationContext(GeodeServerTestConfiguration.class);
|
||||
|
||||
applicationContext.registerShutdownHook();
|
||||
}
|
||||
|
||||
@Bean
|
||||
PetServiceFunctions petServiceFunctions() {
|
||||
return new PetServiceFunctions();
|
||||
}
|
||||
}
|
||||
|
||||
public static class PetServiceFunctions {
|
||||
|
||||
@GemfireFunction(id = "AdministerPetVaccinations", optimizeForWrite = true)
|
||||
public void administerPetVaccinations(FunctionContext functionContext) {
|
||||
|
||||
Optional.ofNullable(functionContext)
|
||||
.filter(RegionFunctionContext.class::isInstance)
|
||||
.map(RegionFunctionContext.class::cast)
|
||||
.map(RegionFunctionContext::getDataSet)
|
||||
.map(Region::values)
|
||||
.ifPresent(pets -> pets.forEach(pet -> {
|
||||
|
||||
Pet resolvePet = (Pet) pet;
|
||||
|
||||
resolvePet.vaccinate();
|
||||
|
||||
((RegionFunctionContext) functionContext).getDataSet().put(resolvePet.getName(), resolvePet);
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration debug="false">
|
||||
|
||||
<statusListener class="ch.qos.logback.core.status.NopStatusListener"/>
|
||||
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d %5p %40.40c:%4L - %m%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="ch.qos.logback" level="${logback.log.level:-ERROR}"/>
|
||||
|
||||
<logger name="org.apache" level="${logback.log.level:-ERROR}"/>
|
||||
|
||||
<logger name="org.springframework" level="${logback.log.level:-ERROR}"/>
|
||||
|
||||
<root level="${logback.log.level:-ERROR}">
|
||||
<appender-ref ref="console"/>
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
Reference in New Issue
Block a user