@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 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.
|
||||
@@ -190,78 +190,78 @@ public class BasicCouchbasePersistentEntityTests {
|
||||
@Configuration
|
||||
static class Config {}
|
||||
|
||||
public static class SimpleDocument {}
|
||||
class SimpleDocument {}
|
||||
|
||||
@Document(expiry = 10)
|
||||
public static class SimpleDocumentWithExpiry {}
|
||||
class SimpleDocumentWithExpiry {}
|
||||
|
||||
@Document(expiry = 10, touchOnRead = true)
|
||||
public static class SimpleDocumentWithTouchOnRead {}
|
||||
class SimpleDocumentWithTouchOnRead {}
|
||||
|
||||
/**
|
||||
* Simple POJO to test default expiry.
|
||||
*/
|
||||
@Document
|
||||
private class DefaultExpiry {}
|
||||
class DefaultExpiry {}
|
||||
|
||||
/**
|
||||
* Simple POJO to test default expiry unit.
|
||||
*/
|
||||
@Document(expiry = 78)
|
||||
private class DefaultExpiryUnit {}
|
||||
class DefaultExpiryUnit {}
|
||||
|
||||
/**
|
||||
* Simple POJO to test limit expiry.
|
||||
*/
|
||||
@Document(expiry = 30, expiryUnit = TimeUnit.DAYS)
|
||||
private class LimitDaysExpiry {}
|
||||
class LimitDaysExpiry {}
|
||||
|
||||
/**
|
||||
* Simple POJO to test larger than 30 days expiry.
|
||||
*/
|
||||
@Document(expiry = 31, expiryUnit = TimeUnit.DAYS)
|
||||
public class OverLimitDaysExpiry {}
|
||||
class OverLimitDaysExpiry {}
|
||||
|
||||
/**
|
||||
* Simple POJO to test larger than 30 days expiry defined as an expression
|
||||
*/
|
||||
@Document(expiryExpression = "${document.expiry.larger.than.30days:31}", expiryUnit = TimeUnit.DAYS)
|
||||
public class OverLimitDaysExpiryExpression {}
|
||||
class OverLimitDaysExpiryExpression {}
|
||||
|
||||
/**
|
||||
* Simple POJO to test larger than 30 days expiry, when expressed in default time unit (SECONDS).
|
||||
*/
|
||||
@Document(expiry = 31 * 24 * 60 * 60)
|
||||
public class OverLimitSecondsExpiry {}
|
||||
class OverLimitSecondsExpiry {}
|
||||
|
||||
/**
|
||||
* Simple POJO to test constant expiry expression
|
||||
*/
|
||||
@Document(expiryExpression = "10")
|
||||
private class ConstantExpiryExpression {}
|
||||
class ConstantExpiryExpression {}
|
||||
|
||||
/**
|
||||
* Simple POJO to test valid expiry expression by resolving simple property from environment
|
||||
*/
|
||||
@Document(expiryExpression = "${valid.document.expiry}")
|
||||
private class ExpiryWithValidExpression {}
|
||||
class ExpiryWithValidExpression {}
|
||||
|
||||
/**
|
||||
* Simple POJO to test invalid expiry expression
|
||||
*/
|
||||
@Document(expiryExpression = "${invalid.document.expiry}")
|
||||
private class ExpiryWithInvalidExpression {}
|
||||
class ExpiryWithInvalidExpression {}
|
||||
|
||||
/**
|
||||
* Simple POJO to test expiry expression logic failure to resolve property placeholder
|
||||
*/
|
||||
@Document(expiryExpression = "${missing.expiry}")
|
||||
private class ExpiryWithMissingProperty {}
|
||||
class ExpiryWithMissingProperty {}
|
||||
|
||||
/**
|
||||
* Simple POJO to test that expiry and expiry expression cannot be used simultaneously
|
||||
*/
|
||||
@Document(expiry = 10, expiryExpression = "10")
|
||||
private class ExpiryAndExpression {}
|
||||
class ExpiryAndExpression {}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import com.couchbase.client.java.json.JsonArray;
|
||||
|
||||
/**
|
||||
* @author Mauro Monti
|
||||
* @author Michael Reiche
|
||||
*/
|
||||
class QueryCriteriaTests {
|
||||
|
||||
@@ -69,7 +70,7 @@ class QueryCriteriaTests {
|
||||
void testNestedAndCriteria() {
|
||||
QueryCriteria c = where(i("name")).is("Bubba").and(where(i("age")).gt(12).or(i("country")).is("Austria"));
|
||||
JsonArray parameters = JsonArray.create();
|
||||
assertEquals("`name` = $1 and (`age` > $2 or `country` = $3)", c.export(new int[1], parameters, null));
|
||||
assertEquals(" (`name` = $1) and (`age` > $2 or `country` = $3)", c.export(new int[1], parameters, null));
|
||||
assertEquals("[\"Bubba\",12,\"Austria\"]", parameters.toString());
|
||||
}
|
||||
|
||||
@@ -77,19 +78,33 @@ class QueryCriteriaTests {
|
||||
void testNestedOrCriteria() {
|
||||
QueryCriteria c = where(i("name")).is("Bubba").or(where(i("age")).gt(12).or(i("country")).is("Austria"));
|
||||
JsonArray parameters = JsonArray.create();
|
||||
assertEquals("`name` = $1 or (`age` > $2 or `country` = $3)", c.export(new int[1], parameters, null));
|
||||
assertEquals(" (`name` = $1) or (`age` > $2 or `country` = $3)", c.export(new int[1], parameters, null));
|
||||
assertEquals("[\"Bubba\",12,\"Austria\"]", parameters.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNestedNotIn() {
|
||||
QueryCriteria c = where(i("name")).is("Bubba").or(where(i("age")).gt(12).or(i("country")).is("Austria"))
|
||||
.and(where(i("state")).notIn((Object) new String[] { "Alabama", "Florida" }));
|
||||
QueryCriteria c = where(i("name")).is("Bubba").or(where(i("age")).gt(12).and(i("country")).is("Austria"))
|
||||
.and(where(i("state")).notIn(new String[] { "Alabama", "Florida" }));
|
||||
JsonArray parameters = JsonArray.create();
|
||||
assertEquals("`name` = $1 or (`age` > $2 or `country` = $3) and (not( (`state` in $4) ))",
|
||||
assertEquals(" ( (`name` = $1) or (`age` > $2 and `country` = $3)) and (not( (`state` in $4) ))",
|
||||
c.export(new int[1], parameters, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNestedNotIn2() {
|
||||
QueryCriteria c = where(i("name")).is("Bubba").or(where(i("age")).gt(12)).and(where(i("state")).eq("1"));
|
||||
JsonArray parameters = JsonArray.create();
|
||||
assertEquals(" ( (`name` = $1) or (`age` > $2)) and (`state` = $3)", c.export(new int[1], parameters, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNestedNotIn3() {
|
||||
QueryCriteria c = where(i("name")).is("Bubba").or(where(i("age")).gt(12)).and(i("state")).eq("1");
|
||||
JsonArray parameters = JsonArray.create();
|
||||
assertEquals(" (`name` = $1) or (`age` > $2) and `state` = $3", c.export(new int[1], parameters, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLt() {
|
||||
QueryCriteria c = where(i("name")).lt("Couch");
|
||||
@@ -252,7 +267,7 @@ class QueryCriteriaTests {
|
||||
@Test
|
||||
void testFalse() {
|
||||
QueryCriteria c = where(i("name")).FALSE();
|
||||
assertEquals("not( (`name`) )", c.export());
|
||||
assertEquals("not(`name`)", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors
|
||||
* Copyright 2012-2022 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.
|
||||
@@ -24,15 +24,21 @@ import org.springframework.data.couchbase.core.mapping.Document;
|
||||
@Document
|
||||
@CompositeQueryIndex(fields = { "id", "name desc" })
|
||||
@CompositeQueryIndex(fields = { "id.something", "name desc" })
|
||||
/**
|
||||
* @author Michael Reiche
|
||||
*/
|
||||
public class Airline extends ComparableEntity {
|
||||
@Id String id;
|
||||
|
||||
@QueryIndexed String name;
|
||||
|
||||
String hqCountry;
|
||||
|
||||
@PersistenceConstructor
|
||||
public Airline(String id, String name) {
|
||||
public Airline(String id, String name, String hqCountry) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.hqCountry = hqCountry;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
@@ -43,4 +49,8 @@ public class Airline extends ComparableEntity {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getHqCountry() {
|
||||
return hqCountry;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2019 the original author or authors.
|
||||
* Copyright 2017-2022 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.
|
||||
@@ -16,17 +16,23 @@
|
||||
|
||||
package org.springframework.data.couchbase.domain;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.couchbase.repository.DynamicProxyable;
|
||||
import org.springframework.data.couchbase.repository.Query;
|
||||
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Michael Reiche
|
||||
*/
|
||||
@Repository
|
||||
public interface AirlineRepository extends PagingAndSortingRepository<Airline, String> {
|
||||
public interface AirlineRepository extends PagingAndSortingRepository<Airline, String>,
|
||||
QuerydslPredicateExecutor<Airline>, DynamicProxyable<AirlineRepository> {
|
||||
|
||||
@Query("#{#n1ql.selectEntity} where #{#n1ql.filter} and (name = $1)")
|
||||
List<User> getByName(@Param("airline_name")String airlineName);
|
||||
List<User> getByName(@Param("airline_name") String airlineName);
|
||||
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ public class CouchbaseRepositoryKeyValueIntegrationTests extends ClusterAwareInt
|
||||
userRepository.delete(user);
|
||||
|
||||
// Airline does not have a version
|
||||
Airline airline = new Airline(UUID.randomUUID().toString(), "MyAirline");
|
||||
Airline airline = new Airline(UUID.randomUUID().toString(), "MyAirline", null);
|
||||
// save the document - we don't care how on this call
|
||||
airlineRepository.save(airline);
|
||||
airlineRepository.save(airline); // If it was an insert it would fail. Can't tell if it is an upsert or replace.
|
||||
|
||||
@@ -67,6 +67,7 @@ import org.springframework.data.couchbase.core.mapping.event.ValidatingCouchbase
|
||||
import org.springframework.data.couchbase.core.query.N1QLExpression;
|
||||
import org.springframework.data.couchbase.core.query.QueryCriteria;
|
||||
import org.springframework.data.couchbase.domain.Address;
|
||||
import org.springframework.data.couchbase.domain.AirlineRepository;
|
||||
import org.springframework.data.couchbase.domain.Airport;
|
||||
import org.springframework.data.couchbase.domain.AirportMini;
|
||||
import org.springframework.data.couchbase.domain.AirportRepository;
|
||||
@@ -124,6 +125,8 @@ public class CouchbaseRepositoryQueryIntegrationTests extends ClusterAwareIntegr
|
||||
|
||||
@Autowired AirportRepository airportRepository;
|
||||
|
||||
@Autowired AirlineRepository airlineRepository;
|
||||
|
||||
@Autowired UserRepository userRepository;
|
||||
|
||||
@Autowired UserSubmissionRepository userSubmissionRepository;
|
||||
|
||||
@@ -76,7 +76,7 @@ public class ReactiveCouchbaseRepositoryKeyValueIntegrationTests extends Cluster
|
||||
userRepository.delete(user);
|
||||
|
||||
// Airline does not have a version
|
||||
Airline airline = new Airline(UUID.randomUUID().toString(), "MyAirline");
|
||||
Airline airline = new Airline(UUID.randomUUID().toString(), "MyAirline", null);
|
||||
// save the document - we don't care how on this call
|
||||
airlineRepository.save(airline).block();
|
||||
airlineRepository.save(airline).block(); // If it was an insert it would fail. Can't tell if an upsert or replace.
|
||||
|
||||
@@ -0,0 +1,647 @@
|
||||
/*
|
||||
* Copyright 2017-2022 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 org.springframework.data.couchbase.repository.query;
|
||||
|
||||
import static com.couchbase.client.java.query.QueryScanConsistency.REQUEST_PLUS;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.springframework.data.couchbase.util.Util.comprises;
|
||||
import static org.springframework.data.couchbase.util.Util.exactly;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.auditing.DateTimeProvider;
|
||||
import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration;
|
||||
import org.springframework.data.couchbase.core.CouchbaseTemplate;
|
||||
import org.springframework.data.couchbase.core.mapping.event.ValidatingCouchbaseEventListener;
|
||||
import org.springframework.data.couchbase.core.query.QueryCriteriaDefinition;
|
||||
import org.springframework.data.couchbase.domain.Airline;
|
||||
import org.springframework.data.couchbase.domain.AirlineRepository;
|
||||
import org.springframework.data.couchbase.domain.NaiveAuditorAware;
|
||||
import org.springframework.data.couchbase.domain.QAirline;
|
||||
import org.springframework.data.couchbase.domain.time.AuditingDateTimeProvider;
|
||||
import org.springframework.data.couchbase.repository.auditing.EnableCouchbaseAuditing;
|
||||
import org.springframework.data.couchbase.repository.config.EnableCouchbaseRepositories;
|
||||
import org.springframework.data.couchbase.repository.support.BasicQuery;
|
||||
import org.springframework.data.couchbase.repository.support.SpringDataCouchbaseSerializer;
|
||||
import org.springframework.data.couchbase.util.Capabilities;
|
||||
import org.springframework.data.couchbase.util.ClusterType;
|
||||
import org.springframework.data.couchbase.util.IgnoreWhen;
|
||||
import org.springframework.data.couchbase.util.JavaIntegrationTests;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
||||
|
||||
import com.couchbase.client.java.env.ClusterEnvironment;
|
||||
import com.couchbase.client.java.query.QueryScanConsistency;
|
||||
import com.querydsl.core.types.Predicate;
|
||||
import com.querydsl.core.types.dsl.BooleanExpression;
|
||||
|
||||
/**
|
||||
* Repository tests
|
||||
*
|
||||
* @author Michael Reiche
|
||||
*/
|
||||
@SpringJUnitConfig(CouchbaseRepositoryQuerydslIntegrationTests.Config.class)
|
||||
@IgnoreWhen(missesCapabilities = Capabilities.QUERY, clusterTypes = ClusterType.MOCKED)
|
||||
public class CouchbaseRepositoryQuerydslIntegrationTests extends JavaIntegrationTests {
|
||||
|
||||
@Autowired AirlineRepository airlineRepository;
|
||||
|
||||
static QAirline airline = QAirline.airline;
|
||||
// saved
|
||||
static Airline united = new Airline("1", "United Airlines", "US");
|
||||
static Airline lufthansa = new Airline("2", "Lufthansa", "DE");
|
||||
static Airline emptyStringAirline = new Airline("3", "Empty String", "");
|
||||
static Airline nullStringAirline = new Airline("4", "Null String", null);
|
||||
static Airline unitedLowercase = new Airline("5", "united airlines", "US");
|
||||
static Airline[] saved = new Airline[] { united, lufthansa, emptyStringAirline, nullStringAirline, unitedLowercase };
|
||||
// not saved
|
||||
static Airline flyByNight = new Airline("1001", "Fly By Night", "UK");
|
||||
static Airline sleepByDay = new Airline("1002", "Sleep By Day", "CA");
|
||||
static Airline[] notSaved = new Airline[] { flyByNight, sleepByDay };
|
||||
|
||||
SpringDataCouchbaseSerializer serializer = new SpringDataCouchbaseSerializer(couchbaseTemplate.getConverter());
|
||||
|
||||
@BeforeAll
|
||||
static public void beforeAll() {
|
||||
callSuperBeforeAll(new Object() {});
|
||||
ApplicationContext ac = new AnnotationConfigApplicationContext(
|
||||
CouchbaseRepositoryQuerydslIntegrationTests.Config.class);
|
||||
CouchbaseTemplate template = (CouchbaseTemplate) ac.getBean("couchbaseTemplate");
|
||||
for (Airline airline : saved) {
|
||||
template.insertById(Airline.class).one(airline);
|
||||
}
|
||||
template.findByQuery(Airline.class).withConsistency(REQUEST_PLUS).all();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static public void afterAll() {
|
||||
ApplicationContext ac = new AnnotationConfigApplicationContext(
|
||||
CouchbaseRepositoryQuerydslIntegrationTests.Config.class);
|
||||
CouchbaseTemplate template = (CouchbaseTemplate) ac.getBean("couchbaseTemplate");
|
||||
for (Airline airline : saved) {
|
||||
template.removeById(Airline.class).one(airline.getId());
|
||||
}
|
||||
template.findByQuery(Airline.class).withConsistency(REQUEST_PLUS).all();
|
||||
callSuperAfterAll(new Object() {});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEq() {
|
||||
{
|
||||
BooleanExpression predicate = airline.name.eq(flyByNight.getName());
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(
|
||||
comprises(result,
|
||||
Arrays.stream(saved).filter(a -> a.getName().equals(flyByNight.getName())).toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE name = $1", bq(predicate));
|
||||
|
||||
}
|
||||
{
|
||||
BooleanExpression predicate = airline.name.eq(united.getName());
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(
|
||||
comprises(result,
|
||||
Arrays.stream(saved).filter(a -> a.getName().equals(united.getName())).toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE name = $1", bq(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
// this gives hqCountry == "" and hqCountry is missing
|
||||
// @Test
|
||||
void testStringIsEmpty() {
|
||||
{
|
||||
BooleanExpression predicate = airline.hqCountry.isEmpty();
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(comprises(result, emptyStringAirline, nullStringAirline), "[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE UPPER(name) like $1", bq(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNot() {
|
||||
{
|
||||
BooleanExpression predicate = airline.name.eq(united.getName()).and(airline.hqCountry.eq(united.getHqCountry()))
|
||||
.not();
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(comprises(result,
|
||||
Arrays.stream(saved)
|
||||
.filter(a -> !(a.getName().equals(united.getName()) && a.getHqCountry().equals(united.getHqCountry())))
|
||||
.toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE not( ( (hqCountry = $1) and (name = $2)) )", bq(predicate));
|
||||
}
|
||||
{
|
||||
BooleanExpression predicate = airline.name.in(Arrays.asList(united.getName())).not();
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(
|
||||
comprises(result,
|
||||
Arrays.stream(saved).filter(a -> !(a.getName().equals(united.getName()))).toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE not( (name = $1) )", bq(predicate));
|
||||
}
|
||||
{
|
||||
BooleanExpression predicate = airline.name.eq(united.getName()).not();
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(
|
||||
comprises(result,
|
||||
Arrays.stream(saved).filter(a -> !(a.getName().equals(united.getName()))).toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE not( (name = $1) )", bq(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAnd() {
|
||||
{
|
||||
BooleanExpression predicate = airline.name.eq(united.getName()).and(airline.hqCountry.eq(united.getHqCountry()));
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(comprises(result,
|
||||
Arrays.stream(saved)
|
||||
.filter(a -> a.getName().equals(united.getName()) && a.getHqCountry().equals(united.getHqCountry()))
|
||||
.toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE (name = $1) and (hqCountry = $2)", bq(predicate));
|
||||
}
|
||||
{
|
||||
BooleanExpression predicate = airline.name.eq(united.getName())
|
||||
.and(airline.hqCountry.eq(lufthansa.getHqCountry()));
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(comprises(result,
|
||||
Arrays.stream(saved)
|
||||
.filter(a -> a.getName().equals(united.getName()) && a.getHqCountry().equals(lufthansa.getHqCountry()))
|
||||
.toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE (name = $1) and (hqCountry = $2)", bq(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testOr() {
|
||||
{
|
||||
BooleanExpression predicate = airline.name.eq(united.getName())
|
||||
.or(airline.hqCountry.eq(lufthansa.getHqCountry()));
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(comprises(result,
|
||||
Arrays.stream(saved)
|
||||
.filter(a -> a.getName().equals(united.getName()) || a.getName().equals(lufthansa.getName()))
|
||||
.toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE (name = $1) or (hqCountry = $2)", bq(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNe() {
|
||||
{
|
||||
BooleanExpression predicate = airline.name.ne(united.getName());
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(
|
||||
comprises(result,
|
||||
Arrays.stream(saved).filter(a -> !a.getName().equals(united.getName())).toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE name != $1", bq(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testStartsWith() {
|
||||
{
|
||||
BooleanExpression predicate = airline.name.startsWith(united.getName().substring(0, 5));
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(comprises(result, Arrays.stream(saved)
|
||||
.filter(a -> a.getName().startsWith(united.getName().substring(0, 5))).toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE name like ($1||\"%\")", bq(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testStartsWithIgnoreCase() {
|
||||
{
|
||||
BooleanExpression predicate = airline.name.startsWithIgnoreCase(united.getName().substring(0, 5));
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(comprises(result,
|
||||
Arrays.stream(saved)
|
||||
.filter(a -> a.getName().toUpperCase().startsWith(united.getName().toUpperCase().substring(0, 5)))
|
||||
.toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE UPPER(name) like ($1||\"%\")", bq(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEndsWith() {
|
||||
{
|
||||
BooleanExpression predicate = airline.name.endsWith(united.getName().substring(1));
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(comprises(result, Arrays.stream(saved).filter(a -> a.getName().endsWith(united.getName().substring(1)))
|
||||
.toArray(Airline[]::new)), "[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE name like (\"%\"||$1)", bq(predicate));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEndsWithIgnoreCase() {
|
||||
{
|
||||
BooleanExpression predicate = airline.name.endsWithIgnoreCase(united.getName().substring(1));
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(comprises(result,
|
||||
Arrays.stream(saved)
|
||||
.filter(a -> a.getName().toUpperCase().endsWith(united.getName().toUpperCase().substring(1)))
|
||||
.toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE UPPER(name) like (\"%\"||$1)", bq(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEqIgnoreCase() {
|
||||
{
|
||||
BooleanExpression predicate = airline.name.equalsIgnoreCase(flyByNight.getName());
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(comprises(result,
|
||||
Arrays.stream(saved).filter(a -> a.getName().equalsIgnoreCase(flyByNight.getName())).toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE UPPER(name) = $1", bq(predicate));
|
||||
}
|
||||
{
|
||||
BooleanExpression predicate = airline.name.equalsIgnoreCase(united.getName());
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(
|
||||
comprises(result,
|
||||
Arrays.stream(saved).filter(a -> a.getName().equalsIgnoreCase(united.getName())).toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE UPPER(name) = $1", bq(predicate));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void testContains() {
|
||||
{
|
||||
BooleanExpression predicate = airline.name.contains("United");
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(
|
||||
comprises(result, Arrays.stream(saved).filter(a -> a.getName().contains("United")).toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE contains(name, $1)", bq(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testContainsIgnoreCase() {
|
||||
{
|
||||
BooleanExpression predicate = airline.name.containsIgnoreCase("united");
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(comprises(result,
|
||||
Arrays.stream(saved)
|
||||
.filter(a -> a.getName().toUpperCase(Locale.ROOT).contains("united".toUpperCase(Locale.ROOT)))
|
||||
.toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE contains(UPPER(name), $1)", bq(predicate));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLike() {
|
||||
{
|
||||
BooleanExpression predicate = airline.name.like("%nited%");
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(
|
||||
comprises(result, Arrays.stream(saved).filter(a -> a.getName().contains("nited")).toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE name like $1", bq(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLikeIgnoreCase() {
|
||||
{
|
||||
BooleanExpression predicate = airline.name.likeIgnoreCase("%Airlines");
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(comprises(result,
|
||||
Arrays.stream(saved)
|
||||
.filter(a -> a.getName().toUpperCase(Locale.ROOT).endsWith("Airlines".toUpperCase(Locale.ROOT)))
|
||||
.toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE UPPER(name) like $1", bq(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
// This is 'between' is inclusive
|
||||
@Test
|
||||
void testBetween() {
|
||||
{
|
||||
BooleanExpression predicate = airline.name.between(flyByNight.getName(), united.getName());
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(comprises(result,
|
||||
Arrays.stream(saved)
|
||||
.filter(
|
||||
a -> a.getName().compareTo(flyByNight.getName()) >= 0 && a.getName().compareTo(united.getName()) <= 0)
|
||||
.toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE name between $1 and $2", bq(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIn() {
|
||||
{
|
||||
BooleanExpression predicate = airline.name.in(Arrays.asList(united.getName()));
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(
|
||||
comprises(result,
|
||||
Arrays.stream(saved).filter(a -> a.getName().equals(united.getName())).toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE name = $1", bq(predicate));
|
||||
}
|
||||
|
||||
{
|
||||
BooleanExpression predicate = airline.name.in(Arrays.asList(united.getName(), lufthansa.getName()));
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(comprises(result,
|
||||
Arrays.stream(saved)
|
||||
.filter(a -> a.getName().equals(united.getName()) || a.getName().equals(lufthansa.getName()))
|
||||
.toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE name in $1", bq(predicate));
|
||||
}
|
||||
|
||||
{
|
||||
BooleanExpression predicate = airline.name.in("Fly By Night", "Sleep By Day");
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(comprises(result,
|
||||
Arrays.stream(saved)
|
||||
.filter(a -> a.getName().equals(flyByNight.getName()) || a.getName().equals(sleepByDay.getName()))
|
||||
.toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE name in $1", bq(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNotIn() {
|
||||
{
|
||||
BooleanExpression predicate = airline.name.notIn("Fly By Night", "Sleep By Day");
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(comprises(result,
|
||||
Arrays.stream(saved)
|
||||
.filter(a -> !(a.getName().equals(flyByNight.getName()) || a.getName().equals(sleepByDay.getName())))
|
||||
.toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE not( (name in $1) )", bq(predicate));
|
||||
}
|
||||
{
|
||||
BooleanExpression predicate = airline.name.notIn(united.getName());
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(
|
||||
comprises(result,
|
||||
Arrays.stream(saved).filter(a -> !a.getName().equals(united.getName())).toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE name != $1", bq(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
void testColIsEmpty() {}
|
||||
|
||||
@Test
|
||||
void testLt() {
|
||||
{
|
||||
BooleanExpression predicate = airline.name.lt(lufthansa.getName());
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(
|
||||
comprises(result,
|
||||
Arrays.stream(saved).filter(a -> a.getName().compareTo(lufthansa.getName()) < 0).toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE name < $1", bq(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGt() {
|
||||
{
|
||||
BooleanExpression predicate = airline.name.gt(lufthansa.getName());
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(
|
||||
comprises(result,
|
||||
Arrays.stream(saved).filter(a -> a.getName().compareTo(lufthansa.getName()) > 0).toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE name > $1", bq(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLoe() {
|
||||
{
|
||||
BooleanExpression predicate = airline.name.loe(lufthansa.getName());
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(comprises(result,
|
||||
Arrays.stream(saved).filter(a -> a.getName().compareTo(lufthansa.getName()) <= 0).toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE name <= $1", bq(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGoe() {
|
||||
{
|
||||
BooleanExpression predicate = airline.name.goe(lufthansa.getName());
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(comprises(result,
|
||||
Arrays.stream(saved).filter(a -> a.getName().compareTo(lufthansa.getName()) >= 0).toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE name >= $1", bq(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
// when hqCountry == null, no value is stored therefore isNull is false. Only hqCountry:null gives isNull
|
||||
// and we don't have that. Conversely, only hqCountry has a value (which is not 'null') gives isNotNull
|
||||
// so isNull and isNotNull are *not* compliments
|
||||
@Test
|
||||
@Disabled
|
||||
void testIsNull() {
|
||||
{
|
||||
BooleanExpression predicate = airline.hqCountry.isNull();
|
||||
Optional<Airline> result = airlineRepository.findOne(predicate);
|
||||
assertNull(exactly(result, nullStringAirline), "[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE name = $1", bq(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
// when hqCountry == null, no value is stored therefore isNull is false. Only hqCountry:null gives isNull
|
||||
// and we don't have that. Conversely, only hqCountry has a value (which is not 'null') gives isNotNull
|
||||
// so isNull and isNotNull are *not* compliments
|
||||
@Test
|
||||
void testIsNotNull() {
|
||||
{
|
||||
BooleanExpression predicate = airline.hqCountry.isNotNull();
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(comprises(result, Arrays.stream(saved).filter(a -> a.getHqCountry() != null).toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE hqCountry is not null", bq(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
void testContainsKey() {}
|
||||
|
||||
@Test
|
||||
void testStringLength() {
|
||||
{
|
||||
BooleanExpression predicate = airline.name.length().eq(united.getName().length());
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(comprises(result,
|
||||
Arrays.stream(saved).filter(a -> a.getName().length() == united.getName().length()).toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE LENGTH(name) = $1", bq(predicate));
|
||||
}
|
||||
{
|
||||
BooleanExpression predicate = airline.name.length().eq(flyByNight.getName().length());
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate);
|
||||
assertNull(comprises(result, Arrays.stream(saved)
|
||||
.filter(a -> a.getName().length() == flyByNight.getName().length()).toArray(Airline[]::new)),
|
||||
"[unexpected] -> [missing]");
|
||||
assertEquals(" WHERE LENGTH(name) = $1", bq(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
private void sleep(int millis) {
|
||||
try {
|
||||
Thread.sleep(millis); // so they are executed out-of-order
|
||||
} catch (InterruptedException ie) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableCouchbaseRepositories("org.springframework.data.couchbase")
|
||||
@EnableCouchbaseAuditing(dateTimeProviderRef = "dateTimeProviderRef")
|
||||
static class Config extends AbstractCouchbaseConfiguration {
|
||||
|
||||
@Override
|
||||
public String getConnectionString() {
|
||||
return connectionString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUserName() {
|
||||
return config().adminUsername();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return config().adminPassword();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBucketName() {
|
||||
return bucketName();
|
||||
}
|
||||
|
||||
@Bean(name = "auditorAwareRef")
|
||||
public NaiveAuditorAware testAuditorAware() {
|
||||
return new NaiveAuditorAware();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureEnvironment(final ClusterEnvironment.Builder builder) {
|
||||
builder.ioConfig().maxHttpConnections(11).idleHttpConnectionTimeout(Duration.ofSeconds(4));
|
||||
return;
|
||||
}
|
||||
|
||||
@Bean(name = "dateTimeProviderRef")
|
||||
public DateTimeProvider testDateTimeProvider() {
|
||||
return new AuditingDateTimeProvider();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LocalValidatorFactoryBean validator() {
|
||||
return new LocalValidatorFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ValidatingCouchbaseEventListener validationEventListener() {
|
||||
return new ValidatingCouchbaseEventListener(validator());
|
||||
}
|
||||
}
|
||||
|
||||
String bq(Predicate predicate) {
|
||||
BasicQuery basicQuery = new BasicQuery((QueryCriteriaDefinition) serializer.handle(predicate), null);
|
||||
return basicQuery.export(new int[1]);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableCouchbaseRepositories("org.springframework.data.couchbase")
|
||||
@EnableCouchbaseAuditing(auditorAwareRef = "auditorAwareRef", dateTimeProviderRef = "dateTimeProviderRef")
|
||||
static class ConfigRequestPlus extends AbstractCouchbaseConfiguration {
|
||||
|
||||
@Override
|
||||
public String getConnectionString() {
|
||||
return connectionString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUserName() {
|
||||
return config().adminUsername();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return config().adminPassword();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBucketName() {
|
||||
return bucketName();
|
||||
}
|
||||
|
||||
@Bean(name = "auditorAwareRef")
|
||||
public NaiveAuditorAware testAuditorAware() {
|
||||
return new NaiveAuditorAware();
|
||||
}
|
||||
|
||||
@Bean(name = "dateTimeProviderRef")
|
||||
public DateTimeProvider testDateTimeProvider() {
|
||||
return new AuditingDateTimeProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryScanConsistency getDefaultConsistency() {
|
||||
return REQUEST_PLUS;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2019 the original author or authors.
|
||||
* Copyright 2017-2022 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.
|
||||
@@ -23,7 +23,6 @@ import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.couchbase.client.java.query.QueryScanConsistency;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
@@ -58,6 +57,8 @@ import org.springframework.data.repository.query.QueryMethodEvaluationContextPro
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
|
||||
import com.couchbase.client.java.query.QueryScanConsistency;
|
||||
|
||||
/**
|
||||
* @author Michael Nitschinger
|
||||
* @author Michael Reiche
|
||||
@@ -82,7 +83,7 @@ class StringN1qlQueryCreatorTests extends ClusterAwareIntegrationTests {
|
||||
@Test
|
||||
@IgnoreWhen(missesCapabilities = Capabilities.QUERY, clusterTypes = ClusterType.MOCKED)
|
||||
void findUsingStringNq1l() throws Exception {
|
||||
Airline airline = new Airline(UUID.randomUUID().toString(), "Continental");
|
||||
Airline airline = new Airline(UUID.randomUUID().toString(), "Continental", "USA");
|
||||
try {
|
||||
Airline modified = couchbaseTemplate.upsertById(Airline.class).one(airline);
|
||||
|
||||
@@ -99,8 +100,8 @@ class StringN1qlQueryCreatorTests extends ClusterAwareIntegrationTests {
|
||||
|
||||
Query query = creator.createQuery();
|
||||
|
||||
ExecutableFindByQuery q = (ExecutableFindByQuery) couchbaseTemplate
|
||||
.findByQuery(Airline.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).matching(query);
|
||||
ExecutableFindByQuery q = (ExecutableFindByQuery) couchbaseTemplate.findByQuery(Airline.class)
|
||||
.withConsistency(QueryScanConsistency.REQUEST_PLUS).matching(query);
|
||||
|
||||
Optional<Airline> al = q.one();
|
||||
assertEquals(airline.toString(), al.get().toString());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors
|
||||
* Copyright 2020-2022 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.
|
||||
@@ -16,84 +16,134 @@
|
||||
|
||||
package org.springframework.data.couchbase.util;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.time.Duration;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.awaitility.Awaitility.with;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.data.util.Pair;
|
||||
|
||||
/**
|
||||
* Provides a bunch of utility APIs that help with testing.
|
||||
*
|
||||
* @author Michael Reiche
|
||||
*/
|
||||
public class Util {
|
||||
|
||||
/**
|
||||
* Waits and sleeps for a little bit of time until the given condition is met.
|
||||
*
|
||||
* <p>Sleeps 1ms between "false" invocations. It will wait at most one minute to prevent hanging forever in case
|
||||
* the condition never becomes true.
|
||||
*
|
||||
* @param supplier return true once it should stop waiting.
|
||||
*/
|
||||
public static void waitUntilCondition(final BooleanSupplier supplier) {
|
||||
waitUntilCondition(supplier, Duration.ofMinutes(1));
|
||||
}
|
||||
/**
|
||||
* Waits and sleeps for a little bit of time until the given condition is met.
|
||||
* <p>
|
||||
* Sleeps 1ms between "false" invocations. It will wait at most one minute to prevent hanging forever in case the
|
||||
* condition never becomes true.
|
||||
*
|
||||
* @param supplier return true once it should stop waiting.
|
||||
*/
|
||||
public static void waitUntilCondition(final BooleanSupplier supplier) {
|
||||
waitUntilCondition(supplier, Duration.ofMinutes(1));
|
||||
}
|
||||
|
||||
public static void waitUntilCondition(final BooleanSupplier supplier, Duration atMost) {
|
||||
with().pollInterval(Duration.ofMillis(1)).await().atMost(atMost).until(supplier::getAsBoolean);
|
||||
}
|
||||
public static void waitUntilCondition(final BooleanSupplier supplier, Duration atMost) {
|
||||
with().pollInterval(Duration.ofMillis(1)).await().atMost(atMost).until(supplier::getAsBoolean);
|
||||
}
|
||||
|
||||
public static void waitUntilCondition(final BooleanSupplier supplier, Duration atMost, Duration delay) {
|
||||
with().pollInterval(delay).await().atMost(atMost).until(supplier::getAsBoolean);
|
||||
}
|
||||
public static void waitUntilCondition(final BooleanSupplier supplier, Duration atMost, Duration delay) {
|
||||
with().pollInterval(delay).await().atMost(atMost).until(supplier::getAsBoolean);
|
||||
}
|
||||
|
||||
public static void waitUntilThrows(final Class<? extends Exception> clazz, final Supplier<Object> supplier) {
|
||||
with()
|
||||
.pollInterval(Duration.ofMillis(1))
|
||||
.await()
|
||||
.atMost(Duration.ofMinutes(1))
|
||||
.until(() -> {
|
||||
try {
|
||||
supplier.get();
|
||||
} catch (final Exception ex) {
|
||||
return ex.getClass().isAssignableFrom(clazz);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
public static void waitUntilThrows(final Class<? extends Exception> clazz, final Supplier<Object> supplier) {
|
||||
with().pollInterval(Duration.ofMillis(1)).await().atMost(Duration.ofMinutes(1)).until(() -> {
|
||||
try {
|
||||
supplier.get();
|
||||
} catch (final Exception ex) {
|
||||
return ex.getClass().isAssignableFrom(clazz);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a thread with the given name is currently running.
|
||||
*
|
||||
* @param name the name of the thread.
|
||||
* @return true if running, false otherwise.
|
||||
*/
|
||||
public static boolean threadRunning(final String name) {
|
||||
for (Thread t : Thread.getAllStackTraces().keySet()) {
|
||||
if (t.getName().equalsIgnoreCase(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Returns true if a thread with the given name is currently running.
|
||||
*
|
||||
* @param name the name of the thread.
|
||||
* @return true if running, false otherwise.
|
||||
*/
|
||||
public static boolean threadRunning(final String name) {
|
||||
for (Thread t : Thread.getAllStackTraces().keySet()) {
|
||||
if (t.getName().equalsIgnoreCase(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a file from the resources folder (in the same path as the requesting test class).
|
||||
*
|
||||
* <p>The class will be automatically loaded relative to the namespace and converted
|
||||
* to a string.
|
||||
*
|
||||
* @param filename the filename of the resource.
|
||||
* @param clazz the reference class.
|
||||
* @return the loaded string.
|
||||
*/
|
||||
public static String readResource(final String filename, final Class<?> clazz) {
|
||||
String path = "/" + clazz.getPackage().getName().replace(".", "/") + "/" + filename;
|
||||
InputStream stream = clazz.getResourceAsStream(path);
|
||||
java.util.Scanner s = new java.util.Scanner(stream, UTF_8.name()).useDelimiter("\\A");
|
||||
return s.hasNext() ? s.next() : "";
|
||||
}
|
||||
/**
|
||||
* Reads a file from the resources folder (in the same path as the requesting test class).
|
||||
* <p>
|
||||
* The class will be automatically loaded relative to the namespace and converted to a string.
|
||||
* </p>
|
||||
*
|
||||
* @param filename the filename of the resource.
|
||||
* @param clazz the reference class.
|
||||
* @return the loaded string.
|
||||
*/
|
||||
public static String readResource(final String filename, final Class<?> clazz) {
|
||||
String path = "/" + clazz.getPackage().getName().replace(".", "/") + "/" + filename;
|
||||
InputStream stream = clazz.getResourceAsStream(path);
|
||||
java.util.Scanner s = new java.util.Scanner(stream, UTF_8.name()).useDelimiter("\\A");
|
||||
return s.hasNext() ? s.next() : "";
|
||||
}
|
||||
|
||||
public static <T> Pair<List<T>, List<T>> comprises(Iterable<T> source, T... airlines) {
|
||||
List<T> unexpected = new LinkedList<>();
|
||||
List<T> missing = new LinkedList<T>();
|
||||
source.forEach(unexpected::add);
|
||||
for (T t : airlines) {
|
||||
if (!unexpected.contains(t)) {
|
||||
missing.add(t);
|
||||
} else {
|
||||
unexpected.remove(t);
|
||||
}
|
||||
}
|
||||
if (unexpected.isEmpty() && missing.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return Pair.of(unexpected, missing);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> Pair<List<T>, List<T>> exactly(Optional<T> result, T... airlines) {
|
||||
List<T> source = new LinkedList<>();
|
||||
if (result.isPresent()) {
|
||||
source.add(result.get());
|
||||
}
|
||||
return comprises(source, airlines);
|
||||
}
|
||||
|
||||
// should return null if items in source match (allAirlines - notAirlines)
|
||||
public static <T> Pair<List<T>, List<T>> comprisesNot(Iterable<T> source, T[] allAirlines, T... notAirlines) {
|
||||
List<T> expected = new LinkedList<>(Arrays.asList(allAirlines));
|
||||
expected.removeAll(Arrays.asList(notAirlines));
|
||||
List<T> unexpected = new LinkedList<>();
|
||||
List<T> missing = new LinkedList<T>();
|
||||
source.forEach(unexpected::add);// initially, everything returned is unexpected
|
||||
for (T t : expected) {
|
||||
if (!unexpected.contains(t)) {
|
||||
missing.add(t); // if not returned, then it is missing
|
||||
} else {
|
||||
unexpected.remove(t); // if returned, then remove from unexpected
|
||||
}
|
||||
}
|
||||
if (unexpected.isEmpty() && missing.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return Pair.of(unexpected, missing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user