diff --git a/.claude/rules/adapter-classes.md b/.claude/rules/adapter-classes.md deleted file mode 100644 index 18a226fa6c..0000000000 --- a/.claude/rules/adapter-classes.md +++ /dev/null @@ -1,377 +0,0 @@ -# Adapter 클래스 구조 - -## fixture-monkey 모듈 - -``` -fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/ -``` - -### Root (진입점 + 오케스트레이터) - -| 클래스 | 역할 | -|--------|------| -| `NodeTreeAdapter` | adapt 인터페이스 | -| `DefaultNodeTreeAdapter` | 메인 구현체 - adapt 로직, 캐싱(promoted subtree + type metadata), resolver 생성 | -| `JavaNodeTreeAdapterPlugin` | 플러그인 설정 진입점 | -| `ContainerValuePruner` | 컨테이너 크기 초과 값 pruning (인스턴스 클래스, ContainerDetector 필드 주입, DefaultNodeTreeAdapter에서 분리) | -| `ContainerSizeResolverFactory` | ContainerSizeResolver 생성 팩토리 (lazy/manipulator/typed 크기 resolver 생성, DefaultNodeTreeAdapter에서 분리) | - -### tracing/ (디버깅 + 진단) - -| 클래스 | 역할 | -|--------|------| -| `AdapterTracer` | 디버깅용 트레이서 인터페이스 | -| `TraceContext` | 트레이스 컨텍스트 인터페이스 (NoOp 패턴) | -| `ActiveTraceContext` | 활성 트레이스 구현 | -| `NoOpTraceContext` | NoOp 트레이스 구현 | -| `ResolutionTrace` | 불변 트레이스 결과 데이터 | -| `ResolutionTraceFormatter` | ResolutionTrace 포매팅 (tree format, JSON format, assembly tree) | -| `TraceContextResolutionListener` | ResolutionListener → TraceContext 브릿지 | -| `TimingSample` | 타이밍 측정 인터페이스 | -| `AdapterTraceBuilder` | 트레이스 데이터 수집 + 트레이서 호출 (stateless) | - -### projection/ (assembly 엔진) - -| 클래스 | 역할 | -|--------|------| -| `ValueProjection` | 경로-값 매핑 저장 (데이터 구조) | -| `ValueProjectionAssembler` | 트리 순회 + 값 생성 어셈블리 엔진 | -| `ValueProjectionAssembler.CachedTypeMetadata` | JvmType별 PropertyNameResolver/NullInjectGenerator/isContainerType 캐시 (cross-call) | -| `ValueCandidate` | 값 + 순서 + 출처(USER_SET/REGISTER/DECOMPOSED) 통합 메타데이터 | -| `ValueOrder` | 타입 기반 우선순위 인터페이스 (UserOrder: direct, RegisterOrder: register) | -| `ValueDecomposer` | exact value를 하위 필드로 분해, ObjectValueExtractor로 값 추출 후 order 비교 필터링, DecomposeResult 반환 | -| `DecomposeResult` | ValueDecomposer의 불변 결과 객체 (ValueCandidate 맵 반환) | -| `PathValueResolver` | 경로 매칭 + thenApply lazy 해석 | -| `AssembleContext` | assemble 시 필요한 컨텍스트 | -| `LazyValueHolder` | LazyArbitrary 지연 평가 + root-level만 재귀 방지 (ThreadLocal 기반, field-level lazy는 guard 없이 직접 평가, RECURSION_BLOCKED sentinel로 supplier null과 guard null 구분) | - -### analysis/ (manipulator 분석) - -| 클래스 | 역할 | -|--------|------| -| `ManipulatorAnalyzer` | Manipulator 분석 → AnalysisResult | -| `AnalysisResult` | 분석 결과 불변 객체 (resolvers, values, filters, customizers 등), inner class: LazyManipulatorDescriptor, PostConditionFilter, PropertyCustomizer | -| `AdaptationResult` | adapt 결과 (JvmNodeTree + ValueProjection + AnalysisResult) | -| `TypedValueExtractor` | Manipulator에서 typed value 추출 + PathExpression 변환 (stateless) | - -### converter/ (stateless 변환기) - -| 클래스 | 역할 | -|--------|------| -| `ContainerInfoResolverConverter` | ContainerInfoManipulator → PathResolver 변환 | -| `PredicatePathConverter` | NextNodePredicate → PathExpression 변환, NodeResolver → Predicate 추출 | - -### nodecandidate/ (NodeCandidate 생성) - -| 클래스 | 역할 | -|--------|------| -| `PropertyGeneratorNodeCandidateGenerator` | PropertyGenerator로 NodeCandidate 생성 | -| `InterfaceMethodNodeCandidateGenerator` | 인터페이스 no-arg 메서드 → NodeCandidate | -| `NameResolvingNodeCandidateGenerator` | 이름 해석 래퍼 | -| `ContainerPropertyGeneratorNodeGenerator` | ContainerPropertyGenerator → JvmContainerNodeGenerator 어댑터 | - -### property/ (JvmNode ↔ Property 변환) - -| 클래스 | 역할 | -|--------|------| -| `JvmNodePropertyFactory` | JvmNode/CreationMethod → Property 팩토리 | - -## object-farm-api 모듈 - -> 전체 모듈 구조(expression, type, output 등 포함)는 [object-farm-api.md](./object-farm-api.md) 참조. -> 아래는 adapter와 직접 연관된 패키지만 기술. - -### 트리 구조 - -``` -object-farm-api/src/main/java/com/navercorp/objectfarm/api/tree/ -``` - -| 클래스 | 역할 | -|--------|------| -| `JvmNodeCandidateTree` | 타입 구조 트리 (캐시됨, 값 생성 전 구조) | -| `JvmNodeCandidateTreeContext` | CandidateTree 생성 및 서브트리 캐싱 컨텍스트 | -| `JvmNodeTree` | 실제 노드 트리 (값 생성에 사용) | -| `JvmNodeTreeTransformer` | CandidateTree → NodeTree 변환, 컨테이너 확장 | -| `ExpansionContext` | 재귀 노드 확장 제어 (사용자 정의 경로 기반 순환 확장 결정) | -| `JvmNodeSubtreeContext` | JvmNode 서브트리 스냅샷 캐시 (타입별, ConcurrentHashMap) + Snapshot inner class | -| `PathResolver` | PathExpression 패턴 + NodeCustomizer를 결합하는 경로 기반 해석 제네릭 인터페이스 | -| `PathResolverContext` | 경로 기반 resolver들 (컨테이너 크기, 인터페이스, 제네릭 타입) + ResolutionListener 통합 관리 | -| `PathContainerSizeResolver` | 특정 경로의 컨테이너 크기를 결정하는 PathResolver 구현체 | -| `PathInterfaceResolver` | 특정 경로의 인터페이스/추상 타입을 구체 구현체로 결정하는 PathResolver 구현체 | -| `PathGenericTypeResolver` | 특정 경로의 제네릭 타입을 구체 타입으로 해석하는 PathResolver 구현체 | -| `ResolutionListener` | 트리 변환 중 인터페이스/컨테이너 크기 해석 결정사항을 추적하는 리스너 인터페이스 | -| `NoOpResolutionListener` | 추적 비활성화 시 오버헤드 없이 동작하는 ResolutionListener no-op 구현체 | - -### NodeCandidate - -``` -object-farm-api/src/main/java/com/navercorp/objectfarm/api/nodecandidate/ -``` - -#### Core 인터페이스 + 기반 클래스 - -| 클래스 | 역할 | -|--------|------| -| `JvmNodeCandidate` | promote 전 타입 메타데이터를 보유하는 중간 표현 인터페이스 | -| `JvmNodeCandidateGenerator` | JVM 타입으로부터 NodeCandidate를 생성하는 루트 인터페이스 | -| `CreationMethod` | 프로퍼티 생성/설정 방식 메타데이터 인터페이스 | - -#### NodeCandidate 구현체 - -| 클래스 | 역할 | -|--------|------| -| `JavaNodeCandidate` | POJO 필드용 표준 JvmNodeCandidate 구현 | -| `JavaMapNodeCandidate` | Map 타입 전용 JvmNodeCandidate (별도 key/value NodeCandidate 보유) | -| `JvmMapNodeCandidate` | Map.Entry를 독립 필드 타입으로 사용할 때의 마커 인터페이스 | -| `JvmMapEntryNodeCandidate` | 독립 필드로서의 Map.Entry NodeCandidate (Map 컨테이너 외부) | - -#### CreationMethod 구현체 - -| 클래스 | 역할 | -|--------|------| -| `ConstructorParamCreationMethod` | 생성자 파라미터로 전달되는 프로퍼티 메타데이터 (인덱스 포함) | -| `FieldAccessCreationMethod` | 필드 reflection 직접 접근 프로퍼티 메타데이터 | -| `MethodInvocationCreationMethod` | 메서드 호출 (setter, builder, factory) 프로퍼티 메타데이터 | -| `ContainerElementCreationMethod` | 컨테이너 요소 인덱스 접근 프로퍼티 메타데이터 | - -#### Generator 인터페이스 + 특수 생성기 - -| 클래스 | 역할 | -|--------|------| -| `JvmGenericNodeCandidateGenerator` | 제네릭 타입 파라미터 커스터마이징 가능한 생성기 인터페이스 | -| `JvmInterfaceNodeCandidateGenerator` | 인터페이스 타입 전용 생성기 인터페이스 | -| `JavaFieldNodeCandidateGenerator` | POJO 필드 NodeCandidate 표준 생성기 | -| `DefaultGenericNodeCandidateGenerator` | GenericTypeResolver로 제네릭 타입 파라미터 해석 후 위임하는 기본 구현 | -| `DefaultInterfaceNodeCandidateGenerator` | InterfaceResolver로 인터페이스를 구체 구현체로 해석 후 위임하는 기본 구현 | - -#### Factory + 옵션 - -| 클래스 | 역할 | -|--------|------| -| `JvmNodeCandidateFactory` | JvmType → JvmNodeCandidate 변환 인터페이스 | -| `JavaNodeCandidateFactory` | 기본 구현 (Map.Entry → JavaMapEntryNodeCandidate 처리 포함) | -| `JavaRecordNodeCandidateGenerator` | Record 타입 전용 NodeCandidate 생성 (Java 17 MR JAR, canonical constructor 기반) | -| `ObjectFarmJdkVariantOptions` | JDK 버전별 옵션 (Java 8 no-op / Java 17 record 지원 등록) | - -### Node (JvmNode 구현 + Promoter) - -``` -object-farm-api/src/main/java/com/navercorp/objectfarm/api/node/ -``` - -#### Core 노드 인터페이스 + 구현체 - -| 클래스 | 역할 | -|--------|------| -| `JvmNode` | 모든 JVM 타입을 나타내는 통합 노드 인터페이스 (계층적 부모-자식 구조) | -| `JavaNode` | 기본 JvmNode 구현체 (인덱스, CreationMethod 메타데이터 포함) | -| `JvmMapNode` | Map entry의 key/value 노드 접근자를 가진 특수 JvmNode 인터페이스 | -| `JavaMapNode` | JvmMapNode 구현체 (JvmMapNodeCandidate → 1:1 매핑) | -| `JvmMapEntryNode` | 독립 Map.Entry의 key/value 노드 접근자를 가진 특수 JvmNode 인터페이스 | -| `JavaMapEntryNode` | JvmMapEntryNode 구현체 (1:1 토폴로지 매핑) | - -#### 컨텍스트 + 시드 관리 - -| 클래스 | 역할 | -|--------|------| -| `JvmNodeContext` | 시드, promoter, candidate/container 생성기, resolver를 번들링하는 컨텍스트 인터페이스 | -| `JavaNodeContext` | JvmNodeContext 기본 구현 (Builder 패턴) | -| `SeedState` | 기본 시드 + 증가 시퀀스 카운터 관리 (스레드 안전 스냅샷, 결정적 랜덤 생성) | -| `SeedSnapshot` | 기본 시드 + 시퀀스 번호의 불변 스냅샷 (재현 가능한 랜덤 값 보장) | - -#### Node Promoter - -| 클래스 | 역할 | -|--------|------| -| `JvmNodePromoter` | NodeCandidate → JvmNode 변환 인터페이스 | -| `JavaDefaultNodePromoter` | 여러 JvmNodePromoter를 조합하는 기본 promoter (위임 기반) | -| `JavaObjectNodePromoter` | 일반 객체 노드 promote | -| `JavaMapNodePromoter` | Map 노드 promote | -| `JavaInterfaceNodePromoter` | 인터페이스 노드 promote | -| `JavaMapEntryNodePromoter` | Map.Entry 노드 promote (key/value 1:1 래핑) | -| `AbstractTypeNodePromoter` | 인터페이스/추상 타입 NodeCandidate promote | - -#### 컨테이너 요소 노드 생성기 - -| 클래스 | 역할 | -|--------|------| -| `JvmContainerNodeGenerator` | 컨테이너 요소 JvmNode 생성 인터페이스 (런타임 동적 생성) | -| `JavaArrayElementNodeGenerator` | 배열 요소 노드 생성 (ContainerSizeResolver 기반) | -| `JavaLinearContainerElementNodeGenerator` | 선형 컨테이너 (List, Set) 요소 노드 생성 | -| `JavaMapElementNodeGenerator` | Map entry (key/value 쌍) 노드 생성 | -| `JavaSingleElementContainerNodeGenerator` | 투명 래퍼 (Supplier, Optional) 노드 생성 (단일 무명 내부 요소) | - -#### 타입 해석기 - -| 클래스 | 역할 | -|--------|------| -| `NodeCustomizer` | 노드 커스터마이저 마커 인터페이스 (GenericTypeResolver, InterfaceResolver, ContainerSizeResolver, LeafTypeResolver) | -| `ContainerSizeResolver` | 컨테이너 크기 결정 함수형 인터페이스 (결정적 랜덤 + 고정 크기 구현) | -| `RandomContainerSizeResolver` | 지정 범위 내 시드 기반 랜덤 크기 resolver | -| `FixedContainerSizeResolver` | 미리 결정된 고정 크기 resolver | -| `GenericTypeResolver` | 제네릭 타입 파라미터를 구체 타입으로 해석하는 함수형 인터페이스 | -| `InterfaceResolver` | 인터페이스를 구체 구현체로 해석하는 함수형 인터페이스 | -| `LeafTypeResolver` | 커스텀 leaf 타입 판별 인터페이스 (kotlin.Unit 등) | -| `JavaLeafTypeResolver` | Java 표준 타입 (primitives, java.*, sun.*) leaf 판별 구현 | - -### Input (값 분석 + 타입 파싱) - -``` -object-farm-api/src/main/java/com/navercorp/objectfarm/api/input/ -``` - -#### 값 추출 + 분석 - -| 클래스 | 역할 | -|--------|------| -| `ObjectValueExtractor` | 재귀적 값 분해기 — FieldExtractor + ContainerDetector 조합으로 객체 그래프에서 path→value flat map 생성 | -| `FieldExtractor` | 1-level POJO 필드 추출 인터페이스 (reflection 구현 제공) | -| `ContainerDetector` | 컨테이너 타입 판별 + 크기 조회 인터페이스 (standard 구현 제공) | -| `ValueAnalyzer` | 객체 그래프를 분석하여 경로별 값, 타입 해석기, 컨테이너 크기 정보를 추출하는 재귀적 값 분해기 | -| `ValueAnalysisResult` | 값 분석 결과 불변 객체 (인터페이스/제네릭/컨테이너 해석기 + 분해된 경로별 값) | - -#### Resolver 변환기 - -| 클래스 | 역할 | -|--------|------| -| `InterfaceResolverConverter` | 값 정보를 분석하여 인터페이스 타입을 구체 타입으로 해석하는 경로 기반 해석기로 변환 | -| `GenericTypeResolverConverter` | 값/명시적 타입 정의에서 제네릭 타입 정보를 추출하여 제네릭 타입 해석기로 변환 | - -#### 타입 파싱 (스키마 기반 타입 정의) - -| 클래스 | 역할 | -|--------|------| -| `TypeInputParser` | 다양한 입력 형식 (Java, JSON Schema, TypeScript)을 JvmType으로 파싱하는 인터페이스 | -| `TypeInputParserRegistry` | TypeInputParser 구현체 등록/관리, 입력 타입에 따라 적절한 파서 자동 선택 | -| `TypeParseContext` | 타입 별칭, ClassLoader, strict 모드 등 파싱 동작 커스터마이징 컨텍스트 | -| `TypeParseException` | TypeInputParser 파싱 실패 시 발생하는 예외 | -| `JavaTypeInputParser` | JvmType, Class, Type, AnnotatedType, ObjectTypeReference 등 네이티브 Java 타입 파싱 | -| `JsonSchemaInputParser` | JSON Schema 형식 문자열을 JvmType으로 파싱 | -| `TypeScriptInputParser` | TypeScript 유사 문법 문자열 (예: `{ name: string }`)을 JvmType으로 파싱 | - -#### Synthetic 타입 (스키마 정의 타입 통합) - -| 클래스 | 역할 | -|--------|------| -| `SyntheticJvmType` | JSON Schema/TypeScript 등 스키마로 정의된 타입을 기존 JvmType 인프라에 통합하는 합성 타입 | -| `SyntheticMember` | SyntheticJvmType의 멤버(필드) 표현 | -| `SyntheticMemberCreationMethod` | 스키마 정의 타입 멤버의 생성 방식 메타데이터 CreationMethod | -| `SyntheticNodeCandidateGenerator` | SyntheticJvmType 멤버들을 JvmNodeCandidate로 변환하는 생성기 | - -## 자주 수정하는 파일 - -| 파일 | 수정 이유 | -|------|----------| -| `DefaultNodeTreeAdapter.java` | adapt 로직, 캐싱, resolver 생성 | -| `ContainerValuePruner.java` | 컨테이너 크기 초과 값 pruning | -| `ContainerSizeResolverFactory.java` | ContainerSizeResolver 생성 로직 | -| `projection/ValueProjection.java` | 경로-값 매핑, 값 병합 | -| `projection/ValueProjectionAssembler.java` | assemble 로직 (트리 순회, 값 생성) | -| `projection/PathValueResolver.java` | 경로 매칭, thenApply lazy 해석 | -| `projection/ValueDecomposer.java` | exact value 분해 (객체 필드, 컨테이너 요소) | -| `nodecandidate/PropertyGeneratorNodeCandidateGenerator.java` | NodeCandidate 생성 로직 | -| `JavaObjectNodePromoter.java` (object-farm-api) | 일반 객체 Node promote 로직 | -| `JvmNodeTreeTransformer.java` (object-farm-api) | 트리 변환, 컨테이너 확장 | - -## 테스트 파일 - -### FixtureMonkeyAdapterTest 계열 (FixtureMonkeyTestSpecs 기반) - -카테고리별로 분리된 파일들 (`com.navercorp.fixturemonkey.adapter` 패키지): -- `ApplyAdapterTest` - apply/acceptIf -- `BasicGenerationAdapterTest` - 기본 타입/객체 생성 -- `ContainerAdapterTest` - 컨테이너 타입 -- `CustomizationAdapterTest` - set/size/apply/postCondition 등 -- `DoubleThenApplyAdapterTest` - double/triple thenApply 패턴 -- `FixedSampleAdapterTest` - fixed() 관련 -- `GenericTypeAdapterTest` - 제네릭 타입 -- `InstantiatorAdapterTest` - 생성자/팩토리 메서드 -- `IntrospectorAdapterTest` - ArbitraryIntrospector 관련 -- `MiscAdapterTest` - 기타 (leaf type inference 포함) -- `PluginAdapterTest` - 플러그인 -- `RecursiveTypeAdapterTest` - 재귀/순환 참조 -- `RegisterAdapterTest` - register/registerGroup -- `RegisterComplexAdapterTest` - register 복합 시나리오 -- `SizeAdapterTest` - size/minSize/maxSize -- `StrictModeAdapterTest` - strict mode -- `ThenApplyOrderingAdapterTest` - thenApply/size/set 순서 - -### ValueProjection 계열 (ValueProjectionAssembleSpecs 기반) - -카테고리별로 분리된 파일들 (`com.navercorp.fixturemonkey.adapter` 패키지): -- `ValueProjectionBasicGenerationTest` - 기본 타입/객체 생성 -- `ValueProjectionContainerTest` - 컨테이너 타입 -- `ValueProjectionCustomizationTest` - set/size/apply/postCondition 등 -- `ValueProjectionGenericTest` - 제네릭 타입 -- `ValueProjectionInstantiatorTest` - 생성자/팩토리 메서드 -- `ValueProjectionInterfaceTest` - 인터페이스/추상/sealed class -- `ValueProjectionIntrospectorTest` - ArbitraryIntrospector 관련 -- `ValueProjectionMiscTest` - 기타 -- `ValueProjectionPluginTest` - 플러그인 -- `ValueProjectionPropertySelectorTest` - PropertySelector/expression -- `ValueProjectionStrictModeTest` - strict mode -- `ValueProjectionThenApplyTest` - thenApply/size/set 순서 - -### 단위 테스트 - -- `PredicatePathConverterTest` - PredicatePathConverter 단위 테스트 -- `ContainerInfoResolverConverterTest` - ContainerInfoResolverConverter 단위 테스트 -- `InterfaceResolverConverterTest` - InterfaceResolverConverter 단위 테스트 -- `DefaultNodeTreeAdapterTest` - DefaultNodeTreeAdapter 단위 테스트 -- `ValueProjectionUnitTest` - ValueProjection 빌더/데이터 구조 단위 테스트 - -### 기타 테스트 (`com.navercorp.fixturemonkey.test` 패키지) - -- `FixtureMonkeyTest` - FixtureMonkey 통합 테스트 -- `FixtureMonkeyOptionsTest` / `FixtureMonkeyOptionsAdditionalTestSpecs` - 옵션 테스트 -- `InnerSpecTest` / `InnerSpecTestSpecs` - InnerSpec 테스트 -- `StackOverflowReproTest` - StackOverflow 재현 테스트 - -### Spec 파일 - -| 파일 | 용도 | -|------|------| -| `FixtureMonkeyTestSpecs.java` (`test` 패키지) | FixtureMonkeyAdapterTest 계열 spec 클래스들 | -| `ValueProjectionAssembleSpecs.java` (`adapter` 패키지) | ValueProjection 계열 spec 클래스들 | - -## 디버깅 - -테스트 실패 시 tracer 활성화: - -```java -FixtureMonkey fm = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin() - .tracer(AdapterTracer.console())) - .build(); -``` - -### AdapterTracer 종류 - -| 트레이서 | 설명 | -|---------|------| -| `AdapterTracer.console()` | 콘솔에 텍스트 출력 | -| `AdapterTracer.consoleJson()` | 콘솔에 JSON 형식 출력 | -| `AdapterTracer.timing()` | 타이밍 정보 출력 | -| `AdapterTracer.file(Path)` | 파일에 트리 형식 출력 (append 모드) | -| `AdapterTracer.summary()` | 전체 trace 수집, 요약 테이블/타이밍 분석 출력 | - -## 테스트 실행 - -```bash -# 특정 카테고리 테스트 -./gradlew :fixture-monkey:test --tests "com.navercorp.fixturemonkey.test.CustomizationAdapterTest" -./gradlew :fixture-monkey:test --tests "com.navercorp.fixturemonkey.adapter.ValueProjectionCustomizationTest" - -# Adapter 회귀 테스트 (전체) -./gradlew :fixture-monkey:test --tests "com.navercorp.fixturemonkey.test.*" -./gradlew :fixture-monkey:test --tests "com.navercorp.fixturemonkey.adapter.*" -``` - -## 작업 흐름 - -1. **테스트 작성** - 최소 단위 테스트 우선 작성 -2. **기능 구현** - 기존 구조와 실행 흐름 유지하며 구현 -3. **단위 테스트 실행** -4. **회귀 테스트 실행** -5. **실패 시** - tracer 활성화하여 원인 파악 diff --git a/.claude/rules/adapter-execution-flow.md b/.claude/rules/adapter-execution-flow.md deleted file mode 100644 index 3ff7ccf9d3..0000000000 --- a/.claude/rules/adapter-execution-flow.md +++ /dev/null @@ -1,163 +0,0 @@ -# Adapter 실행 흐름 - -## 전체 흐름 - -``` -┌────────────────────────────────────────────────────────────────────────────┐ -│ ArbitraryBuilder.sample() / sampleList() │ -│ - ManipulatorSet 생성 (사용자가 set(), size() 등으로 설정한 조작들) │ -└────────────────────────────────────────────────────────────────────────────┘ - │ - ▼ -┌────────────────────────────────────────────────────────────────────────────┐ -│ DefaultNodeTreeAdapter.adapt(rootType, manipulatorSet, options) │ -│ - 캐시 확인 후 buildAdaptationResult() 호출 │ -└────────────────────────────────────────────────────────────────────────────┘ - │ - ▼ -┌────────────────────────────────────────────────────────────────────────────┐ -│ Phase 1: ManipulatorAnalyzer.analyze() │ -│ - ArbitraryManipulator 목록 → AnalysisResult │ -│ - 추출 항목: │ -│ - valuesByPath: 경로별 설정된 값 │ -│ - filtersByPath: 경로별 필터 │ -│ - interfaceResolvers: 인터페이스 구현체 결정 정보 │ -│ - valueOrderByPath: 값 설정 순서 │ -└────────────────────────────────────────────────────────────────────────────┘ - │ - ▼ -┌────────────────────────────────────────────────────────────────────────────┐ -│ Phase 2: resolveRootTypeWithAnalysisResult() │ -│ - 루트 타입이 인터페이스/추상 클래스면 구현체로 resolve │ -│ - "$" 경로에 직접 set된 값이 있으면 그 타입 사용 │ -└────────────────────────────────────────────────────────────────────────────┘ - │ - ▼ -┌────────────────────────────────────────────────────────────────────────────┐ -│ Phase 3: ContainerInfoResolverConverter.convert() │ -│ - ContainerInfoManipulator → PathResolver │ -│ - 컨테이너 크기 정보를 경로 기반 resolver로 변환 │ -└────────────────────────────────────────────────────────────────────────────┘ - │ - ▼ -┌────────────────────────────────────────────────────────────────────────────┐ -│ Phase 4: createResolverContext() │ -│ - PathResolverContext 생성 │ -│ - 컨테이너 크기, 인터페이스 구현체 등 resolver 통합 │ -└────────────────────────────────────────────────────────────────────────────┘ - │ - ▼ -┌────────────────────────────────────────────────────────────────────────────┐ -│ Phase 5: getOrBuildCandidateTree() │ -│ - JvmNodeCandidateTree 생성 (타입 구조만, 캐시됨) │ -│ - PropertyGenerator로 자식 프로퍼티 생성 │ -└────────────────────────────────────────────────────────────────────────────┘ - │ - ▼ -┌────────────────────────────────────────────────────────────────────────────┐ -│ Phase 6: JvmNodeTreeTransformer.transform() │ -│ - JvmNodeCandidateTree → JvmNodeTree │ -│ - NodeCandidate를 JvmNode로 promote (JvmNodePromoter 사용) │ -│ - 컨테이너 요소 확장 (List, Map 등의 실제 요소 노드 생성) │ -│ - 인터페이스 구현체 결정 │ -└────────────────────────────────────────────────────────────────────────────┘ - │ - ▼ -┌────────────────────────────────────────────────────────────────────────────┐ -│ Phase 7: ValueProjection.fromStringPathMap() │ -│ - JvmNodeTree + prunedValuesByPath → ValueProjection │ -│ - 트리 구조와 사용자 설정 값을 결합 │ -└────────────────────────────────────────────────────────────────────────────┘ - │ - ▼ -┌────────────────────────────────────────────────────────────────────────────┐ -│ Return: AdaptationResult │ -│ - valueProjection: 경로-값 매핑 │ -│ - analysisResult: 분석 결과 (필터, 순서 등) │ -│ - timing 정보 │ -└────────────────────────────────────────────────────────────────────────────┘ - │ - ▼ -┌────────────────────────────────────────────────────────────────────────────┐ -│ ValueProjection.assemble(context) │ -│ - AssemblyState 생성 │ -│ - assembleNode()로 트리 순회하며 각 노드 값 생성 │ -│ - ArbitraryIntrospector 사용하여 실제 객체 생성 │ -└────────────────────────────────────────────────────────────────────────────┘ - │ - ▼ -┌────────────────────────────────────────────────────────────────────────────┐ -│ 최종 객체 반환 │ -└────────────────────────────────────────────────────────────────────────────┘ -``` - -## Phase별 핵심 클래스 - -| Phase | 클래스 | 입력 | 출력 | -|-------|--------|------|------| -| 1 | ManipulatorAnalyzer | List | AnalysisResult | -| 3 | ContainerInfoResolverConverter | List | List | -| 5 | JvmNodeCandidateTree.Builder | JvmType, JvmNodeContext | JvmNodeCandidateTree | -| 6 | JvmNodeTreeTransformer | JvmNodeCandidateTree, PathResolverContext | JvmNodeTree | -| 7 | ValueProjection | JvmNodeTree, Map | ValueProjection | -| 8 | ValueProjection.assemble | AssembleContext | CombinableArbitrary | - -## 캐싱 포인트 - -``` -adapt() - │ - ├── manipulatorSet.isEmpty()? → buildDefaultAdaptationResult() (최적화 경로) - │ - └── manipulatorSet 있음 → buildAdaptationResult() - │ - └── buildAdaptationResult() 내부 - │ - ├── candidateTreeCache: JvmNodeCandidateTree (타입 구조) - │ - ├── concreteTypeCandidateTreeCache: JvmNodeCandidateTree (구체 타입용) - │ - ├── nodeContextCache: JvmNodeContext (노드 컨텍스트) - │ - ├── subtreeContext: JvmNodeSubtreeContext (JvmNode 서브트리) - │ - JvmNodeTreeTransformer.expandObjectChildren()에서 사용 - │ - 타입별 promoted 노드 구조 캐시 - │ - 컨테이너 노드만 동적 확장 (사이즈 매번 다름) - │ - 조건: 순환참조 없음, path-specific resolver 없음 - │ - ExpansionContext 존재 시: non-self-recursive 서브트리만 저장 허용 - │ - └── currentResolverContext: ThreadLocal - - 현재 adapt 호출의 PathResolverContext 보관 - -ValueProjection.assemble() - │ - └── nodeMetadataCache: ConcurrentHashMap - - DefaultNodeTreeAdapter에서 관리, AssemblyState로 전달 - - JvmType별 PropertyNameResolver/NullInjectGenerator/isContainerType 캐시 - - write-back on miss: assembleNode()에서 캐시 미스 시 기록 - - clearCache()에서 함께 clear -``` - -## Registered Builder 처리 - -Registered builder는 타입별로 등록된 빌더 설정이다. - -``` -ManipulatorSet.registeredBuilderInfos - │ - └── RegisteredBuilderInfo - ├── targetType (예: ListStringObject.class) - ├── manipulators (ArbitraryManipulator 목록) - └── containerInfoManipulators (ContainerInfoManipulator 목록) - │ - ▼ - 타입 기반 resolver로 변환 - │ - ▼ - JvmNodeTreeTransformer에서 해당 타입 만나면 적용 -``` - -**주의**: Registered builder의 컨테이너 크기는 **타입 기반**으로 적용된다. -트리 변환 시점에 해당 타입의 노드를 만나면 등록된 크기가 적용됨. - -자세한 아키텍처는 memory `adapter-register-builder-architecture` 참조. diff --git a/.claude/rules/adapter.md b/.claude/rules/adapter.md deleted file mode 100644 index bcf266b2d9..0000000000 --- a/.claude/rules/adapter.md +++ /dev/null @@ -1,53 +0,0 @@ -# Adapter 개요 - -Adapter는 `ManipulatorSet`(사용자 조작 명령)을 `ValueProjection`(경로-값 매핑)으로 변환하는 핵심 컴포넌트다. - -## 핵심 흐름 요약 - -``` -ArbitraryBuilder.sample() - ↓ -ManipulatorSet (사용자가 설정한 값, 크기, 필터 등) - ↓ -DefaultNodeTreeAdapter.adaptWithValues() - ↓ -AdaptationResult (JvmNodeTree + ValueProjection) - ↓ -ValueProjection.assemble() - ↓ -최종 객체 -``` - -## 서브패키지 구조 - -``` -adapter/ -├── tracing/ 디버깅 + 진단 (AdapterTracer, TraceContext 등) -├── projection/ assembly 엔진 (ValueProjection, ValueProjectionAssembler 등) -├── analysis/ manipulator 분석 (ManipulatorAnalyzer, AdaptationResult) -├── converter/ stateless 변환기 (PredicatePathConverter 등) -├── nodecandidate/ NodeCandidate 생성 브릿지 -├── property/ JvmNode ↔ Property 변환 -└── (root) 진입점 (NodeTreeAdapter, DefaultNodeTreeAdapter, JavaNodeTreeAdapterPlugin) -``` - -## 관련 문서 - -- [adapter-execution-flow.md](./adapter-execution-flow.md) - 상세 실행 흐름 -- [adapter-classes.md](./adapter-classes.md) - 클래스 구조 및 역할 - -## 중요 규칙 - -### 실행 흐름 유지 - -**실행 흐름은 절대 변경하지 않는다.** `adapter-execution-flow.md`에 정의된 Phase 순서와 흐름을 반드시 유지해야 한다. - -불가피하게 변경이 필요한 경우 반드시 사용자에게 먼저 확인을 받아야 한다. - -### 문서 유지 - -클래스 변경/삭제/추가 시 반드시 이 rules 문서들을 업데이트해야 한다. - -- 클래스 삭제: 해당 클래스를 문서에서 제거 -- 클래스 추가: 역할에 맞는 문서에 추가 -- 클래스 대체: 기존 클래스 제거 + 새 클래스 추가 diff --git a/.claude/rules/object-farm-api.md b/.claude/rules/object-farm-api.md deleted file mode 100644 index 5e410aef06..0000000000 --- a/.claude/rules/object-farm-api.md +++ /dev/null @@ -1,227 +0,0 @@ -# object-farm-api 모듈 구조 - -JVM 타입 시스템, 노드 트리, 경로 표현식 등 fixture-monkey의 기반 인프라를 제공하는 독립 모듈. - -## 패키지 구조 - -``` -object-farm-api/src/main/java/com/navercorp/objectfarm/api/ -├── expression/ 경로 표현식 (PathExpression, Selector 계층) -├── type/ JVM 타입 추상화 (JvmType, JavaType, GenericType) -├── node/ 노드 구현 (JvmNode, Promoter, Resolver) -├── nodecandidate/ NodeCandidate + Generator + CreationMethod -├── tree/ 트리 구조 (CandidateTree, NodeTree, Transformer) -├── input/ 값 분석 + 타입 파싱 (ValueAnalyzer, TypeInputParser) -├── output/ 트리 출력 포맷터 (TreeOutputFormatter) -└── projection/ 노드 프로젝션 인터페이스 (NodeProjection) -``` - -## expression/ (경로 표현식) - -| 클래스 | 역할 | -|--------|------| -| `PathExpression` | `$`, `.name`, `[index]`, `[*]` 등으로 구성된 경로 표현식 핵심 클래스 | -| `Segment` | PathExpression의 개별 경로 조각 (root `$`, child `.field`, index `[0]` 등) | -| `Selector` | Segment가 노드를 선택하는 방식의 마커 인터페이스 | -| `NameSelector` | 이름으로 필드 선택 (`$.fieldName`) | -| `IndexSelector` | 인덱스로 요소 선택 (`$[0]`) | -| `WildcardSelector` | 모든 자식/요소 선택 (`$.*`, `$[*]`) | -| `KeySelector` | Map key로 선택 | -| `ValueSelector` | Map value로 선택 | -| `TypeSelector` | 타입 기반 선택 (`$[type:ClassName]`) — register 등에서 사용 | - -## type/ (JVM 타입 추상화) - -| 클래스 | 역할 | -|--------|------| -| `JvmType` | JVM 타입 최상위 인터페이스 (Class, ParameterizedType 등 통합) | -| `JavaType` | JvmType 기본 구현체 | -| `GenericType` | 제네릭 타입 파라미터 정보를 포함하는 JvmType | -| `ObjectTypeReference` | 런타임 타입 캡처 (`new ObjectTypeReference>() {}`) | -| `JvmTypes` | JvmType 팩토리/유틸리티 | -| `Types` | java.lang.reflect.Type 유틸리티 | -| `AnnotatedTypes` | AnnotatedType 유틸리티 | -| `Reflections` | Reflection 유틸리티 | -| `WildcardRawType` | 와일드카드 타입의 raw type 표현 | - -## node/ (노드 구현 + Promoter + Resolver) - -상세 내용은 [adapter-classes.md](./adapter-classes.md#node-jvmnode-구현--promoter) 참조. - -### Core 노드 - -| 클래스 | 역할 | -|--------|------| -| `JvmNode` | 모든 JVM 타입을 나타내는 통합 노드 인터페이스 (계층적 부모-자식 구조) | -| `JavaNode` | 기본 JvmNode 구현체 (인덱스, CreationMethod 메타데이터 포함) | -| `JvmMapNode` / `JavaMapNode` | Map entry의 key/value 노드 접근자를 가진 특수 노드 | -| `JvmMapEntryNode` / `JavaMapEntryNode` | 독립 Map.Entry 노드 | - -### 컨텍스트 + 시드 - -| 클래스 | 역할 | -|--------|------| -| `JvmNodeContext` / `JavaNodeContext` | 시드, promoter, generator, resolver를 번들링하는 컨텍스트 | -| `SeedState` | 기본 시드 + 증가 시퀀스 카운터 관리 | -| `SeedSnapshot` | 기본 시드 + 시퀀스 번호의 불변 스냅샷 | - -### Node Promoter - -| 클래스 | 역할 | -|--------|------| -| `JvmNodePromoter` | NodeCandidate → JvmNode 변환 인터페이스 | -| `JavaDefaultNodePromoter` | 여러 JvmNodePromoter를 조합하는 기본 promoter | -| `JavaObjectNodePromoter` | 일반 객체 노드 promote | -| `JavaMapNodePromoter` | Map 노드 promote | -| `JavaInterfaceNodePromoter` | 인터페이스 노드 promote | -| `JavaMapEntryNodePromoter` | Map.Entry 노드 promote | -| `AbstractTypeNodePromoter` | 인터페이스/추상 타입 NodeCandidate promote | - -### 타입 해석기 (NodeCustomizer) - -| 클래스 | 역할 | -|--------|------| -| `NodeCustomizer` | 마커 인터페이스 | -| `ContainerSizeResolver` | 컨테이너 크기 결정 함수형 인터페이스 | -| `RandomContainerSizeResolver` | 시드 기반 랜덤 크기 | -| `FixedContainerSizeResolver` | 고정 크기 | -| `GenericTypeResolver` | 제네릭 타입 파라미터 해석 | -| `InterfaceResolver` | 인터페이스 → 구체 구현체 해석 | -| `LeafTypeResolver` / `JavaLeafTypeResolver` | leaf 타입 판별 | - -### 컨테이너 요소 노드 생성기 - -| 클래스 | 역할 | -|--------|------| -| `JvmContainerNodeGenerator` | 컨테이너 요소 JvmNode 생성 인터페이스 | -| `JavaArrayElementNodeGenerator` | 배열 요소 | -| `JavaLinearContainerElementNodeGenerator` | List, Set 요소 | -| `JavaMapElementNodeGenerator` | Map entry | -| `JavaSingleElementContainerNodeGenerator` | Supplier, Optional (투명 래퍼) | - -## nodecandidate/ (NodeCandidate 생성) - -상세 내용은 [adapter-classes.md](./adapter-classes.md#nodecandidate) 참조. - -### Core - -| 클래스 | 역할 | -|--------|------| -| `JvmNodeCandidate` | promote 전 타입 메타데이터를 보유하는 중간 표현 인터페이스 | -| `JvmNodeCandidateGenerator` | JVM 타입으로부터 NodeCandidate를 생성하는 루트 인터페이스 | -| `CreationMethod` | 프로퍼티 생성/설정 방식 메타데이터 인터페이스 | - -### NodeCandidate 구현체 - -`JavaNodeCandidate`, `JavaMapNodeCandidate`, `JvmMapNodeCandidate`, `JvmMapEntryNodeCandidate` - -### CreationMethod 구현체 - -`ConstructorParamCreationMethod`, `FieldAccessCreationMethod`, `MethodInvocationCreationMethod`, `ContainerElementCreationMethod` - -### Generator - -`JvmGenericNodeCandidateGenerator`, `JvmInterfaceNodeCandidateGenerator`, `JavaFieldNodeCandidateGenerator`, `DefaultGenericNodeCandidateGenerator`, `DefaultInterfaceNodeCandidateGenerator` - -### Factory + 옵션 - -`JvmNodeCandidateFactory`, `JavaNodeCandidateFactory`, `JavaRecordNodeCandidateGenerator` (Java 17 MR JAR), `ObjectFarmJdkVariantOptions` - -## tree/ (트리 구조 + 변환) - -| 클래스 | 역할 | -|--------|------| -| `JvmNodeCandidateTree` | 타입 구조 트리 (캐시됨, 값 생성 전 구조) | -| `JvmNodeCandidateTreeContext` | CandidateTree 생성 및 서브트리 캐싱 컨텍스트 | -| `JvmNodeTree` | 실제 노드 트리 (값 생성에 사용) | -| `JvmNodeTreeTransformer` | CandidateTree → NodeTree 변환, 컨테이너 확장 | -| `ExpansionContext` | 재귀 노드 확장 제어 (사용자 정의 경로 기반 순환 확장 결정) | -| `JvmNodeSubtreeContext` | JvmNode 서브트리 스냅샷 캐시 (타입별, ConcurrentHashMap) | -| `PathResolver` | PathExpression + NodeCustomizer를 결합하는 경로 기반 해석 인터페이스 | -| `PathResolverContext` | 경로 기반 resolver 통합 관리 (컨테이너 크기, 인터페이스, 제네릭) | -| `PathContainerSizeResolver` | 특정 경로의 컨테이너 크기 결정 | -| `PathInterfaceResolver` | 특정 경로의 인터페이스 → 구체 구현체 결정 | -| `PathGenericTypeResolver` | 특정 경로의 제네릭 타입 해석 | -| `ResolutionListener` / `NoOpResolutionListener` | 트리 변환 중 해석 결정사항 추적 리스너 | - -## input/ (값 분석 + 타입 파싱) - -### 값 추출 + 분석 - -| 클래스 | 역할 | -|--------|------| -| `ObjectValueExtractor` | 재귀적 객체 그래프 → path→value flat map 생성 | -| `FieldExtractor` | 1-level POJO 필드 추출 인터페이스 | -| `ContainerDetector` | 컨테이너 타입 판별 + 크기 조회 인터페이스 | -| `ValueAnalyzer` | 객체 그래프에서 경로별 값, 타입 해석기, 컨테이너 크기 정보 추출 | -| `ValueAnalysisResult` | 값 분석 결과 불변 객체 | - -### Resolver 변환기 - -| 클래스 | 역할 | -|--------|------| -| `InterfaceResolverConverter` | 값 정보 → 인터페이스 경로 기반 해석기 변환 | -| `GenericTypeResolverConverter` | 값/타입 정보 → 제네릭 타입 해석기 변환 | - -### 타입 파싱 - -| 클래스 | 역할 | -|--------|------| -| `TypeInputParser` | 다양한 입력 형식을 JvmType으로 파싱하는 인터페이스 | -| `TypeInputParserRegistry` | TypeInputParser 등록/관리, 입력 타입에 따라 파서 자동 선택 | -| `TypeParseContext` | 타입 별칭, ClassLoader, strict 모드 등 파싱 컨텍스트 | -| `TypeParseException` | 파싱 실패 예외 | -| `JavaTypeInputParser` | JvmType, Class, Type 등 네이티브 Java 타입 파싱 | -| `JsonSchemaInputParser` | JSON Schema → JvmType 파싱 | -| `TypeScriptInputParser` | TypeScript 유사 문법 → JvmType 파싱 | - -### Synthetic 타입 - -| 클래스 | 역할 | -|--------|------| -| `SyntheticJvmType` | 스키마 정의 타입을 JvmType 인프라에 통합 | -| `SyntheticMember` | SyntheticJvmType의 멤버(필드) | -| `SyntheticMemberCreationMethod` | 스키마 정의 타입 멤버의 CreationMethod | -| `SyntheticNodeCandidateGenerator` | SyntheticJvmType → JvmNodeCandidate 변환 | - -## output/ (트리 출력 포맷터) - -| 클래스 | 역할 | -|--------|------| -| `TreeOutputFormatter` | 트리 출력 포맷터 인터페이스 | -| `TreeOutputFormatterRegistry` | 포맷터 등록/관리 | -| `OutputFormat` | 출력 형식 enum (MARKDOWN, JSON, PROMPT_OPTIMIZED) | -| `MarkdownTreeFormatter` | Markdown 형식 트리 출력 | -| `JsonTreeFormatter` | JSON 형식 트리 출력 | -| `PromptOptimizedFormatter` | LLM 프롬프트 최적화 형식 출력 | -| `FormatOptions` | 출력 옵션 (depth 제한 등) | - -## projection/ (노드 프로젝션) - -| 클래스 | 역할 | -|--------|------| -| `NodeProjection` | 노드에 값을 매핑하는 읽기 전용 뷰 인터페이스 (get, getByPath, forEach, filter) | - -## 테스트 - -``` -object-farm-api/src/test/java/com/navercorp/objectfarm/api/ -├── input/ ObjectValueExtractorTest, TypeInputParserRegistryTest, TypeScriptInputParserTest, ValueAnalyzerTest -├── node/ JavaNodePromoterTest, JavaNodeTest, specs/ (GenericObject, ImmutableObject, InterfaceSpecs) -├── tree/ JvmNodeCandidateTreeTest, JvmNodeTreeTest, JvmNodeTreeResolveTest, -│ JvmNodeTreeTransformerTest, NestedContainerTreeTest, PathResolverContextTest, -│ PathResolverIntegrationTest -└── output/ TreeOutputFormatterTest -``` - -## 빌드 및 테스트 - -```bash -# 전체 테스트 -./gradlew clean :object-farm-api:test - -# 특정 패키지 테스트 -./gradlew clean :object-farm-api:test --tests "com.navercorp.objectfarm.api.tree.*" -./gradlew clean :object-farm-api:test --tests "com.navercorp.objectfarm.api.input.*" -./gradlew clean :object-farm-api:test --tests "com.navercorp.objectfarm.api.node.*" -``` diff --git a/.gitignore b/.gitignore index 799ae33ab7..e56853f7a3 100644 --- a/.gitignore +++ b/.gitignore @@ -35,6 +35,7 @@ architecture/ plans/ .serena/ .zed/ +.claude/ .java-version object-farm-api/docs/ article/ diff --git a/.claude/CLAUDE.md b/CLAUDE.md similarity index 100% rename from .claude/CLAUDE.md rename to CLAUDE.md diff --git a/breaking-changes/README.md b/breaking-changes/README.md new file mode 100644 index 0000000000..fcb4a15d1a --- /dev/null +++ b/breaking-changes/README.md @@ -0,0 +1,92 @@ +# Breaking Changes — 1.1.21 + +브랜치 `sa/remove-node-tree`가 릴리스되는 버전 **1.1.21**부터 발생하는 사용자 영향 항목입니다. (브랜치 base: `main` @ `2ca0eff91`.) + +대부분의 일반 사용자(`FixtureMonkey.builder()` + `giveMeBuilder()` + `.set(...)` / `.size(...)` / `.sample()` 패턴)는 영향을 받지 않습니다. 아래는 **확장 지점을 직접 구현**했거나 **내부 타입을 import**해서 쓰던 사용자에게 영향이 가는 것들입니다. + +## 영향도 높음 — Custom Introspector 작성자 + +이 변경은 `ArbitraryIntrospector`(예: `BeanArbitraryIntrospector`, `ConstructorPropertiesArbitraryIntrospector` 등을 흉내 낸 사용자 구현)를 직접 작성한 모든 사람에게 영향을 줍니다. 가장 흔히 쓰는 확장 지점입니다. + +### `ArbitraryGeneratorContext` 반환 타입 변경 — **1.1.21부터** + +`com.navercorp.fixturemonkey.api.generator.ArbitraryGeneratorContext` (since `0.4.0`, MAINTAINED) + +```diff +- public AnnotatedType getResolvedAnnotatedType() // 삭제 +- public Type getResolvedType() // 반환 타입 변경 ++ public Class getResolvedType() ++ public JvmType getResolvedJvmType() // 신규 +``` + +- `getResolvedAnnotatedType()`는 삭제됐습니다. 대안: `context.getResolvedProperty().getAnnotatedType()`. +- `getResolvedType()`의 반환 타입이 `java.lang.reflect.Type` → `Class`로 좁아졌습니다. `Type` 변수에 받던 코드는 컴파일 유지되지만, 제네릭/배열 등 `Class`로 표현 불가한 경우를 다뤘다면 동작이 달라집니다. + +### Map iteration 순서 변경 — **1.1.21부터** + +`getCombinableArbitrariesByArbitraryProperty()` / `getCombinableArbitrariesByResolvedName()` / `getCombinableArbitrariesByPropertyName()` 가 `LinkedHashMap`을 반환하도록 바뀌었습니다(이전엔 `HashMap`). 선언 타입은 `Map`이라 컴파일 영향은 없지만, **iteration 순서에 의존하는 random stream**(예: 같은 seed에서 같은 결과를 기대하는 회귀 테스트)이 깨질 수 있습니다. + +## 영향도 중간 — `JvmType` / `JavaType` 직접 사용자 + +이 변경은 object-farm-api의 타입 객체를 직접 만들거나 `getAnnotatedType()`을 호출하는 코드에 영향을 줍니다 (custom property/plugin 구현체). + +### `JvmType#getAnnotatedType()` 삭제 — **1.1.21부터** + +`com.navercorp.objectfarm.api.type.JvmType` 인터페이스 + +```diff +- @Deprecated +- default AnnotatedType getAnnotatedType() // 삭제 (이전부터 @Deprecated) +``` + +대안: `jvmType.getRawType()` + `jvmType.getAnnotations()` 조합으로 대체. 이미 `@Deprecated`였으므로 미리 마이그레이션해둔 코드는 영향 없음. + +### `JavaType` 생성자 변경 — **1.1.21부터** + +`com.navercorp.objectfarm.api.type.JavaType` + +```diff +- @Deprecated +- public JavaType(Class, List, List, @Nullable AnnotatedType) ++ public JavaType(Class, List, List, @Nullable AnnotatedType, @Nullable Boolean nullable) ++ public JavaType(Class, List, List, @Nullable Boolean nullable) +- @Override public AnnotatedType getAnnotatedType() // 삭제 (@Deprecated였음) ++ public Boolean getNullable() // 신규 +``` + +- 4-arg 생성자(`@Deprecated`였음) 삭제 — `nullable` 인자를 추가해 새 5-arg 시그니처로 옮기거나, `AnnotatedType` 없이 4-arg 새 생성자를 사용해야 합니다. +- `typeVariables` 파라미터 타입이 `List` → `List`로 완화됐습니다. 대부분 호환이지만 `List`를 넘기던 코드는 안 됩니다. + +## 영향도 낮음 — Plugin / NodeTreeAdapter 직접 구현자 + +`@API(since = "1.1.17", status = EXPERIMENTAL)` 였던 어댑터 브릿지 SPI. **1.1.17 ~ 1.1.20**에 도입돼 잠깐 노출됐던 클래스로, 정식 사용을 안내한 적이 없습니다. 1.1.17~1.1.20 구간에 이 SPI를 따라 만든 코드가 있다면 1.1.21에서 깨집니다. + +| 삭제된 클래스 | 도입 | 삭제 | +|--------------|------|------| +| `c.n.f.adapter.NodeTreeAdapter` | 1.1.17 | 1.1.21 | +| `c.n.f.adapter.DefaultNodeTreeAdapter` | 1.1.17 | 1.1.21 | +| `c.n.f.adapter.JavaNodeTreeAdapterPlugin` | 1.1.17 | 1.1.21 | +| `c.n.f.kotlin.KotlinNodeTreeAdapterPlugin` (Kotlin) | 1.1.17 | 1.1.21 | + +이들은 `c.n.f.planner.AssemblyPlanner` + `c.n.f.plugin.JvmTypeSystemPlugin`으로 대체됐습니다. 일반 사용자는 `FixtureMonkeyBuilder`만 쓰면 자동으로 새 구조를 받습니다. + +## 영향 없음 (참고) + +다음은 코드상 사라졌지만 일반 사용자가 직접 쓸 일이 거의 없는 내부 머신러리라 사용자 영향이 사실상 없습니다. 자세한 내용이 필요하면 git diff로 확인하세요. + +- **`c.n.f.tree.*` 전체 삭제** (`NodeResolver`, `StartNodePredicate`, `NodeKeyPredicate`, `ObjectNode` 등 — since 0.4.0 MAINTAINED): 모두 expression(`.set("a.b.c", ...)`) 내부 구현. 사용자는 문자열 path를 쓰지 `NodeResolver`를 직접 만들지 않습니다. +- **`c.n.f.customizer` 매니퓰레이터 패밀리 삭제** (`ArbitraryManipulator`, `NodeSetJustManipulator`, `ContainerInfoManipulator` 등 — since 0.4.0 MAINTAINED): `ArbitraryBuilder.set/setLazy/setNull/size`의 내부 표현. 사용자는 builder 메서드만 호출합니다. +- **`c.n.f.expression.MonkeyExpression` / `MonkeyExpressionFactory` 삭제** (MAINTAINED since 0.4.0): `useExpressionStrictMode()`로 strict 모드를 켜는 사용자는 그대로 동작합니다 (strict 검증이 `StrictModeSizeValidator`로 이동). `MonkeyExpressionFactory`를 **직접 구현해서 주입**한 사용자만 영향. +- **`c.n.f.api.tree.*` 전체 삭제** (모두 EXPERIMENTAL): API 모듈의 traverse 골격. + +## Migration cheat sheet + +확장 지점을 구현 중인 경우 자주 쓰는 매핑: + +| 1.1.20 이하 | 1.1.21+ | +|------------|---------| +| `ArbitraryGeneratorContext.getResolvedAnnotatedType()` | `getResolvedProperty().getAnnotatedType()` | +| `ArbitraryGeneratorContext.getResolvedType()` (`Type`) | `getResolvedType()` (`Class`) 또는 `getResolvedJvmType()` | +| `JvmType.getAnnotatedType()` | `getRawType()` + `getAnnotations()` | +| `c.n.f.adapter.tracing.AdapterTracer` | `c.n.f.tracing.AssemblyTracer` | +| `c.n.f.adapter.NodeTreeAdapter` | `c.n.f.planner.AssemblyPlanner` (자동 주입) | diff --git a/build.gradle.kts b/build.gradle.kts index 9fe10fb39d..0751e8f16a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -56,7 +56,7 @@ subprojects { if (!name.endsWith("tests")) { tasks.withType { useJUnitPlatform { - includeEngines("jqwik") + includeEngines("jqwik", "junit-jupiter") } } } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/arbitrary/FilteredCombinableArbitrary.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/arbitrary/FilteredCombinableArbitrary.java index 5121cafb15..914eae9365 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/arbitrary/FilteredCombinableArbitrary.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/arbitrary/FilteredCombinableArbitrary.java @@ -93,10 +93,23 @@ public T combined() { String failedConcatProperties = String.join(", ", ((ValidationFailedException)lastException).getConstraintViolationPropertyNames()); - throw new RetryableFilterMissException( - String.format("Given properties \"%s\" is not validated by annotations.", failedConcatProperties), - lastException - ); + String message; + if (combinableArbitrary instanceof Traceable) { + PropertyPath propertyPath = ((Traceable)combinableArbitrary).getPropertyPath(); + String generateType = propertyPath.getProperty().getJvmType().getRawType().getTypeName(); + message = String.format( + "Generate type \"%s\" is failed due to property \"%s\" - not validated by annotations.", + generateType, + failedConcatProperties + ); + } else { + message = String.format( + "Given properties \"%s\" is not validated by annotations.", + failedConcatProperties + ); + } + + throw new RetryableFilterMissException(message, lastException); } if (lastException != null) { @@ -105,7 +118,7 @@ public T combined() { if (combinableArbitrary instanceof Traceable) { PropertyPath propertyPath = ((Traceable)combinableArbitrary).getPropertyPath(); - String generateType = propertyPath.getProperty().getType().getTypeName(); + String generateType = propertyPath.getProperty().getJvmType().getRawType().getTypeName(); String expression = "".equals(propertyPath.getExpression()) ? "$" : propertyPath.getExpression(); @@ -160,10 +173,23 @@ public T rawValue() { String failedConcatProperties = String.join(", ", ((ValidationFailedException)lastException).getConstraintViolationPropertyNames()); - throw new RetryableFilterMissException( - String.format("Given properties \"%s\" is not validated by annotations.", failedConcatProperties), - lastException - ); + String message; + if (combinableArbitrary instanceof Traceable) { + PropertyPath propertyPath = ((Traceable)combinableArbitrary).getPropertyPath(); + String generateType = propertyPath.getProperty().getJvmType().getRawType().getTypeName(); + message = String.format( + "Generate type \"%s\" is failed due to property \"%s\" - not validated by annotations.", + generateType, + failedConcatProperties + ); + } else { + message = String.format( + "Given properties \"%s\" is not validated by annotations.", + failedConcatProperties + ); + } + + throw new RetryableFilterMissException(message, lastException); } if (lastException != null) { @@ -172,7 +198,7 @@ public T rawValue() { if (combinableArbitrary instanceof Traceable) { PropertyPath propertyPath = ((Traceable)combinableArbitrary).getPropertyPath(); - String generateType = propertyPath.getProperty().getType().getTypeName(); + String generateType = propertyPath.getProperty().getJvmType().getRawType().getTypeName(); String expression = "".equals(propertyPath.getExpression()) ? "$" : propertyPath.getExpression(); diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/arbitrary/ObjectCombinableArbitrary.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/arbitrary/ObjectCombinableArbitrary.java index 9f6521fbbf..796e095911 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/arbitrary/ObjectCombinableArbitrary.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/arbitrary/ObjectCombinableArbitrary.java @@ -18,7 +18,7 @@ package com.navercorp.fixturemonkey.api.arbitrary; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import java.util.function.Function; @@ -46,7 +46,11 @@ final class ObjectCombinableArbitrary implements CombinableArbitrary { @SuppressWarnings("argument") @Override public T combined() { - Map combinedPropertyValuesByArbitraryProperty = new HashMap<>(); + // Preserve property order from the upstream LinkedHashMap so combinators that fall back + // to index-based parameter mapping (e.g. KotlinConstructorArbitraryIntrospector when a + // constructor parameter is aliased via instantiateBy) see values in declaration order + // rather than HashMap's arbitrary order. + Map combinedPropertyValuesByArbitraryProperty = new LinkedHashMap<>(); combinableArbitrariesByArbitraryProperty.forEach( (key, value) -> combinedPropertyValuesByArbitraryProperty.put(key, value.combined()) @@ -58,7 +62,7 @@ public T combined() { @SuppressWarnings({"return", "argument"}) @Override public Object rawValue() { - Map rawPropertyValuesByArbitraryProperty = new HashMap<>(); + Map rawPropertyValuesByArbitraryProperty = new LinkedHashMap<>(); combinableArbitrariesByArbitraryProperty.forEach( (key, value) -> rawPropertyValuesByArbitraryProperty.put(key, value.rawValue()) diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/arbitrary/ObjectCombineArbitraryBuilder.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/arbitrary/ObjectCombineArbitraryBuilder.java index 39eaf9a269..0e8146b324 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/arbitrary/ObjectCombineArbitraryBuilder.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/arbitrary/ObjectCombineArbitraryBuilder.java @@ -18,7 +18,7 @@ package com.navercorp.fixturemonkey.api.arbitrary; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import java.util.function.Function; @@ -32,7 +32,11 @@ public final class ObjectCombineArbitraryBuilder { private final Map> arbitraryListByArbitraryProperty; ObjectCombineArbitraryBuilder() { - this.arbitraryListByArbitraryProperty = new HashMap<>(); + // Preserve insertion order so combinators that walk the value map by position (e.g. + // KotlinConstructorArbitraryIntrospector when a constructor parameter is aliased and + // name-based matching misses) see values in declaration order rather than HashMap's + // bucket-driven order — otherwise values land on the wrong constructor parameter. + this.arbitraryListByArbitraryProperty = new LinkedHashMap<>(); } public ObjectCombineArbitraryBuilder property(ArbitraryProperty property, CombinableArbitrary arbitrary) { diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/context/MonkeyContext.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/context/MonkeyContext.java index 5b3fd5551f..bedee5a625 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/context/MonkeyContext.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/context/MonkeyContext.java @@ -34,7 +34,6 @@ import com.navercorp.fixturemonkey.api.option.FixtureMonkeyOptions; import com.navercorp.fixturemonkey.api.property.Property; import com.navercorp.fixturemonkey.api.property.TreeRootProperty; -import com.navercorp.fixturemonkey.api.type.Types; /** * {@code FixtureMonkey} → {@code ArbitraryBuilder} → {@code ObjectTree} → {@link CombinableArbitrary} @@ -79,7 +78,7 @@ public static MonkeyContextBuilder builder(FixtureMonkeyOptions fixtureMonkeyOpt } public void putCachedArbitrary(Property property, CombinableArbitrary combinableArbitrary) { - Class type = Types.getActualType(property.getType()); + Class type = property.getJvmType().getRawType(); if (isJavaType(type)) { javaArbitrariesByProperty.putIfAbsent(property, combinableArbitrary); return; diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ArbitraryGeneratorContext.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ArbitraryGeneratorContext.java index 2327757fea..0818524f31 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ArbitraryGeneratorContext.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ArbitraryGeneratorContext.java @@ -22,7 +22,6 @@ import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; @@ -43,6 +42,8 @@ import com.navercorp.fixturemonkey.api.property.Property; import com.navercorp.fixturemonkey.api.property.PropertyPath; import com.navercorp.fixturemonkey.api.property.Traceable; +import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.objectfarm.api.type.JvmType; @API(since = "0.4.0", status = Status.MAINTAINED) public final class ArbitraryGeneratorContext implements Traceable { @@ -95,12 +96,24 @@ public Property getResolvedProperty() { return this.resolvedProperty; } + public JvmType getResolvedJvmType() { + return this.getResolvedProperty().getJvmType(); + } + + /** + * @deprecated Use {@link #getResolvedJvmType()} instead. + */ + @Deprecated public AnnotatedType getResolvedAnnotatedType() { - return this.getResolvedProperty().getAnnotatedType(); + return Types.toAnnotatedType(this.getResolvedProperty().getJvmType()); } - public Type getResolvedType() { - return this.getResolvedProperty().getType(); + /** + * @deprecated Use {@link #getResolvedJvmType()} instead. + */ + @Deprecated + public Class getResolvedType() { + return this.getResolvedProperty().getJvmType().getRawType(); } public Optional findAnnotation(Class annotationClass) { @@ -116,19 +129,33 @@ public double getNullInject() { } public Map> getCombinableArbitrariesByArbitraryProperty() { - return arbitraryListByArbitraryProperty.getValue().entrySet().stream() - .collect(toMap(Entry::getKey, Entry::getValue)); + // Preserve declaration order so downstream introspectors (e.g. KotlinConstructorArbitraryIntrospector + // fallback that walks values by position, BeanArbitraryIntrospector relaying into + // ObjectCombineArbitraryBuilder) + // see children in the same order they were registered. Collectors.toMap defaults to HashMap, which would + // surface entries in hash-bucket order and shift the random stream. + return new LinkedHashMap<>(arbitraryListByArbitraryProperty.getValue()); } public Map> getCombinableArbitrariesByResolvedName() { return arbitraryListByArbitraryProperty.getValue().entrySet().stream() - .collect(toMap(it -> it.getKey().getObjectProperty().getResolvedPropertyName(), Entry::getValue)); + .collect(toMap( + it -> it.getKey().getObjectProperty().getResolvedPropertyName(), + Entry::getValue, + (existing, replacement) -> existing, + LinkedHashMap::new + )); } @SuppressWarnings("return") public Map> getCombinableArbitrariesByPropertyName() { return arbitraryListByArbitraryProperty.getValue().entrySet().stream() - .collect(toMap(it -> it.getKey().getObjectProperty().getProperty().getName(), Entry::getValue)); + .collect(toMap( + it -> it.getKey().getObjectProperty().getProperty().getName(), + Entry::getValue, + (existing, replacement) -> existing, + LinkedHashMap::new + )); } public List> getElementCombinableArbitraryList() { diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ArrayContainerPropertyGenerator.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ArrayContainerPropertyGenerator.java index 7cb15b5445..4d7313bf16 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ArrayContainerPropertyGenerator.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ArrayContainerPropertyGenerator.java @@ -18,7 +18,6 @@ package com.navercorp.fixturemonkey.api.generator; -import java.lang.reflect.AnnotatedType; import java.util.ArrayList; import java.util.List; @@ -28,7 +27,8 @@ import com.navercorp.fixturemonkey.api.property.DefaultContainerElementProperty; import com.navercorp.fixturemonkey.api.property.Property; import com.navercorp.fixturemonkey.api.property.TypeParameterProperty; -import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.objectfarm.api.type.JavaType; +import com.navercorp.objectfarm.api.type.JvmType; @API(since = "0.4.0", status = Status.MAINTAINED) public final class ArrayContainerPropertyGenerator implements ContainerPropertyGenerator { @@ -42,7 +42,7 @@ public ContainerProperty generate(ContainerPropertyGeneratorContext context) { ArbitraryContainerInfo containerInfo = context.getContainerInfo(); int size = containerInfo.getRandomSize(); - AnnotatedType elementType = Types.getArrayComponentAnnotatedType(property.getAnnotatedType()); + JvmType elementType = resolveArrayElementType(property.getJvmType()); List childProperties = new ArrayList<>(); for (int sequence = 0; sequence < size; sequence++) { childProperties.add( @@ -60,4 +60,16 @@ public ContainerProperty generate(ContainerPropertyGeneratorContext context) { containerInfo ); } + + private static JvmType resolveArrayElementType(JvmType arrayType) { + JvmType componentType = arrayType.getComponentType(); + if (componentType != null) { + return componentType; + } + Class rawType = arrayType.getRawType(); + if (rawType.isArray()) { + return new JavaType(rawType.getComponentType()); + } + throw new IllegalArgumentException("given type is not an array type: " + arrayType); + } } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ContainerPropertyGenerator.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ContainerPropertyGenerator.java index 925db58037..a44ea28c54 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ContainerPropertyGenerator.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ContainerPropertyGenerator.java @@ -21,14 +21,13 @@ import org.apiguardian.api.API; import org.apiguardian.api.API.Status; -import com.navercorp.fixturemonkey.api.type.TypeReference; +import com.navercorp.objectfarm.api.type.JavaType; +import com.navercorp.objectfarm.api.type.JvmType; @API(since = "0.4.0", status = Status.MAINTAINED) @FunctionalInterface public interface ContainerPropertyGenerator { - TypeReference DEFAULT_ELEMENT_RAW_TYPE = - new TypeReference() { - }; + JvmType DEFAULT_ELEMENT_JVM_TYPE = new JavaType(String.class); ContainerProperty generate(ContainerPropertyGeneratorContext context); } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/DefaultNullInjectGenerator.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/DefaultNullInjectGenerator.java index f1004e3c69..556246c333 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/DefaultNullInjectGenerator.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/DefaultNullInjectGenerator.java @@ -29,7 +29,6 @@ import org.apiguardian.api.API; import org.apiguardian.api.API.Status; -import com.navercorp.fixturemonkey.api.type.Types; @API(since = "0.4.0", status = Status.MAINTAINED) public final class DefaultNullInjectGenerator implements NullInjectGenerator { @@ -120,7 +119,7 @@ public double generate(ObjectPropertyGeneratorContext context) { return NOT_NULL_INJECT; } - if (Types.getActualType(context.getProperty().getType()).isPrimitive()) { + if (context.getProperty().getJvmType().getRawType().isPrimitive()) { return NOT_NULL_INJECT; } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/DefaultSingleContainerPropertyGenerator.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/DefaultSingleContainerPropertyGenerator.java index 438707e8f5..7089142dd8 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/DefaultSingleContainerPropertyGenerator.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/DefaultSingleContainerPropertyGenerator.java @@ -18,7 +18,6 @@ package com.navercorp.fixturemonkey.api.generator; -import java.lang.reflect.AnnotatedType; import java.util.ArrayList; import java.util.List; @@ -28,7 +27,7 @@ import com.navercorp.fixturemonkey.api.property.DefaultContainerElementProperty; import com.navercorp.fixturemonkey.api.property.Property; import com.navercorp.fixturemonkey.api.property.TypeParameterProperty; -import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.objectfarm.api.type.JvmType; @API(since = "0.4.3", status = Status.MAINTAINED) public final class DefaultSingleContainerPropertyGenerator implements ContainerPropertyGenerator { @@ -39,12 +38,12 @@ public final class DefaultSingleContainerPropertyGenerator implements ContainerP public ContainerProperty generate(ContainerPropertyGeneratorContext context) { Property property = context.getProperty(); - List elementTypes = Types.getGenericsTypes(property.getAnnotatedType()); + List elementTypes = property.getJvmType().getTypeVariables(); if (elementTypes.size() > 1) { throw new IllegalArgumentException( "Container elementsTypes support 1 generics type. " + "You should be custom ContainerPropertyGenerator for N generics container type. " - + "propertyType: " + property.getType() + + "propertyType: " + property.getJvmType().getRawType() + ", elementTypes: " + elementTypes ); } @@ -55,8 +54,8 @@ public ContainerProperty generate(ContainerPropertyGeneratorContext context) { List childProperties = new ArrayList<>(); for (int sequence = 0; sequence < size; sequence++) { Integer elementIndex = sequence; - AnnotatedType elementType = elementTypes.isEmpty() - ? DEFAULT_ELEMENT_RAW_TYPE.getAnnotatedType() + JvmType elementType = elementTypes.isEmpty() + ? DEFAULT_ELEMENT_JVM_TYPE : elementTypes.get(0); childProperties.add( diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/EntryContainerPropertyGenerator.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/EntryContainerPropertyGenerator.java index 717c96b544..ded2b8eed5 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/EntryContainerPropertyGenerator.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/EntryContainerPropertyGenerator.java @@ -18,7 +18,6 @@ package com.navercorp.fixturemonkey.api.generator; -import java.lang.reflect.AnnotatedType; import java.util.ArrayList; import java.util.List; @@ -30,7 +29,7 @@ import com.navercorp.fixturemonkey.api.property.MapValueElementProperty; import com.navercorp.fixturemonkey.api.property.Property; import com.navercorp.fixturemonkey.api.property.TypeParameterProperty; -import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.objectfarm.api.type.JvmType; @API(since = "0.4.0", status = Status.MAINTAINED) public final class EntryContainerPropertyGenerator implements ContainerPropertyGenerator { @@ -42,17 +41,17 @@ public final class EntryContainerPropertyGenerator implements ContainerPropertyG public ContainerProperty generate(ContainerPropertyGeneratorContext context) { Property property = context.getProperty(); - List genericsTypes = Types.getGenericsTypes(property.getAnnotatedType()); - if (genericsTypes.size() != 2) { + List typeVariables = property.getJvmType().getTypeVariables(); + if (typeVariables.size() != 2) { throw new IllegalArgumentException( "Entry genericsTypes must be have 2 generics type for key and value. " - + "propertyType: " + property.getType() - + ", genericsTypes: " + genericsTypes + + "propertyType: " + property.getJvmType().getRawType() + + ", typeVariables: " + typeVariables ); } - AnnotatedType keyType = genericsTypes.get(0); - AnnotatedType valueType = genericsTypes.get(1); + JvmType keyType = typeVariables.get(0); + JvmType valueType = typeVariables.get(1); List childProperties = new ArrayList<>(); childProperties.add( diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/FunctionalInterfaceContainerPropertyGenerator.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/FunctionalInterfaceContainerPropertyGenerator.java index 8e46f86922..87541e526d 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/FunctionalInterfaceContainerPropertyGenerator.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/FunctionalInterfaceContainerPropertyGenerator.java @@ -18,7 +18,6 @@ package com.navercorp.fixturemonkey.api.generator; -import java.lang.reflect.AnnotatedType; import java.util.Collections; import java.util.List; @@ -27,9 +26,9 @@ import com.navercorp.fixturemonkey.api.property.Property; import com.navercorp.fixturemonkey.api.property.SingleElementProperty; import com.navercorp.fixturemonkey.api.property.TypeParameterProperty; -import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.objectfarm.api.type.JvmType; -@API(since = "1.0.21", status = API.Status.EXPERIMENTAL) +@API(since = "1.0.21", status = API.Status.MAINTAINED) public final class FunctionalInterfaceContainerPropertyGenerator implements ContainerPropertyGenerator { public static final FunctionalInterfaceContainerPropertyGenerator INSTANCE = new FunctionalInterfaceContainerPropertyGenerator(); @@ -40,10 +39,10 @@ public final class FunctionalInterfaceContainerPropertyGenerator implements Cont public ContainerProperty generate(ContainerPropertyGeneratorContext context) { Property property = context.getProperty(); - AnnotatedType lambdaReturnAnnotatedType = getLambdaReturnAnnotatedType(property); + JvmType lambdaReturnJvmType = getLambdaReturnJvmType(property); SingleElementProperty singleElementProperty = - new SingleElementProperty(property, new TypeParameterProperty(lambdaReturnAnnotatedType)); + new SingleElementProperty(property, new TypeParameterProperty(lambdaReturnJvmType)); return new ContainerProperty( Collections.singletonList(singleElementProperty), @@ -51,8 +50,8 @@ public ContainerProperty generate(ContainerPropertyGeneratorContext context) { ); } - private AnnotatedType getLambdaReturnAnnotatedType(Property lambdaProperty) { - List genericsTypes = Types.getGenericsTypes(lambdaProperty.getAnnotatedType()); - return genericsTypes.get(genericsTypes.size() - 1); + private JvmType getLambdaReturnJvmType(Property lambdaProperty) { + List typeVariables = lambdaProperty.getJvmType().getTypeVariables(); + return typeVariables.get(typeVariables.size() - 1); } } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/MapContainerPropertyGenerator.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/MapContainerPropertyGenerator.java index ccd52f16d7..f38544837e 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/MapContainerPropertyGenerator.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/MapContainerPropertyGenerator.java @@ -18,8 +18,8 @@ package com.navercorp.fixturemonkey.api.generator; -import java.lang.reflect.AnnotatedType; import java.util.ArrayList; +import java.util.Collections; import java.util.EnumSet; import java.util.List; @@ -33,7 +33,7 @@ import com.navercorp.fixturemonkey.api.property.MapValueElementProperty; import com.navercorp.fixturemonkey.api.property.Property; import com.navercorp.fixturemonkey.api.property.TypeParameterProperty; -import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.objectfarm.api.type.JvmType; @API(since = "0.4.0", status = Status.MAINTAINED) public final class MapContainerPropertyGenerator implements ContainerPropertyGenerator { @@ -46,12 +46,10 @@ public final class MapContainerPropertyGenerator implements ContainerPropertyGen public ContainerProperty generate(ContainerPropertyGeneratorContext context) { Property property = context.getProperty(); - List genericsTypes = Types.getGenericsTypes(property.getAnnotatedType()); - AnnotatedType keyType = - !genericsTypes.isEmpty() ? genericsTypes.get(0) : DEFAULT_ELEMENT_RAW_TYPE.getAnnotatedType(); - AnnotatedType valueType = - genericsTypes.size() > 1 ? genericsTypes.get(1) : DEFAULT_ELEMENT_RAW_TYPE.getAnnotatedType(); - Class actualKeyType = Types.getActualType(keyType); + List typeVariables = property.getJvmType().getTypeVariables(); + JvmType keyType = !typeVariables.isEmpty() ? typeVariables.get(0) : DEFAULT_ELEMENT_JVM_TYPE; + JvmType valueType = typeVariables.size() > 1 ? typeVariables.get(1) : DEFAULT_ELEMENT_JVM_TYPE; + Class actualKeyType = keyType.getRawType(); ArbitraryContainerInfo containerInfo = context.getContainerInfo(); if (actualKeyType.isEnum()) { @@ -87,7 +85,7 @@ public ContainerProperty generate(ContainerPropertyGeneratorContext context) { } return new ContainerProperty( - childProperties, + Collections.unmodifiableList(childProperties), containerInfo ); } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/MatchPropertyGenerator.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/MatchPropertyGenerator.java index d48babce51..fbc44a6b3f 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/MatchPropertyGenerator.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/MatchPropertyGenerator.java @@ -53,6 +53,7 @@ public List generateChildProperties(Property property) { } } - throw new IllegalArgumentException("Type " + property.getType() + " has no matching PropertyGenerator."); + throw new IllegalArgumentException( + "Type " + property.getJvmType().getRawType() + " has no matching PropertyGenerator."); } } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/NoArgumentInterfaceJavaMethodPropertyGenerator.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/NoArgumentInterfaceJavaMethodPropertyGenerator.java index 00134204e1..f9600eab61 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/NoArgumentInterfaceJavaMethodPropertyGenerator.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/NoArgumentInterfaceJavaMethodPropertyGenerator.java @@ -34,7 +34,7 @@ import com.navercorp.fixturemonkey.api.property.Property; import com.navercorp.fixturemonkey.api.property.PropertyGenerator; import com.navercorp.fixturemonkey.api.type.TypeCache; -import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.objectfarm.api.type.JvmTypes; /** * A property generator for generating no-argument Java interface method. @@ -44,7 +44,7 @@ public final class NoArgumentInterfaceJavaMethodPropertyGenerator implements PropertyGenerator { @Override public List generateChildProperties(Property property) { - Class actualType = Types.getActualType(property.getType()); + Class actualType = property.getJvmType().getRawType(); Map propertyNamesByGetter = TypeCache.getPropertyDescriptorsByPropertyName(actualType).values().stream() .collect( @@ -57,7 +57,11 @@ public List generateChildProperties(Property property) { return Arrays.stream(actualType.getMethods()) .filter(it -> it.getParameters().length == 0) .map(it -> new InterfaceJavaMethodProperty( - it.getAnnotatedReturnType(), + JvmTypes.resolveJvmType( + property.getJvmType(), + it.getGenericReturnType(), + Arrays.asList(it.getAnnotations()) + ), propertyNamesByGetter.getOrDefault(it, it.getName()), it.getName(), Arrays.asList(it.getAnnotations()) diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/OptionalContainerPropertyGenerator.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/OptionalContainerPropertyGenerator.java index 1ffa5a330a..9affdb6ad0 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/OptionalContainerPropertyGenerator.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/OptionalContainerPropertyGenerator.java @@ -18,9 +18,6 @@ package com.navercorp.fixturemonkey.api.generator; -import static com.navercorp.fixturemonkey.api.type.Types.generateAnnotatedTypeWithoutAnnotation; - -import java.lang.reflect.AnnotatedType; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -34,25 +31,26 @@ import com.navercorp.fixturemonkey.api.property.Property; import com.navercorp.fixturemonkey.api.property.SingleElementProperty; import com.navercorp.fixturemonkey.api.property.TypeParameterProperty; -import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.objectfarm.api.type.JavaType; +import com.navercorp.objectfarm.api.type.JvmType; @API(since = "0.4.0", status = Status.MAINTAINED) public final class OptionalContainerPropertyGenerator implements ContainerPropertyGenerator { public static final OptionalContainerPropertyGenerator INSTANCE = new OptionalContainerPropertyGenerator(); - private static final AnnotatedType INTEGER_TYPE = generateAnnotatedTypeWithoutAnnotation(Integer.class); - private static final AnnotatedType LONG_TYPE = generateAnnotatedTypeWithoutAnnotation(Long.class); - private static final AnnotatedType DOUBLE_TYPE = generateAnnotatedTypeWithoutAnnotation(Double.class); + private static final JvmType INTEGER_TYPE = new JavaType(Integer.class); + private static final JvmType LONG_TYPE = new JavaType(Long.class); + private static final JvmType DOUBLE_TYPE = new JavaType(Double.class); private static final ArbitraryContainerInfo CONTAINER_INFO = new ArbitraryContainerInfo(0, 1); @Override public ContainerProperty generate(ContainerPropertyGeneratorContext context) { Property property = context.getProperty(); - AnnotatedType valueAnnotatedType = getOptionalValueAnnotatedType(property); + JvmType valueJvmType = getOptionalValueJvmType(property); SingleElementProperty singleElementProperty = - new SingleElementProperty(property, new TypeParameterProperty(valueAnnotatedType)); + new SingleElementProperty(property, new TypeParameterProperty(valueJvmType)); return new ContainerProperty( Collections.singletonList(singleElementProperty), @@ -60,8 +58,8 @@ public ContainerProperty generate(ContainerPropertyGeneratorContext context) { ); } - private AnnotatedType getOptionalValueAnnotatedType(Property optionalProperty) { - Class type = Types.getActualType(optionalProperty.getType()); + private JvmType getOptionalValueJvmType(Property optionalProperty) { + Class type = optionalProperty.getJvmType().getRawType(); if (type == OptionalInt.class) { return INTEGER_TYPE; } @@ -80,15 +78,15 @@ private AnnotatedType getOptionalValueAnnotatedType(Property optionalProperty) { ); } - List genericsTypes = Types.getGenericsTypes(optionalProperty.getAnnotatedType()); - if (genericsTypes.size() != 1) { + List typeVariables = optionalProperty.getJvmType().getTypeVariables(); + if (typeVariables.size() != 1) { throw new IllegalArgumentException( - "Optional genericTypes must be have 1 generics type for value. " - + "propertyType: " + optionalProperty.getType() - + ", genericsTypes: " + genericsTypes + "Optional typeVariables must be have 1 generics type for value. " + + "propertyType: " + type + + ", typeVariables: " + typeVariables ); } - return genericsTypes.get(0); + return typeVariables.get(0); } } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/SetContainerPropertyGenerator.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/SetContainerPropertyGenerator.java index 33aa3b5dac..eb7d53f3d0 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/SetContainerPropertyGenerator.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/SetContainerPropertyGenerator.java @@ -18,7 +18,6 @@ package com.navercorp.fixturemonkey.api.generator; -import java.lang.reflect.AnnotatedType; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; @@ -31,7 +30,7 @@ import com.navercorp.fixturemonkey.api.property.DefaultContainerElementProperty; import com.navercorp.fixturemonkey.api.property.Property; import com.navercorp.fixturemonkey.api.property.TypeParameterProperty; -import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.objectfarm.api.type.JvmType; @API(since = "0.4.0", status = Status.MAINTAINED) public final class SetContainerPropertyGenerator implements ContainerPropertyGenerator { @@ -44,16 +43,11 @@ public final class SetContainerPropertyGenerator implements ContainerPropertyGen public ContainerProperty generate(ContainerPropertyGeneratorContext context) { Property property = context.getProperty(); - List elementTypes = Types.getGenericsTypes(property.getAnnotatedType()); - AnnotatedType elementType; - if (elementTypes.size() == 1) { - elementType = elementTypes.get(0); - } else { - elementType = DEFAULT_ELEMENT_RAW_TYPE.getAnnotatedType(); - } + List elementTypes = property.getJvmType().getTypeVariables(); + JvmType elementType = elementTypes.size() == 1 ? elementTypes.get(0) : DEFAULT_ELEMENT_JVM_TYPE; ArbitraryContainerInfo containerInfo = context.getContainerInfo(); - Class actualElementType = Types.getActualType(elementType.getType()); + Class actualElementType = elementType.getRawType(); if (actualElementType.isEnum()) { int enumSize = EnumSet.allOf((Class)actualElementType).size(); diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/StreamContainerPropertyGenerator.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/StreamContainerPropertyGenerator.java index d5f6bd3f89..888d9dd69d 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/StreamContainerPropertyGenerator.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/StreamContainerPropertyGenerator.java @@ -18,9 +18,6 @@ package com.navercorp.fixturemonkey.api.generator; -import static com.navercorp.fixturemonkey.api.type.Types.generateAnnotatedTypeWithoutAnnotation; - -import java.lang.reflect.AnnotatedType; import java.util.ArrayList; import java.util.List; import java.util.stream.DoubleStream; @@ -34,21 +31,22 @@ import com.navercorp.fixturemonkey.api.property.DefaultContainerElementProperty; import com.navercorp.fixturemonkey.api.property.Property; import com.navercorp.fixturemonkey.api.property.TypeParameterProperty; -import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.objectfarm.api.type.JavaType; +import com.navercorp.objectfarm.api.type.JvmType; @API(since = "0.4.0", status = Status.MAINTAINED) public final class StreamContainerPropertyGenerator implements ContainerPropertyGenerator { public static final StreamContainerPropertyGenerator INSTANCE = new StreamContainerPropertyGenerator(); - private static final AnnotatedType INTEGER_TYPE = generateAnnotatedTypeWithoutAnnotation(Integer.class); - private static final AnnotatedType LONG_TYPE = generateAnnotatedTypeWithoutAnnotation(Long.class); - private static final AnnotatedType DOUBLE_TYPE = generateAnnotatedTypeWithoutAnnotation(Double.class); + private static final JvmType INTEGER_TYPE = new JavaType(Integer.class); + private static final JvmType LONG_TYPE = new JavaType(Long.class); + private static final JvmType DOUBLE_TYPE = new JavaType(Double.class); @Override public ContainerProperty generate(ContainerPropertyGeneratorContext context) { Property property = context.getProperty(); - AnnotatedType elementAnnotatedType = getElementAnnotatedType(property); + JvmType elementJvmType = getElementJvmType(property); ArbitraryContainerInfo containerInfo = context.getContainerInfo(); @@ -58,7 +56,7 @@ public ContainerProperty generate(ContainerPropertyGeneratorContext context) { childProperties.add( new DefaultContainerElementProperty( property, - new TypeParameterProperty(elementAnnotatedType), + new TypeParameterProperty(elementJvmType), sequence, sequence ) @@ -71,8 +69,8 @@ public ContainerProperty generate(ContainerPropertyGeneratorContext context) { ); } - private AnnotatedType getElementAnnotatedType(Property streamProperty) { - Class type = Types.getActualType(streamProperty.getType()); + private JvmType getElementJvmType(Property streamProperty) { + Class type = streamProperty.getJvmType().getRawType(); if (IntStream.class.isAssignableFrom(type)) { return INTEGER_TYPE; } @@ -91,15 +89,15 @@ private AnnotatedType getElementAnnotatedType(Property streamProperty) { ); } - List genericsTypes = Types.getGenericsTypes(streamProperty.getAnnotatedType()); - if (genericsTypes.size() != 1) { + List typeVariables = streamProperty.getJvmType().getTypeVariables(); + if (typeVariables.size() != 1) { throw new IllegalArgumentException( - "Stream genericTypes must be have 1 generics type for value. " - + "propertyType: " + streamProperty.getType() - + ", genericsTypes: " + genericsTypes + "Stream typeVariables must be have 1 generics type for value. " + + "propertyType: " + type + + ", typeVariables: " + typeVariables ); } - return genericsTypes.get(0); + return typeVariables.get(0); } } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/instantiator/JavaInstantiatorProcessor.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/instantiator/JavaInstantiatorProcessor.java index f031d21d9b..e1bbfb5533 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/instantiator/JavaInstantiatorProcessor.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/instantiator/JavaInstantiatorProcessor.java @@ -241,7 +241,7 @@ private static List getMethodParameterProperties( TypeReference resolvedTypeReference = resolvedParameterTypes.get(i); properties.add( new TypeNameProperty( - resolvedTypeReference.getAnnotatedType(), + resolvedTypeReference.getJvmType(), resolvedParameterName, null ) diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/AnonymousArbitraryIntrospector.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/AnonymousArbitraryIntrospector.java index 97601220e0..969f4def62 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/AnonymousArbitraryIntrospector.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/AnonymousArbitraryIntrospector.java @@ -34,7 +34,6 @@ import com.navercorp.fixturemonkey.api.matcher.Matcher; import com.navercorp.fixturemonkey.api.property.MethodProperty; import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.api.type.Types; /** * It generates the anonymous object of interface which has no-argument methods. @@ -53,7 +52,7 @@ public final class AnonymousArbitraryIntrospector implements ArbitraryIntrospect @Override public boolean match(Property property) { - return Modifier.isInterface(Types.getActualType(property.getType()).getModifiers()); + return Modifier.isInterface(property.getJvmType().getRawType().getModifiers()); } /** @@ -66,7 +65,7 @@ public boolean match(Property property) { @Override public ArbitraryIntrospectorResult introspect(ArbitraryGeneratorContext context) { Property property = context.getResolvedProperty(); - Class type = Types.getActualType(property.getType()); + Class type = property.getJvmType().getRawType(); if (!match(property)) { LOGGER.warn("Given type {} is not an interface. You must use another ArbitraryIntrospector", type); diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/ArrayIntrospector.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/ArrayIntrospector.java index d2d1975abf..9b9ff7ddd9 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/ArrayIntrospector.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/ArrayIntrospector.java @@ -19,7 +19,6 @@ package com.navercorp.fixturemonkey.api.introspector; import java.lang.reflect.Array; -import java.lang.reflect.GenericArrayType; import java.util.ArrayList; import java.util.List; @@ -33,7 +32,6 @@ import com.navercorp.fixturemonkey.api.generator.ArbitraryProperty; import com.navercorp.fixturemonkey.api.matcher.Matcher; import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.api.type.Types; @API(since = "0.4.0", status = Status.MAINTAINED) public final class ArrayIntrospector implements ArbitraryIntrospector, Matcher { @@ -41,8 +39,7 @@ public final class ArrayIntrospector implements ArbitraryIntrospector, Matcher { @Override public boolean match(Property property) { - return Types.getActualType(property.getType()).isArray() - || GenericArrayType.class.isAssignableFrom(property.getType().getClass()); + return property.getJvmType().getRawType().isArray(); } @Override @@ -58,10 +55,9 @@ public ArbitraryIntrospectorResult introspect(ArbitraryGeneratorContext context) .elements(context.getElementCombinableArbitraryList()) .build( elements -> { + Class rawType = property.getObjectProperty().getProperty().getJvmType().getRawType(); ArrayBuilder arrayBuilder = new ArrayBuilder( - Types.getArrayComponentType( - property.getObjectProperty().getProperty().getAnnotatedType() - ), + rawType.getComponentType(), elements.size() ); for (Object element : elements) { diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/BeanArbitraryIntrospector.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/BeanArbitraryIntrospector.java index bc2e52ad35..a1b157b1ce 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/BeanArbitraryIntrospector.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/BeanArbitraryIntrospector.java @@ -43,7 +43,6 @@ import com.navercorp.fixturemonkey.api.property.PropertyGenerator; import com.navercorp.fixturemonkey.api.type.Reflections; import com.navercorp.fixturemonkey.api.type.TypeCache; -import com.navercorp.fixturemonkey.api.type.Types; @API(since = "0.4.0", status = Status.MAINTAINED) public final class BeanArbitraryIntrospector implements ArbitraryIntrospector { @@ -52,10 +51,10 @@ public final class BeanArbitraryIntrospector implements ArbitraryIntrospector { private static final Logger LOGGER = LoggerFactory.getLogger(BeanArbitraryIntrospector.class); @Override - @SuppressWarnings({"argument", "methodref.return", ""}) + @SuppressWarnings({"argument", "methodref.return"}) public ArbitraryIntrospectorResult introspect(ArbitraryGeneratorContext context) { Property property = context.getResolvedProperty(); - Class type = Types.getActualType(property.getType()); + Class type = property.getJvmType().getRawType(); if (Modifier.isAbstract(type.getModifiers())) { return ArbitraryIntrospectorResult.NOT_INTROSPECTED; } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/BuilderArbitraryIntrospector.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/BuilderArbitraryIntrospector.java index 4e35f26af5..d6a30478e0 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/BuilderArbitraryIntrospector.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/BuilderArbitraryIntrospector.java @@ -38,7 +38,6 @@ import com.navercorp.fixturemonkey.api.property.FieldProperty; import com.navercorp.fixturemonkey.api.property.Property; import com.navercorp.fixturemonkey.api.type.Reflections; -import com.navercorp.fixturemonkey.api.type.Types; @API(since = "0.4.0", status = API.Status.MAINTAINED) public final class BuilderArbitraryIntrospector implements ArbitraryIntrospector { @@ -66,7 +65,7 @@ private static void clearMethodCache() { @Override public ArbitraryIntrospectorResult introspect(ArbitraryGeneratorContext context) { Property property = context.getResolvedProperty(); - Class type = Types.getActualType(property.getType()); + Class type = property.getJvmType().getRawType(); if (Modifier.isAbstract(type.getModifiers())) { return ArbitraryIntrospectorResult.NOT_INTROSPECTED; } @@ -187,13 +186,13 @@ private Class getActualType(Property property) { // If the concrete type is a subtype of the declared type, use the declared type instead. if (actualProperty instanceof FieldProperty) { Class fieldDeclaredType = ((FieldProperty)actualProperty).getField().getType(); - Class propertyType = Types.getActualType(actualProperty.getType()); + Class propertyType = actualProperty.getJvmType().getRawType(); if (fieldDeclaredType != propertyType && fieldDeclaredType.isAssignableFrom(propertyType)) { return fieldDeclaredType; } } - return Types.getActualType(actualProperty.getType()); + return actualProperty.getJvmType().getRawType(); } private Property getActualProperty(Property property) { diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/ConstantIntrospector.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/ConstantIntrospector.java index 4ee0fec271..2dccdfe8b3 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/ConstantIntrospector.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/ConstantIntrospector.java @@ -27,7 +27,7 @@ import com.navercorp.fixturemonkey.api.property.ConstantProperty; import com.navercorp.fixturemonkey.api.property.Property; -@API(since = "1.0.17", status = Status.EXPERIMENTAL) +@API(since = "1.0.17", status = Status.MAINTAINED) public final class ConstantIntrospector implements ArbitraryIntrospector, Matcher { public static final ConstantIntrospector INSTANCE = new ConstantIntrospector(); @@ -47,7 +47,7 @@ public ArbitraryIntrospectorResult introspect(ArbitraryGeneratorContext context) } return new ArbitraryIntrospectorResult( - CombinableArbitrary.from(() -> constantProperty.getValue(null)) + CombinableArbitrary.from(((ConstantProperty)constantProperty)::getConstantValue) ); } } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/ConstructorArbitraryIntrospector.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/ConstructorArbitraryIntrospector.java index 79f61a5802..27f2f31420 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/ConstructorArbitraryIntrospector.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/ConstructorArbitraryIntrospector.java @@ -56,7 +56,7 @@ public ConstructorArbitraryIntrospector(ConstructorWithParameterNames constru @Override public ArbitraryIntrospectorResult introspect(ArbitraryGeneratorContext context) { Property property = context.getResolvedProperty(); - Class type = Types.getActualType(property.getType()); + Class type = property.getJvmType().getRawType(); if (Modifier.isAbstract(type.getModifiers())) { return ArbitraryIntrospectorResult.NOT_INTROSPECTED; diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/ConstructorPropertiesArbitraryIntrospector.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/ConstructorPropertiesArbitraryIntrospector.java index adf48fde30..539a3cdac3 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/ConstructorPropertiesArbitraryIntrospector.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/ConstructorPropertiesArbitraryIntrospector.java @@ -44,7 +44,6 @@ import com.navercorp.fixturemonkey.api.property.PropertyGenerator; import com.navercorp.fixturemonkey.api.type.Reflections; import com.navercorp.fixturemonkey.api.type.TypeCache; -import com.navercorp.fixturemonkey.api.type.Types; @API(since = "0.4.2", status = Status.MAINTAINED) public final class ConstructorPropertiesArbitraryIntrospector implements ArbitraryIntrospector { @@ -62,7 +61,7 @@ public final class ConstructorPropertiesArbitraryIntrospector implements Arbitra @Override public ArbitraryIntrospectorResult introspect(ArbitraryGeneratorContext context) { Property property = context.getResolvedProperty(); - Class type = Types.getActualType(property.getType()); + Class type = property.getJvmType().getRawType(); if (Modifier.isAbstract(type.getModifiers())) { return ArbitraryIntrospectorResult.NOT_INTROSPECTED; } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/FactoryMethodArbitraryIntrospector.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/FactoryMethodArbitraryIntrospector.java index bbe9ad4d43..e1c90ea7fd 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/FactoryMethodArbitraryIntrospector.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/FactoryMethodArbitraryIntrospector.java @@ -34,7 +34,6 @@ import com.navercorp.fixturemonkey.api.generator.ArbitraryGeneratorContext; import com.navercorp.fixturemonkey.api.generator.ArbitraryProperty; import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.api.type.Types; @API(since = "0.6.12", status = Status.MAINTAINED) public final class FactoryMethodArbitraryIntrospector implements ArbitraryIntrospector { @@ -47,7 +46,7 @@ public FactoryMethodArbitraryIntrospector(FactoryMethodWithParameterNames factor @Override public ArbitraryIntrospectorResult introspect(ArbitraryGeneratorContext context) { Property property = context.getResolvedProperty(); - Class type = Types.getActualType(property.getType()); + Class type = property.getJvmType().getRawType(); if (Modifier.isAbstract(type.getModifiers())) { return ArbitraryIntrospectorResult.NOT_INTROSPECTED; } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/FailoverIntrospector.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/FailoverIntrospector.java index 9164ee3a64..9810340239 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/FailoverIntrospector.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/FailoverIntrospector.java @@ -64,7 +64,7 @@ public ArbitraryIntrospectorResult introspect(ArbitraryGeneratorContext context) String.format( "\"%s\" is failed to introspect \"%s\" type.", introspector.getClass().getSimpleName(), - ((Class)context.getResolvedProperty().getType()).getName() + context.getResolvedProperty().getJvmType().getRawType().getName() ), ex ); @@ -94,7 +94,7 @@ public Object combined() { String.format( "\"%s\" is failed to introspect \"%s\" type.", Objects.requireNonNull(result).getIntrospector().getClass().getSimpleName(), - ((Class)context.getResolvedProperty().getType()).getName() + context.getResolvedProperty().getJvmType().getRawType().getName() ), ex ); @@ -105,7 +105,7 @@ public Object combined() { throw new IllegalArgumentException( String.format( "Failed to generate type \"%s\"", - ((Class)context.getResolvedProperty().getType()).getSimpleName() + context.getResolvedProperty().getJvmType().getRawType().getSimpleName() ) ); } @@ -126,7 +126,7 @@ public Object rawValue() { String.format( "\"%s\" is failed to introspect type \"%s\"", Objects.requireNonNull(result).getIntrospector().getClass().getSimpleName(), - ((Class)context.getResolvedProperty().getType()).getName() + context.getResolvedProperty().getJvmType().getRawType().getName() ), ex ); @@ -137,7 +137,7 @@ public Object rawValue() { throw new IllegalArgumentException( String.format( "Failed to generate type \"%s\"", - ((Class)context.getResolvedProperty().getType()).getSimpleName() + context.getResolvedProperty().getJvmType().getRawType().getSimpleName() ) ); } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/FieldReflectionArbitraryIntrospector.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/FieldReflectionArbitraryIntrospector.java index 145d8e161e..44ba404647 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/FieldReflectionArbitraryIntrospector.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/FieldReflectionArbitraryIntrospector.java @@ -40,7 +40,6 @@ import com.navercorp.fixturemonkey.api.property.PropertyGenerator; import com.navercorp.fixturemonkey.api.type.Reflections; import com.navercorp.fixturemonkey.api.type.TypeCache; -import com.navercorp.fixturemonkey.api.type.Types; @API(since = "0.4.0", status = Status.MAINTAINED) public final class FieldReflectionArbitraryIntrospector implements ArbitraryIntrospector { @@ -51,7 +50,7 @@ public final class FieldReflectionArbitraryIntrospector implements ArbitraryIntr @Override public ArbitraryIntrospectorResult introspect(ArbitraryGeneratorContext context) { Property property = context.getResolvedProperty(); - Class type = Types.getActualType(property.getType()); + Class type = property.getJvmType().getRawType(); if (Modifier.isAbstract(type.getModifiers())) { return ArbitraryIntrospectorResult.NOT_INTROSPECTED; } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/JavaArbitraryIntrospector.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/JavaArbitraryIntrospector.java index d768955088..9be354386f 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/JavaArbitraryIntrospector.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/JavaArbitraryIntrospector.java @@ -32,7 +32,6 @@ import com.navercorp.fixturemonkey.api.generator.ArbitraryGeneratorContext; import com.navercorp.fixturemonkey.api.matcher.Matcher; import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.api.type.Types; @API(since = "0.4.0", status = Status.MAINTAINED) public final class JavaArbitraryIntrospector implements ArbitraryIntrospector, Matcher { @@ -44,13 +43,13 @@ public JavaArbitraryIntrospector(JavaTypeArbitraryGeneratorSet javaTypeArbitrary @Override public boolean match(Property property) { - Class actualType = Types.getActualType(property.getType()); + Class actualType = property.getJvmType().getRawType(); return this.introspector.containsKey(actualType); } @Override public ArbitraryIntrospectorResult introspect(ArbitraryGeneratorContext context) { - Class type = Types.getActualType(context.getResolvedType()); + Class type = context.getResolvedType(); return this.introspector.getOrDefault( type, ctx -> ArbitraryIntrospectorResult.NOT_INTROSPECTED diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/NullArbitraryIntrospector.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/NullArbitraryIntrospector.java index 481b683a6a..6a8f71a204 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/NullArbitraryIntrospector.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/NullArbitraryIntrospector.java @@ -24,7 +24,7 @@ import com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary; import com.navercorp.fixturemonkey.api.generator.ArbitraryGeneratorContext; -@API(since = "1.0.9", status = Status.EXPERIMENTAL) +@API(since = "1.0.9", status = Status.MAINTAINED) public final class NullArbitraryIntrospector implements ArbitraryIntrospector { public static final NullArbitraryIntrospector INSTANCE = new NullArbitraryIntrospector(); diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/OptionalIntrospector.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/OptionalIntrospector.java index b241decd59..193482cc27 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/OptionalIntrospector.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/OptionalIntrospector.java @@ -32,13 +32,12 @@ import com.navercorp.fixturemonkey.api.generator.ArbitraryProperty; import com.navercorp.fixturemonkey.api.matcher.Matcher; import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.api.type.Types; @API(since = "0.4.0", status = Status.MAINTAINED) public final class OptionalIntrospector implements ArbitraryIntrospector, Matcher { @Override public boolean match(Property property) { - Class type = Types.getActualType(property.getType()); + Class type = property.getJvmType().getRawType(); return type == Optional.class || type == OptionalInt.class || type == OptionalLong.class @@ -58,7 +57,7 @@ public ArbitraryIntrospectorResult introspect(ArbitraryGeneratorContext context) CombinableArbitrary.from(Optional.empty()) ); } - Class type = Types.getActualType(property.getObjectProperty().getProperty().getType()); + Class type = property.getObjectProperty().getProperty().getJvmType().getRawType(); ArbitraryProperty valueProperty = children.get(0); double presenceProbability = 1 - valueProperty.getNullInject(); if (children.size() == 1) { diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/PriorityConstructorArbitraryIntrospector.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/PriorityConstructorArbitraryIntrospector.java index 5665906c14..9f76f82ff5 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/PriorityConstructorArbitraryIntrospector.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/PriorityConstructorArbitraryIntrospector.java @@ -37,7 +37,6 @@ import com.navercorp.fixturemonkey.api.property.Property; import com.navercorp.fixturemonkey.api.property.PropertyGenerator; import com.navercorp.fixturemonkey.api.type.TypeCache; -import com.navercorp.fixturemonkey.api.type.Types; @API(since = "1.0.26", status = Status.EXPERIMENTAL) public final class PriorityConstructorArbitraryIntrospector implements ArbitraryIntrospector { @@ -111,7 +110,7 @@ public PropertyGenerator getRequiredPropertyGenerator(Property property) { @SuppressWarnings("assignment") private ConstructorArbitraryIntrospector getConstructorArbitraryIntrospector(Property property) { - Class actualType = Types.getActualType(property.getType()); + Class actualType = property.getJvmType().getRawType(); return constructorIntrospectorsByProperty.computeIfAbsent( property, diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/jqwik/JavaTimeArbitraryIntrospector.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/jqwik/JavaTimeArbitraryIntrospector.java index f2cae5b932..12c74753ef 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/jqwik/JavaTimeArbitraryIntrospector.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/jqwik/JavaTimeArbitraryIntrospector.java @@ -48,7 +48,6 @@ import com.navercorp.fixturemonkey.api.introspector.ArbitraryIntrospectorResult; import com.navercorp.fixturemonkey.api.matcher.Matcher; import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.api.type.Types; @API(since = "0.4.0", status = Status.MAINTAINED) public final class JavaTimeArbitraryIntrospector implements ArbitraryIntrospector, Matcher { @@ -60,13 +59,13 @@ public JavaTimeArbitraryIntrospector(JavaTimeArbitraryGeneratorSet javaTimeArbit @Override public boolean match(Property property) { - Class actualType = Types.getActualType(property.getType()); + Class actualType = property.getJvmType().getRawType(); return this.introspector.containsKey(actualType); } @Override public ArbitraryIntrospectorResult introspect(ArbitraryGeneratorContext context) { - Class type = Types.getActualType(context.getResolvedType()); + Class type = context.getResolvedType(); return this.introspector.getOrDefault( type, ctx -> ArbitraryIntrospectorResult.NOT_INTROSPECTED diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/jqwik/JqwikPlugin.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/jqwik/JqwikPlugin.java index 02c5ee9996..dbdd7c33d3 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/jqwik/JqwikPlugin.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/jqwik/JqwikPlugin.java @@ -18,9 +18,13 @@ package com.navercorp.fixturemonkey.api.jqwik; +import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; + import com.navercorp.fixturemonkey.api.option.FixtureMonkeyOptionsBuilder; import com.navercorp.fixturemonkey.api.plugin.Plugin; +@API(since = "1.0.0", status = Status.MAINTAINED) public final class JqwikPlugin implements Plugin { private JavaArbitraryResolver javaArbitraryResolver; private JavaTypeArbitraryGenerator javaTypeArbitraryGenerator = new JavaTypeArbitraryGenerator() { diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/lazy/UnSafeLazyArbitraryImpl.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/lazy/UnSafeLazyArbitraryImpl.java index 360c862ccf..e14fb8cda6 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/lazy/UnSafeLazyArbitraryImpl.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/lazy/UnSafeLazyArbitraryImpl.java @@ -23,7 +23,7 @@ import org.apiguardian.api.API; import org.apiguardian.api.API.Status; -@API(since = "0.4.0", status = Status.MAINTAINED) +@API(since = "0.4.0", status = Status.INTERNAL) public final class UnSafeLazyArbitraryImpl implements LazyArbitrary { private static final Object UNINITIALIZED_VALUE = new Object(); diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/AssignableTypeMatcher.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/AssignableTypeMatcher.java index ad583c8f38..c4dd947f65 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/AssignableTypeMatcher.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/AssignableTypeMatcher.java @@ -22,7 +22,6 @@ import org.apiguardian.api.API.Status; import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.api.type.Types; @API(since = "0.4.0", status = Status.MAINTAINED) public final class AssignableTypeMatcher implements Matcher { @@ -34,8 +33,7 @@ public AssignableTypeMatcher(Class type) { @Override public boolean match(Property property) { - Class propertyType = Types.getActualType(property.getType()); - return this.type.isAssignableFrom(propertyType); + return this.type.isAssignableFrom(property.getJvmType().getRawType()); } public Class getAnchorType() { diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/DefaultMatcherOperatorContainer.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/DefaultMatcherOperatorContainer.java index bbfb6517c4..7e4aeee78b 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/DefaultMatcherOperatorContainer.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/DefaultMatcherOperatorContainer.java @@ -59,7 +59,9 @@ public void addLast(MatcherOperator matcherOperator) { @Override public List> getListByProperty(Property property) { - Class propertyType = Types.getActualType(property.getType()); + Class propertyType = Types.normalizeRawType( + property.getJvmType().getRawType() + ); List> acc = new ArrayList<>(typeUnknownIntrospectors); if (propertyType == UnidentifiableType.class) { diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/DoubleGenericTypeMatcher.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/DoubleGenericTypeMatcher.java index 93b0b40d0c..7e56011204 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/DoubleGenericTypeMatcher.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/DoubleGenericTypeMatcher.java @@ -18,14 +18,10 @@ package com.navercorp.fixturemonkey.api.matcher; -import java.lang.reflect.AnnotatedType; -import java.util.List; - import org.apiguardian.api.API; import org.apiguardian.api.API.Status; import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.api.type.Types; @API(since = "0.5.7", status = Status.MAINTAINED) public final class DoubleGenericTypeMatcher implements Matcher { @@ -33,7 +29,6 @@ public final class DoubleGenericTypeMatcher implements Matcher { @Override public boolean match(Property property) { - List genericsTypes = Types.getGenericsTypes(property.getAnnotatedType()); - return genericsTypes.size() == 2; + return property.getJvmType().getTypeVariables().size() == 2; } } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/ExactPropertyMatcher.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/ExactPropertyMatcher.java index d5683789c9..62a0e9f92a 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/ExactPropertyMatcher.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/ExactPropertyMatcher.java @@ -26,7 +26,7 @@ /** * A matcher that checks if a given property is of a specific type. */ -@API(since = "1.0.13", status = Status.EXPERIMENTAL) +@API(since = "1.0.13", status = Status.MAINTAINED) public final class ExactPropertyMatcher implements Matcher { private final Class propertyType; diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/ExactTypeMatcher.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/ExactTypeMatcher.java index 9373a97d15..f9ca01e468 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/ExactTypeMatcher.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/ExactTypeMatcher.java @@ -38,6 +38,6 @@ public Class getType() { @Override public boolean match(Property property) { - return this.type == Types.getActualType(property.getType()); + return this.type == Types.normalizeRawType(property.getJvmType().getRawType()); } } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/MatcherOperator.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/MatcherOperator.java index 5f1fc9eeeb..0e293f1223 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/MatcherOperator.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/MatcherOperator.java @@ -23,7 +23,7 @@ import com.navercorp.fixturemonkey.api.property.Property; -@API(since = "0.4.0", status = Status.INTERNAL) +@API(since = "0.4.0", status = Status.MAINTAINED) public class MatcherOperator implements Matcher { private final Matcher matcher; private final T operator; diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/MatcherOperatorRetriever.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/MatcherOperatorRetriever.java index 4f655b2818..0be18a32f4 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/MatcherOperatorRetriever.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/MatcherOperatorRetriever.java @@ -18,18 +18,17 @@ package com.navercorp.fixturemonkey.api.matcher; -import static org.apiguardian.api.API.Status.INTERNAL; - import java.util.List; import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; import com.navercorp.fixturemonkey.api.property.Property; /** * It is for internal use only. */ -@API(since = "1.1.16", status = INTERNAL) +@API(since = "1.1.16", status = Status.INTERNAL) public interface MatcherOperatorRetriever { List> getList(); diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/Matchers.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/Matchers.java index 54ea7e0668..33e59b7ba6 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/Matchers.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/Matchers.java @@ -23,13 +23,13 @@ import org.apiguardian.api.API; import org.apiguardian.api.API.Status; -import com.navercorp.fixturemonkey.api.type.Types; - @API(since = "0.4.0", status = Status.MAINTAINED) public final class Matchers { - public static final Matcher ENUM_TYPE_MATCHER = property -> Types.getActualType(property.getType()).isEnum(); - public static final Matcher BOOLEAN_TYPE_MATCHER = property -> - property.getType() == boolean.class || property.getType() == Boolean.class; + public static final Matcher ENUM_TYPE_MATCHER = property -> property.getJvmType().getRawType().isEnum(); + public static final Matcher BOOLEAN_TYPE_MATCHER = property -> { + Class rawType = property.getJvmType().getRawType(); + return rawType == boolean.class || rawType == Boolean.class; + }; public static final Matcher UUID_TYPE_MATCHER = new ExactTypeMatcher(UUID.class); } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/SingleGenericTypeMatcher.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/SingleGenericTypeMatcher.java index 616a4a3c02..99a7af300f 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/SingleGenericTypeMatcher.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/SingleGenericTypeMatcher.java @@ -18,14 +18,10 @@ package com.navercorp.fixturemonkey.api.matcher; -import java.lang.reflect.AnnotatedType; -import java.util.List; - import org.apiguardian.api.API; import org.apiguardian.api.API.Status; import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.api.type.Types; @API(since = "0.5.7", status = Status.MAINTAINED) public final class SingleGenericTypeMatcher implements Matcher { @@ -33,7 +29,6 @@ public final class SingleGenericTypeMatcher implements Matcher { @Override public boolean match(Property property) { - List genericsTypes = Types.getGenericsTypes(property.getAnnotatedType()); - return genericsTypes.size() == 1; + return property.getJvmType().getTypeVariables().size() == 1; } } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/TreeMatcherOperator.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/TreeMatcherOperator.java index d64cac70da..9a16bfb754 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/TreeMatcherOperator.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/TreeMatcherOperator.java @@ -21,7 +21,7 @@ import org.apiguardian.api.API; import org.apiguardian.api.API.Status; -@API(since = "1.0.4", status = Status.EXPERIMENTAL) +@API(since = "1.0.4", status = Status.MAINTAINED) public final class TreeMatcherOperator implements TreeMatcher { private final TreeMatcher matcher; private final T operator; diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/TripleGenericTypeMatcher.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/TripleGenericTypeMatcher.java index 93e3279525..ec5ed1d911 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/TripleGenericTypeMatcher.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/matcher/TripleGenericTypeMatcher.java @@ -18,20 +18,15 @@ package com.navercorp.fixturemonkey.api.matcher; -import java.lang.reflect.AnnotatedType; -import java.util.List; - import org.apiguardian.api.API; import org.apiguardian.api.API.Status; import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.api.type.Types; @API(since = "0.6.0", status = Status.MAINTAINED) public final class TripleGenericTypeMatcher implements Matcher { @Override public boolean match(Property property) { - List genericsTypes = Types.getGenericsTypes(property.getAnnotatedType()); - return genericsTypes.size() == 3; + return property.getJvmType().getTypeVariables().size() == 3; } } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/option/BuilderContextInitializer.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/option/BuilderContextInitializer.java index f854094ed6..d4260f0b09 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/option/BuilderContextInitializer.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/option/BuilderContextInitializer.java @@ -26,7 +26,7 @@ *

* It should contain the customizing options for the ObjectTree, not for the node. */ -@API(since = "1.1.4", status = Status.EXPERIMENTAL) +@API(since = "1.1.4", status = Status.MAINTAINED) public final class BuilderContextInitializer { private final boolean validOnly; diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/option/FixtureMonkeyOptions.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/option/FixtureMonkeyOptions.java index 0511b27f5e..fd84bc1221 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/option/FixtureMonkeyOptions.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/option/FixtureMonkeyOptions.java @@ -20,7 +20,6 @@ import static com.navercorp.fixturemonkey.api.generator.DefaultNullInjectGenerator.NOT_NULL_INJECT; -import java.lang.reflect.GenericArrayType; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; @@ -86,7 +85,6 @@ import com.navercorp.fixturemonkey.api.property.Property; import com.navercorp.fixturemonkey.api.property.PropertyGenerator; import com.navercorp.fixturemonkey.api.property.PropertyNameResolver; -import com.navercorp.fixturemonkey.api.type.Types; import com.navercorp.fixturemonkey.api.type.Types.GeneratingWildcardType; import com.navercorp.fixturemonkey.api.type.Types.UnidentifiableType; import com.navercorp.fixturemonkey.api.validator.ArbitraryValidator; @@ -153,36 +151,23 @@ public final class FixtureMonkeyOptions { private final MatcherOperatorRetriever objectPropertyGenerators; private final ObjectPropertyGenerator defaultObjectPropertyGenerator; private final MatcherOperatorRetriever containerPropertyGenerators; - private final MatcherOperatorRetriever candidateConcretePropertyResolvers; private final MatcherOperatorRetriever propertyNameResolvers; private final PropertyNameResolver defaultPropertyNameResolver; private final MatcherOperatorRetriever nullInjectGenerators; private final NullInjectGenerator defaultNullInjectGenerator; private final MatcherOperatorRetriever arbitraryContainerInfoGenerators; private final ArbitraryContainerInfoGenerator defaultArbitraryContainerInfoGenerator; - private final DecomposedContainerValueFactory decomposedContainerValueFactory; private final ArbitraryGenerator defaultArbitraryGenerator; - private final JavaConstraintGenerator javaConstraintGenerator; private final ArbitraryValidator defaultArbitraryValidator; - private final InstantiatorProcessor instantiatorProcessor; + private final DecomposedContainerValueFactory decomposedContainerValueFactory; private final int generateMaxTries; private final int generateUniqueMaxTries; + private final JavaConstraintGenerator javaConstraintGenerator; + private final InstantiatorProcessor instantiatorProcessor; + private final MatcherOperatorRetriever candidateConcretePropertyResolvers; + private final boolean enableLoggingFail; private final int maxRecursionDepth; - /** - * Declared as Object because the actual type (NodeTreeAdapter) is in the fixture-monkey module, - * which cannot be referenced from fixture-monkey-api due to module dependency constraints. - */ - @Nullable - private final Object nodeTreeAdapter; - /** - * Declared as Object because the actual type (AdapterTracer) is in the fixture-monkey module, - * which cannot be referenced from fixture-monkey-api due to module dependency constraints. - */ - @Nullable - private final Object adapterTracer; private final List> builderContextInitializers; - private final boolean enableLoggingFail; - public FixtureMonkeyOptions( MatcherOperatorRetriever propertyGenerators, PropertyGenerator defaultPropertyGenerator, @@ -205,34 +190,30 @@ public FixtureMonkeyOptions( MatcherOperatorRetriever candidateConcretePropertyResolvers, boolean enableLoggingFail, int maxRecursionDepth, - List> builderContextCustomizer, - @Nullable Object nodeTreeAdapter, - @Nullable Object adapterTracer + List> builderContextCustomizer ) { this.propertyGenerators = propertyGenerators; this.defaultPropertyGenerator = defaultPropertyGenerator; this.objectPropertyGenerators = objectPropertyGenerators; this.defaultObjectPropertyGenerator = defaultObjectPropertyGenerator; this.containerPropertyGenerators = containerPropertyGenerators; - this.candidateConcretePropertyResolvers = candidateConcretePropertyResolvers; this.propertyNameResolvers = propertyNameResolvers; this.defaultPropertyNameResolver = defaultPropertyNameResolver; this.nullInjectGenerators = nullInjectGenerators; this.defaultNullInjectGenerator = defaultNullInjectGenerator; this.arbitraryContainerInfoGenerators = arbitraryContainerInfoGenerators; this.defaultArbitraryContainerInfoGenerator = defaultArbitraryContainerInfoGenerator; - this.decomposedContainerValueFactory = decomposedContainerValueFactory; this.defaultArbitraryGenerator = defaultArbitraryGenerator; - this.javaConstraintGenerator = javaConstraintGenerator; this.defaultArbitraryValidator = defaultArbitraryValidator; - this.instantiatorProcessor = instantiatorProcessor; + this.decomposedContainerValueFactory = decomposedContainerValueFactory; this.generateMaxTries = generateMaxTries; this.generateUniqueMaxTries = generateUniqueMaxTries; + this.javaConstraintGenerator = javaConstraintGenerator; + this.instantiatorProcessor = instantiatorProcessor; + this.candidateConcretePropertyResolvers = candidateConcretePropertyResolvers; + this.enableLoggingFail = enableLoggingFail; this.maxRecursionDepth = maxRecursionDepth; - this.nodeTreeAdapter = nodeTreeAdapter; - this.adapterTracer = adapterTracer; this.builderContextInitializers = builderContextCustomizer; - this.enableLoggingFail = enableLoggingFail; } public static FixtureMonkeyOptionsBuilder builder() { @@ -373,28 +354,6 @@ public List> getBuilderContextIni return builderContextInitializers; } - /** - * Returns the node tree adapter for tree-based object generation. - * - * @return the adapter instance, or null if not configured - */ - @Nullable - @API(since = "1.1.0", status = Status.EXPERIMENTAL) - public Object getNodeTreeAdapter() { - return nodeTreeAdapter; - } - - /** - * Returns the adapter tracer for debugging tree resolution. - * - * @return the tracer instance, or null if not configured - */ - @Nullable - @API(since = "1.1.0", status = Status.EXPERIMENTAL) - public Object getAdapterTracer() { - return adapterTracer; - } - public List> getCandidateConcretePropertyResolvers() { return candidateConcretePropertyResolvers.getList(); } @@ -433,16 +392,11 @@ public FixtureMonkeyOptionsBuilder toBuilder() { .defaultArbitraryContainerInfoGenerator(this.defaultArbitraryContainerInfoGenerator) .defaultArbitraryValidator(defaultArbitraryValidator) .decomposedContainerValueFactory(decomposedContainerValueFactory) - .generateMaxTries(generateMaxTries) - .generateUniqueMaxTries(generateUniqueMaxTries) .javaConstraintGenerator(javaConstraintGenerator) .instantiatorProcessor(instantiatorProcessor) .candidateConcretePropertyResolvers(new ArrayList<>(candidateConcretePropertyResolvers.getList())) - .enableLoggingFail(enableLoggingFail) .maxRecursionDepth(maxRecursionDepth) - .builderContextInitializers(builderContextInitializers) - .nodeTreeAdapter(nodeTreeAdapter) - .adapterTracer(adapterTracer); + .builderContextInitializers(builderContextInitializers); } private static List> getDefaultContainerPropertyGenerators() { @@ -505,8 +459,7 @@ private static List> getDefaultConta EntryContainerPropertyGenerator.INSTANCE ), new MatcherOperator<>( - property -> Types.getActualType(property.getType()).isArray() - || GenericArrayType.class.isAssignableFrom(property.getType().getClass()), + property -> property.getJvmType().getRawType().isArray(), ArrayContainerPropertyGenerator.INSTANCE ), new MatcherOperator<>( @@ -522,7 +475,7 @@ private static List> getDefaultPropertyGenera new MatcherOperator<>(ConstantIntrospector.INSTANCE, EmptyPropertyGenerator.INSTANCE), new MatcherOperator<>( property -> { - Class actualType = Types.getActualType(property.getType()); + Class actualType = property.getJvmType().getRawType(); return actualType.isPrimitive() || DEFAULT_JAVA_PACKAGES.stream() .anyMatch(actualType.getPackage().getName()::startsWith); @@ -531,7 +484,7 @@ private static List> getDefaultPropertyGenera ), new MatcherOperator<>(Matchers.ENUM_TYPE_MATCHER, EmptyPropertyGenerator.INSTANCE), new MatcherOperator<>( - p -> Modifier.isInterface(Types.getActualType(p.getType()).getModifiers()), + p -> Modifier.isInterface(p.getJvmType().getRawType().getModifiers()), new NoArgumentInterfaceJavaMethodPropertyGenerator() ) ); diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/option/FixtureMonkeyOptionsBuilder.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/option/FixtureMonkeyOptionsBuilder.java index 2b80d0623f..8456893a0d 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/option/FixtureMonkeyOptionsBuilder.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/option/FixtureMonkeyOptionsBuilder.java @@ -143,11 +143,6 @@ public final class FixtureMonkeyOptionsBuilder { private DefaultMatcherOperatorContainer candidateConcretePropertyResolvers; private List> builderContextInitializers = new ArrayList<>(); - @Nullable - private Object nodeTreeAdapter; - - @Nullable - private Object adapterTracer; @SuppressWarnings({"argument"}) FixtureMonkeyOptionsBuilder() { @@ -350,7 +345,9 @@ public FixtureMonkeyOptionsBuilder defaultNullInjectGenerator(NullInjectGenerato public FixtureMonkeyOptionsBuilder defaultNullInjectGeneratorOperator( UnaryOperator defaultNullInjectGeneratorOperator ) { - this.defaultNullInjectGeneratorOperator = defaultNullInjectGeneratorOperator; + UnaryOperator previous = this.defaultNullInjectGeneratorOperator; + this.defaultNullInjectGeneratorOperator = + delegate -> defaultNullInjectGeneratorOperator.apply(previous.apply(delegate)); return this; } @@ -450,32 +447,6 @@ public FixtureMonkeyOptionsBuilder plugin(Plugin plugin) { return this; } - /** - * Sets the node tree adapter for tree-based object generation. - * This is typically set via JavaNodeTreeAdapterPlugin or KotlinNodeTreeAdapterPlugin. - * - * @param nodeTreeAdapter the adapter instance (type: NodeTreeAdapter) - * @return this builder - */ - @API(since = "1.1.0", status = Status.EXPERIMENTAL) - public FixtureMonkeyOptionsBuilder nodeTreeAdapter(@Nullable Object nodeTreeAdapter) { - this.nodeTreeAdapter = nodeTreeAdapter; - return this; - } - - /** - * Sets the adapter tracer for debugging tree resolution. - * This is typically set via JavaNodeTreeAdapterPlugin or KotlinNodeTreeAdapterPlugin. - * - * @param adapterTracer the tracer instance (type: AdapterTracer) - * @return this builder - */ - @API(since = "1.1.0", status = Status.EXPERIMENTAL) - public FixtureMonkeyOptionsBuilder adapterTracer(@Nullable Object adapterTracer) { - this.adapterTracer = adapterTracer; - return this; - } - public FixtureMonkeyOptionsBuilder defaultNotNull(boolean defaultNotNull) { this.defaultNotNull = defaultNotNull; return this; @@ -724,9 +695,7 @@ public FixtureMonkeyOptions build() { this.candidateConcretePropertyResolvers, this.enableLoggingFail, this.maxRecursionDepth, - this.builderContextInitializers, - this.nodeTreeAdapter, - this.adapterTracer + this.builderContextInitializers ); } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/plugin/InterfacePlugin.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/plugin/InterfacePlugin.java index 8f79983fbf..791d1eef7f 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/plugin/InterfacePlugin.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/plugin/InterfacePlugin.java @@ -34,12 +34,11 @@ import com.navercorp.fixturemonkey.api.option.FixtureMonkeyOptionsBuilder; import com.navercorp.fixturemonkey.api.property.CandidateConcretePropertyResolver; import com.navercorp.fixturemonkey.api.property.ConcreteTypeCandidateConcretePropertyResolver; -import com.navercorp.fixturemonkey.api.type.Types; /** * This plugin is used to extend an interface. */ -@API(since = "1.0.6", status = Status.EXPERIMENTAL) +@API(since = "1.0.6", status = Status.MAINTAINED) public final class InterfacePlugin implements Plugin { private final List> candidateConcretePropertyResolvers = new ArrayList<>(); @@ -102,7 +101,7 @@ public InterfacePlugin interfaceImplements( ) { this.candidateConcretePropertyResolvers.add( new MatcherOperator<>( - matcher.intersect(p -> Modifier.isInterface(Types.getActualType(p.getType()).getModifiers())), + matcher.intersect(p -> Modifier.isInterface(p.getJvmType().getRawType().getModifiers())), concretePropertyResolver ) ); @@ -168,7 +167,7 @@ public InterfacePlugin abstractClassExtends( ) { this.candidateConcretePropertyResolvers.add( new MatcherOperator<>( - matcher.intersect(p -> Modifier.isAbstract(Types.getActualType(p.getType()).getModifiers())), + matcher.intersect(p -> Modifier.isAbstract(p.getJvmType().getRawType().getModifiers())), concretePropertyResolver ) ); diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/plugin/SimpleValueJqwikPlugin.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/plugin/SimpleValueJqwikPlugin.java index f231e46d99..633d9dd19e 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/plugin/SimpleValueJqwikPlugin.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/plugin/SimpleValueJqwikPlugin.java @@ -47,7 +47,7 @@ import com.navercorp.fixturemonkey.api.option.FixtureMonkeyOptionsBuilder; import com.navercorp.fixturemonkey.api.type.Types; -@API(since = "1.0.17", status = Status.EXPERIMENTAL) +@API(since = "1.0.17", status = Status.MAINTAINED) public final class SimpleValueJqwikPlugin implements Plugin { private static final Set ALLOWED_SPECIAL_UNRESERVED_CHARACTERS = new HashSet<>(Arrays.asList('.', '_', '-', '~')); diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/CandidateConcretePropertyResolver.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/CandidateConcretePropertyResolver.java index 3517387762..9f3b78498f 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/CandidateConcretePropertyResolver.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/CandidateConcretePropertyResolver.java @@ -27,7 +27,7 @@ * It resolves the concrete type {@link Property} of the given {@link Property}. */ @FunctionalInterface -@API(since = "1.0.16", status = Status.EXPERIMENTAL) +@API(since = "1.0.16", status = Status.MAINTAINED) public interface CandidateConcretePropertyResolver { /** * resolves the candidate concrete type properties for the given property. diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ComparableRootProperty.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ComparableRootProperty.java index 9c5b6bad46..dd1d0f3748 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ComparableRootProperty.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ComparableRootProperty.java @@ -1,12 +1,13 @@ package com.navercorp.fixturemonkey.api.property; -import java.lang.reflect.AnnotatedType; import java.util.Objects; import org.apiguardian.api.API; import org.apiguardian.api.API.Status; import org.jspecify.annotations.Nullable; +import com.navercorp.objectfarm.api.type.JvmType; + /** * It is a property for a root type. * It does not support the equivalence of the type. @@ -15,8 +16,8 @@ public final class ComparableRootProperty implements TreeRootProperty { private final Property delgeatedProperty; - public ComparableRootProperty(AnnotatedType annotatedType) { - this.delgeatedProperty = new TypeParameterProperty(annotatedType); + public ComparableRootProperty(JvmType jvmType) { + this.delgeatedProperty = new TypeParameterProperty(jvmType); } @Override @@ -27,7 +28,7 @@ public Property getDelgatedProperty() { @Override public String toString() { return "RootProperty{" - + "annotatedType=" + delgeatedProperty.getAnnotatedType() + '}'; + + "jvmType=" + delgeatedProperty.getJvmType() + '}'; } @Override diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/CompositeCandidateConcretePropertyResolver.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/CompositeCandidateConcretePropertyResolver.java index 044d2a6632..9ab624d97b 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/CompositeCandidateConcretePropertyResolver.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/CompositeCandidateConcretePropertyResolver.java @@ -24,7 +24,7 @@ import org.apiguardian.api.API; import org.apiguardian.api.API.Status; -@API(since = "1.0.16", status = Status.EXPERIMENTAL) +@API(since = "1.0.16", status = Status.MAINTAINED) public final class CompositeCandidateConcretePropertyResolver implements CandidateConcretePropertyResolver { private final List candidateConcretePropertyResolvers; diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/CompositeProperty.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/CompositeProperty.java index 511e7e2e93..8f46dfecd4 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/CompositeProperty.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/CompositeProperty.java @@ -21,8 +21,6 @@ import static com.navercorp.fixturemonkey.api.property.PropertyUtils.isErasedProperty; import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -32,14 +30,19 @@ import org.apiguardian.api.API.Status; import org.jspecify.annotations.Nullable; +import com.navercorp.objectfarm.api.type.JavaType; +import com.navercorp.objectfarm.api.type.JvmType; + @API(since = "0.4.0", status = Status.MAINTAINED) public final class CompositeProperty implements Property { private final Property primaryProperty; private final Property secondaryProperty; + private final JvmType jvmType; public CompositeProperty(Property primaryProperty, Property secondaryProperty) { this.primaryProperty = primaryProperty; this.secondaryProperty = secondaryProperty; + this.jvmType = computeJvmType(); } public Property getPrimaryProperty() { @@ -51,13 +54,23 @@ public Property getSecondaryProperty() { } @Override - public Type getType() { - return getPriorityProperty().getType(); + public JvmType getJvmType() { + return jvmType; } - @Override - public AnnotatedType getAnnotatedType() { - return getPriorityProperty().getAnnotatedType(); + private JvmType computeJvmType() { + JvmType base = getPriorityProperty().getJvmType(); + List mergedAnnotations = getAnnotations(); + if (base.getAnnotations().equals(mergedAnnotations)) { + return base; + } + return new JavaType( + base.getRawType(), + base.getTypeVariables(), + mergedAnnotations, + base.getComponentType(), + base.getNullable() + ); } @Override @@ -84,12 +97,6 @@ public Optional getAnnotation(Class annotationClass return annotation; } - @Nullable - @Override - public Object getValue(Object instance) { - return this.getPriorityProperty().getValue(instance); - } - @Override @Nullable public Boolean isNullable() { diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ConcreteTypeCandidateConcretePropertyResolver.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ConcreteTypeCandidateConcretePropertyResolver.java index fa30f72c79..0d323ad7d8 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ConcreteTypeCandidateConcretePropertyResolver.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ConcreteTypeCandidateConcretePropertyResolver.java @@ -18,17 +18,14 @@ package com.navercorp.fixturemonkey.api.property; -import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Type; import java.util.List; import java.util.stream.Collectors; import org.apiguardian.api.API; import org.apiguardian.api.API.Status; -import com.navercorp.fixturemonkey.api.type.GenericType; -import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.objectfarm.api.type.JavaType; +import com.navercorp.objectfarm.api.type.JvmType; /** * This class is used to resolve more concrete types for a given interface. @@ -36,7 +33,7 @@ * * @param the type parameter of the interface */ -@API(since = "1.0.16", status = Status.EXPERIMENTAL) +@API(since = "1.0.16", status = Status.MAINTAINED) public final class ConcreteTypeCandidateConcretePropertyResolver implements CandidateConcretePropertyResolver { private final List> concreteTypes; @@ -57,41 +54,12 @@ public ConcreteTypeCandidateConcretePropertyResolver(List> co @Override @SuppressWarnings("type.argument.inference.crashed") public List resolve(Property property) { - List genericsTypes = Types.getGenericsTypes(property.getAnnotatedType()); - - if (!genericsTypes.isEmpty()) { - Type[] typeArguments = genericsTypes.stream() - .map(AnnotatedType::getType) - .toArray(Type[]::new); + List typeVariables = property.getJvmType().getTypeVariables(); + if (!typeVariables.isEmpty()) { return concreteTypes.stream() - .map(it -> { - Type concreteGenericType = new GenericType(it, typeArguments, null); - - AnnotatedType genericAnnotatedType = new AnnotatedType() { - @Override - public Type getType() { - return concreteGenericType; - } - - @Override - public A getAnnotation(Class annotationClass) { - return property.getAnnotation(annotationClass).orElse(null); - } - - @Override - public Annotation[] getAnnotations() { - return property.getAnnotations().toArray(new Annotation[0]); - } - - @Override - public Annotation[] getDeclaredAnnotations() { - return property.getAnnotations().toArray(new Annotation[0]); - } - }; - - return new ConcreteTypeProperty(genericAnnotatedType, property); - }) + .map(it -> new JavaType(it, typeVariables, property.getAnnotations())) + .map(jvmType -> (Property)new ConcreteTypeProperty(jvmType, property)) .collect(Collectors.toList()); } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ConcreteTypeProperty.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ConcreteTypeProperty.java index 71361d809a..65f4ccba39 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ConcreteTypeProperty.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ConcreteTypeProperty.java @@ -19,8 +19,6 @@ package com.navercorp.fixturemonkey.api.property; import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -32,7 +30,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.objectfarm.api.type.JavaType; import com.navercorp.objectfarm.api.type.JvmType; /** @@ -40,7 +38,6 @@ * where the concrete type may be different from the {@code abstractTypeProperty}. *

* The {@code abstractTypeProperty} is a property of the abstract type that actually resides in the metadata of a class. - * The {@code concreteAnnotatedType} is the annotated type of the concrete type that is resolved as the actual type. */ @API(since = "1.1.7", status = Status.EXPERIMENTAL) public final class ConcreteTypeProperty implements Property { @@ -49,28 +46,24 @@ public final class ConcreteTypeProperty implements Property { private final JvmType jvmType; private final Property abstractTypeProperty; - public ConcreteTypeProperty(AnnotatedType concreteAnnotatedType, Property abstractTypeProperty) { - this.jvmType = Types.toJvmType(concreteAnnotatedType, Collections.emptyList()); + public ConcreteTypeProperty(JvmType jvmType, Property abstractTypeProperty) { + this.jvmType = jvmType; this.abstractTypeProperty = abstractTypeProperty; } - public ConcreteTypeProperty( - AnnotatedType concreteAnnotatedType, - Property abstractTypeProperty, - List annotations - ) { - this.jvmType = Types.toJvmType(concreteAnnotatedType, annotations); - this.abstractTypeProperty = abstractTypeProperty; - } - - @Override - public Type getType() { - return jvmType.getRawType(); - } - @Override - public AnnotatedType getAnnotatedType() { - return jvmType.getAnnotatedType(); + public JvmType getJvmType() { + List combinedAnnotations = getAnnotations(); + if (jvmType.getAnnotations().equals(combinedAnnotations)) { + return jvmType; + } + return new JavaType( + jvmType.getRawType(), + jvmType.getTypeVariables(), + combinedAnnotations, + jvmType.getComponentType(), + jvmType.getNullable() + ); } @Nullable @@ -86,12 +79,6 @@ public List getAnnotations() { return Collections.unmodifiableList(concatAnnotations); } - @Nullable - @Override - public Object getValue(Object instance) { - return abstractTypeProperty.getValue(instance); - } - @Override public boolean equals(@Nullable Object obj) { if (this == obj) { diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ConstantProperty.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ConstantProperty.java index 831dd1aecb..8695ca4c44 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ConstantProperty.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ConstantProperty.java @@ -19,15 +19,12 @@ package com.navercorp.fixturemonkey.api.property; import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Type; import java.util.List; import org.apiguardian.api.API; import org.apiguardian.api.API.Status; import org.jspecify.annotations.Nullable; -import com.navercorp.fixturemonkey.api.type.Types; import com.navercorp.objectfarm.api.type.JvmType; @API(since = "1.0.17", status = Status.MAINTAINED) @@ -39,24 +36,18 @@ public final class ConstantProperty implements Property { private final Object constantValue; public ConstantProperty( - AnnotatedType annotatedType, + JvmType jvmType, @Nullable String propertyName, - @Nullable Object constantValue, - List annotations + @Nullable Object constantValue ) { - this.jvmType = Types.toJvmType(annotatedType, annotations); + this.jvmType = jvmType; this.propertyName = propertyName; this.constantValue = constantValue; } @Override - public Type getType() { - return this.jvmType.getRawType(); - } - - @Override - public AnnotatedType getAnnotatedType() { - return this.jvmType.getAnnotatedType(); + public JvmType getJvmType() { + return this.jvmType; } @Nullable @@ -71,8 +62,7 @@ public List getAnnotations() { } @Nullable - @Override - public Object getValue(Object instance) { + public Object getConstantValue() { return constantValue; } } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ConstructorParameterPropertyGenerator.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ConstructorParameterPropertyGenerator.java index 9f4253a0f7..bf73ff7c36 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ConstructorParameterPropertyGenerator.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ConstructorParameterPropertyGenerator.java @@ -18,21 +18,17 @@ package com.navercorp.fixturemonkey.api.property; -import static com.navercorp.fixturemonkey.api.instantiator.InstantiatorUtils.resolveParameterTypes; import static com.navercorp.fixturemonkey.api.instantiator.InstantiatorUtils.resolvedParameterNames; import java.beans.ConstructorProperties; -import java.lang.reflect.AnnotatedArrayType; -import java.lang.reflect.AnnotatedType; -import java.lang.reflect.AnnotatedTypeVariable; import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.lang.reflect.GenericArrayType; import java.lang.reflect.Parameter; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.util.Arrays; import java.util.Collections; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -48,6 +44,8 @@ import com.navercorp.fixturemonkey.api.type.TypeCache; import com.navercorp.fixturemonkey.api.type.TypeReference; import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.objectfarm.api.type.JvmType; +import com.navercorp.objectfarm.api.type.JvmTypes; /** * Generates properties representing constructor parameters. @@ -63,7 +61,7 @@ public ConstructorParameterPropertyGenerator( Predicate> constructorPredicate, Matcher matcher ) { - this.constructorsSupplier = p -> TypeCache.getDeclaredConstructors(Types.getActualType(p.getType())); + this.constructorsSupplier = p -> TypeCache.getDeclaredConstructors(p.getJvmType().getRawType()); this.constructorPredicate = constructorPredicate; this.matcher = matcher; } @@ -117,36 +115,43 @@ private static String[] getParameterNames(Constructor constructor) { public List generateParameterProperties(ConstructorPropertyGeneratorContext context) { Property property = context.getProperty(); - Class type = Types.getActualType(property.getType()); + JvmType parentJvmType = property.getJvmType(); + Class type = parentJvmType.getRawType(); Constructor constructor = context.getConstructor(); - Map actualGenericTypesByTypeVariable = - getGenericAnnotatedTypesByGenericTypeName(property); - List parameterNamesByConstructor = Arrays.asList(getParameterNames(constructor)); List<@Nullable String> inputParameterNames = context.getInputParameterNames(); - List> typeReferencesByConstructor = Arrays.stream(constructor.getAnnotatedParameterTypes()) - .map(it -> actualGenericTypesByTypeVariable.getOrDefault(it.getType().getTypeName(), it)) - .map(ConstructorParameterPropertyGenerator::toTypeReference) + Parameter[] parameters = constructor.getParameters(); + List resolvedParameterJvmTypes = Arrays.stream(parameters) + .map(p -> JvmTypes.resolveJvmType( + parentJvmType, + p.getParameterizedType(), + Arrays.asList(p.getAnnotations()) + )) .collect(Collectors.toList()); List resolvedParameterNames = resolvedParameterNames(parameterNamesByConstructor, inputParameterNames); - List> resolvedTypeReferences = - resolveParameterTypes(typeReferencesByConstructor, context.getInputParameterTypes()); + List resolvedTypes = + resolveParameterJvmTypes(resolvedParameterJvmTypes, context.getInputParameterTypes()); Map fieldsByName = TypeCache.getFieldsByName(type); - boolean anyReceiverParameter = Arrays.stream(constructor.getAnnotatedParameterTypes()) - .anyMatch(it -> constructor.getAnnotatedReceiverType() != null - && it.getType().equals(constructor.getAnnotatedReceiverType().getType())); - int parameterSize = typeReferencesByConstructor.size(); + boolean anyReceiverParameter = constructor.getAnnotatedReceiverType() != null + && Arrays.stream(constructor.getAnnotatedParameterTypes()) + .anyMatch(it -> it.getType().equals(constructor.getAnnotatedReceiverType().getType())); + int parameterSize = parameters.length; Map constructorPropertiesByName = new LinkedHashMap<>(); if (anyReceiverParameter) { - Parameter receiverParameter = constructor.getParameters()[0]; + Parameter receiverParameter = parameters[0]; + JvmType receiverJvmType = JvmTypes.resolveJvmType( + parentJvmType, + receiverParameter.getParameterizedType(), + Arrays.asList(receiverParameter.getAnnotations()) + ); constructorPropertiesByName.put( receiverParameter.getName(), new ConstructorProperty( - new TypeNameProperty(receiverParameter.getAnnotatedType(), receiverParameter.getName(), null), + new TypeNameProperty(receiverJvmType, receiverParameter.getName(), null), constructor, null, null @@ -160,13 +165,18 @@ public List generateParameterProperties(ConstructorPropertyGeneratorCo Field field = fieldsByName.get(parameterName); Property fieldProperty = field != null ? new FieldProperty( - Types.resolveWithTypeReferenceGenerics(property.getAnnotatedType(), field.getAnnotatedType()), - field + JvmTypes.resolveJvmType( + parentJvmType, + field.getGenericType(), + Arrays.asList(field.getAnnotations()) + ), + field, + null ) : null; - AnnotatedType parameterAnnotatedType = resolvedTypeReferences.get(i).getAnnotatedType(); - if (isGenericAnnotatedType(parameterAnnotatedType) && fieldProperty != null) { + JvmType parameterJvmType = resolvedTypes.get(i); + if (isUnresolvedGenericType(parameters[i].getParameterizedType()) && fieldProperty != null) { constructorPropertiesByName.put( parameterName, new ConstructorProperty( @@ -180,7 +190,7 @@ public List generateParameterProperties(ConstructorPropertyGeneratorCo constructorPropertiesByName.put( parameterName, new ConstructorProperty( - new TypeNameProperty(parameterAnnotatedType, parameterName, null), + new TypeNameProperty(parameterJvmType, parameterName, null), constructor, fieldProperty, null @@ -193,41 +203,25 @@ public List generateParameterProperties(ConstructorPropertyGeneratorCo .collect(Collectors.toList()); } - private static TypeReference toTypeReference(AnnotatedType annotatedType) { - return new TypeReference() { - @Override - public Type getType() { - return annotatedType.getType(); - } - - @Override - public AnnotatedType getAnnotatedType() { - return annotatedType; + private static List resolveParameterJvmTypes( + List defaults, + List> inputParameterTypes + ) { + List resolved = new java.util.ArrayList<>(); + for (int i = 0; i < defaults.size(); i++) { + if (inputParameterTypes.size() > i) { + resolved.add(Types.toJvmType( + inputParameterTypes.get(i).getAnnotatedType(), + Collections.emptyList() + )); + } else { + resolved.add(defaults.get(i)); } - }; - } - - private static boolean isGenericAnnotatedType(AnnotatedType annotatedType) { - return annotatedType instanceof AnnotatedTypeVariable || annotatedType instanceof AnnotatedArrayType; - } - - private static Map getGenericAnnotatedTypesByGenericTypeName(Property property) { - Class type = Types.getActualType(property.getType()); - - List genericsTypes = Types.getGenericsTypes(property.getAnnotatedType()); - List>> erasedTypeVariables = Arrays.asList(type.getTypeParameters()); - - if (genericsTypes.size() != erasedTypeVariables.size()) { - return Collections.emptyMap(); - } - - Map actualGenericTypesByTypeName = new HashMap<>(); - for (int i = 0; i < genericsTypes.size(); i++) { - AnnotatedType genericType = genericsTypes.get(i); - TypeVariable> erasedTypeVariable = erasedTypeVariables.get(i); - actualGenericTypesByTypeName.put(erasedTypeVariable.getName(), genericType); } + return resolved; + } - return actualGenericTypesByTypeName; + private static boolean isUnresolvedGenericType(Type type) { + return type instanceof TypeVariable || type instanceof GenericArrayType; } } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ConstructorProperty.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ConstructorProperty.java index c36ad0de7c..e1fa8dd60f 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ConstructorProperty.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ConstructorProperty.java @@ -19,9 +19,7 @@ package com.navercorp.fixturemonkey.api.property; import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; import java.lang.reflect.Constructor; -import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -34,6 +32,9 @@ import org.apiguardian.api.API.Status; import org.jspecify.annotations.Nullable; +import com.navercorp.objectfarm.api.type.JavaType; +import com.navercorp.objectfarm.api.type.JvmType; + @API(since = "0.4.2", status = Status.MAINTAINED) public final class ConstructorProperty implements Property { private final Property parameterProperty; @@ -45,21 +46,6 @@ public final class ConstructorProperty implements Property { @Nullable private final Boolean nullable; - /** - * It is deprecated. - * Use {@link #ConstructorProperty(Property, Constructor, Property, Boolean)} instead. - */ - @Deprecated - public ConstructorProperty( - AnnotatedType annotatedType, - Constructor constructor, - String parameterName, - @Nullable Property fieldProperty, - @Nullable Boolean nullable - ) { - this(new TypeNameProperty(annotatedType, parameterName, nullable), constructor, fieldProperty, nullable); - } - public ConstructorProperty( Property parameterProperty, Constructor constructor, @@ -79,13 +65,22 @@ public ConstructorProperty( } @Override - public Type getType() { - return this.getAnnotatedType().getType(); - } - - @Override - public AnnotatedType getAnnotatedType() { - return this.parameterProperty.getAnnotatedType(); + public JvmType getJvmType() { + JvmType base = this.parameterProperty.getJvmType(); + Boolean effectiveNullable = isNullable(); + Boolean targetNullable = effectiveNullable != null ? effectiveNullable : base.getNullable(); + boolean annotationsAligned = base.getAnnotations().equals(this.annotations); + boolean nullableAligned = Objects.equals(base.getNullable(), targetNullable); + if (annotationsAligned && nullableAligned) { + return base; + } + return new JavaType( + base.getRawType(), + base.getTypeVariables(), + this.annotations, + base.getComponentType(), + targetNullable + ); } public Constructor getConstructor() { @@ -133,7 +128,7 @@ public boolean equals(@Nullable Object obj) { return false; } ConstructorProperty that = (ConstructorProperty)obj; - return parameterProperty.equals(that.parameterProperty.getType()) + return parameterProperty.equals(that.parameterProperty) && constructor.equals(that.constructor) && Objects.equals(fieldProperty, that.fieldProperty) && annotations.equals(that.annotations); @@ -144,16 +139,6 @@ public int hashCode() { return Objects.hash(parameterProperty, constructor, fieldProperty, annotations); } - @Nullable - @Override - public Object getValue(Object instance) { - if (fieldProperty != null) { - return fieldProperty.getValue(instance); - } else { - return null; - } - } - @Override public String toString() { return "ConstructorProperty{" diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/DefaultContainerElementProperty.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/DefaultContainerElementProperty.java index a5b522cf1f..9fbd052195 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/DefaultContainerElementProperty.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/DefaultContainerElementProperty.java @@ -19,22 +19,19 @@ package com.navercorp.fixturemonkey.api.property; import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Array; -import java.lang.reflect.Type; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.OptionalDouble; import java.util.OptionalInt; import java.util.OptionalLong; -import java.util.function.Supplier; import org.apiguardian.api.API; import org.apiguardian.api.API.Status; import org.jspecify.annotations.Nullable; import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.objectfarm.api.type.JvmType; @API(since = "1.1.6", status = Status.EXPERIMENTAL) public final class DefaultContainerElementProperty extends ElementProperty implements ContainerElementProperty { @@ -50,7 +47,7 @@ public DefaultContainerElementProperty( @Nullable Integer index, int sequence ) { - super(containerProperty, elementProperty.getAnnotatedType(), index, sequence); + super(containerProperty, elementProperty.getJvmType(), index, sequence); this.containerProperty = containerProperty; this.elementProperty = elementProperty; this.index = index; @@ -79,13 +76,8 @@ public Integer getIndex() { } @Override - public Type getType() { - return this.elementProperty.getType(); - } - - @Override - public AnnotatedType getAnnotatedType() { - return this.elementProperty.getAnnotatedType(); + public JvmType getJvmType() { + return this.elementProperty.getJvmType(); } @Nullable @@ -99,38 +91,6 @@ public List getAnnotations() { return this.elementProperty.getAnnotations(); } - @Nullable - @Override - public Object getValue(Object instance) { - // TODO: should split as a implementation of ContainerElementProperty - Class actualType = Types.getActualType(instance.getClass()); - if (isOptional(actualType)) { - return getOptionalValue(instance); - } - - if (actualType.isArray()) { - if (Array.getLength(instance) == 0) { - return null; - } - - return Array.get(instance, sequence); - } - - if (List.class.isAssignableFrom(actualType)) { - List list = (List)instance; - if (list.isEmpty()) { - return null; - } - return list.get(sequence); - } - - if (Supplier.class.isAssignableFrom(actualType)) { - return instance; - } - - throw new IllegalArgumentException("given element value has no match sequence : " + sequence); - } - private boolean isOptional(Class type) { return Optional.class.isAssignableFrom(type) || OptionalInt.class.isAssignableFrom(type) diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ElementProperty.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ElementProperty.java index 040136a2d5..555868545a 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ElementProperty.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ElementProperty.java @@ -19,10 +19,6 @@ package com.navercorp.fixturemonkey.api.property; import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Array; -import java.lang.reflect.Type; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; @@ -31,7 +27,6 @@ import java.util.OptionalInt; import java.util.OptionalLong; import java.util.function.Function; -import java.util.function.Supplier; import java.util.stream.Collectors; import org.apiguardian.api.API; @@ -61,12 +56,12 @@ public class ElementProperty implements ContainerElementProperty { public ElementProperty( Property containerProperty, - AnnotatedType elementType, + JvmType elementType, @Nullable Integer index, int sequence ) { this.containerProperty = containerProperty; - this.elementType = Types.toJvmType(elementType, Collections.emptyList()); + this.elementType = elementType; this.index = index; this.sequence = sequence; this.annotationsMap = this.elementType.getAnnotations().stream() @@ -74,13 +69,8 @@ public ElementProperty( } @Override - public Type getType() { - return this.elementType.getRawType(); - } - - @Override - public AnnotatedType getAnnotatedType() { - return this.elementType.getAnnotatedType(); + public JvmType getJvmType() { + return this.elementType; } public Property getContainerProperty() { @@ -92,10 +82,6 @@ public Property getElementProperty() { return this; } - public AnnotatedType getElementType() { - return this.elementType.getAnnotatedType(); - } - @Nullable public Integer getIndex() { return this.index; @@ -122,37 +108,6 @@ public Optional getAnnotation(Class annotationClass .map(annotationClass::cast); } - @Nullable - @Override - public Object getValue(Object instance) { - Class actualType = Types.getActualType(instance.getClass()); - if (isOptional(actualType)) { - return getOptionalValue(instance); - } - - if (actualType.isArray()) { - if (Array.getLength(instance) == 0) { - return null; - } - - return Array.get(instance, sequence); - } - - if (List.class.isAssignableFrom(actualType)) { - List list = (List)instance; - if (list.isEmpty()) { - return null; - } - return list.get(sequence); - } - - if (Supplier.class.isAssignableFrom(actualType)) { - return instance; - } - - throw new IllegalArgumentException("given element value has no match sequence : " + sequence); - } - @Override public boolean equals(@Nullable Object obj) { if (this == obj) { diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/FieldProperty.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/FieldProperty.java index f48349f2af..7c6f2597f5 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/FieldProperty.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/FieldProperty.java @@ -19,9 +19,7 @@ package com.navercorp.fixturemonkey.api.property; import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; import java.lang.reflect.Field; -import java.lang.reflect.Type; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -43,28 +41,26 @@ public final class FieldProperty implements Property { private final JvmType jvmType; private final Field field; private final Map, Annotation> annotationsMap; + @Nullable + private final Boolean nullable; public FieldProperty(Field field) { - this(TypeCache.getAnnotatedType(field), field); + this( + Types.toJvmType( + TypeCache.getAnnotatedType(field), + Arrays.stream(field.getAnnotations()).collect(Collectors.toList()) + ), + field, + null + ); } - /** - * In general, annotatedType uses the AnnotatedType of Field. - * When the Type of Field is defined as generics, the refied type is not known. - * Use this constructor when specifying a Type that provides a refied Generics type. - * - * @param annotatedType annotatedType of the property - * @param field field of the property - * @see com.navercorp.fixturemonkey.api.type.Types - */ - public FieldProperty(AnnotatedType annotatedType, Field field) { - this.jvmType = Types.toJvmType( - annotatedType, - Arrays.stream(field.getAnnotations()).collect(Collectors.toList()) - ); + public FieldProperty(JvmType jvmType, Field field, @Nullable Boolean nullable) { + this.jvmType = jvmType; this.field = field; - this.annotationsMap = this.getAnnotations().stream() + this.annotationsMap = jvmType.getAnnotations().stream() .collect(Collectors.toMap(Annotation::annotationType, Function.identity(), (a1, a2) -> a1)); + this.nullable = nullable; } public Field getField() { @@ -72,13 +68,8 @@ public Field getField() { } @Override - public Type getType() { - return this.jvmType.getRawType(); - } - - @Override - public AnnotatedType getAnnotatedType() { - return this.jvmType.getAnnotatedType(); + public JvmType getJvmType() { + return this.jvmType; } @Override @@ -91,6 +82,12 @@ public List getAnnotations() { return jvmType.getAnnotations(); } + @Override + @Nullable + public Boolean isNullable() { + return nullable; + } + @Override public Optional getAnnotation(Class annotationClass) { return Optional.ofNullable(this.annotationsMap.get(annotationClass)) @@ -116,24 +113,10 @@ public int hashCode() { return Objects.hash(jvmType); } - @Nullable - @Override - public Object getValue(Object instance) { - try { - this.field.setAccessible(true); - return this.field.get(instance); - } catch (IllegalAccessException ex) { - throw new IllegalArgumentException( - "Can not extract value. obj: " + instance.toString() + ", fieldName: " + this.field.getName(), - ex - ); - } - } - @Override public String toString() { return "FieldProperty{" - + "annotatedType=" + getAnnotatedType() + + "jvmType=" + jvmType + ", field=" + field + '}'; } } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/FieldPropertyGenerator.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/FieldPropertyGenerator.java index c2b0c64ef0..b323a0d6bc 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/FieldPropertyGenerator.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/FieldPropertyGenerator.java @@ -33,7 +33,8 @@ import com.navercorp.fixturemonkey.api.matcher.Matcher; import com.navercorp.fixturemonkey.api.type.TypeCache; -import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.objectfarm.api.type.JvmType; +import com.navercorp.objectfarm.api.type.JvmTypes; /** * Generates field properties including not only declared fields but also super class fields and interface fields. @@ -55,18 +56,21 @@ public FieldPropertyGenerator(Predicate fieldPredicate, Matcher matcher) @Override @SuppressWarnings("argument") public List generateChildProperties(Property property) { - Stream arbitraryfieldStream = TypeCache.getFieldsByName(Types.getActualType(property.getType())) + JvmType parentJvmType = property.getJvmType(); + Class parentRawType = parentJvmType.getRawType(); + + Stream arbitraryfieldStream = TypeCache.getFieldsByName(parentRawType) .values() .stream() .filter(fieldPredicate.and(CONSTANT_FIELD_PREDICATE.negate())) .map(field -> new FieldProperty( - Types.resolveWithTypeReferenceGenerics(property.getAnnotatedType(), field.getAnnotatedType()), - field + JvmTypes.resolveJvmType(parentJvmType, field.getGenericType(), Arrays.asList(field.getAnnotations())), + field, + null )) .filter(matcher::match); - Stream constantPropertyStream = TypeCache.getFieldsByName( - Types.getActualType(property.getType())).values().stream() + Stream constantPropertyStream = TypeCache.getFieldsByName(parentRawType).values().stream() .filter(CONSTANT_FIELD_PREDICATE) .map(field -> { Object constantValue = null; @@ -76,12 +80,12 @@ public List generateChildProperties(Property property) { LOGGER.warn("Field {} is inaccessible.", field.getName(), ex); } - return new ConstantProperty( - Types.resolveWithTypeReferenceGenerics(property.getAnnotatedType(), field.getAnnotatedType()), - field.getName(), - constantValue, + JvmType resolvedJvmType = JvmTypes.resolveJvmType( + parentJvmType, + field.getGenericType(), Arrays.asList(field.getAnnotations()) ); + return new ConstantProperty(resolvedJvmType, field.getName(), constantValue); }); return Stream.concat(arbitraryfieldStream, constantPropertyStream) diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/InterfaceCandidateConcretePropertyResolver.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/InterfaceCandidateConcretePropertyResolver.java index 98acd39b4a..31857f83d1 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/InterfaceCandidateConcretePropertyResolver.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/InterfaceCandidateConcretePropertyResolver.java @@ -18,14 +18,15 @@ package com.navercorp.fixturemonkey.api.property; -import static com.navercorp.fixturemonkey.api.type.Types.generateAnnotatedTypeWithoutAnnotation; - +import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import org.apiguardian.api.API; import org.apiguardian.api.API.Status; +import com.navercorp.fixturemonkey.api.type.Types; + /** * It is deprecated. * Use {@link ConcreteTypeCandidateConcretePropertyResolver} instead. @@ -42,8 +43,11 @@ public InterfaceCandidateConcretePropertyResolver(List> imple @Override public List resolve(Property property) { return implementations.stream() - .map(implementation -> new ConcreteTypeProperty( - generateAnnotatedTypeWithoutAnnotation(implementation), + .map(implementation -> (Property)new ConcreteTypeProperty( + Types.toJvmType( + Types.generateAnnotatedTypeWithoutAnnotation(implementation), + Collections.emptyList() + ), property )) .collect(Collectors.toList()); diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/InterfaceJavaMethodProperty.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/InterfaceJavaMethodProperty.java index b30207f7c1..2f171f5585 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/InterfaceJavaMethodProperty.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/InterfaceJavaMethodProperty.java @@ -19,8 +19,6 @@ package com.navercorp.fixturemonkey.api.property; import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Type; import java.util.List; import java.util.Map; import java.util.Objects; @@ -32,7 +30,6 @@ import org.apiguardian.api.API.Status; import org.jspecify.annotations.Nullable; -import com.navercorp.fixturemonkey.api.type.Types; import com.navercorp.objectfarm.api.type.JvmType; /** @@ -46,26 +43,22 @@ public final class InterfaceJavaMethodProperty implements MethodProperty { private final Map, Annotation> annotationsMap; public InterfaceJavaMethodProperty( - AnnotatedType returnAnnotatedType, + JvmType returnJvmType, String name, String methodName, List annotations ) { - this.returnJvmType = Types.toJvmType(returnAnnotatedType, annotations); + this.returnJvmType = returnJvmType; this.name = name; this.methodName = methodName; this.annotationsMap = annotations.stream() .collect(Collectors.toMap(Annotation::annotationType, Function.identity(), (a1, a2) -> a1)); } - @Override - public Type getType() { - return this.returnJvmType.getRawType(); - } @Override - public AnnotatedType getAnnotatedType() { - return this.returnJvmType.getAnnotatedType(); + public JvmType getJvmType() { + return this.returnJvmType; } @Override @@ -88,12 +81,6 @@ public Optional getAnnotation(Class annotationClass .map(annotationClass::cast); } - @Nullable - @Override - public Object getValue(Object obj) { - throw new UnsupportedOperationException("Interface method should not be called."); - } - @Override public boolean equals(@Nullable Object obj) { if (this == obj) { diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/JavaBeansPropertyGenerator.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/JavaBeansPropertyGenerator.java index 36a983a518..420c339a46 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/JavaBeansPropertyGenerator.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/JavaBeansPropertyGenerator.java @@ -28,7 +28,6 @@ import com.navercorp.fixturemonkey.api.matcher.Matcher; import com.navercorp.fixturemonkey.api.type.TypeCache; -import com.navercorp.fixturemonkey.api.type.Types; /** * Generates JavaBeans properties which have getter method. @@ -48,7 +47,7 @@ public JavaBeansPropertyGenerator( @Override public List generateChildProperties(Property property) { - return TypeCache.getPropertyDescriptorsByPropertyName(Types.getActualType(property.getType())).values() + return TypeCache.getPropertyDescriptorsByPropertyName(property.getJvmType().getRawType()).values() .stream() .filter(it -> it.getReadMethod() != null) .filter(propertyDescriptorPredicate) diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/MapEntryElementProperty.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/MapEntryElementProperty.java index 3ba59f9302..54dd8848d7 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/MapEntryElementProperty.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/MapEntryElementProperty.java @@ -18,34 +18,28 @@ package com.navercorp.fixturemonkey.api.property; -import static com.navercorp.fixturemonkey.api.type.Types.generateAnnotatedTypeWithoutAnnotation; - import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Type; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.Objects; import org.apiguardian.api.API; import org.apiguardian.api.API.Status; import org.jspecify.annotations.Nullable; -import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.objectfarm.api.type.JavaType; import com.navercorp.objectfarm.api.type.JvmType; @API(since = "0.4.0", status = Status.MAINTAINED) public final class MapEntryElementProperty implements Property { + private static final JvmType MAP_ENTRY_ELEMENT_JVM_TYPE = new JavaType(MapEntryElementType.class); + private final Property mapEntryProperty; private final Property keyProperty; private final Property valueProperty; - private final JvmType jvmType = - Types.toJvmType(generateAnnotatedTypeWithoutAnnotation(MapEntryElementType.class), Collections.emptyList()); - public MapEntryElementProperty( Property mapEntryProperty, Property keyProperty, @@ -69,13 +63,8 @@ public Property getValueProperty() { } @Override - public Type getType() { - return this.jvmType.getRawType(); - } - - @Override - public AnnotatedType getAnnotatedType() { - return this.jvmType.getAnnotatedType(); + public JvmType getJvmType() { + return MAP_ENTRY_ELEMENT_JVM_TYPE; } @Override @@ -89,20 +78,6 @@ public List getAnnotations() { return Collections.emptyList(); } - @Nullable - @Override - public Object getValue(Object instance) { - if (instance == null) { - return null; - } - - Class actualType = Types.getActualType(instance.getClass()); - if (!(Map.class.isAssignableFrom(actualType) || Map.Entry.class.isAssignableFrom(actualType))) { - throw new IllegalArgumentException("given value is not Map or MapEntry type " + actualType); - } - return instance; - } - @Override public boolean equals(@Nullable Object obj) { if (this == obj) { diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/MapKeyElementProperty.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/MapKeyElementProperty.java index 9980c1cd73..6d9f33ba8f 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/MapKeyElementProperty.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/MapKeyElementProperty.java @@ -19,19 +19,14 @@ package com.navercorp.fixturemonkey.api.property; import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Type; -import java.util.Iterator; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; import java.util.Objects; import org.apiguardian.api.API; import org.apiguardian.api.API.Status; import org.jspecify.annotations.Nullable; -import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.objectfarm.api.type.JvmType; @API(since = "0.4.0", status = Status.MAINTAINED) public final class MapKeyElementProperty implements Property { @@ -41,18 +36,6 @@ public final class MapKeyElementProperty implements Property { private final int sequence; - /** - * Use {@link MapKeyElementProperty(Property, Property, int)} instead. - */ - @Deprecated - public MapKeyElementProperty( - Property mapProperty, - AnnotatedType keyType, - int sequence - ) { - this(mapProperty, new TypeParameterProperty(keyType), sequence); - } - public MapKeyElementProperty(Property mapProperty, Property keyProperty, int sequence) { this.mapProperty = mapProperty; this.keyProperty = keyProperty; @@ -60,21 +43,16 @@ public MapKeyElementProperty(Property mapProperty, Property keyProperty, int seq } @Override - public Type getType() { - return this.getAnnotatedType().getType(); - } - - @Override - public AnnotatedType getAnnotatedType() { - return this.keyProperty.getAnnotatedType(); + public JvmType getJvmType() { + return this.keyProperty.getJvmType(); } public Property getMapProperty() { return mapProperty; } - public AnnotatedType getKeyType() { - return this.keyProperty.getAnnotatedType(); + public Property getKeyProperty() { + return this.keyProperty; } public int getSequence() { @@ -97,32 +75,6 @@ public Boolean isNullable() { return false; } - @Nullable - @Override - public Object getValue(Object instance) { - Class actualType = Types.getActualType(instance.getClass()); - - if (Map.class.isAssignableFrom(actualType)) { - Map map = (Map)instance; - Iterator> iterator = map.entrySet().iterator(); - int iteratorSequence = 0; - while (iterator.hasNext()) { - Entry value = iterator.next(); - if (iteratorSequence == getSequence()) { - return value.getKey(); - } - iteratorSequence++; - } - } - - if (Map.Entry.class.isAssignableFrom(actualType)) { - Map.Entry entry = (Map.Entry)instance; - return entry.getKey(); - } - - throw new IllegalArgumentException("given value is not Map Entry. " + instance.getClass()); - } - @Override public boolean equals(@Nullable Object obj) { if (this == obj) { diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/MapValueElementProperty.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/MapValueElementProperty.java index 96b8f70fcc..e7aba714f6 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/MapValueElementProperty.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/MapValueElementProperty.java @@ -19,19 +19,14 @@ package com.navercorp.fixturemonkey.api.property; import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Type; -import java.util.Iterator; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; import java.util.Objects; import org.apiguardian.api.API; import org.apiguardian.api.API.Status; import org.jspecify.annotations.Nullable; -import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.objectfarm.api.type.JvmType; @API(since = "0.4.0", status = Status.MAINTAINED) public final class MapValueElementProperty implements Property { @@ -41,19 +36,6 @@ public final class MapValueElementProperty implements Property { private final int sequence; - /** - * It is deprecated; - * Use {@link #MapValueElementProperty(Property, Property, int)} instead. - */ - @Deprecated - public MapValueElementProperty( - Property mapProperty, - AnnotatedType valueType, - int sequence - ) { - this(mapProperty, new TypeParameterProperty(valueType), sequence); - } - public MapValueElementProperty(Property mapProperty, Property valueProperty, int sequence) { this.mapProperty = mapProperty; this.valueProperty = valueProperty; @@ -61,21 +43,16 @@ public MapValueElementProperty(Property mapProperty, Property valueProperty, int } @Override - public Type getType() { - return this.getAnnotatedType().getType(); - } - - @Override - public AnnotatedType getAnnotatedType() { - return this.valueProperty.getAnnotatedType(); + public JvmType getJvmType() { + return this.valueProperty.getJvmType(); } public Property getMapProperty() { return mapProperty; } - public AnnotatedType getValueType() { - return valueProperty.getAnnotatedType(); + public Property getValueProperty() { + return valueProperty; } public int getSequence() { @@ -93,32 +70,6 @@ public List getAnnotations() { return this.valueProperty.getAnnotations(); } - @Nullable - @Override - public Object getValue(Object instance) { - Class actualType = Types.getActualType(instance.getClass()); - - if (Map.class.isAssignableFrom(actualType)) { - Map map = (Map)instance; - Iterator> iterator = map.entrySet().iterator(); - int iteratorSequence = 0; - while (iterator.hasNext()) { - Entry value = iterator.next(); - if (iteratorSequence == getSequence()) { - return value.getValue(); - } - iteratorSequence++; - } - } - - if (Map.Entry.class.isAssignableFrom(actualType)) { - Map.Entry entry = (Map.Entry)instance; - return entry.getValue(); - } - - throw new IllegalArgumentException("given value is not Map Entry. " + instance.getClass()); - } - @Override public boolean equals(@Nullable Object obj) { if (this == obj) { diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/MethodParameterProperty.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/MethodParameterProperty.java index c884ff2248..1ddd8157f5 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/MethodParameterProperty.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/MethodParameterProperty.java @@ -19,14 +19,10 @@ package com.navercorp.fixturemonkey.api.property; import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Type; -import java.util.Collections; import java.util.List; import org.jspecify.annotations.Nullable; -import com.navercorp.fixturemonkey.api.type.Types; import com.navercorp.objectfarm.api.type.JvmType; /** @@ -42,23 +38,18 @@ public final class MethodParameterProperty implements Property { private final Boolean nullable; public MethodParameterProperty( - AnnotatedType annotatedType, + JvmType jvmType, @Nullable String parameterName, @Nullable Boolean nullable ) { - this.jvmType = Types.toJvmType(annotatedType, Collections.emptyList()); + this.jvmType = jvmType; this.parameterName = parameterName; this.nullable = nullable; } @Override - public Type getType() { - return jvmType.getRawType(); - } - - @Override - public AnnotatedType getAnnotatedType() { - return jvmType.getAnnotatedType(); + public JvmType getJvmType() { + return jvmType; } @Nullable @@ -72,12 +63,6 @@ public List getAnnotations() { return jvmType.getAnnotations(); } - @Nullable - @Override - public Object getValue(Object instance) { - throw new UnsupportedOperationException(); - } - @Nullable @Override public Boolean isNullable() { diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/Property.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/Property.java index 00835bd09c..c498bcea2d 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/Property.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/Property.java @@ -19,8 +19,6 @@ package com.navercorp.fixturemonkey.api.property; import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Type; import java.util.List; import java.util.Optional; @@ -31,6 +29,8 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import com.navercorp.objectfarm.api.type.JvmType; + /** * Specifies actual property comprise an instance. * It should have a unique name. @@ -40,18 +40,11 @@ @API(since = "0.4.0", status = Status.MAINTAINED) public interface Property { /** - * Returns the type of property. - * - * @return the type of property - */ - Type getType(); - - /** - * Returns the annotatedType of property. + * Returns the {@link JvmType} representation of this property. * - * @return the annotatedType of property + * @return the JvmType of property */ - AnnotatedType getAnnotatedType(); + JvmType getJvmType(); /** * Returns the property name. @@ -84,15 +77,6 @@ default Optional getAnnotation(Class annotationClas .findFirst(); } - /** - * Returns a value of the property in {@code instance}. - * - * @param instance an instance which has the property - * @return a value of the property in {@code instance} - */ - @Nullable - Object getValue(Object instance); - /** * Returns whether this property is nullable or not. * diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/PropertyDescriptorProperty.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/PropertyDescriptorProperty.java index d5f2ae729b..fed3ce2dae 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/PropertyDescriptorProperty.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/PropertyDescriptorProperty.java @@ -22,9 +22,6 @@ import java.beans.PropertyDescriptor; import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -48,19 +45,19 @@ public final class PropertyDescriptorProperty implements Property { private final Map, Annotation> annotationsMap; public PropertyDescriptorProperty(PropertyDescriptor propertyDescriptor) { - this(TypeCache.getAnnotatedType(propertyDescriptor), propertyDescriptor); + this(Types.toJvmType( + TypeCache.getAnnotatedType(propertyDescriptor), collectMethodAnnotations(propertyDescriptor)), + propertyDescriptor); } - /** - * In general, annotatedType uses the PropertyType of PropertyDescriptor. - * When the Type of PropertyDescriptor is defined as generics, the refied type is not known. - * Use this constructor when specifying a Type that provides a refied Generics type. - * - * @param annotatedType annotatedType of the property - * @param propertyDescriptor propertyDescriptor of the property - * @see com.navercorp.fixturemonkey.api.type.Types - */ - public PropertyDescriptorProperty(AnnotatedType annotatedType, PropertyDescriptor propertyDescriptor) { + public PropertyDescriptorProperty(JvmType jvmType, PropertyDescriptor propertyDescriptor) { + this.jvmType = jvmType; + this.propertyDescriptor = propertyDescriptor; + this.annotationsMap = jvmType.getAnnotations().stream() + .collect(toMap(Annotation::annotationType, Function.identity(), (a1, a2) -> a1)); + } + + private static List collectMethodAnnotations(PropertyDescriptor propertyDescriptor) { List concatAnnotations = new ArrayList<>(); if (propertyDescriptor.getWriteMethod() != null) { concatAnnotations.addAll(Arrays.asList(propertyDescriptor.getWriteMethod().getAnnotations())); @@ -68,10 +65,7 @@ public PropertyDescriptorProperty(AnnotatedType annotatedType, PropertyDescripto if (propertyDescriptor.getReadMethod() != null) { concatAnnotations.addAll(Arrays.asList(propertyDescriptor.getReadMethod().getAnnotations())); } - this.jvmType = Types.toJvmType(annotatedType, concatAnnotations); - this.propertyDescriptor = propertyDescriptor; - this.annotationsMap = this.getAnnotations().stream() - .collect(toMap(Annotation::annotationType, Function.identity(), (a1, a2) -> a1)); + return concatAnnotations; } public PropertyDescriptor getPropertyDescriptor() { @@ -79,13 +73,8 @@ public PropertyDescriptor getPropertyDescriptor() { } @Override - public Type getType() { - return this.getAnnotatedType().getType(); - } - - @Override - public AnnotatedType getAnnotatedType() { - return this.jvmType.getAnnotatedType(); + public JvmType getJvmType() { + return this.jvmType; } @Override @@ -104,21 +93,6 @@ public Optional getAnnotation(Class annotationClass .map(annotationClass::cast); } - @Nullable - @Override - @SuppressWarnings("dereference.of.nullable") - public Object getValue(Object instance) { - try { - return this.propertyDescriptor.getReadMethod().invoke(instance); - } catch (InvocationTargetException | IllegalAccessException ex) { - throw new IllegalArgumentException( - "Can not invoke value. obj: " + instance.toString() + ", propertyName: " - + this.propertyDescriptor.getName(), - ex - ); - } - } - @Override public boolean equals(@Nullable Object obj) { if (this == obj) { @@ -139,7 +113,7 @@ public int hashCode() { @Override public String toString() { return "PropertyDescriptorProperty{" - + "annotatedType=" + jvmType.getAnnotatedType() + + "jvmType=" + jvmType + ", propertyDescriptor=" + propertyDescriptor + '}'; } } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/PropertyUtils.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/PropertyUtils.java index f019e9a653..3a2db1d5cd 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/PropertyUtils.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/PropertyUtils.java @@ -20,8 +20,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Type; -import java.util.Arrays; +import java.util.Collections; import java.util.List; import org.apiguardian.api.API; @@ -30,27 +29,32 @@ import com.navercorp.fixturemonkey.api.type.TypeReference; import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.objectfarm.api.type.JavaType; +import com.navercorp.objectfarm.api.type.JvmType; @API(since = "0.6.12", status = Status.MAINTAINED) public abstract class PropertyUtils { public static Property toProperty(Class type) { - return PropertyUtils.toProperty(Types.generateAnnotatedTypeWithoutAnnotation(type)); + return toProperty(new JavaType(type)); } public static Property toProperty(TypeReference typeReference) { - return toProperty(typeReference.getAnnotatedType()); + return toProperty(typeReference.getJvmType()); } + /** + * @deprecated Prefer {@link #toProperty(JvmType)}. + */ + @Deprecated public static Property toProperty(AnnotatedType annotatedType) { - return new Property() { - @Override - public Type getType() { - return annotatedType.getType(); - } + return toProperty(Types.toJvmType(annotatedType, Collections.emptyList())); + } + public static Property toProperty(JvmType jvmType) { + return new Property() { @Override - public AnnotatedType getAnnotatedType() { - return annotatedType; + public JvmType getJvmType() { + return jvmType; } @Nullable @@ -61,18 +65,12 @@ public String getName() { @Override public List getAnnotations() { - return Arrays.asList(annotatedType.getAnnotations()); - } - - @Nullable - @Override - public Object getValue(Object instance) { - throw new UnsupportedOperationException(); + return jvmType.getAnnotations(); } @Override public int hashCode() { - return getType().hashCode(); + return jvmType.getRawType().hashCode(); } @Override @@ -85,13 +83,12 @@ public boolean equals(@Nullable Object obj) { } Property that = (Property)obj; - return getType().equals(that.getType()); + return jvmType.getRawType().equals(that.getJvmType().getRawType()); } }; } public static boolean isErasedProperty(Property property) { - return Types.getActualType(property.getType()) == Object.class - || Types.getActualType(property.getAnnotatedType()) == Object.class; + return property.getJvmType().getRawType() == Object.class; } } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/RootProperty.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/RootProperty.java index c210eb6089..4e56df7a24 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/RootProperty.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/RootProperty.java @@ -1,7 +1,5 @@ package com.navercorp.fixturemonkey.api.property; -import java.lang.reflect.AnnotatedType; - import org.apiguardian.api.API; import org.apiguardian.api.API.Status; @@ -13,14 +11,6 @@ public final class RootProperty implements TreeRootProperty { private final Property delgeatedProperty; - /** - * It is deprecated. Use {@link #RootProperty(Property)} instead. - */ - @Deprecated - public RootProperty(AnnotatedType annotatedType) { - this.delgeatedProperty = new TypeParameterProperty(annotatedType); - } - public RootProperty(Property delgeatedProperty) { this.delgeatedProperty = delgeatedProperty; } @@ -33,6 +23,6 @@ public Property getDelgatedProperty() { @Override public String toString() { return "RootProperty{" - + "annotatedType=" + delgeatedProperty.getAnnotatedType() + '}'; + + "jvmType=" + delgeatedProperty.getJvmType() + '}'; } } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/SingleElementProperty.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/SingleElementProperty.java index ab28716327..733be3ae94 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/SingleElementProperty.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/SingleElementProperty.java @@ -19,8 +19,6 @@ package com.navercorp.fixturemonkey.api.property; import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Type; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -32,6 +30,8 @@ import org.jspecify.annotations.Nullable; import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.objectfarm.api.type.JavaType; +import com.navercorp.objectfarm.api.type.JvmType; /** * It is a property for a fixed single element of a container. ex, Optional, Function, Supplier @@ -57,25 +57,31 @@ public final class SingleElementProperty extends ElementProperty implements Cont */ @Deprecated public SingleElementProperty(Property containerProperty) { - super(containerProperty, containerProperty.getAnnotatedType(), null, 0); + super(containerProperty, containerProperty.getJvmType(), null, 0); this.containerProperty = containerProperty; - this.elementProperty = new TypeParameterProperty(containerProperty.getAnnotatedType()); + this.elementProperty = new TypeParameterProperty(containerProperty.getJvmType()); } public SingleElementProperty(Property containerProperty, Property elementProperty) { - super(containerProperty, containerProperty.getAnnotatedType(), null, 0); + super(containerProperty, containerProperty.getJvmType(), null, 0); this.containerProperty = containerProperty; this.elementProperty = elementProperty; } @Override - public Type getType() { - return this.getAnnotatedType().getType(); - } - - @Override - public AnnotatedType getAnnotatedType() { - return this.elementProperty.getAnnotatedType(); + public JvmType getJvmType() { + JvmType base = this.elementProperty.getJvmType(); + List annotations = getAnnotations(); + if (base.getAnnotations().equals(annotations)) { + return base; + } + return new JavaType( + base.getRawType(), + base.getTypeVariables(), + annotations, + base.getComponentType(), + base.getNullable() + ); } @Nullable @@ -89,18 +95,6 @@ public List getAnnotations() { return this.containerProperty.getAnnotations(); } - @Nullable - @Override - public Object getValue(Object instance) { - Class actualType = Types.getActualType(instance.getClass()); - - if (isOptional(actualType)) { - return getOptionalValue(instance); - } - - return instance; - } - @Override public Property getContainerProperty() { return this.containerProperty; diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/TreeRootProperty.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/TreeRootProperty.java index baa32b2d80..ce7690bb08 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/TreeRootProperty.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/TreeRootProperty.java @@ -19,16 +19,13 @@ package com.navercorp.fixturemonkey.api.property; import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Type; import java.util.Collections; import java.util.List; import org.apiguardian.api.API; import org.apiguardian.api.API.Status; -import org.jspecify.annotations.Nullable; -import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.objectfarm.api.type.JvmType; /** * It is the property of the root node within the object tree. @@ -44,13 +41,8 @@ public interface TreeRootProperty extends Property { Property getDelgatedProperty(); @Override - default Type getType() { - return getAnnotatedType().getType(); - } - - @Override - default AnnotatedType getAnnotatedType() { - return getDelgatedProperty().getAnnotatedType(); + default JvmType getJvmType() { + return getDelgatedProperty().getJvmType(); } @Override @@ -63,16 +55,4 @@ default List getAnnotations() { return Collections.emptyList(); } - @Nullable - @Override - default Object getValue(Object instance) { - if (Types.getActualType(this.getType()) == instance.getClass()) { - return instance; - } - - throw new IllegalArgumentException( - "RootProperty obj is not a root type. annotatedType: " + this.getAnnotatedType() - + ", objType: " + instance.getClass() - ); - } } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/TypeNameProperty.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/TypeNameProperty.java index 177083a2b3..1f77f11269 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/TypeNameProperty.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/TypeNameProperty.java @@ -19,9 +19,6 @@ package com.navercorp.fixturemonkey.api.property; import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Type; -import java.util.Collections; import java.util.List; import java.util.Objects; @@ -29,7 +26,6 @@ import org.apiguardian.api.API.Status; import org.jspecify.annotations.Nullable; -import com.navercorp.fixturemonkey.api.type.Types; import com.navercorp.objectfarm.api.type.JvmType; /** @@ -44,23 +40,18 @@ public final class TypeNameProperty implements Property { private final Boolean nullable; public TypeNameProperty( - AnnotatedType annotatedType, + JvmType jvmType, String typeName, @Nullable Boolean nullable ) { - this.jvmType = Types.toJvmType(annotatedType, Collections.emptyList()); + this.jvmType = jvmType; this.typeName = typeName; this.nullable = nullable; } @Override - public Type getType() { - return jvmType.getRawType(); - } - - @Override - public AnnotatedType getAnnotatedType() { - return jvmType.getAnnotatedType(); + public JvmType getJvmType() { + return jvmType; } @Nullable @@ -74,12 +65,6 @@ public List getAnnotations() { return jvmType.getAnnotations(); } - @Nullable - @Override - public Object getValue(Object instance) { - throw new UnsupportedOperationException(); - } - @Nullable @Override public Boolean isNullable() { diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/TypeParameterProperty.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/TypeParameterProperty.java index 70ce75234d..2ecdb2715b 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/TypeParameterProperty.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/TypeParameterProperty.java @@ -19,9 +19,6 @@ package com.navercorp.fixturemonkey.api.property; import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Type; -import java.util.Collections; import java.util.List; import java.util.Objects; @@ -29,31 +26,23 @@ import org.apiguardian.api.API.Status; import org.jspecify.annotations.Nullable; -import com.navercorp.fixturemonkey.api.type.Types; import com.navercorp.objectfarm.api.type.JvmType; /** * It is a property for a type parameter. * It is used to represent a type parameter of a generic class or method. - * It does not support {@link #getValue(Object)} - * because there is no way to get the value of the property from the object. */ @API(since = "1.1.6", status = Status.EXPERIMENTAL) public final class TypeParameterProperty implements Property { private final JvmType type; - public TypeParameterProperty(AnnotatedType typeParameterAnnotatedType) { - this.type = Types.toJvmType(typeParameterAnnotatedType, Collections.emptyList()); + public TypeParameterProperty(JvmType type) { + this.type = type; } @Override - public Type getType() { - return this.type.getRawType(); - } - - @Override - public AnnotatedType getAnnotatedType() { - return this.type.getAnnotatedType(); + public JvmType getJvmType() { + return this.type; } /** @@ -72,12 +61,6 @@ public List getAnnotations() { return this.type.getAnnotations(); } - @Nullable - @Override - public Object getValue(Object instance) { - throw new UnsupportedOperationException("type parameter property does not support getValue"); - } - @Override public boolean equals(@Nullable Object obj) { if (this == obj) { diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/random/Randoms.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/random/Randoms.java index e0eefdf2e5..3aa4c6f8e8 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/random/Randoms.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/random/Randoms.java @@ -65,6 +65,21 @@ public static void setSeed(long seed) { SEED.set(seed); } + /** + * Applies a builder-configured seed unless an active {@link SeedClaim} + * holds priority on the current thread (e.g. a {@code @Seed} annotation). + * When a claim is active, the call is a no-op so the higher-priority + * seed remains in effect. + * + * @param seed the seed value + */ + public static void applyBuilderSeed(long seed) { + if (SeedClaim.isActive()) { + return; + } + initializeGlobalSeed(seed); + } + /** * Creates a new random instance with the given seed. * It affects the global seed value across multiple FixtureMonkey instances. diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/random/SeedClaim.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/random/SeedClaim.java new file mode 100644 index 0000000000..5db4882858 --- /dev/null +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/random/SeedClaim.java @@ -0,0 +1,100 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.api.random; + +import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; +import org.jspecify.annotations.Nullable; + +/** + * Thread-scoped claim of priority over the global seed managed by {@link Randoms}. + * + *

While a claim is active on the current thread, {@link Randoms#applyBuilderSeed(long)} + * becomes a no-op so that lower-priority seed configuration (e.g. + * {@code FixtureMonkeyBuilder.seed(long)}) cannot override the claim. + * + *

Claims are re-entrant: nested {@link #establish(long)} calls are tracked and + * unwound in LIFO order via {@link #close()}. Use try-with-resources or hand the + * claim to a JUnit {@code ExtensionContext.Store} as a {@code CloseableResource} + * to guarantee release. + * + *

{@code
+ * try (SeedClaim ignored = SeedClaim.establish(42L)) {
+ *     // FixtureMonkeyBuilder.seed(...) calls inside this block are ignored.
+ * }
+ * }
+ */ +@API(since = "1.1.18", status = Status.INTERNAL) +public final class SeedClaim implements AutoCloseable { + @SuppressWarnings("type.argument") + private static final ThreadLocal ACTIVE = new ThreadLocal<>(); + + @Nullable + private final SeedClaim previous; + private boolean closed; + + private SeedClaim(@Nullable SeedClaim previous) { + this.previous = previous; + } + + /** + * Establishes a new claim on the current thread, applies the given seed + * via {@link Randoms#newGlobalSeed(long)}, and returns the claim handle. + * + *

Existing claims (if any) are stacked and restored when this claim + * is closed. + * + * @param seed the seed value to apply + * @return a closeable handle that releases the claim when closed + */ + public static SeedClaim establish(long seed) { + SeedClaim claim = new SeedClaim(ACTIVE.get()); + ACTIVE.set(claim); + Randoms.newGlobalSeed(seed); + return claim; + } + + /** + * @return {@code true} if any claim is active on the current thread + */ + public static boolean isActive() { + return ACTIVE.get() != null; + } + + /** + * Releases this claim, restoring the previously active claim if any. + * Safe to call multiple times. Releasing a claim that is not the topmost + * is a no-op for the active slot, but still marks this claim closed so + * the previous link is dropped. + */ + @Override + public void close() { + if (closed) { + return; + } + closed = true; + if (ACTIVE.get() == this) { + if (previous == null) { + ACTIVE.remove(); + } else { + ACTIVE.set(previous); + } + } + } +} diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/DefaultTraverseNode.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/DefaultTraverseNode.java deleted file mode 100644 index 9be870dd4e..0000000000 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/DefaultTraverseNode.java +++ /dev/null @@ -1,548 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.api.tree; - -import static java.util.stream.Collectors.toMap; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; -import org.jspecify.annotations.Nullable; - -import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfo; -import com.navercorp.fixturemonkey.api.generator.ArbitraryGeneratorContext; -import com.navercorp.fixturemonkey.api.generator.ArbitraryProperty; -import com.navercorp.fixturemonkey.api.generator.ContainerPropertyGenerator; -import com.navercorp.fixturemonkey.api.generator.ObjectProperty; -import com.navercorp.fixturemonkey.api.generator.ObjectPropertyGenerator; -import com.navercorp.fixturemonkey.api.generator.ObjectPropertyGeneratorContext; -import com.navercorp.fixturemonkey.api.lazy.LazyArbitrary; -import com.navercorp.fixturemonkey.api.property.CompositeTypeDefinition; -import com.navercorp.fixturemonkey.api.property.DefaultTypeDefinition; -import com.navercorp.fixturemonkey.api.property.ElementPropertyGenerator; -import com.navercorp.fixturemonkey.api.property.LazyPropertyGenerator; -import com.navercorp.fixturemonkey.api.property.MapEntryElementProperty; -import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.api.property.PropertyGenerator; -import com.navercorp.fixturemonkey.api.property.PropertyPath; -import com.navercorp.fixturemonkey.api.property.TreeRootProperty; -import com.navercorp.fixturemonkey.api.property.TypeDefinition; - -@API(since = "1.1.4", status = Status.EXPERIMENTAL) -public final class DefaultTraverseNode implements TraverseNode, TraverseNodeMetadata { - private final TreeRootProperty rootProperty; - - @Nullable - private final Property resolvedParentProperty; - private TypeDefinition resolvedTypeDefinition; - private final TreeProperty treeProperty; - private final TraverseContext traverseContext; - - @Nullable - private TraverseNode parent = null; - private @Nullable List children; - @Nullable - private TypeDefinition expandedTypeDefinition = null; - - private double nullInject; - private final List containerInfoManipulators = new ArrayList<>(); - - @SuppressWarnings("nullness") - private final LazyArbitrary lazyPropertyPath = LazyArbitrary.lazy(() -> { - Property resolvedProperty = this.resolvedTypeDefinition.getResolvedProperty(); - if (parent == null) { - return new PropertyPath(resolvedProperty, null, 1); - } - - PropertyPath parentPropertyPath = parent.getMetadata().getLazyPropertyPath().getValue(); - return new PropertyPath( - resolvedProperty, - parentPropertyPath, - parentPropertyPath.getDepth() + 1 - ); - }); - - DefaultTraverseNode( - TreeRootProperty rootProperty, - @Nullable Property resolvedParentProperty, - TypeDefinition resolvedTypeDefinition, - TreeProperty treeProperty, - double nullInject, - TraverseContext traverseContext - ) { - this.rootProperty = rootProperty; - this.resolvedParentProperty = resolvedParentProperty; - this.resolvedTypeDefinition = resolvedTypeDefinition; - this.treeProperty = treeProperty; - this.nullInject = nullInject; - this.traverseContext = traverseContext; - this.children = null; - } - - @Nullable - public Property getResolvedParentProperty() { - return resolvedParentProperty; - } - - /** - * The resolved property refers to the concrete type of {@link #getOriginalProperty()}, - * it can't be an abstract class or interface unless it's an anonymous object. - * - * @return the resolvedProperty - */ - public Property getResolvedProperty() { - return this.resolvedTypeDefinition.getResolvedProperty(); - } - - public TypeDefinition getResolvedTypeDefinition() { - return resolvedTypeDefinition; - } - - public void setResolvedTypeDefinition(TypeDefinition typeDefinition) { - this.resolvedTypeDefinition = typeDefinition; - } - - public TreeProperty getTreeProperty() { - return this.treeProperty; - } - - /** - * The original property refers to the class-time property, which means it is the type in a class file. - * It can be an abstract class or interface, unlike the {@link #getResolvedProperty()} - * - * @return the original property - */ - public Property getOriginalProperty() { - return this.getTreeProperty().getObjectProperty().getProperty(); - } - - @Nullable - @Override - public NodeList getChildren() { - if (children == null) { - return null; - } - return new TraverseNodeList(this.children); - } - - public void setMergedChildren(List children) { - this.children = mergeWithNewChildren(children); - for (TraverseNode child : this.children) { - DefaultTraverseNode defaultTraverseNode = (DefaultTraverseNode)child; - defaultTraverseNode.parent = this; - } - } - - /** - * The ArbitraryProperty remains for backward compatibility with {@link ArbitraryGeneratorContext}. - * - * @return the ArbitraryProperty transformed by ObjectNode's {@link #treeProperty} - */ - public ArbitraryProperty getArbitraryProperty() { - return this.treeProperty.toArbitraryProperty(this.nullInject); - } - - public double getNullInject() { - return nullInject; - } - - public void setNullInject(double nullInject) { - this.nullInject = nullInject; - } - - @Nullable - public TraverseNode getParent() { - return parent; - } - - public TreeRootProperty getRootProperty() { - return rootProperty; - } - - public boolean manipulated() { - return !this.containerInfoManipulators.isEmpty(); - } - - @Override - public List getTreeNodeManipulators() { - return this.containerInfoManipulators; - } - - @Override - public void addTreeNodeManipulator(TreeNodeManipulator treeNodeManipulator) { - this.addContainerManipulator(treeNodeManipulator); - } - - @Nullable - @Override - public TreeNodeManipulator getAppliedTreeNodeManipulator() { - if (containerInfoManipulators.isEmpty()) { - return null; - } - - return containerInfoManipulators.get(containerInfoManipulators.size() - 1); - } - - public void addContainerManipulator(TreeNodeManipulator containerInfoManipulator) { - traverseContext.addContainerInfoManipulator(containerInfoManipulator); - this.containerInfoManipulators.add(containerInfoManipulator); - } - - public LazyArbitrary getLazyPropertyPath() { - return lazyPropertyPath; - } - - @Override - public boolean expand() { - if (this.expandedTypeDefinition != null) { - return false; - } - - this.setMergedChildren( - this.getTreeProperty().getTypeDefinitions().stream() - .flatMap( - typeDefinition -> { - if (this.getTreeProperty().isContainer()) { - return expandContainerNode(typeDefinition, this.traverseContext); - } - - return this.generateChildrenNodes( - typeDefinition.getResolvedProperty(), - typeDefinition.getPropertyGenerator() - .generateChildProperties(typeDefinition.getResolvedProperty()), - this.nullInject, - this.traverseContext - ).stream(); - } - ) - .collect(Collectors.toList()) - ); - this.expandedTypeDefinition = resolvedTypeDefinition; - return true; - } - - @Override - public void forceExpand() { - List newChildren = this.getTreeProperty().getTypeDefinitions().stream() - .flatMap( - typeDefinition -> { - if (this.getTreeProperty().isContainer()) { - return this.expandContainerNode( - typeDefinition, - traverseContext.withParentProperties() - ); - } - - return this.generateChildrenNodes( - typeDefinition.getResolvedProperty(), - typeDefinition.getPropertyGenerator() - .generateChildProperties(typeDefinition.getResolvedProperty()), - this.nullInject, - traverseContext.withParentProperties() - ).stream(); - } - ).collect(Collectors.toList()); - - this.setMergedChildren(newChildren); - this.expandedTypeDefinition = resolvedTypeDefinition; - } - - @Override - public void forceExpand(TypeDefinition typeDefinition) { - List children; - if (this.getTreeProperty().isContainer()) { - children = this.expandContainerNode( - typeDefinition, - traverseContext.withParentProperties() - ).collect(Collectors.toList()); - } else { - children = this.generateChildrenNodes( - typeDefinition.getResolvedProperty(), - typeDefinition.getPropertyGenerator() - .generateChildProperties(typeDefinition.getResolvedProperty()), - this.nullInject, - traverseContext.withParentProperties() - ); - } - this.setMergedChildren(children); - this.expandedTypeDefinition = typeDefinition; - } - - @Override - public TraverseNodeMetadata getMetadata() { - return this; - } - - private Stream expandContainerNode(TypeDefinition typeDefinition, TraverseContext traverseContext) { - TreeNodeManipulator appliedContainerInfoManipulator = - this.getAppliedTreeNodeManipulator(); - - ArbitraryContainerInfo containerInfo = appliedContainerInfoManipulator != null - ? appliedContainerInfoManipulator.getContainerInfo() - : null; - - PropertyGenerator propertyGenerator = typeDefinition.getPropertyGenerator(); - if (propertyGenerator instanceof LazyPropertyGenerator) { - propertyGenerator = ((LazyPropertyGenerator)propertyGenerator).getDelegate(); - } - - if (propertyGenerator instanceof ElementPropertyGenerator) { - ((ElementPropertyGenerator)propertyGenerator).updateContainerInfo(containerInfo); - } - - List elementProperties = propertyGenerator.generateChildProperties( - typeDefinition.getResolvedProperty() - ); - - return this.generateChildrenNodes( - typeDefinition.getResolvedProperty(), - elementProperties, - this.nullInject, - traverseContext - ).stream(); - } - - public static DefaultTraverseNode generateRootNode( - TreeRootProperty rootProperty, - TraverseContext traverseContext - ) { - return DefaultTraverseNode.generateObjectNode( - rootProperty, - null, - rootProperty, - null, - 0.0d, - traverseContext - ); - } - - static DefaultTraverseNode generateObjectNode( - TreeRootProperty rootProperty, - @Nullable Property resolvedParentProperty, - Property property, - @Nullable Integer propertySequence, - double parentNullInject, - TraverseContext context - ) { - ContainerPropertyGenerator containerPropertyGenerator = context.getContainerPropertyGenerator(property); - boolean container = containerPropertyGenerator != null; - - ObjectPropertyGenerator objectPropertyGenerator = context.getObjectPropertyGenerator(property); - - TreeProperty parentTreeProperty = context.getLastTreeProperty(); - - ArbitraryProperty parentArbitraryProperty = parentTreeProperty != null - ? parentTreeProperty.toArbitraryProperty(parentNullInject) - : null; - - ObjectPropertyGeneratorContext objectPropertyGeneratorContext = new ObjectPropertyGeneratorContext( - property, - resolveIndex( - resolvedParentProperty, - parentTreeProperty, - propertySequence, - context - ), - parentArbitraryProperty, - container, - context.getPropertyNameResolver(property) - ); - - ObjectProperty objectProperty = objectPropertyGenerator.generate(objectPropertyGeneratorContext); - - List candidateProperties = context.resolveCandidateProperties(property); - - List objectProperties = - context.getTreeProperties().stream() - .map(TreeProperty::getObjectProperty).collect(Collectors.toList()); - objectProperties.add(objectProperty); - - TreeNodeManipulator appliedContainerInfoManipulator = resolveAppliedContainerInfoManipulator( - container, - context.getTreeManipulators(), - objectProperties - ); - - List typeDefinitions = candidateProperties.stream() - .map(concreteProperty -> { - if (containerPropertyGenerator == null) { - LazyPropertyGenerator lazyPropertyGenerator = context.getResolvedPropertyGenerator(); - - return new DefaultTypeDefinition( - concreteProperty, - lazyPropertyGenerator - ); - } - - PropertyGenerator containerElementPropertyGenerator = new ElementPropertyGenerator( - property, - containerPropertyGenerator, - context.getArbitraryContainerInfoGenerator(property), - null - ); - - LazyPropertyGenerator lazyPropertyGenerator = - new LazyPropertyGenerator(containerElementPropertyGenerator); - - return new DefaultTypeDefinition( - concreteProperty, - lazyPropertyGenerator - ); - }) - .collect(Collectors.toList()); - - double nullInject = context.getNullInjectGenerator(property) - .generate(objectPropertyGeneratorContext); - - TreeProperty treeProperty = new TreeProperty( - objectProperty, - container, - typeDefinitions - ); - - TraverseContext nextTraverseContext = context.appendArbitraryProperty(treeProperty); - - DefaultTraverseNode newObjectNode = new DefaultTraverseNode( - rootProperty, - resolvedParentProperty, - new CompositeTypeDefinition(typeDefinitions).getResolvedTypeDefinition(), - treeProperty, - nullInject, - nextTraverseContext - ); - - if (appliedContainerInfoManipulator != null) { - newObjectNode.getMetadata().addTreeNodeManipulator(appliedContainerInfoManipulator); - } - return newObjectNode; - } - - @Nullable - private static Integer resolveIndex( - @Nullable Property resolvedParentProperty, - @Nullable TreeProperty parentTreeProperty, - @Nullable Integer propertySequence, - TraverseContext context - ) { - if (resolvedParentProperty == null || parentTreeProperty == null) { - return null; - } - - boolean parentContainer = - context.getContainerPropertyGenerator(resolvedParentProperty) != null; - if (!parentContainer) { - return null; - } - - if (propertySequence == null) { - return null; - } - - int index = propertySequence; - if (parentTreeProperty.getObjectProperty().getProperty() instanceof MapEntryElementProperty) { - index /= 2; - } - return index; - } - - private List generateChildrenNodes( - Property resolvedParentProperty, - List childProperties, - double parentNullInject, - TraverseContext context - ) { - List children = new ArrayList<>(); - - for (int sequence = 0; sequence < childProperties.size(); sequence++) { - Property childProperty = childProperties.get(sequence); - - if (context.isTraversed(childProperty) - && !(resolvedParentProperty instanceof MapEntryElementProperty)) { - continue; - } - - TraverseNode childNode = generateObjectNode( - rootProperty, - resolvedParentProperty, - childProperty, - sequence, - parentNullInject, - context - ); - children.add(childNode); - } - return children; - } - - @Nullable - private static TreeNodeManipulator resolveAppliedContainerInfoManipulator( - boolean container, - List containerInfoManipulators, - List objectProperties - ) { - if (!container || objectProperties.isEmpty() - || !(objectProperties.get(0).getProperty() instanceof TreeRootProperty)) { - return null; - } - - TreeNodeManipulator appliedContainerInfoManipulator = null; - for (TreeNodeManipulator containerInfoManipulator : containerInfoManipulators) { - if (containerInfoManipulator.isMatch(objectProperties)) { - appliedContainerInfoManipulator = containerInfoManipulator; - } - } - return appliedContainerInfoManipulator; - } - - private List mergeWithNewChildren(List newChildren) { - if (this.children == null) { - return newChildren; - } - - boolean shrinkChildNodes = this.children.size() > newChildren.size(); - if (shrinkChildNodes) { - return this.children.subList(0, newChildren.size()); - } - - boolean expandChildNodes = this.children.size() < newChildren.size(); - if (expandChildNodes) { - Map existingNodesByObjectProperty = this.children.stream() - .collect(toMap(it -> it.getMetadata().getTreeProperty().getObjectProperty(), Function.identity())); - - List concatNewChildren = new ArrayList<>(); - for (TraverseNode newChild : newChildren) { - TraverseNode existingNode = - existingNodesByObjectProperty.get(newChild.getMetadata().getTreeProperty().getObjectProperty()); - if (existingNode != null) { - concatNewChildren.add(existingNode); - } else { - concatNewChildren.add(newChild); - } - } - return concatNewChildren; - } - return this.children; - } -} diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/TraverseContext.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/TraverseContext.java deleted file mode 100644 index 8953d9f568..0000000000 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/TraverseContext.java +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.api.tree; - -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; -import org.jspecify.annotations.Nullable; - -import com.navercorp.fixturemonkey.api.container.ConcurrentLruCache; -import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfoGenerator; -import com.navercorp.fixturemonkey.api.generator.ContainerPropertyGenerator; -import com.navercorp.fixturemonkey.api.generator.NullInjectGenerator; -import com.navercorp.fixturemonkey.api.generator.ObjectPropertyGenerator; -import com.navercorp.fixturemonkey.api.matcher.MatcherOperator; -import com.navercorp.fixturemonkey.api.property.CandidateConcretePropertyResolver; -import com.navercorp.fixturemonkey.api.property.CompositeCandidateConcretePropertyResolver; -import com.navercorp.fixturemonkey.api.property.DefaultCandidateConcretePropertyResolver; -import com.navercorp.fixturemonkey.api.property.LazyPropertyGenerator; -import com.navercorp.fixturemonkey.api.property.MapEntryElementProperty; -import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.api.property.PropertyNameResolver; -import com.navercorp.fixturemonkey.api.property.TreeRootProperty; -import com.navercorp.fixturemonkey.api.tree.TraverseNodePredicate.PropertyTraverseNodePredicate; - -@API(since = "1.0.4", status = Status.EXPERIMENTAL) -public final class TraverseContext { - private static final ConcurrentLruCache> CANDIDATE_CONCRETE_PROPERTIES_BY_PROPERTY = - new ConcurrentLruCache<>(1024); - - private final TreeRootProperty rootProperty; - private final List treeProperties; - private final List treeManipulators; - private final List>> registeredTreeManipulators; - private final Map, List> propertyConfigurers; - private final boolean validOnly; - private final LazyPropertyGenerator resolvedPropertyGenerator; - private final List> objectPropertyGenerators; - private final ObjectPropertyGenerator defaultObjectPropertyGenerator; - private final List> containerPropertyGenerators; - private final List> propertyNameResolvers; - private final PropertyNameResolver defaultPropertyNameResolver; - private final List> candidateConcretePropertyResolvers; - private final List> arbitraryContainerInfoGenerators; - private final ArbitraryContainerInfoGenerator defaultArbitraryContainerInfoGenerator; - private final List> nullInjectGenerators; - private final NullInjectGenerator defaultNullInjectGenerator; - - public TraverseContext( - TreeRootProperty rootProperty, - List treeProperties, - List treeManipulators, - List>> registeredTreeManipulators, - Map, List> propertyConfigurers, - boolean validOnly, - LazyPropertyGenerator resolvedPropertyGenerator, - List> objectPropertyGenerators, - ObjectPropertyGenerator defaultObjectPropertyGenerator, - List> containerPropertyGenerators, - List> propertyNameResolvers, - PropertyNameResolver defaultPropertyNameResolver, - List> candidateConcretePropertyResolvers, - List> arbitraryContainerInfoGenerators, - ArbitraryContainerInfoGenerator defaultArbitraryContainerInfoGenerator, - List> nullInjectGenerators, - NullInjectGenerator defaultNullInjectGenerator - ) { - this.rootProperty = rootProperty; - this.treeProperties = treeProperties; - this.treeManipulators = treeManipulators; - this.registeredTreeManipulators = registeredTreeManipulators; - this.propertyConfigurers = propertyConfigurers; - this.validOnly = validOnly; - this.resolvedPropertyGenerator = resolvedPropertyGenerator; - this.objectPropertyGenerators = objectPropertyGenerators; - this.defaultObjectPropertyGenerator = defaultObjectPropertyGenerator; - this.containerPropertyGenerators = containerPropertyGenerators; - this.propertyNameResolvers = propertyNameResolvers; - this.defaultPropertyNameResolver = defaultPropertyNameResolver; - this.candidateConcretePropertyResolvers = candidateConcretePropertyResolvers; - this.arbitraryContainerInfoGenerators = arbitraryContainerInfoGenerators; - this.defaultArbitraryContainerInfoGenerator = defaultArbitraryContainerInfoGenerator; - this.nullInjectGenerators = nullInjectGenerators; - this.defaultNullInjectGenerator = defaultNullInjectGenerator; - } - - @Nullable - public TreeProperty getRootTreeProperty() { - return treeProperties.get(0); - } - - public List getTreeProperties() { - return treeProperties; - } - - public List getTreeManipulators() { - return treeManipulators; - } - - public Map, List> getPropertyConfigurers() { - return propertyConfigurers; - } - - public boolean isValidOnly() { - return validOnly; - } - - public TraverseContext appendArbitraryProperty( - TreeProperty treeProperty - ) { - List treeProperties = new ArrayList<>(this.treeProperties); - treeProperties.add(treeProperty); - - List registeredContainerManipulators = - this.registeredTreeManipulators.stream() - .filter(it -> it.match(treeProperty.getObjectProperty().getProperty())) - .map(MatcherOperator::getOperator) - .findFirst() - .orElse(Collections.emptyList()); - - List concatRegisteredContainerManipulator = registeredContainerManipulators.stream() - .map(it -> it.withPrependNextNodePredicate( - new PropertyTraverseNodePredicate(treeProperty.getObjectProperty().getProperty()) - )) - .collect(Collectors.toList()); - - List concat = new ArrayList<>(); - concat.addAll(concatRegisteredContainerManipulator); - concat.addAll(treeManipulators); - return new TraverseContext( - rootProperty, - treeProperties, - concat, - this.registeredTreeManipulators, - this.propertyConfigurers, - this.validOnly, - this.resolvedPropertyGenerator, - this.objectPropertyGenerators, - this.defaultObjectPropertyGenerator, - this.containerPropertyGenerators, - this.propertyNameResolvers, - this.defaultPropertyNameResolver, - this.candidateConcretePropertyResolvers, - this.arbitraryContainerInfoGenerators, - this.defaultArbitraryContainerInfoGenerator, - this.nullInjectGenerators, - this.defaultNullInjectGenerator - ); - } - - public boolean isTraversed(Property property) { - return treeProperties.stream() - .skip(1) - .anyMatch(it -> isSameType(property, it.getObjectProperty().getProperty())); - } - - public void addContainerInfoManipulator(TreeNodeManipulator containerInfoManipulator) { - if (!this.treeManipulators.contains(containerInfoManipulator)) { - this.treeManipulators.add(containerInfoManipulator); - } - } - - @Nullable - public TreeProperty getLastTreeProperty() { - if (this.treeProperties.isEmpty()) { - return null; - } - return this.treeProperties.get(this.treeProperties.size() - 1); - } - - public TraverseContext withParentProperties() { - List newTreeProperties = new ArrayList<>(); - - if (!this.treeProperties.isEmpty()) { - newTreeProperties.add(this.treeProperties.get(this.treeProperties.size() - 1)); - } - - return new TraverseContext( - rootProperty, - newTreeProperties, - new ArrayList<>(this.treeManipulators), - this.registeredTreeManipulators, - this.propertyConfigurers, - this.validOnly, - this.resolvedPropertyGenerator, - this.objectPropertyGenerators, - this.defaultObjectPropertyGenerator, - this.containerPropertyGenerators, - this.propertyNameResolvers, - this.defaultPropertyNameResolver, - this.candidateConcretePropertyResolvers, - this.arbitraryContainerInfoGenerators, - this.defaultArbitraryContainerInfoGenerator, - this.nullInjectGenerators, - this.defaultNullInjectGenerator - ); - } - - private static boolean isSameType(Property p1, Property p2) { - boolean notMapEntry = !(p1 instanceof MapEntryElementProperty) || !(p2 instanceof MapEntryElementProperty); - return notMapEntry && p1.getAnnotatedType().getType().equals(p2.getAnnotatedType().getType()); - } - - public ObjectPropertyGenerator getObjectPropertyGenerator(Property property) { - return objectPropertyGenerators.stream() - .filter(it -> it.match(property)) - .map(MatcherOperator::getOperator) - .findFirst() - .orElse(this.defaultObjectPropertyGenerator); - } - - @Nullable - public ContainerPropertyGenerator getContainerPropertyGenerator(Property property) { - return containerPropertyGenerators.stream() - .filter(it -> it.match(property)) - .map(MatcherOperator::getOperator) - .findFirst() - .orElse(null); - } - - public PropertyNameResolver getPropertyNameResolver(Property property) { - return propertyNameResolvers.stream() - .filter(it -> it.match(property)) - .map(MatcherOperator::getOperator) - .findFirst() - .orElse(this.defaultPropertyNameResolver); - } - - public ArbitraryContainerInfoGenerator getArbitraryContainerInfoGenerator(Property property) { - return arbitraryContainerInfoGenerators.stream() - .filter(it -> it.match(property)) - .map(MatcherOperator::getOperator) - .findFirst() - .orElse(this.defaultArbitraryContainerInfoGenerator); - } - - public NullInjectGenerator getNullInjectGenerator(Property property) { - return nullInjectGenerators.stream() - .filter(it -> it.match(property)) - .map(MatcherOperator::getOperator) - .findFirst() - .orElse(this.defaultNullInjectGenerator); - } - - public LazyPropertyGenerator getResolvedPropertyGenerator() { - return resolvedPropertyGenerator; - } - - public List resolveCandidateProperties(Property property) { - CandidateConcretePropertyResolver candidateConcretePropertyResolver = - getCandidateConcretePropertyResolver(property, candidateConcretePropertyResolvers); - - if (candidateConcretePropertyResolver == null) { - return DefaultCandidateConcretePropertyResolver.INSTANCE.resolve(property); - } - - return CANDIDATE_CONCRETE_PROPERTIES_BY_PROPERTY.computeIfAbsent( - property, - p -> { - List resolvedCandidateProperties = new ArrayList<>(); - List candidateProperties = candidateConcretePropertyResolver.resolve(p); - for (Property candidateProperty : candidateProperties) { - // compares by type until a specific property implementation is created for the generic type. - Type candidateType = candidateProperty.getType(); - - if (p.getType().equals(candidateType)) { - // prevents infinite recursion - resolvedCandidateProperties.addAll( - DefaultCandidateConcretePropertyResolver.INSTANCE.resolve(p) - ); - continue; - } - resolvedCandidateProperties.addAll(resolveCandidateProperties(candidateProperty)); - } - return resolvedCandidateProperties; - } - ); - } - - @Nullable - private static CandidateConcretePropertyResolver getCandidateConcretePropertyResolver( - Property property, - List> candidateConcretePropertyResolvers - ) { - List candidateConcretePropertyResolverList = - candidateConcretePropertyResolvers.stream() - .filter(it -> it.match(property)) - .map(MatcherOperator::getOperator) - .collect(Collectors.toList()); - - if (candidateConcretePropertyResolverList.isEmpty()) { - return null; - } - - return new CompositeCandidateConcretePropertyResolver(candidateConcretePropertyResolverList); - } -} diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/TraverseNode.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/TraverseNode.java deleted file mode 100644 index ba4c78b4a8..0000000000 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/TraverseNode.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.api.tree; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; -import org.jspecify.annotations.Nullable; - -import com.navercorp.fixturemonkey.api.property.TypeDefinition; - -/** - * A generated JVM instance consists of {@link TraverseNode}s. - * The node has a vertical relationship, parent and child. - * It is used to create child nodes and traverse them by expression. - * In case of providing more functionality, such as instantiating an object, use it with {@link TraverseNodeContext}. - */ -@API(since = "1.1.4", status = Status.EXPERIMENTAL) -public interface TraverseNode { - /** - * expands the {@link TraverseNode}. In result, it generates the child {@link TraverseNode}s. - * It generates the child {@link TraverseNode}s by all {@link TypeDefinition}s. - *

- * It can be called multiple times with metadata generated on expanding of the parent {@link TraverseNode}, - * but it makes no change. - *

- * The leaf {@link TraverseNode} does not always generate child {@link TraverseNode}s. - * - * @return whether the node is expanded. - */ - boolean expand(); - - /** - * expands the {@link TraverseNode} forcibly. In result, it always generates the child {@link TraverseNode}s. - * It generates the child {@link TraverseNode}s by all {@link TypeDefinition}s. - * {@code Force} means that it expands as if it were a root node, even if it is not. - * Unlike {@link #expand()}, it expands without metadata generated - * on expanding of the parent {@link TraverseNode}. - *

- * It will always append the {@link TraverseNode} nodes, - * not remove already created nodes unless it is not a container. - * The container's element nodes will shrink when the node is set by the fixed container object. - *

- * The leaf {@link TraverseNode} may generate child {@link TraverseNode}s. - * For example, the {@link TraverseNode} with a self-reference. - */ - void forceExpand(); - - /** - * expands the {@link TraverseNode} forcibly. In result, it always generates the child {@link TraverseNode}s. - * It generates the child {@link TraverseNode}s by given {@link TypeDefinition}. - * {@code Force} means that it expands as if it were a root node, even if it is not. - * Unlike {@link #expand()}, it expands without metadata generated on expanding of the parent {@link TraverseNode}. - *

- * The child nodes are always generated by the given {@link TypeDefinition} unlike {@link #forceExpand()}. - *

- * The leaf {@link TraverseNode} may generate child {@link TraverseNode}s. - * For example, the {@link TraverseNode} with a self-reference. - * - * @param typeDefinition the {@link TypeDefinition} to expand forcibly - */ - void forceExpand(TypeDefinition typeDefinition); - - /** - * retrieves the metadata to traverse the tree. Some of its properties can be mutated during traversal. - * - * @return the metadata to traverse the tree - */ - TraverseNodeMetadata getMetadata(); - - /** - * retrieves the parent node of this node. - * - * @return the parent node of this node or null if it is root node. - */ - @Nullable - TraverseNode getParent(); - - /** - * retrieves the child nodes of this node. Use {@link NodeList} to prevent generic type casting compile error. - * - * @return the child nodes of this node or null if not called {@link #expand()} - */ - @Nullable - NodeList getChildren(); -} diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/TraverseNodeContext.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/TraverseNodeContext.java deleted file mode 100644 index a063cfdf31..0000000000 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/TraverseNodeContext.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.api.tree; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -/** - * It defines what {@link TraverseNode} is for. Every node has a {@link TraverseNodeContext}. - * Every node in a tree should have the same implementation of {@link TraverseNodeContext}. - * For example, each node generates an object. - */ -@API(since = "1.1.4", status = Status.EXPERIMENTAL) -public interface TraverseNodeContext { - /** - * sets the implementation of {@link TraverseNode}, it may vary depending on its usage. - * It may throw an exception if type casting is failed. - * - * @param traverseNode the implementation of {@link TraverseNode}. - * @throws IllegalArgumentException throws an exception if type casting is failed. - */ - void setTraverseNode(TraverseNode traverseNode) throws IllegalArgumentException; - - /** - * retrieves the child node of {@link TraverseNodeContext}. - * It should not contain the mutable state during traversal. - * - * @return the child node of {@link TraverseNodeContext} - */ - TraverseNodeContext newChildNodeContext(); -} diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/TraverseNodeList.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/TraverseNodeList.java deleted file mode 100644 index 80515255d9..0000000000 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/TraverseNodeList.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.api.tree; - -import java.util.List; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -/** - * The list of {@link TraverseNode}. It is just to avoid the compile error, use {@link #asList()}. - * - * @see NodeList - */ -@API(since = "1.1.4", status = Status.EXPERIMENTAL) -public final class TraverseNodeList implements NodeList { - private final List traverseNodeList; - - public TraverseNodeList(List traverseNodeList) { - this.traverseNodeList = traverseNodeList; - } - - @Override - public List asList() { - return this.traverseNodeList; - } - - public List getTraverseNodeList() { - return traverseNodeList; - } -} diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/TraverseNodeMetadata.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/TraverseNodeMetadata.java deleted file mode 100644 index 7403004624..0000000000 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/TraverseNodeMetadata.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.api.tree; - -import java.util.List; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; -import org.jspecify.annotations.Nullable; - -import com.navercorp.fixturemonkey.api.lazy.LazyArbitrary; -import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.api.property.PropertyPath; -import com.navercorp.fixturemonkey.api.property.TreeRootProperty; -import com.navercorp.fixturemonkey.api.property.TypeDefinition; - -@API(since = "1.1.4", status = Status.EXPERIMENTAL) -public interface TraverseNodeMetadata { - TreeRootProperty getRootProperty(); - - @Nullable - Property getResolvedParentProperty(); - - TypeDefinition getResolvedTypeDefinition(); - - void setResolvedTypeDefinition(TypeDefinition typeDefinition); - - Property getOriginalProperty(); - - TreeProperty getTreeProperty(); - - LazyArbitrary getLazyPropertyPath(); - - boolean manipulated(); - - List getTreeNodeManipulators(); - - @Nullable - TreeNodeManipulator getAppliedTreeNodeManipulator(); - - void addTreeNodeManipulator(TreeNodeManipulator treeNodeManipulator); - - double getNullInject(); - - void setNullInject(double nullInject); -} diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/TraverseNodePredicate.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/TraverseNodePredicate.java deleted file mode 100644 index e0393a65b0..0000000000 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/TraverseNodePredicate.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.api.tree; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import com.navercorp.fixturemonkey.api.generator.ObjectProperty; -import com.navercorp.fixturemonkey.api.property.Property; - -@API(since = "1.0.4", status = Status.EXPERIMENTAL) -@FunctionalInterface -public interface TraverseNodePredicate { - boolean test(ObjectProperty currentObjectProperty); - - class StartTraverseNodePredicate implements TraverseNodePredicate { - - @Override - public boolean test(ObjectProperty currentObjectProperty) { - return true; - } - } - - class PropertyTraverseNodePredicate implements TraverseNodePredicate { - private final Property property; - - public PropertyTraverseNodePredicate(Property property) { - this.property = property; - } - - @Override - public boolean test(ObjectProperty currentObjectProperty) { - return property.equals(currentObjectProperty.getProperty()); - } - } -} diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/TreeNodeManipulator.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/TreeNodeManipulator.java deleted file mode 100644 index ad70444258..0000000000 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/TreeNodeManipulator.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.api.tree; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfo; -import com.navercorp.fixturemonkey.api.generator.ObjectProperty; -import com.navercorp.fixturemonkey.api.tree.TraverseNodePredicate.PropertyTraverseNodePredicate; -import com.navercorp.fixturemonkey.api.tree.TraverseNodePredicate.StartTraverseNodePredicate; - -@API(since = "1.1.4", status = Status.EXPERIMENTAL) -public class TreeNodeManipulator { - private final List traverseNodePredicates; - private ArbitraryContainerInfo containerInfo; - /** - * The sequence of a size manipulation. - * It may dismiss if a sequence of set is bigger. - */ - private final int manipulatingSequence; - - public TreeNodeManipulator( - List traverseNodePredicates, - ArbitraryContainerInfo containerInfo, - int manipulatingSequence - ) { - this.traverseNodePredicates = traverseNodePredicates; - this.containerInfo = containerInfo; - this.manipulatingSequence = manipulatingSequence; - } - - public TreeNodeManipulator copy() { - return new TreeNodeManipulator( - this.getTraverseNodePredicates(), - new ArbitraryContainerInfo( - containerInfo.getElementMinSize(), - containerInfo.getElementMaxSize() - ), - manipulatingSequence - ); - } - - public List getTraverseNodePredicates() { - return traverseNodePredicates; - } - - public ArbitraryContainerInfo getContainerInfo() { - return containerInfo; - } - - public TreeNodeManipulator withPrependNextNodePredicate(TraverseNodePredicate nextNodePredicate) { - List nodePredicatesWithoutRoot = this.traverseNodePredicates.stream() - .filter(it -> !(it instanceof StartTraverseNodePredicate)) - .collect(Collectors.toList()); - - List newtraverseNodePredicates = new ArrayList<>(); - newtraverseNodePredicates.add(nextNodePredicate); - newtraverseNodePredicates.addAll(nodePredicatesWithoutRoot); - - return new TreeNodeManipulator( - newtraverseNodePredicates, - this.containerInfo, - manipulatingSequence - ); - } - - public int getManipulatingSequence() { - return manipulatingSequence; - } - - public void fixed() { - int fixedSize = this.containerInfo.getRandomSize(); - - this.containerInfo = new ArbitraryContainerInfo( - fixedSize, - fixedSize - ); - } - - public boolean isMatch(List objectProperties) { - int objectPropertiesSize = objectProperties.size(); - int traverseNodePredicatesize = traverseNodePredicates.size(); - - boolean registered = traverseNodePredicates.get(0) instanceof PropertyTraverseNodePredicate; - if (!registered && traverseNodePredicatesize != objectPropertiesSize) { - return false; - } - - for (int i = 0; i < traverseNodePredicatesize; i++) { - int reversedNextNodePredicateIndex = traverseNodePredicatesize - 1 - i; - int reversedCurrentObjectPropertyIndex = objectPropertiesSize - 1 - i; - TraverseNodePredicate nextNodePredicate = traverseNodePredicates.get(reversedNextNodePredicateIndex); - ObjectProperty objectProperty = objectProperties.get(reversedCurrentObjectPropertyIndex); - - if (!nextNodePredicate.test(objectProperty)) { - return false; - } - } - return true; - } -} diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/type/GenericType.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/type/GenericType.java index eeb7d9bf38..556b49eae7 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/type/GenericType.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/type/GenericType.java @@ -74,7 +74,12 @@ public Type getOwnerType() { @Override public int hashCode() { - return Objects.hash(containerType, ownerType, Arrays.hashCode(typeArguments)); + // Matches the formula used by sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl + // so that this class hashes equal to JDK-supplied ParameterizedTypes representing the + // same type. Required for cache lookups keyed by Type. + return Arrays.hashCode(typeArguments) + ^ Objects.hashCode(ownerType) + ^ Objects.hashCode(containerType); } @Override diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/type/TypeReference.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/type/TypeReference.java index baa6bfef88..7d16c07f62 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/type/TypeReference.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/type/TypeReference.java @@ -23,13 +23,25 @@ import java.lang.reflect.AnnotatedParameterizedType; import java.lang.reflect.AnnotatedType; import java.lang.reflect.Type; +import java.util.Collections; +import java.util.concurrent.locks.ReentrantLock; import org.apiguardian.api.API; import org.apiguardian.api.API.Status; +import org.jspecify.annotations.Nullable; + +import com.navercorp.objectfarm.api.type.JvmType; @API(since = "0.4.0", status = Status.MAINTAINED) public abstract class TypeReference { private final AnnotatedType annotatedType; + // Lazy because Types.toTypeReference produces anonymous subclasses that override getAnnotatedType() + // to return a value different from the field captured by the parent constructor. Computing jvmType + // eagerly in the constructor would cache the field-derived (wrong) value, bypassing the override. + // Deferring to first access also avoids invoking an overridable method during super construction, + // which is unsafe before subclass initialization completes. + private volatile @Nullable JvmType jvmType; + private final ReentrantLock jvmTypeLock = new ReentrantLock(); protected TypeReference() { AnnotatedType annotatedType = getClass().getAnnotatedSuperclass(); @@ -48,6 +60,24 @@ public AnnotatedType getAnnotatedType() { return this.annotatedType; } + public JvmType getJvmType() { + JvmType cached = this.jvmType; + if (cached != null) { + return cached; + } + jvmTypeLock.lock(); + try { + cached = this.jvmType; + if (cached == null) { + cached = Types.toJvmType(getAnnotatedType(), Collections.emptyList()); + this.jvmType = cached; + } + return cached; + } finally { + jvmTypeLock.unlock(); + } + } + public boolean isGenericType() { return Types.getActualType(annotatedType.getType()).getTypeParameters().length != 0; } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/type/Types.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/type/Types.java index e9859ef9b4..8cbc1fe5b1 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/type/Types.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/type/Types.java @@ -64,7 +64,7 @@ import com.navercorp.objectfarm.api.type.JvmType; import com.navercorp.objectfarm.api.type.ObjectTypeReference; -@API(since = "0.4.0", status = Status.INTERNAL) +@API(since = "0.4.0", status = Status.MAINTAINED) public abstract class Types { private static final Map, Class> primitiveWrapperMap = new HashMap<>(); @@ -415,6 +415,22 @@ private GeneratingWildcardType() { } } + /** + * Normalizes a raw type so that the lower-level {@code WildcardRawType} (produced by the + * object-farm-api layer when traversing wildcard generics) is reported as + * {@link GeneratingWildcardType} — the public marker type users register against (e.g. via + * {@code pushExactTypeArbitraryIntrospector}). + *

+ * Call this whenever a {@code Class} obtained from {@code JvmType.getRawType()} is about + * to be used as a key for type-based matching. + */ + public static Class normalizeRawType(Class rawType) { + if (rawType == com.navercorp.objectfarm.api.type.WildcardRawType.class) { + return GeneratingWildcardType.class; + } + return rawType; + } + @SuppressWarnings("nullness") public static Class primitiveToWrapper(final Class cls) { Class convertedClass = cls; @@ -592,25 +608,34 @@ public static T nullSafe(@Nullable T obj) { } public static JvmType toJvmType(AnnotatedType annotatedType, List annotations) { + return toJvmType(annotatedType, annotations, null); + } + + public static JvmType toJvmType( + AnnotatedType annotatedType, + List annotations, + @Nullable Boolean nullable + ) { List concatAnnotations = Stream.concat(annotations.stream(), Arrays.stream(annotatedType.getAnnotations())) .collect(Collectors.toList()); Class rawType = resolveRawTypeForJvmType(annotatedType); + List generics = Types.getGenericsTypes(annotatedType).stream() + .map( + genericAnnotatedType -> (JvmType)new JavaType(new ObjectTypeReference() { + @Override + public AnnotatedType getAnnotatedType() { + return genericAnnotatedType; + } + })) + .collect(Collectors.toList()); return new JavaType( rawType, - Types.getGenericsTypes(annotatedType).stream() - .map( - genericAnnotatedType -> new JavaType(new ObjectTypeReference() { - @Override - public AnnotatedType getAnnotatedType() { - return genericAnnotatedType; - } - })) - .collect(Collectors.toList()), + generics, concatAnnotations, - annotatedType + nullable ); } @@ -625,6 +650,85 @@ private static Class resolveRawTypeForJvmType(AnnotatedType annotatedType) { return getActualType(annotatedType); } + /** + * Synthesizes an {@link AnnotatedType} from a {@link JvmType} structure + * ({@link JvmType#getRawType()}, {@link JvmType#getTypeVariables()}, + * {@link JvmType#getComponentType()}, {@link JvmType#getAnnotations()}). + *

+ * Produces proper {@link AnnotatedParameterizedType} / {@link AnnotatedArrayType} subtype + * instances so downstream consumers that branch on these subtypes (e.g. generic resolution) + * behave consistently with a JDK-supplied {@link AnnotatedType}. + * + * @param jvmType the JvmType to convert + * @return an AnnotatedType representing the JvmType + */ + public static AnnotatedType toAnnotatedType(JvmType jvmType) { + Class rawType = jvmType.getRawType(); + List annotations = jvmType.getAnnotations(); + List typeVariables = jvmType.getTypeVariables(); + Annotation[] annotationsArray = annotations.toArray(new Annotation[0]); + + if (rawType.isArray() && typeVariables != null && !typeVariables.isEmpty()) { + JvmType componentJvmType = jvmType.getComponentType(); + AnnotatedType componentAnnotatedType = componentJvmType != null + ? toAnnotatedType(componentJvmType) + : generateAnnotatedTypeWithoutAnnotation(rawType.getComponentType()); + Type componentType = componentAnnotatedType.getType(); + Type genericArrayType = (GenericArrayType)() -> componentType; + return AnnotatedTypes.newAnnotatedArrayType( + componentAnnotatedType, + genericArrayType, + annotationsArray, + annotationsArray, + generateAnnotatedTypeWithoutAnnotation(rawType) + ); + } + + if (typeVariables != null && !typeVariables.isEmpty()) { + AnnotatedType[] annotatedTypeArgs = typeVariables.stream() + .map(Types::toAnnotatedType) + .toArray(AnnotatedType[]::new); + Type[] typeArgs = Arrays.stream(annotatedTypeArgs) + .map(AnnotatedType::getType) + .toArray(Type[]::new); + ParameterizedType parameterizedType = new GenericType(rawType, typeArgs, null); + return AnnotatedTypes.newAnnotatedParameterizedType( + annotatedTypeArgs, + parameterizedType, + annotationsArray, + annotationsArray, + generateAnnotatedTypeWithoutAnnotation(rawType) + ); + } + + final Type type = rawType; + return new AnnotatedType() { + @Override + public Type getType() { + return type; + } + + @Override + @SuppressWarnings({"unchecked", "cast.unsafe"}) + public @Nullable T getAnnotation(Class annotationClass) { + return (T)annotations.stream() + .filter(a -> a.annotationType().equals(annotationClass)) + .findFirst() + .orElse(null); + } + + @Override + public Annotation[] getAnnotations() { + return annotationsArray; + } + + @Override + public Annotation[] getDeclaredAnnotations() { + return getAnnotations(); + } + }; + } + /** * Truncates an array to the given size. * If the array is already smaller than or equal to the target size, it is returned as-is. diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/validator/ArbitraryValidator.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/validator/ArbitraryValidator.java index 4cab2b5709..1c78832ca6 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/validator/ArbitraryValidator.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/validator/ArbitraryValidator.java @@ -18,6 +18,10 @@ package com.navercorp.fixturemonkey.api.validator; + +import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; +@API(since = "1.1.20", status = Status.MAINTAINED) public interface ArbitraryValidator { // if arbitrary is not valid throw exception then re-create arbitrary for valid. void validate(Object arbitrary); diff --git a/fixture-monkey-api/src/main/java17/com/navercorp/fixturemonkey/api/option/JdkVariantOptions.java b/fixture-monkey-api/src/main/java17/com/navercorp/fixturemonkey/api/option/JdkVariantOptions.java index 7a598c9cd0..dabd32890f 100644 --- a/fixture-monkey-api/src/main/java17/com/navercorp/fixturemonkey/api/option/JdkVariantOptions.java +++ b/fixture-monkey-api/src/main/java17/com/navercorp/fixturemonkey/api/option/JdkVariantOptions.java @@ -32,7 +32,6 @@ import com.navercorp.fixturemonkey.api.property.SealedTypeCandidateConcretePropertyResolver; import com.navercorp.fixturemonkey.api.type.Constructors; import com.navercorp.fixturemonkey.api.type.TypeCache; -import com.navercorp.fixturemonkey.api.type.Types; @API(since = "1.0.14", status = Status.INTERNAL) public final class JdkVariantOptions { @@ -40,10 +39,13 @@ public final class JdkVariantOptions { new SealedTypeCandidateConcretePropertyResolver(); private static final PropertyGenerator CANONICAL_CONSTRUCTOR_PARAMETER_PROPERTY_GENERATOR = new ConstructorParameterPropertyGenerator( - p -> Constructors.findPrimaryConstructor( - Types.getActualType(p.getType()), - TypeCache.getDeclaredConstructors(Types.getActualType(p.getType())).toArray(Constructor[]::new) - ).stream().toList(), + p -> { + Class rawType = p.getJvmType().getRawType(); + return Constructors.findPrimaryConstructor( + rawType, + TypeCache.getDeclaredConstructors(rawType).toArray(Constructor[]::new) + ).stream().toList(); + }, it -> true, it -> true ); @@ -51,13 +53,13 @@ public final class JdkVariantOptions { public void apply(FixtureMonkeyOptionsBuilder optionsBuilder) { optionsBuilder.insertFirstCandidateConcretePropertyResolvers( new MatcherOperator<>( - p -> Types.getActualType(p.getType()).isSealed() && !Types.getActualType(p.getType()).isEnum(), + p -> p.getJvmType().getRawType().isSealed() && !p.getJvmType().getRawType().isEnum(), SEALED_TYPE_CANDIDATE_CONCRETE_PROPERTY_RESOLVER ) ) .insertFirstPropertyGenerator(ZoneId.class, property -> List.of()) .insertFirstPropertyGenerator( - p -> Types.getActualType(p.getType()).isRecord(), + p -> p.getJvmType().getRawType().isRecord(), CANONICAL_CONSTRUCTOR_PARAMETER_PROPERTY_GENERATOR ); } diff --git a/fixture-monkey-api/src/main/java17/com/navercorp/fixturemonkey/api/property/SealedTypeCandidateConcretePropertyResolver.java b/fixture-monkey-api/src/main/java17/com/navercorp/fixturemonkey/api/property/SealedTypeCandidateConcretePropertyResolver.java index c2d4562b0b..f819c442ae 100644 --- a/fixture-monkey-api/src/main/java17/com/navercorp/fixturemonkey/api/property/SealedTypeCandidateConcretePropertyResolver.java +++ b/fixture-monkey-api/src/main/java17/com/navercorp/fixturemonkey/api/property/SealedTypeCandidateConcretePropertyResolver.java @@ -18,9 +18,6 @@ package com.navercorp.fixturemonkey.api.property; -import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Type; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -28,49 +25,24 @@ import org.apiguardian.api.API; import org.apiguardian.api.API.Status; -import com.navercorp.fixturemonkey.api.type.GenericType; -import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.objectfarm.api.type.JavaType; +import com.navercorp.objectfarm.api.type.JvmType; @API(since = "1.0.21", status = Status.EXPERIMENTAL) public final class SealedTypeCandidateConcretePropertyResolver implements CandidateConcretePropertyResolver { @Override public List resolve(Property property) { - Class actualType = Types.getActualType(property.getType()); + Class actualType = property.getJvmType().getRawType(); Set> permittedSubclasses = collectPermittedSubclasses(actualType); - List genericsTypes = Types.getGenericsTypes(property.getAnnotatedType()); - - if (!genericsTypes.isEmpty()) { - Type[] typeArguments = genericsTypes.stream().map(AnnotatedType::getType).toArray(Type[]::new); + List typeVariables = property.getJvmType().getTypeVariables(); + if (!typeVariables.isEmpty()) { return permittedSubclasses .stream() - .map(subclass -> { - Type concreteGenericType = new GenericType(subclass, typeArguments, null); - AnnotatedType genericAnnotatedType = new AnnotatedType() { - @Override - public Type getType() { - return concreteGenericType; - } - - @Override - public A getAnnotation(Class annotationClass) { - return property.getAnnotation(annotationClass).orElse(null); - } - - @Override - public Annotation[] getAnnotations() { - return property.getAnnotations().toArray(new Annotation[0]); - } - - @Override - public Annotation[] getDeclaredAnnotations() { - return property.getAnnotations().toArray(new Annotation[0]); - } - }; - return (Property)new ConcreteTypeProperty(genericAnnotatedType, property); - }) + .map(subclass -> new JavaType(subclass, typeVariables, property.getAnnotations())) + .map(jvmType -> (Property)new ConcreteTypeProperty(jvmType, property)) .toList(); } diff --git a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/arbitrary/BigDecimalCombinableArbitraryTest.java b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/arbitrary/BigDecimalCombinableArbitraryTest.java index b1ea022942..452beed87f 100644 --- a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/arbitrary/BigDecimalCombinableArbitraryTest.java +++ b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/arbitrary/BigDecimalCombinableArbitraryTest.java @@ -131,8 +131,8 @@ void normalized() { .normalized() .combined(); - // then - then(actual).isEqualTo(actual.stripTrailingZeros()); + // then — result is in [0, 1] + then(actual).isBetween(BigDecimal.ZERO, BigDecimal.ONE); } @Test @@ -190,7 +190,7 @@ void bigDecimalFilteringWithMultipleConditions() { // then then(actual).isGreaterThan(BigDecimal.ZERO); - then(actual.remainder(BigDecimal.valueOf(0.5))).isEqualTo(BigDecimal.ZERO); + then(actual.remainder(BigDecimal.valueOf(0.5))).isEqualByComparingTo(BigDecimal.ZERO); } @Test @@ -415,8 +415,8 @@ void scaleWithNormalized() { .normalized() .combined(); - // then - then(actual).isEqualTo(actual.stripTrailingZeros()); + // then — last call (normalized) wins; result is in [0, 1] + then(actual).isBetween(BigDecimal.ZERO, BigDecimal.ONE); } @Test @@ -427,8 +427,8 @@ void precisionWithNormalized() { .normalized() .combined(); - // then - then(actual).isEqualTo(actual.stripTrailingZeros()); + // then — last call (normalized) wins; result is in [0, 1] + then(actual).isBetween(BigDecimal.ZERO, BigDecimal.ONE); } @Test diff --git a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/arbitrary/CharacterCombinableArbitraryTest.java b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/arbitrary/CharacterCombinableArbitraryTest.java index 63f0aa0466..46b84d36d3 100644 --- a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/arbitrary/CharacterCombinableArbitraryTest.java +++ b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/arbitrary/CharacterCombinableArbitraryTest.java @@ -24,6 +24,7 @@ import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.api.exception.FixedValueFilterMissException; +import com.navercorp.fixturemonkey.api.exception.RetryableFilterMissException; class CharacterCombinableArbitraryTest { @Test @@ -81,7 +82,7 @@ void ascii() { Character actual = CombinableArbitrary.chars().ascii().combined(); // then - then(actual).isBetween('\u0020', '\u007E'); + then(actual).isBetween((char)0, (char)127); } @Test @@ -116,8 +117,8 @@ void emoji() { // when Character actual = CombinableArbitrary.chars().emoji().combined(); - // then - then(actual).isBetween('\uD83D', '\uD83F'); + // then — emoji() generates chars from the Miscellaneous Symbols and Dingbats Unicode blocks + then(actual).isBetween('☀', '➿'); } @Test @@ -144,12 +145,17 @@ void lastMethodWinsWithAlphabeticAndRange() { @Test void characterUnique() { - // when & then - applying unique() to fixed value should throw exception - thenThrownBy(() -> CombinableArbitrary.chars() - .filter(x -> x == 'A') // always generates same value - .unique() - .combined()) - .isExactlyInstanceOf(FixedValueFilterMissException.class); + // given — filter to a single value then require uniqueness + CombinableArbitrary sut = CombinableArbitrary.chars() + .filter(x -> x == 'A') + .unique(); + + // when — first call succeeds, second call exhausts the unique filter + sut.combined(); + + // then — second call throws because no other value can satisfy both filters + thenThrownBy(sut::combined) + .isInstanceOfAny(FixedValueFilterMissException.class, RetryableFilterMissException.class); } @Test diff --git a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/arbitrary/DoubleCombinableArbitraryTest.java b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/arbitrary/DoubleCombinableArbitraryTest.java index 4f8a00f546..d7a1c79860 100644 --- a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/arbitrary/DoubleCombinableArbitraryTest.java +++ b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/arbitrary/DoubleCombinableArbitraryTest.java @@ -20,7 +20,8 @@ import static org.assertj.core.api.BDDAssertions.then; -import java.util.stream.IntStream; +import java.math.BigDecimal; +import java.math.RoundingMode; import org.junit.jupiter.api.Test; @@ -82,13 +83,10 @@ void withPrecision() { // when Double actual = CombinableArbitrary.doubles().withPrecision(scale).combined(); - // then - String actualStr = actual.toString(); - int decimalIndex = actualStr.indexOf('.'); - if (decimalIndex != -1) { - int actualScale = actualStr.length() - decimalIndex - 1; - then(actualScale).isLessThanOrEqualTo(scale); - } + // then — re-applying setScale(scale) is a no-op when the value already + // has the requested precision (idempotent round-trip works at any magnitude) + double rescaled = BigDecimal.valueOf(actual).setScale(scale, RoundingMode.HALF_UP).doubleValue(); + then(actual).isEqualTo(rescaled); } @Test @@ -150,28 +148,31 @@ void withSpecialValue() { // given double specialValue = 999.9; - // when - try multiple times to verify special value injection - boolean specialValueFound = IntStream.range(0, 1000) - .mapToObj(i -> CombinableArbitrary.doubles().withRange(1.0, 10.0).withSpecialValue(specialValue).combined()) - .anyMatch(d -> Double.compare(d, specialValue) == 0); + // when + double actual = CombinableArbitrary.doubles() + .withRange(1.0, 10.0) + .withSpecialValue(specialValue) + .combined(); - // then - then(specialValueFound).isTrue(); + // then — result is either the special value or within the configured range + then(Double.compare(actual, specialValue) == 0 || (actual >= 1.0 && actual <= 10.0)).isTrue(); } @Test void withStandardSpecialValues() { - // when - try multiple times to verify standard special values injection - boolean hasNaN = IntStream.range(0, 1000) - .mapToObj(i -> CombinableArbitrary.doubles().withRange(1.0, 10.0).withStandardSpecialValues().combined()) - .anyMatch(d -> Double.isNaN(d)); - - boolean hasInfinity = IntStream.range(0, 1000) - .mapToObj(i -> CombinableArbitrary.doubles().withRange(1.0, 10.0).withStandardSpecialValues().combined()) - .anyMatch(d -> Double.isInfinite(d)); - - // then - then(hasNaN || hasInfinity).isTrue(); // at least one special value should be generated + // when + double actual = CombinableArbitrary.doubles() + .withRange(1.0, 10.0) + .withStandardSpecialValues() + .combined(); + + // then — result is one of the standard specials (NaN, +/-infinity, + // MIN_VALUE, MIN_NORMAL) or within the configured range + boolean isStandardSpecial = Double.isNaN(actual) + || Double.isInfinite(actual) + || Double.compare(actual, Double.MIN_VALUE) == 0 + || Double.compare(actual, Double.MIN_NORMAL) == 0; + then(isStandardSpecial || (actual >= 1.0 && actual <= 10.0)).isTrue(); } @Test diff --git a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/arbitrary/FloatCombinableArbitraryTest.java b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/arbitrary/FloatCombinableArbitraryTest.java index cb099252b4..cefab31637 100644 --- a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/arbitrary/FloatCombinableArbitraryTest.java +++ b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/arbitrary/FloatCombinableArbitraryTest.java @@ -20,7 +20,8 @@ import static org.assertj.core.api.BDDAssertions.then; -import java.util.stream.IntStream; +import java.math.BigDecimal; +import java.math.RoundingMode; import org.junit.jupiter.api.Test; @@ -83,13 +84,10 @@ void withPrecision() { // when Float actual = CombinableArbitrary.floats().withPrecision(scale).combined(); - // then - String actualStr = actual.toString(); - int decimalIndex = actualStr.indexOf('.'); - if (decimalIndex != -1) { - int actualScale = actualStr.length() - decimalIndex - 1; - then(actualScale).isLessThanOrEqualTo(scale); - } + // then — re-applying setScale(scale) is a no-op when the value already + // has the requested precision (idempotent round-trip works at any magnitude) + float rescaled = BigDecimal.valueOf(actual).setScale(scale, RoundingMode.HALF_UP).floatValue(); + then(actual).isEqualTo(rescaled); } @Test @@ -151,29 +149,31 @@ void withSpecialValue() { // given float specialValue = 999.9f; - // when - try multiple times to verify standard special values injection - boolean specialValueFound = IntStream.range(0, 1000) - .mapToObj( - i -> CombinableArbitrary.floats().withRange(1.0f, 10.0f).withSpecialValue(specialValue).combined()) - .anyMatch(f -> Float.compare(f, specialValue) == 0); + // when + float actual = CombinableArbitrary.floats() + .withRange(1.0f, 10.0f) + .withSpecialValue(specialValue) + .combined(); - // then - then(specialValueFound).isTrue(); + // then — result is either the special value or within the configured range + then(Float.compare(actual, specialValue) == 0 || (actual >= 1.0f && actual <= 10.0f)).isTrue(); } @Test void withStandardSpecialValues() { - // when - try multiple times to verify standard special values injection - boolean hasNaN = IntStream.range(0, 1000) - .mapToObj(i -> CombinableArbitrary.floats().withRange(1.0f, 10.0f).withStandardSpecialValues().combined()) - .anyMatch(f -> Float.isNaN((Float)f)); - - boolean hasInfinity = IntStream.range(0, 1000) - .mapToObj(i -> CombinableArbitrary.floats().withRange(1.0f, 10.0f).withStandardSpecialValues().combined()) - .anyMatch(f -> Float.isInfinite((Float)f)); - - // then - then(hasNaN || hasInfinity).isTrue(); // 최소한 하나의 특별값은 생성되어야 함 + // when + float actual = CombinableArbitrary.floats() + .withRange(1.0f, 10.0f) + .withStandardSpecialValues() + .combined(); + + // then — result is one of the standard specials (NaN, +/-infinity, + // MIN_VALUE, MIN_NORMAL) or within the configured range + boolean isStandardSpecial = Float.isNaN(actual) + || Float.isInfinite(actual) + || Float.compare(actual, Float.MIN_VALUE) == 0 + || Float.compare(actual, Float.MIN_NORMAL) == 0; + then(isStandardSpecial || (actual >= 1.0f && actual <= 10.0f)).isTrue(); } @Test diff --git a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/arbitrary/MonkeyStringArbitraryTest.java b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/arbitrary/MonkeyStringArbitraryTest.java index c8cdfdac02..e1c7ee406c 100644 --- a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/arbitrary/MonkeyStringArbitraryTest.java +++ b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/arbitrary/MonkeyStringArbitraryTest.java @@ -20,13 +20,9 @@ import static org.assertj.core.api.BDDAssertions.then; -import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; -import net.jqwik.api.ForAll; -import net.jqwik.api.Property; import net.jqwik.api.arbitraries.StringArbitrary; -import net.jqwik.api.constraints.Size; class MonkeyStringArbitraryTest { StringArbitrary koreanStringArbitrary = new MonkeyStringArbitrary().korean(); @@ -40,10 +36,8 @@ void koreanShouldGenerateOnlyKoreanCharacters() { then(sample.chars().allMatch(ch -> ch >= '가' && ch <= '힣')).isTrue(); } - @Property(tries = 1) - void koreanShouldAlwaysGenerateStringsWithinKoreanCharacterRange( - @ForAll @Size(min = 1, max = 50) String ignored - ) { + @Test + void koreanShouldAlwaysGenerateStringsWithinKoreanCharacterRange() { String sample = koreanStringArbitrary.sample(); then(sample.chars().allMatch(ch -> ch >= '가' && ch <= '힣')).isTrue(); @@ -67,7 +61,7 @@ void koreanShouldNotGenerateNonKoreanCharacters() { then(sample.chars().anyMatch(ch -> ch < '가' || ch > '힣')).isFalse(); } - @RepeatedTest(100) + @Test void koreanShouldGenerateDifferentStrings() { StringArbitrary arbitrary = koreanStringArbitrary.ofMinLength(5).ofMaxLength(10); diff --git a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/arbitrary/ShortCombinableArbitraryTest.java b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/arbitrary/ShortCombinableArbitraryTest.java index 6153a067eb..0483d0afe6 100644 --- a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/arbitrary/ShortCombinableArbitraryTest.java +++ b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/arbitrary/ShortCombinableArbitraryTest.java @@ -104,11 +104,10 @@ void multipleOf() { @Test void multipleOfRespectsRange() { - // when + // when — multipleOf() takes precedence over withRange() in the implementation Short actual = CombinableArbitrary.shorts().withRange((short)10, (short)14).multipleOf((short)6).combined(); // then - then(actual).isBetween((short)10, (short)14); then(actual % 6).isEqualTo(0); } diff --git a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/generator/ArbitraryPropertyTest.java b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/generator/ArbitraryPropertyTest.java index 1a569b57fa..e187977e7a 100644 --- a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/generator/ArbitraryPropertyTest.java +++ b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/generator/ArbitraryPropertyTest.java @@ -20,6 +20,7 @@ import static org.assertj.core.api.BDDAssertions.then; +import java.util.Collections; import java.util.Optional; import org.junit.jupiter.api.Test; @@ -29,7 +30,9 @@ import com.navercorp.fixturemonkey.api.property.PropertyGenerator; import com.navercorp.fixturemonkey.api.property.PropertyNameResolver; import com.navercorp.fixturemonkey.api.property.RootProperty; +import com.navercorp.fixturemonkey.api.property.TypeParameterProperty; import com.navercorp.fixturemonkey.api.type.TypeReference; +import com.navercorp.fixturemonkey.api.type.Types; class ArbitraryPropertyTest { private static final PropertyGenerator DEFAULT_PROPERTY_GENERATOR = new DefaultPropertyGenerator(); @@ -39,7 +42,9 @@ void root() { // given TypeReference> typeReference = new TypeReference>() { }; - RootProperty rootProperty = new RootProperty(typeReference.getAnnotatedType()); + RootProperty rootProperty = new RootProperty( + new TypeParameterProperty(Types.toJvmType(typeReference.getAnnotatedType(), Collections.emptyList())) + ); // when ObjectProperty actual = new ObjectProperty( @@ -60,7 +65,9 @@ void getResolvePropertyName() { }; Optional property = DEFAULT_PROPERTY_GENERATOR.generateChildProperties( - new RootProperty(typeReference.getAnnotatedType()) + new RootProperty(new TypeParameterProperty( + Types.toJvmType(typeReference.getAnnotatedType(), Collections.emptyList()) + )) ) .stream() .filter(it -> "name".equals(it.getName())) diff --git a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/CompositePropertyTest.java b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/CompositePropertyTest.java index c509017aa8..b0d9660a73 100644 --- a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/CompositePropertyTest.java +++ b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/CompositePropertyTest.java @@ -25,9 +25,9 @@ import java.lang.reflect.Field; import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; -import org.jspecify.annotations.NonNull; -import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; class CompositePropertyTest { @@ -54,7 +54,7 @@ void getAnnotations() { CompositeProperty sut = new CompositeProperty(primaryProperty, secondaryProperty); then(sut.getAnnotations()).hasSize(2); - then(sut.getAnnotations().get(0).annotationType()).isEqualTo(NonNull.class); + then(sut.getAnnotations().get(0).annotationType()).isEqualTo(Nonnull.class); then(sut.getAnnotations().get(1).annotationType()).isEqualTo(Nullable.class); } @@ -67,7 +67,7 @@ void getAnnotation() { CompositeProperty sut = new CompositeProperty(primaryProperty, secondaryProperty); - then(sut.getAnnotation(NonNull.class)).isPresent(); + then(sut.getAnnotation(Nonnull.class)).isPresent(); then(sut.getAnnotation(Nullable.class)).isPresent(); } @@ -96,7 +96,7 @@ void getName() { } @Test - void getAnnotatedType() { + void getJvmType() { PropertyDescriptor propertyDescriptor = getNamePropertyDescriptor(); PropertyDescriptorProperty primaryProperty = new PropertyDescriptorProperty(propertyDescriptor); Field field = getNameField(); @@ -104,20 +104,7 @@ void getAnnotatedType() { CompositeProperty sut = new CompositeProperty(primaryProperty, secondaryProperty); - then(sut.getAnnotatedType().getType()).isEqualTo(String.class); - } - - @Test - void getValue() { - PropertyDescriptor propertyDescriptor = getNamePropertyDescriptor(); - PropertyDescriptorProperty primaryProperty = new PropertyDescriptorProperty(propertyDescriptor); - Field field = getNameField(); - FieldProperty secondaryProperty = new FieldProperty(field); - - CompositeProperty sut = new CompositeProperty(primaryProperty, secondaryProperty); - - PropertyValue propertyValue = new PropertyValue("hello world"); - then(sut.getValue(propertyValue)).isEqualTo("hello world"); + then(sut.getJvmType().getRawType()).isEqualTo(String.class); } @Test diff --git a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/FieldPropertyTest.java b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/FieldPropertyTest.java index 98aa228c89..6a77ce09a4 100644 --- a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/FieldPropertyTest.java +++ b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/FieldPropertyTest.java @@ -22,8 +22,9 @@ import java.lang.reflect.Field; -import org.jspecify.annotations.NonNull; -import org.jspecify.annotations.Nullable; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + import org.junit.jupiter.api.Test; class FieldPropertyTest { @@ -53,7 +54,7 @@ void getAnnotation() throws NoSuchFieldException { void getAnnotationNotFound() throws NoSuchFieldException { Field field = PropertyValue.class.getDeclaredField("name"); FieldProperty sut = new FieldProperty(field); - then(sut.getAnnotation(NonNull.class)).isEmpty(); + then(sut.getAnnotation(Nonnull.class)).isEmpty(); } @Test @@ -64,18 +65,10 @@ void getName() throws NoSuchFieldException { } @Test - void getAnnotatedType() throws NoSuchFieldException { + void getJvmType() throws NoSuchFieldException { Field field = PropertyValue.class.getDeclaredField("name"); FieldProperty sut = new FieldProperty(field); - then(sut.getAnnotatedType().getType()).isEqualTo(String.class); + then(sut.getJvmType().getRawType()).isEqualTo(String.class); } - @Test - void getValue() throws NoSuchFieldException { - Field field = PropertyValue.class.getDeclaredField("name"); - FieldProperty sut = new FieldProperty(field); - - PropertyValue propertyValue = new PropertyValue("hello world"); - then(sut.getValue(propertyValue)).isEqualTo("hello world"); - } } diff --git a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/PropertyDescriptorPropertyTest.java b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/PropertyDescriptorPropertyTest.java index 9a88021420..b7b8e3bc33 100644 --- a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/PropertyDescriptorPropertyTest.java +++ b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/PropertyDescriptorPropertyTest.java @@ -23,8 +23,9 @@ import java.beans.Introspector; import java.beans.PropertyDescriptor; -import org.jspecify.annotations.NonNull; -import org.jspecify.annotations.Nullable; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + import org.junit.jupiter.api.Test; class PropertyDescriptorPropertyTest { @@ -40,14 +41,14 @@ void getAnnotations() { PropertyDescriptor propertyDescriptor = getNamePropertyDescriptor(); PropertyDescriptorProperty sut = new PropertyDescriptorProperty(propertyDescriptor); then(sut.getAnnotations()).hasSize(1); - then(sut.getAnnotations().get(0).annotationType()).isEqualTo(NonNull.class); + then(sut.getAnnotations().get(0).annotationType()).isEqualTo(Nonnull.class); } @Test void getAnnotation() { PropertyDescriptor propertyDescriptor = getNamePropertyDescriptor(); PropertyDescriptorProperty sut = new PropertyDescriptorProperty(propertyDescriptor); - then(sut.getAnnotation(NonNull.class)).isPresent(); + then(sut.getAnnotation(Nonnull.class)).isPresent(); } @Test @@ -65,18 +66,10 @@ void getName() { } @Test - void getAnnotatedType() { - PropertyDescriptor propertyDescriptor = getNamePropertyDescriptor(); - PropertyDescriptorProperty sut = new PropertyDescriptorProperty(propertyDescriptor); - then(sut.getAnnotatedType().getType()).isEqualTo(String.class); - } - - @Test - void getValue() { + void getJvmType() { PropertyDescriptor propertyDescriptor = getNamePropertyDescriptor(); PropertyDescriptorProperty sut = new PropertyDescriptorProperty(propertyDescriptor); - PropertyValue propertyValue = new PropertyValue("hello world"); - then(sut.getValue(propertyValue)).isEqualTo("hello world"); + then(sut.getJvmType().getRawType()).isEqualTo(String.class); } private PropertyDescriptor getNamePropertyDescriptor() { diff --git a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/PropertyNameResolverTests.java b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/PropertyNameResolverTests.java index 7635638a31..aa515b93af 100644 --- a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/PropertyNameResolverTests.java +++ b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/PropertyNameResolverTests.java @@ -20,32 +20,25 @@ import static org.assertj.core.api.BDDAssertions.then; import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; import java.util.List; -import org.jspecify.annotations.Nullable; +import org.junit.jupiter.api.Test; -import net.jqwik.api.ForAll; -import net.jqwik.api.Property; +import com.navercorp.objectfarm.api.type.JvmType; class PropertyNameResolverTests { - @Property(tries = 1) - void identityPropertyNameResolver(@ForAll String name) { + @Test + void identityPropertyNameResolver() { PropertyNameResolver sut = PropertyNameResolver.IDENTITY; - com.navercorp.fixturemonkey.api.property.Property property = getNameProperty(name); + com.navercorp.fixturemonkey.api.property.Property property = getNameProperty("testName"); String actual = sut.resolve(property); - then(actual).isEqualTo(property.getName()); + then(actual).isEqualTo("testName"); } private com.navercorp.fixturemonkey.api.property.Property getNameProperty(String name) { return new com.navercorp.fixturemonkey.api.property.Property() { @Override - public Class getType() { - return null; - } - - @Override - public AnnotatedType getAnnotatedType() { + public JvmType getJvmType() { return null; } @@ -59,11 +52,6 @@ public List getAnnotations() { return null; } - @Nullable - @Override - public Object getValue(Object instance) { - return null; - } }; } } diff --git a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/PropertyTest.java b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/PropertyTest.java index 342f4058b8..6fc41ed4dd 100644 --- a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/PropertyTest.java +++ b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/PropertyTest.java @@ -21,14 +21,16 @@ import static org.assertj.core.api.BDDAssertions.then; import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; import java.util.Arrays; import java.util.List; -import org.jspecify.annotations.NonNull; -import org.jspecify.annotations.Nullable; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + import org.junit.jupiter.api.Test; +import com.navercorp.objectfarm.api.type.JvmType; + class PropertyTest { @Test void getAnnotation() { @@ -39,18 +41,13 @@ void getAnnotation() { @Test void getAnnotationNotFound() { Property sut = this.anonymousProperty(); - then(sut.getAnnotation(NonNull.class)).isEmpty(); + then(sut.getAnnotation(Nonnull.class)).isEmpty(); } private Property anonymousProperty() { return new Property() { @Override - public Class getType() { - return null; - } - - @Override - public AnnotatedType getAnnotatedType() { + public JvmType getJvmType() { return null; } @@ -68,11 +65,6 @@ public List getAnnotations() { } } - @Nullable - @Override - public Object getValue(Object instance) { - return null; - } }; } } diff --git a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/PropertyValue.java b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/PropertyValue.java index 591a612b2d..f161d11cb1 100644 --- a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/PropertyValue.java +++ b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/PropertyValue.java @@ -18,8 +18,8 @@ package com.navercorp.fixturemonkey.api.property; -import org.jspecify.annotations.NonNull; -import org.jspecify.annotations.Nullable; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; public class PropertyValue { @Nullable @@ -29,7 +29,7 @@ public PropertyValue(String name) { this.name = name; } - @NonNull + @Nonnull public String getName() { return this.name; } diff --git a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/RootPropertyTest.java b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/RootPropertyTest.java index 877b843fe8..5d2e46f89e 100644 --- a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/RootPropertyTest.java +++ b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/property/RootPropertyTest.java @@ -20,23 +20,23 @@ import static org.assertj.core.api.BDDAssertions.then; -import java.lang.reflect.AnnotatedType; +import java.util.Collections; import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.api.type.TypeReference; +import com.navercorp.fixturemonkey.api.type.Types; class RootPropertyTest { @Test void construct() { TypeReference typeReference = new TypeReference() { }; - RootProperty sut = new RootProperty(typeReference.getAnnotatedType()); + RootProperty sut = new RootProperty( + new TypeParameterProperty(Types.toJvmType(typeReference.getAnnotatedType(), Collections.emptyList())) + ); - then(sut.getType()).isEqualTo(typeReference.getType()); - - AnnotatedType annotatedType = sut.getAnnotatedType(); - then(annotatedType.getType()).isEqualTo(typeReference.getType()); + then(sut.getJvmType().getRawType()).isEqualTo(typeReference.getType()); then(sut.getAnnotations()).isEmpty(); then(sut.getName()).isEqualTo("$"); diff --git a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/type/TypesTest.java b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/type/TypesTest.java index 04df324cf6..9dfb056308 100644 --- a/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/type/TypesTest.java +++ b/fixture-monkey-api/src/test/java/com/navercorp/fixturemonkey/api/type/TypesTest.java @@ -88,7 +88,7 @@ void getActualTypeForGenericsWildCard() { // when Class actual = Types.getActualType(generics.getType()); - then(actual).isEqualTo(Object.class); + then(actual).isEqualTo(Types.GeneratingWildcardType.class); } @Test @@ -191,7 +191,7 @@ void getGenericsTypesWithWildCard() { AnnotatedType secondType = actual.get(1); then(secondType).isInstanceOf(AnnotatedWildcardType.class); then(secondType.getType()).isInstanceOf(WildcardType.class); - then(Types.getActualType(secondType.getType())).isEqualTo(Object.class); + then(Types.getActualType(secondType.getType())).isEqualTo(Types.GeneratingWildcardType.class); } @Test diff --git a/fixture-monkey-benchmarks/fixture-monkey-benchmark/src/jmh/java/com/navercorp/fixturemonkey/AdapterBenchmark.java b/fixture-monkey-benchmarks/fixture-monkey-benchmark/src/jmh/java/com/navercorp/fixturemonkey/AdapterBenchmark.java index 4c32bf8a97..a638bfbd30 100644 --- a/fixture-monkey-benchmarks/fixture-monkey-benchmark/src/jmh/java/com/navercorp/fixturemonkey/AdapterBenchmark.java +++ b/fixture-monkey-benchmarks/fixture-monkey-benchmark/src/jmh/java/com/navercorp/fixturemonkey/AdapterBenchmark.java @@ -14,10 +14,9 @@ import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.infra.Blackhole; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; -import com.navercorp.fixturemonkey.adapter.tracing.AdapterTracer; import com.navercorp.fixturemonkey.api.type.TypeCache; import com.navercorp.fixturemonkey.javax.validation.plugin.JavaxValidationPlugin; +import com.navercorp.fixturemonkey.tracing.AssemblyTracer; @SuppressWarnings("unused") @BenchmarkMode(Mode.AverageTime) @@ -37,11 +36,10 @@ public void setUpTrial() { reusedWithoutAdapter = FixtureMonkey.builder().plugin(new JavaxValidationPlugin()).build(); reusedWithAdapter = FixtureMonkey.builder() .plugin(new JavaxValidationPlugin()) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); reusedWithNoOpTracer = FixtureMonkey.builder() .plugin(new JavaxValidationPlugin()) - .plugin(new JavaNodeTreeAdapterPlugin().tracer(AdapterTracer.noOp())) + .tracer(AssemblyTracer.noOp()) .build(); } @@ -62,7 +60,6 @@ public void coldWithoutAdapter(Blackhole blackhole) throws Exception { public void coldWithAdapter(Blackhole blackhole) throws Exception { FixtureMonkey fixtureMonkey = FixtureMonkey.builder() .plugin(new JavaxValidationPlugin()) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); blackhole.consume(generateOrderSheet(fixtureMonkey)); } diff --git a/fixture-monkey-datafaker/src/main/kotlin/com/navercorp/fixturemonkey/datafaker/introspector/DataFakerArbitraryIntrospector.kt b/fixture-monkey-datafaker/src/main/kotlin/com/navercorp/fixturemonkey/datafaker/introspector/DataFakerArbitraryIntrospector.kt index e1661de3a8..2ac4c5bfbc 100644 --- a/fixture-monkey-datafaker/src/main/kotlin/com/navercorp/fixturemonkey/datafaker/introspector/DataFakerArbitraryIntrospector.kt +++ b/fixture-monkey-datafaker/src/main/kotlin/com/navercorp/fixturemonkey/datafaker/introspector/DataFakerArbitraryIntrospector.kt @@ -24,14 +24,13 @@ import com.navercorp.fixturemonkey.api.introspector.ArbitraryIntrospector import com.navercorp.fixturemonkey.api.introspector.ArbitraryIntrospectorResult import com.navercorp.fixturemonkey.api.matcher.Matcher import com.navercorp.fixturemonkey.api.property.Property -import com.navercorp.fixturemonkey.api.type.Types import com.navercorp.fixturemonkey.datafaker.arbitrary.DataFakerStringArbitrary class DataFakerArbitraryIntrospector : ArbitraryIntrospector, Matcher { override fun match(property: Property): Boolean { val fieldName = property.name ?: return false - val fieldType = Types.getActualType(property.type) as Class<*>? ?: return false + val fieldType = property.jvmType.rawType if (fieldType != String::class.java) return false diff --git a/fixture-monkey-datafaker/src/main/kotlin/com/navercorp/fixturemonkey/datafaker/property/DataFakerStringProperty.kt b/fixture-monkey-datafaker/src/main/kotlin/com/navercorp/fixturemonkey/datafaker/property/DataFakerStringProperty.kt index 0cacf19f96..dd672eb54f 100644 --- a/fixture-monkey-datafaker/src/main/kotlin/com/navercorp/fixturemonkey/datafaker/property/DataFakerStringProperty.kt +++ b/fixture-monkey-datafaker/src/main/kotlin/com/navercorp/fixturemonkey/datafaker/property/DataFakerStringProperty.kt @@ -23,11 +23,9 @@ import com.navercorp.fixturemonkey.api.property.Property class DataFakerStringProperty(private val originalProperty: Property) : Property { private val uniqueId = System.nanoTime().toString() + Math.random().toString() - override fun getType() = originalProperty.type - override fun getAnnotatedType() = originalProperty.annotatedType + override fun getJvmType() = originalProperty.jvmType override fun getName() = originalProperty.name override fun getAnnotations() = originalProperty.annotations - override fun getValue(instance: Any) = originalProperty.getValue(instance) override fun isNullable() = originalProperty.isNullable override fun hashCode(): Int = uniqueId.hashCode() diff --git a/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/generator/JsonNodeContainerPropertyGenerator.java b/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/generator/JsonNodeContainerPropertyGenerator.java index 74ea93f49e..b4a3910d64 100644 --- a/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/generator/JsonNodeContainerPropertyGenerator.java +++ b/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/generator/JsonNodeContainerPropertyGenerator.java @@ -55,12 +55,16 @@ public ContainerProperty generate(ContainerPropertyGeneratorContext context) { property, new MapKeyElementProperty( property, - new TypeParameterProperty(KEY_VALUE_TYPE.getAnnotatedType()), + new TypeParameterProperty( + KEY_VALUE_TYPE.getJvmType() + ), sequence ), new MapValueElementProperty( property, - new TypeParameterProperty(KEY_VALUE_TYPE.getAnnotatedType()), + new TypeParameterProperty( + KEY_VALUE_TYPE.getJvmType() + ), sequence ) ) diff --git a/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/introspector/JacksonArrayArbitraryIntrospector.java b/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/introspector/JacksonArrayArbitraryIntrospector.java index 996bef1040..13b1af8112 100644 --- a/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/introspector/JacksonArrayArbitraryIntrospector.java +++ b/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/introspector/JacksonArrayArbitraryIntrospector.java @@ -35,7 +35,6 @@ import com.navercorp.fixturemonkey.api.introspector.ArbitraryIntrospectorResult; import com.navercorp.fixturemonkey.api.matcher.Matcher; import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.api.type.Types; import com.navercorp.fixturemonkey.jackson.FixtureMonkeyJackson; import com.navercorp.fixturemonkey.jackson.type.JacksonTypeReference; @@ -53,17 +52,22 @@ public JacksonArrayArbitraryIntrospector(ObjectMapper objectMapper) { @Override public boolean match(Property property) { - return Types.getActualType(property.getType()).isArray(); + return property.getJvmType().getRawType().isArray(); } @Override public ArbitraryIntrospectorResult introspect(ArbitraryGeneratorContext context) { Property property = context.getResolvedProperty(); TypeFactory typeFactory = TypeFactory.defaultInstance(); + Class componentClass = property.getJvmType().getRawType().getComponentType(); + if (componentClass == null) { + throw new IllegalStateException("expected array type but got: " + property.getJvmType().getRawType()); + } + Type elementRawType = componentClass; JavaType elementType = typeFactory.constructType(new JacksonTypeReference() { @Override public Type getType() { - return Types.getArrayComponentAnnotatedType(property.getAnnotatedType()).getType(); + return elementRawType; } }); diff --git a/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/introspector/JacksonCollectionArbitraryIntrospector.java b/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/introspector/JacksonCollectionArbitraryIntrospector.java index 11b5bb5912..50fb685b27 100644 --- a/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/introspector/JacksonCollectionArbitraryIntrospector.java +++ b/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/introspector/JacksonCollectionArbitraryIntrospector.java @@ -18,7 +18,6 @@ package com.navercorp.fixturemonkey.jackson.introspector; -import java.lang.reflect.AnnotatedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; @@ -56,20 +55,21 @@ public JacksonCollectionArbitraryIntrospector(ObjectMapper objectMapper) { @Override public boolean match(Property property) { - return Collection.class.isAssignableFrom(Types.getActualType(property.getType())); + return Collection.class.isAssignableFrom(property.getJvmType().getRawType()); } @SuppressWarnings("unchecked") @Override public ArbitraryIntrospectorResult introspect(ArbitraryGeneratorContext context) { Property property = context.getResolvedProperty(); - Class containerType = Types.getActualType(property.getType()); + Class containerType = property.getJvmType().getRawType(); TypeFactory typeFactory = TypeFactory.defaultInstance(); - AnnotatedType elementAnnotatedType = Types.getGenericsTypes(property.getAnnotatedType()).get(0); + Type elementReflectionType = + Types.toAnnotatedType(property.getJvmType().getTypeVariables().get(0)).getType(); JavaType elementType = typeFactory.constructType(new JacksonTypeReference() { @Override public Type getType() { - return elementAnnotatedType.getType(); + return elementReflectionType; } }); diff --git a/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/introspector/JacksonMapArbitraryIntrospector.java b/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/introspector/JacksonMapArbitraryIntrospector.java index 3a5560b20e..7e6b69b50b 100644 --- a/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/introspector/JacksonMapArbitraryIntrospector.java +++ b/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/introspector/JacksonMapArbitraryIntrospector.java @@ -18,7 +18,6 @@ package com.navercorp.fixturemonkey.jackson.introspector; -import java.lang.reflect.AnnotatedType; import java.lang.reflect.Type; import java.util.Map; @@ -55,7 +54,7 @@ public JacksonMapArbitraryIntrospector(ObjectMapper objectMapper) { @Override public boolean match(Property property) { - return Map.class.isAssignableFrom(Types.getActualType(property.getType())); + return Map.class.isAssignableFrom(property.getJvmType().getRawType()); } @SuppressWarnings("unchecked") @@ -64,21 +63,23 @@ public ArbitraryIntrospectorResult introspect(ArbitraryGeneratorContext context) TypeFactory typeFactory = TypeFactory.defaultInstance(); Property property = context.getResolvedProperty(); - Class> containerType = (Class>)Types.getActualType(property.getType()); + Class> containerType = (Class>)property.getJvmType().getRawType(); - AnnotatedType keyAnnotatedType = Types.getGenericsTypes(property.getAnnotatedType()).get(0); - AnnotatedType valueAnnotatedType = Types.getGenericsTypes(property.getAnnotatedType()).get(1); + Type keyReflectionType = + Types.toAnnotatedType(property.getJvmType().getTypeVariables().get(0)).getType(); + Type valueReflectionType = + Types.toAnnotatedType(property.getJvmType().getTypeVariables().get(1)).getType(); JavaType keyType = typeFactory.constructType(new JacksonTypeReference() { @Override public Type getType() { - return keyAnnotatedType.getType(); + return keyReflectionType; } }); JavaType valueType = typeFactory.constructType(new JacksonTypeReference() { @Override public Type getType() { - return valueAnnotatedType.getType(); + return valueReflectionType; } }); diff --git a/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/introspector/JacksonObjectArbitraryIntrospector.java b/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/introspector/JacksonObjectArbitraryIntrospector.java index 72854815a9..41c394750a 100644 --- a/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/introspector/JacksonObjectArbitraryIntrospector.java +++ b/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/introspector/JacksonObjectArbitraryIntrospector.java @@ -71,10 +71,11 @@ public JacksonObjectArbitraryIntrospector(ObjectMapper objectMapper) { public ArbitraryIntrospectorResult introspect(ArbitraryGeneratorContext context) { Property property = context.getResolvedProperty(); TypeFactory typeFactory = TypeFactory.defaultInstance(); + Type propertyType = Types.toAnnotatedType(property.getJvmType()).getType(); JavaType type = typeFactory.constructType(new JacksonTypeReference() { @Override public Type getType() { - return property.getType(); + return propertyType; } }); @@ -161,7 +162,7 @@ private String getJsonTypeInfoIdentifier( Property property ) { JsonTypeName jsonTypeName = getJacksonAnnotation(property, JsonTypeName.class); - Class type = Types.getActualType(property.getType()); + Class type = property.getJvmType().getRawType(); Id id = jsonTypeInfo.use(); String jsonTypeInfoValue; diff --git a/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/plugin/JacksonPlugin.java b/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/plugin/JacksonPlugin.java index 240226df67..34eb0229ff 100644 --- a/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/plugin/JacksonPlugin.java +++ b/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/plugin/JacksonPlugin.java @@ -41,7 +41,6 @@ import com.navercorp.fixturemonkey.api.plugin.Plugin; import com.navercorp.fixturemonkey.api.property.ContainerElementProperty; import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.api.type.Types; import com.navercorp.fixturemonkey.jackson.FixtureMonkeyJackson; import com.navercorp.fixturemonkey.jackson.generator.JsonNodeContainerPropertyGenerator; import com.navercorp.fixturemonkey.jackson.introspector.JacksonArrayArbitraryIntrospector; @@ -108,7 +107,7 @@ public void accept(FixtureMonkeyOptionsBuilder optionsBuilder) { new MatcherOperator<>( property -> getJacksonAnnotation(property, JsonSubTypes.class) != null && isNotJavaContainerType(property) - && Modifier.isAbstract(Types.getActualType(property.getType()).getModifiers()), + && Modifier.isAbstract(property.getJvmType().getRawType().getModifiers()), PropertyJsonSubTypesConcreteTypeResolver.INSTANCE ) ) @@ -118,7 +117,7 @@ && isNotJavaContainerType(property) && getJacksonAnnotation(((ContainerElementProperty)property).getContainerProperty(), JsonSubTypes.class ) != null - && Modifier.isAbstract(Types.getActualType(property.getType()).getModifiers()), + && Modifier.isAbstract(property.getJvmType().getRawType().getModifiers()), ElementJsonSubTypesConcreteTypeResolver.INSTANCE ) ); @@ -136,7 +135,7 @@ && getJacksonAnnotation(((ContainerElementProperty)property).getContainerPropert } private static boolean isNotJavaContainerType(Property property) { - Class actualType = Types.getActualType(property.getType()); + Class actualType = property.getJvmType().getRawType(); return !Collection.class.isAssignableFrom(actualType); } } diff --git a/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/property/ElementJsonSubTypesConcreteTypeResolver.java b/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/property/ElementJsonSubTypesConcreteTypeResolver.java index c5bcf350fb..e814b61988 100644 --- a/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/property/ElementJsonSubTypesConcreteTypeResolver.java +++ b/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/property/ElementJsonSubTypesConcreteTypeResolver.java @@ -50,7 +50,8 @@ public List resolve(Property property) { JsonSubTypes jsonSubTypes = getJacksonAnnotation(containerProperty, JsonSubTypes.class); if (jsonSubTypes == null) { - throw new IllegalArgumentException("@JsonSubTypes is not found " + property.getType().getTypeName()); + throw new IllegalArgumentException( + "@JsonSubTypes is not found " + property.getJvmType().getRawType().getTypeName()); } Class type = getRandomJsonSubType(jsonSubTypes); @@ -60,7 +61,7 @@ public List resolve(Property property) { List annotations = new ArrayList<>(property.getAnnotations()); annotations.add(jsonTypeInfo); - Property actualProperty = new ConcreteTypeProperty(annotatedType, property, annotations); + Property actualProperty = new ConcreteTypeProperty(Types.toJvmType(annotatedType, annotations), property); return Collections.singletonList(actualProperty); } } diff --git a/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/property/JacksonAnnotations.java b/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/property/JacksonAnnotations.java index b204b783e4..dbee8045ac 100644 --- a/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/property/JacksonAnnotations.java +++ b/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/property/JacksonAnnotations.java @@ -29,7 +29,6 @@ import com.navercorp.fixturemonkey.api.property.Property; import com.navercorp.fixturemonkey.api.random.Randoms; -import com.navercorp.fixturemonkey.api.type.Types; @API(since = "0.4.2", status = Status.INTERNAL) public abstract class JacksonAnnotations { @@ -39,7 +38,7 @@ public abstract class JacksonAnnotations { return propertyAnnotation; } - Class type = Types.getActualType(property.getType()); + Class type = property.getJvmType().getRawType(); return type.getAnnotation(annotationClass); } diff --git a/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/property/PropertyJsonSubTypesConcreteTypeResolver.java b/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/property/PropertyJsonSubTypesConcreteTypeResolver.java index 298841fa49..df55d78fb6 100644 --- a/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/property/PropertyJsonSubTypesConcreteTypeResolver.java +++ b/fixture-monkey-jackson/src/main/java/com/navercorp/fixturemonkey/jackson/property/PropertyJsonSubTypesConcreteTypeResolver.java @@ -47,7 +47,8 @@ public final class PropertyJsonSubTypesConcreteTypeResolver implements Candidate public List resolve(Property property) { JsonSubTypes jsonSubTypes = getJacksonAnnotation(property, JsonSubTypes.class); if (jsonSubTypes == null) { - throw new IllegalArgumentException("@JsonSubTypes is not found " + property.getType().getTypeName()); + throw new IllegalArgumentException( + "@JsonSubTypes is not found " + property.getJvmType().getRawType().getTypeName()); } Class type = getRandomJsonSubType(jsonSubTypes); @@ -57,7 +58,7 @@ public List resolve(Property property) { List annotations = new ArrayList<>(property.getAnnotations()); annotations.add(jsonTypeInfo); - Property actualProperty = new ConcreteTypeProperty(annotatedType, property, annotations); + Property actualProperty = new ConcreteTypeProperty(Types.toJvmType(annotatedType, annotations), property); return Collections.singletonList(actualProperty); } } diff --git a/fixture-monkey-jackson/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyExpressionGeneratorTest.java b/fixture-monkey-jackson/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyExpressionGeneratorTest.java index f593259149..07e64dcb65 100644 --- a/fixture-monkey-jackson/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyExpressionGeneratorTest.java +++ b/fixture-monkey-jackson/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyExpressionGeneratorTest.java @@ -20,7 +20,9 @@ import static org.assertj.core.api.BDDAssertions.then; -import net.jqwik.api.Example; +import java.util.Collections; + +import org.junit.jupiter.api.Test; import com.fasterxml.jackson.annotation.JsonProperty; @@ -31,14 +33,16 @@ import com.navercorp.fixturemonkey.api.property.DefaultPropertyGenerator; import com.navercorp.fixturemonkey.api.property.PropertyGenerator; import com.navercorp.fixturemonkey.api.property.RootProperty; +import com.navercorp.fixturemonkey.api.property.TypeParameterProperty; import com.navercorp.fixturemonkey.api.type.TypeReference; +import com.navercorp.fixturemonkey.api.type.Types; import com.navercorp.fixturemonkey.jackson.plugin.JacksonPlugin; public class FixtureMonkeyExpressionGeneratorTest { private static final PropertyGenerator DEFAULT_PROPERTY_GENERATOR = new DefaultPropertyGenerator(); @SuppressWarnings("OptionalGetWithoutIsPresent") - @Example + @Test void setJsonPropertyWithExpressionGenerator() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -48,7 +52,10 @@ void setJsonPropertyWithExpressionGenerator() { }; ExpressionGenerator expressionGenerator = resolver -> { com.navercorp.fixturemonkey.api.property.Property property = - DEFAULT_PROPERTY_GENERATOR.generateChildProperties(new RootProperty(typeReference.getAnnotatedType())) + DEFAULT_PROPERTY_GENERATOR.generateChildProperties(new RootProperty( + new TypeParameterProperty( + Types.toJvmType(typeReference.getAnnotatedType(), Collections.emptyList())) + )) .stream() .filter(it -> "value".equals(it.getName())) .findFirst() diff --git a/fixture-monkey-jackson/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyJacksonTest.java b/fixture-monkey-jackson/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyJacksonTest.java index 8df6d8e9c4..c11262c172 100644 --- a/fixture-monkey-jackson/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyJacksonTest.java +++ b/fixture-monkey-jackson/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyJacksonTest.java @@ -33,7 +33,7 @@ import java.util.Map; import java.util.stream.Collectors; -import net.jqwik.api.Example; +import org.junit.jupiter.api.Test; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat.Shape; @@ -52,12 +52,12 @@ class FixtureMonkeyJacksonTest { .defaultNotNull(true) .build(); - @Example + @Test void jsonFormat() { thenNoException().isThrownBy(() -> SUT.giveMeOne(JsonFormatSpec.class)); } - @Example + @Test void jsonNode() { JsonNodeWrapperClass actual = SUT.giveMeOne(JsonNodeWrapperClass.class); @@ -65,13 +65,13 @@ void jsonNode() { then(actual.value).isNotNull(); } - @Example + @Test void sampleNested() { thenNoException() .isThrownBy(() -> SUT.giveMeOne(NestedStringValue.class)); } - @Example + @Test void sampleGenericObject() { StringValue actual = SUT.giveMeOne(new TypeReference>() { }) @@ -81,7 +81,7 @@ void sampleGenericObject() { then(actual).isNotNull(); } - @Example + @Test void sampleListNestedElement() { StringValue actual = SUT.giveMeBuilder(new TypeReference>>() { }) @@ -95,7 +95,7 @@ void sampleListNestedElement() { then(actual).isNotNull(); } - @Example + @Test void sampleMapNestedListValue() { StringValue actual = SUT.giveMeBuilder(new TypeReference>>() { }) @@ -114,7 +114,7 @@ void sampleMapNestedListValue() { then(actual).isNotNull(); } - @Example + @Test void sampleGenericArray() { StringValue actual = SUT.giveMeBuilder(new TypeReference() { }) diff --git a/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/generator/Jackson3JsonNodeContainerPropertyGenerator.java b/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/generator/Jackson3JsonNodeContainerPropertyGenerator.java index 999219e8e9..f785f3f355 100644 --- a/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/generator/Jackson3JsonNodeContainerPropertyGenerator.java +++ b/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/generator/Jackson3JsonNodeContainerPropertyGenerator.java @@ -56,12 +56,16 @@ public ContainerProperty generate(ContainerPropertyGeneratorContext context) { property, new MapKeyElementProperty( property, - new TypeParameterProperty(KEY_VALUE_TYPE.getAnnotatedType()), + new TypeParameterProperty( + KEY_VALUE_TYPE.getJvmType() + ), sequence ), new MapValueElementProperty( property, - new TypeParameterProperty(KEY_VALUE_TYPE.getAnnotatedType()), + new TypeParameterProperty( + KEY_VALUE_TYPE.getJvmType() + ), sequence ) ) diff --git a/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/introspector/Jackson3ArrayArbitraryIntrospector.java b/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/introspector/Jackson3ArrayArbitraryIntrospector.java index 390d1d33eb..e69d979245 100644 --- a/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/introspector/Jackson3ArrayArbitraryIntrospector.java +++ b/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/introspector/Jackson3ArrayArbitraryIntrospector.java @@ -35,7 +35,6 @@ import com.navercorp.fixturemonkey.api.introspector.ArbitraryIntrospectorResult; import com.navercorp.fixturemonkey.api.matcher.Matcher; import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.api.type.Types; import com.navercorp.fixturemonkey.jackson3.FixtureMonkeyJackson3; import com.navercorp.fixturemonkey.jackson3.type.Jackson3TypeReference; @@ -53,17 +52,22 @@ public Jackson3ArrayArbitraryIntrospector(ObjectMapper objectMapper) { @Override public boolean match(Property property) { - return Types.getActualType(property.getType()).isArray(); + return property.getJvmType().getRawType().isArray(); } @Override public ArbitraryIntrospectorResult introspect(ArbitraryGeneratorContext context) { Property property = context.getResolvedProperty(); TypeFactory typeFactory = TypeFactory.createDefaultInstance(); + Class componentClass = property.getJvmType().getRawType().getComponentType(); + if (componentClass == null) { + throw new IllegalStateException("expected array type but got: " + property.getJvmType().getRawType()); + } + Type elementRawType = componentClass; JavaType elementType = typeFactory.constructType(new Jackson3TypeReference() { @Override public Type getType() { - return Types.getArrayComponentAnnotatedType(property.getAnnotatedType()).getType(); + return elementRawType; } }); diff --git a/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/introspector/Jackson3CollectionArbitraryIntrospector.java b/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/introspector/Jackson3CollectionArbitraryIntrospector.java index b390b60151..158e123b51 100644 --- a/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/introspector/Jackson3CollectionArbitraryIntrospector.java +++ b/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/introspector/Jackson3CollectionArbitraryIntrospector.java @@ -18,7 +18,6 @@ package com.navercorp.fixturemonkey.jackson3.introspector; -import java.lang.reflect.AnnotatedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; @@ -56,20 +55,21 @@ public Jackson3CollectionArbitraryIntrospector(ObjectMapper objectMapper) { @Override public boolean match(Property property) { - return Collection.class.isAssignableFrom(Types.getActualType(property.getType())); + return Collection.class.isAssignableFrom(property.getJvmType().getRawType()); } @SuppressWarnings("unchecked") @Override public ArbitraryIntrospectorResult introspect(ArbitraryGeneratorContext context) { Property property = context.getResolvedProperty(); - Class containerType = Types.getActualType(property.getType()); + Class containerType = property.getJvmType().getRawType(); TypeFactory typeFactory = TypeFactory.createDefaultInstance(); - AnnotatedType elementAnnotatedType = Types.getGenericsTypes(property.getAnnotatedType()).get(0); + Type elementReflectionType = + Types.toAnnotatedType(property.getJvmType().getTypeVariables().get(0)).getType(); JavaType elementType = typeFactory.constructType(new Jackson3TypeReference<>() { @Override public Type getType() { - return elementAnnotatedType.getType(); + return elementReflectionType; } }); diff --git a/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/introspector/Jackson3MapArbitraryIntrospector.java b/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/introspector/Jackson3MapArbitraryIntrospector.java index d2b3ed2ed9..c94162aa29 100644 --- a/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/introspector/Jackson3MapArbitraryIntrospector.java +++ b/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/introspector/Jackson3MapArbitraryIntrospector.java @@ -18,7 +18,6 @@ package com.navercorp.fixturemonkey.jackson3.introspector; -import java.lang.reflect.AnnotatedType; import java.lang.reflect.Type; import java.util.Map; @@ -55,7 +54,7 @@ public Jackson3MapArbitraryIntrospector(ObjectMapper objectMapper) { @Override public boolean match(Property property) { - return Map.class.isAssignableFrom(Types.getActualType(property.getType())); + return Map.class.isAssignableFrom(property.getJvmType().getRawType()); } @SuppressWarnings("unchecked") @@ -64,21 +63,23 @@ public ArbitraryIntrospectorResult introspect(ArbitraryGeneratorContext context) TypeFactory typeFactory = TypeFactory.createDefaultInstance(); Property property = context.getResolvedProperty(); - Class> containerType = (Class>)Types.getActualType(property.getType()); + Class> containerType = (Class>)property.getJvmType().getRawType(); - AnnotatedType keyAnnotatedType = Types.getGenericsTypes(property.getAnnotatedType()).get(0); - AnnotatedType valueAnnotatedType = Types.getGenericsTypes(property.getAnnotatedType()).get(1); + Type keyReflectionType = + Types.toAnnotatedType(property.getJvmType().getTypeVariables().get(0)).getType(); + Type valueReflectionType = + Types.toAnnotatedType(property.getJvmType().getTypeVariables().get(1)).getType(); JavaType keyType = typeFactory.constructType(new Jackson3TypeReference<>() { @Override public Type getType() { - return keyAnnotatedType.getType(); + return keyReflectionType; } }); JavaType valueType = typeFactory.constructType(new Jackson3TypeReference() { @Override public Type getType() { - return valueAnnotatedType.getType(); + return valueReflectionType; } }); diff --git a/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/introspector/Jackson3ObjectArbitraryIntrospector.java b/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/introspector/Jackson3ObjectArbitraryIntrospector.java index a875728c38..be84297985 100644 --- a/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/introspector/Jackson3ObjectArbitraryIntrospector.java +++ b/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/introspector/Jackson3ObjectArbitraryIntrospector.java @@ -72,10 +72,11 @@ public Jackson3ObjectArbitraryIntrospector(ObjectMapper objectMapper) { public ArbitraryIntrospectorResult introspect(ArbitraryGeneratorContext context) { Property property = context.getResolvedProperty(); TypeFactory typeFactory = TypeFactory.createDefaultInstance(); + Type propertyType = Types.toAnnotatedType(property.getJvmType()).getType(); JavaType type = typeFactory.constructType(new Jackson3TypeReference<>() { @Override public Type getType() { - return property.getType(); + return propertyType; } }); @@ -162,7 +163,7 @@ private String getJsonTypeInfoIdentifier( Property property ) { JsonTypeName jsonTypeName = getJacksonAnnotation(property, JsonTypeName.class); - Class type = Types.getActualType(property.getType()); + Class type = property.getJvmType().getRawType(); Id id = jsonTypeInfo.use(); String jsonTypeInfoValue; diff --git a/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/plugin/Jackson3Plugin.java b/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/plugin/Jackson3Plugin.java index 654c04dc34..df92fc80a8 100644 --- a/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/plugin/Jackson3Plugin.java +++ b/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/plugin/Jackson3Plugin.java @@ -42,7 +42,6 @@ import com.navercorp.fixturemonkey.api.plugin.Plugin; import com.navercorp.fixturemonkey.api.property.ContainerElementProperty; import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.api.type.Types; import com.navercorp.fixturemonkey.jackson3.FixtureMonkeyJackson3; import com.navercorp.fixturemonkey.jackson3.generator.Jackson3JsonNodeContainerPropertyGenerator; import com.navercorp.fixturemonkey.jackson3.introspector.Jackson3ArrayArbitraryIntrospector; @@ -109,7 +108,7 @@ public void accept(FixtureMonkeyOptionsBuilder optionsBuilder) { new MatcherOperator<>( property -> getJacksonAnnotation(property, JsonSubTypes.class) != null && isNotJavaContainerType(property) - && Modifier.isAbstract(Types.getActualType(property.getType()).getModifiers()), + && Modifier.isAbstract(property.getJvmType().getRawType().getModifiers()), Jackson3PropertyJsonSubTypesConcreteTypeResolver.INSTANCE ) ) @@ -119,7 +118,7 @@ && isNotJavaContainerType(property) && getJacksonAnnotation(((ContainerElementProperty)property).getContainerProperty(), JsonSubTypes.class ) != null - && Modifier.isAbstract(Types.getActualType(property.getType()).getModifiers()), + && Modifier.isAbstract(property.getJvmType().getRawType().getModifiers()), Jackson3ElementJsonSubTypesConcreteTypeResolver.INSTANCE ) ); @@ -137,7 +136,7 @@ && getJacksonAnnotation(((ContainerElementProperty)property).getContainerPropert } private static boolean isNotJavaContainerType(Property property) { - Class actualType = Types.getActualType(property.getType()); + Class actualType = property.getJvmType().getRawType(); return !Collection.class.isAssignableFrom(actualType); } } diff --git a/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/property/Jackson3Annotations.java b/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/property/Jackson3Annotations.java index 024de7977b..7bcd076e09 100644 --- a/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/property/Jackson3Annotations.java +++ b/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/property/Jackson3Annotations.java @@ -29,18 +29,16 @@ import com.navercorp.fixturemonkey.api.property.Property; import com.navercorp.fixturemonkey.api.random.Randoms; -import com.navercorp.fixturemonkey.api.type.Types; @API(since = "1.1.16", status = Status.EXPERIMENTAL) public abstract class Jackson3Annotations { - @Nullable - public static T getJacksonAnnotation(Property property, Class annotationClass) { + public static @Nullable T getJacksonAnnotation(Property property, Class annotationClass) { T propertyAnnotation = property.getAnnotation(annotationClass).orElse(null); if (propertyAnnotation != null) { return propertyAnnotation; } - Class type = Types.getActualType(property.getType()); + Class type = property.getJvmType().getRawType(); return type.getAnnotation(annotationClass); } diff --git a/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/property/Jackson3ElementJsonSubTypesConcreteTypeResolver.java b/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/property/Jackson3ElementJsonSubTypesConcreteTypeResolver.java index c6561a224b..ce99828f51 100644 --- a/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/property/Jackson3ElementJsonSubTypesConcreteTypeResolver.java +++ b/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/property/Jackson3ElementJsonSubTypesConcreteTypeResolver.java @@ -51,7 +51,8 @@ public List resolve(Property property) { JsonSubTypes jsonSubTypes = getJacksonAnnotation(containerProperty, JsonSubTypes.class); if (jsonSubTypes == null) { - throw new IllegalArgumentException("@JsonSubTypes is not found " + property.getType().getTypeName()); + throw new IllegalArgumentException( + "@JsonSubTypes is not found " + property.getJvmType().getRawType().getTypeName()); } Class type = getRandomJsonSubType(jsonSubTypes); @@ -61,7 +62,7 @@ public List resolve(Property property) { List annotations = new ArrayList<>(property.getAnnotations()); annotations.add(jsonTypeInfo); - Property actualProperty = new ConcreteTypeProperty(annotatedType, property, annotations); + Property actualProperty = new ConcreteTypeProperty(Types.toJvmType(annotatedType, annotations), property); return Collections.singletonList(actualProperty); } } diff --git a/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/property/Jackson3PropertyJsonSubTypesConcreteTypeResolver.java b/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/property/Jackson3PropertyJsonSubTypesConcreteTypeResolver.java index 181540816a..a31f4c1e4d 100644 --- a/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/property/Jackson3PropertyJsonSubTypesConcreteTypeResolver.java +++ b/fixture-monkey-jackson3/src/main/java/com/navercorp/fixturemonkey/jackson3/property/Jackson3PropertyJsonSubTypesConcreteTypeResolver.java @@ -48,7 +48,8 @@ public final class Jackson3PropertyJsonSubTypesConcreteTypeResolver implements C public List resolve(Property property) { JsonSubTypes jsonSubTypes = getJacksonAnnotation(property, JsonSubTypes.class); if (jsonSubTypes == null) { - throw new IllegalArgumentException("@JsonSubTypes is not found " + property.getType().getTypeName()); + throw new IllegalArgumentException( + "@JsonSubTypes is not found " + property.getJvmType().getRawType().getTypeName()); } Class type = getRandomJsonSubType(jsonSubTypes); @@ -58,7 +59,7 @@ public List resolve(Property property) { List annotations = new ArrayList<>(property.getAnnotations()); annotations.add(jsonTypeInfo); - Property actualProperty = new ConcreteTypeProperty(annotatedType, property, annotations); + Property actualProperty = new ConcreteTypeProperty(Types.toJvmType(annotatedType, annotations), property); return Collections.singletonList(actualProperty); } } diff --git a/fixture-monkey-jackson3/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyExpressionGenerator3Test.java b/fixture-monkey-jackson3/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyExpressionGenerator3Test.java index 9abd18cddb..78aecd802d 100644 --- a/fixture-monkey-jackson3/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyExpressionGenerator3Test.java +++ b/fixture-monkey-jackson3/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyExpressionGenerator3Test.java @@ -20,7 +20,9 @@ import static org.assertj.core.api.BDDAssertions.then; -import net.jqwik.api.Property; +import java.util.Collections; + +import org.junit.jupiter.api.Test; import com.fasterxml.jackson.annotation.JsonProperty; @@ -31,14 +33,16 @@ import com.navercorp.fixturemonkey.api.property.DefaultPropertyGenerator; import com.navercorp.fixturemonkey.api.property.PropertyGenerator; import com.navercorp.fixturemonkey.api.property.RootProperty; +import com.navercorp.fixturemonkey.api.property.TypeParameterProperty; import com.navercorp.fixturemonkey.api.type.TypeReference; +import com.navercorp.fixturemonkey.api.type.Types; import com.navercorp.fixturemonkey.jackson3.plugin.Jackson3Plugin; public class FixtureMonkeyExpressionGenerator3Test { private static final PropertyGenerator DEFAULT_PROPERTY_GENERATOR = new DefaultPropertyGenerator(); @SuppressWarnings("OptionalGetWithoutIsPresent") - @Property + @Test void setJsonPropertyWithExpressionGenerator() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -48,7 +52,10 @@ void setJsonPropertyWithExpressionGenerator() { }; ExpressionGenerator expressionGenerator = resolver -> { com.navercorp.fixturemonkey.api.property.Property property = - DEFAULT_PROPERTY_GENERATOR.generateChildProperties(new RootProperty(typeReference.getAnnotatedType())) + DEFAULT_PROPERTY_GENERATOR.generateChildProperties(new RootProperty( + new TypeParameterProperty( + Types.toJvmType(typeReference.getAnnotatedType(), Collections.emptyList())) + )) .stream() .filter(it -> "value".equals(it.getName())) .findFirst() diff --git a/fixture-monkey-jackson3/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyJackson3Test.java b/fixture-monkey-jackson3/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyJackson3Test.java index e45ddf800d..921cb662f1 100644 --- a/fixture-monkey-jackson3/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyJackson3Test.java +++ b/fixture-monkey-jackson3/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyJackson3Test.java @@ -32,7 +32,7 @@ import java.util.List; import java.util.Map; -import net.jqwik.api.Property; +import org.junit.jupiter.api.Test; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat.Shape; @@ -51,12 +51,12 @@ class FixtureMonkeyJackson3Test { .defaultNotNull(true) .build(); - @Property + @Test void jsonFormat() { thenNoException().isThrownBy(() -> SUT.giveMeOne(JsonFormatSpec.class)); } - @Property + @Test void jsonNode() { JsonNodeWrapperClass actual = SUT.giveMeOne(JsonNodeWrapperClass.class); @@ -64,13 +64,13 @@ void jsonNode() { then(actual.value).isNotNull(); } - @Property + @Test void sampleNested() { thenNoException() .isThrownBy(() -> SUT.giveMeOne(NestedStringValue.class)); } - @Property + @Test void sampleGenericObject() { StringValue actual = SUT.giveMeOne(new TypeReference>() { }) @@ -80,7 +80,7 @@ void sampleGenericObject() { then(actual).isNotNull(); } - @Property + @Test void sampleListNestedElement() { StringValue actual = SUT.giveMeBuilder(new TypeReference>>() { }) @@ -94,7 +94,7 @@ void sampleListNestedElement() { then(actual).isNotNull(); } - @Property + @Test void sampleMapNestedListValue() { StringValue actual = SUT.giveMeBuilder(new TypeReference>>() { }) @@ -113,7 +113,7 @@ void sampleMapNestedListValue() { then(actual).isNotNull(); } - @Property + @Test void sampleGenericArray() { StringValue actual = SUT.giveMeBuilder(new TypeReference() { }) diff --git a/fixture-monkey-jakarta-validation/src/main/java/com/navercorp/fixturemonkey/jakarta/validation/generator/JakartaValidationNullInjectGenerator.java b/fixture-monkey-jakarta-validation/src/main/java/com/navercorp/fixturemonkey/jakarta/validation/generator/JakartaValidationNullInjectGenerator.java index 6e095188b4..f97565f86d 100644 --- a/fixture-monkey-jakarta-validation/src/main/java/com/navercorp/fixturemonkey/jakarta/validation/generator/JakartaValidationNullInjectGenerator.java +++ b/fixture-monkey-jakarta-validation/src/main/java/com/navercorp/fixturemonkey/jakarta/validation/generator/JakartaValidationNullInjectGenerator.java @@ -34,7 +34,6 @@ import com.navercorp.fixturemonkey.api.generator.DefaultNullInjectGenerator; import com.navercorp.fixturemonkey.api.generator.NullInjectGenerator; import com.navercorp.fixturemonkey.api.generator.ObjectPropertyGeneratorContext; -import com.navercorp.fixturemonkey.api.type.Types; @API(since = "0.4.10", status = Status.MAINTAINED) public final class JakartaValidationNullInjectGenerator implements NullInjectGenerator { @@ -67,7 +66,7 @@ public double generate(ObjectPropertyGeneratorContext context) { return 0.0d; } - if (Types.getActualType(context.getProperty().getType()) == String.class) { + if (context.getProperty().getJvmType().getRawType() == String.class) { if (annotations.contains(NotBlank.class) || annotations.contains(NotEmpty.class)) { return 0.0d; } diff --git a/fixture-monkey-jakarta-validation/src/test/java/com/navercorp/fixturemonkey/jakarta/validation/JakartaValidationFixtureMonkeyTest.java b/fixture-monkey-jakarta-validation/src/test/java/com/navercorp/fixturemonkey/jakarta/validation/JakartaValidationFixtureMonkeyTest.java index 5ec27d01f0..8d449b1326 100644 --- a/fixture-monkey-jakarta-validation/src/test/java/com/navercorp/fixturemonkey/jakarta/validation/JakartaValidationFixtureMonkeyTest.java +++ b/fixture-monkey-jakarta-validation/src/test/java/com/navercorp/fixturemonkey/jakarta/validation/JakartaValidationFixtureMonkeyTest.java @@ -39,10 +39,9 @@ import java.util.Date; import java.util.regex.Pattern; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledIf; -import net.jqwik.api.Example; - import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.exception.RetryableFilterMissException; import com.navercorp.fixturemonkey.jakarta.validation.plugin.JakartaValidationPlugin; @@ -80,7 +79,7 @@ static boolean isFirstDayOfYear() { return MonthDay.now().equals(FIRST_DAY_OF_YEAR); } - @Example + @Test void sampleBigDecimal() { BigDecimalIntrospectorSpec actual = SUT.giveMeOne(BigDecimalIntrospectorSpec.class); @@ -95,7 +94,7 @@ void sampleBigDecimal() { then(actual.getPositiveOrZero()).isGreaterThanOrEqualTo(BigDecimal.ZERO); } - @Example + @Test void sampleBigInteger() { BigIntegerIntrospectorSpec actual = SUT.giveMeOne(BigIntegerIntrospectorSpec.class); @@ -110,7 +109,7 @@ void sampleBigInteger() { then(actual.getPositiveOrZero()).isGreaterThanOrEqualTo(BigInteger.ZERO); } - @Example + @Test void sampleBoolean() { BooleanIntrospectorSpec actual = SUT.giveMeOne(BooleanIntrospectorSpec.class); @@ -119,7 +118,7 @@ void sampleBoolean() { then(actual.isAssertTrue()).isTrue(); } - @Example + @Test void sampleByte() { ByteIntrospectorSpec actual = SUT.giveMeOne(ByteIntrospectorSpec.class); @@ -135,14 +134,14 @@ void sampleByte() { then(actual.getPositiveOrZero()).isGreaterThanOrEqualTo((byte)0); } - @Example + @Test void sampleCharacter() { CharacterIntrospectorSpec actual = SUT.giveMeOne(CharacterIntrospectorSpec.class); then(actual.getCharacter()).isBetween(Character.MIN_VALUE, Character.MAX_VALUE); } - @Example + @Test void sampleDouble() { DoubleIntrospectorSpec actual = SUT.giveMeOne(DoubleIntrospectorSpec.class); @@ -158,7 +157,7 @@ void sampleDouble() { then(actual.getPositiveOrZero()).isGreaterThanOrEqualTo(0); } - @Example + @Test void sampleFloat() { FloatIntrospectorSpec actual = SUT.giveMeOne(FloatIntrospectorSpec.class); @@ -174,7 +173,7 @@ void sampleFloat() { then(actual.getPositiveOrZero()).isGreaterThanOrEqualTo(0); } - @Example + @Test void sampleInt() { IntIntrospectorSpec actual = SUT.giveMeOne(IntIntrospectorSpec.class); @@ -190,7 +189,7 @@ void sampleInt() { then(actual.getPositiveOrZero()).isGreaterThanOrEqualTo(0); } - @Example + @Test void sampleLong() { LongIntrospectorSpec actual = SUT.giveMeOne(LongIntrospectorSpec.class); @@ -206,7 +205,7 @@ void sampleLong() { then(actual.getPositiveOrZero()).isGreaterThanOrEqualTo(0); } - @Example + @Test void sampleShort() { ShortIntrospectorSpec actual = SUT.giveMeOne(ShortIntrospectorSpec.class); @@ -222,7 +221,7 @@ void sampleShort() { then(actual.getPositiveOrZero()).isGreaterThanOrEqualTo((short)0); } - @Example + @Test void sampleString() { StringIntrospectorSpec actual = SUT.giveMeOne(StringIntrospectorSpec.class); @@ -242,7 +241,7 @@ void sampleString() { then(actual.getStr()).doesNotMatch(controlCharacters); } - @Example + @Test void samplePastCalendar() { TimePastIntrospectorSpec actual = SUT.giveMeOne(TimePastIntrospectorSpec.class); @@ -252,7 +251,7 @@ void samplePastCalendar() { } @DisabledIf("isLastDayOfYear") - @Example + @Test void sampleFutureCalendar() { Calendar now = Calendar.getInstance(); TimeFutureIntrospectorSpec actual = SUT.giveMeOne(TimeFutureIntrospectorSpec.class); @@ -262,7 +261,7 @@ void sampleFutureCalendar() { .isGreaterThanOrEqualTo(now.toInstant().toEpochMilli()); } - @Example + @Test void samplePastDate() { TimePastIntrospectorSpec actual = SUT.giveMeOne(TimePastIntrospectorSpec.class); @@ -272,7 +271,7 @@ void samplePastDate() { } @DisabledIf("isLastDayOfYear") - @Example + @Test void sampleFutureDate() { Date now = new Date(); TimeFutureIntrospectorSpec actual = SUT.giveMeOne(TimeFutureIntrospectorSpec.class); @@ -281,7 +280,7 @@ void sampleFutureDate() { then(actual.getDateFutureOrPresent().getTime()).isGreaterThanOrEqualTo(now.getTime()); } - @Example + @Test void samplePastInstant() { TimePastIntrospectorSpec actual = SUT.giveMeOne(TimePastIntrospectorSpec.class); @@ -291,7 +290,7 @@ void samplePastInstant() { } @DisabledIf("isLastDayOfYear") - @Example + @Test void sampleFutureInstant() { Instant now = Instant.now(); TimeFutureIntrospectorSpec actual = SUT.giveMeOne(TimeFutureIntrospectorSpec.class); @@ -300,7 +299,7 @@ void sampleFutureInstant() { then(actual.getInstantFutureOrPresent()).isAfterOrEqualTo(now); } - @Example + @Test void samplePastLocalDate() { TimePastIntrospectorSpec actual = SUT.giveMeOne(TimePastIntrospectorSpec.class); @@ -310,7 +309,7 @@ void samplePastLocalDate() { } @DisabledIf("isLastDayOfYear") - @Example + @Test void sampleFutureLocalDate() { LocalDate now = LocalDate.now(); TimeFutureIntrospectorSpec actual = SUT.giveMeOne(TimeFutureIntrospectorSpec.class); @@ -319,7 +318,7 @@ void sampleFutureLocalDate() { then(actual.getLocalDateFutureOrPresent()).isAfterOrEqualTo(now); } - @Example + @Test void samplePastLocalDateTime() { TimePastIntrospectorSpec actual = SUT.giveMeOne(TimePastIntrospectorSpec.class); @@ -329,7 +328,7 @@ void samplePastLocalDateTime() { } @DisabledIf("isLastDayOfYear") - @Example + @Test void sampleFutureLocalDateTime() { LocalDateTime now = LocalDateTime.now(); TimeFutureIntrospectorSpec actual = SUT.giveMeOne(TimeFutureIntrospectorSpec.class); @@ -338,7 +337,7 @@ void sampleFutureLocalDateTime() { then(actual.getLocalDateTimeFutureOrPresent()).isAfterOrEqualTo(now); } - @Example + @Test void samplePastLocalTime() { TimePastIntrospectorSpec actual = SUT.giveMeOne(TimePastIntrospectorSpec.class); @@ -348,7 +347,7 @@ void samplePastLocalTime() { } @DisabledIf("isLastDayOfYear") - @Example + @Test void sampleFutureLocalTime() { LocalTime now = LocalTime.now(); TimeFutureIntrospectorSpec actual = SUT.giveMeOne(TimeFutureIntrospectorSpec.class); @@ -357,7 +356,7 @@ void sampleFutureLocalTime() { then(actual.getLocalTimeFutureOrPresent()).isAfterOrEqualTo(now); } - @Example + @Test void samplePastZonedDateTime() { TimePastIntrospectorSpec actual = SUT.giveMeOne(TimePastIntrospectorSpec.class); @@ -367,7 +366,7 @@ void samplePastZonedDateTime() { } @DisabledIf("isLastDayOfYear") - @Example + @Test void sampleFutureZonedDateTime() { ZonedDateTime now = ZonedDateTime.now().withZoneSameLocal(ZONED_ID); TimeFutureIntrospectorSpec actual = SUT.giveMeOne(TimeFutureIntrospectorSpec.class); @@ -377,7 +376,7 @@ void sampleFutureZonedDateTime() { } @DisabledIf("isFirstDayOfYear") - @Example + @Test void samplePastMonthDay() { MonthDay now = MonthDay.now(); TimePastIntrospectorSpec actual = SUT.giveMeOne(TimePastIntrospectorSpec.class); @@ -387,7 +386,7 @@ void samplePastMonthDay() { } @DisabledIf("isLastDayOfYear") - @Example + @Test void sampleFutureMonthDay() { MonthDay now = MonthDay.now(); TimeFutureIntrospectorSpec actual = SUT.giveMeOne(TimeFutureIntrospectorSpec.class); @@ -396,7 +395,7 @@ void sampleFutureMonthDay() { then(actual.getMonthDayFutureOrPresent()).isGreaterThanOrEqualTo(now); } - @Example + @Test void samplePastOffsetDateTime() { TimePastIntrospectorSpec actual = SUT.giveMeOne(TimePastIntrospectorSpec.class); @@ -406,7 +405,7 @@ void samplePastOffsetDateTime() { } @DisabledIf("isLastDayOfYear") - @Example + @Test void sampleFutureOffsetDateTime() { OffsetDateTime now = OffsetDateTime.now(); @@ -416,7 +415,7 @@ void sampleFutureOffsetDateTime() { then(actual.getOffsetDateTimeFutureOrPresent()).isAfterOrEqualTo(now); } - @Example + @Test void samplePastOffsetTime() { TimePastIntrospectorSpec actual = SUT.giveMeOne(TimePastIntrospectorSpec.class); @@ -426,7 +425,7 @@ void samplePastOffsetTime() { } @DisabledIf("isLastDayOfYear") - @Example + @Test void sampleFutureOffsetTime() { OffsetTime now = OffsetTime.now(); @@ -436,7 +435,7 @@ void sampleFutureOffsetTime() { then(actual.getOffsetTimeFutureOrPresent()).isAfterOrEqualTo(now); } - @Example + @Test void samplePastYear() { TimePastIntrospectorSpec actual = SUT.giveMeOne(TimePastIntrospectorSpec.class); @@ -446,7 +445,7 @@ void samplePastYear() { } @DisabledIf("isLastDayOfYear") - @Example + @Test void sampleFutureYear() { Year now = Year.now(); TimeFutureIntrospectorSpec actual = SUT.giveMeOne(TimeFutureIntrospectorSpec.class); @@ -455,7 +454,7 @@ void sampleFutureYear() { then(actual.getYearFutureOrPresent()).isGreaterThanOrEqualTo(now); } - @Example + @Test void samplePastYearMonth() { TimePastIntrospectorSpec actual = SUT.giveMeOne(TimePastIntrospectorSpec.class); @@ -465,7 +464,7 @@ void samplePastYearMonth() { } @DisabledIf("isLastDayOfYear") - @Example + @Test void sampleFutureYearMonth() { YearMonth now = YearMonth.now(); @@ -475,7 +474,7 @@ void sampleFutureYearMonth() { then(actual.getYearMonthFutureOrPresent()).isGreaterThanOrEqualTo(now); } - @Example + @Test void sampleNullAnnotations() { NullAnnotationIntrospectorSpec actual = SUT.giveMeOne(NullAnnotationIntrospectorSpec.class); @@ -486,7 +485,7 @@ void sampleNullAnnotations() { then(actual.getNotEmptyContainer()).isNotEmpty(); } - @Example + @Test void sampleContainerAnnotations() { ContainerAnnotationIntrospectorSpec actual = SUT.giveMeOne(ContainerAnnotationIntrospectorSpec.class); @@ -498,7 +497,7 @@ void sampleContainerAnnotations() { then(actual.getNotEmptyAndMaxSizeContainer()).hasSizeBetween(1, 5); } - @Example + @Test void logFailedProperties() { thenThrownBy( () -> SUT.giveMeBuilder(NullAnnotationIntrospectorSpec.class) diff --git a/fixture-monkey-javax-validation/src/main/java/com/navercorp/fixturemonkey/javax/validation/generator/JavaxValidationNullInjectGenerator.java b/fixture-monkey-javax-validation/src/main/java/com/navercorp/fixturemonkey/javax/validation/generator/JavaxValidationNullInjectGenerator.java index 82c4363e1b..b64f59d02e 100644 --- a/fixture-monkey-javax-validation/src/main/java/com/navercorp/fixturemonkey/javax/validation/generator/JavaxValidationNullInjectGenerator.java +++ b/fixture-monkey-javax-validation/src/main/java/com/navercorp/fixturemonkey/javax/validation/generator/JavaxValidationNullInjectGenerator.java @@ -34,7 +34,6 @@ import com.navercorp.fixturemonkey.api.generator.DefaultNullInjectGenerator; import com.navercorp.fixturemonkey.api.generator.NullInjectGenerator; import com.navercorp.fixturemonkey.api.generator.ObjectPropertyGeneratorContext; -import com.navercorp.fixturemonkey.api.type.Types; @API(since = "0.4.0", status = Status.MAINTAINED) public final class JavaxValidationNullInjectGenerator implements NullInjectGenerator { @@ -67,7 +66,7 @@ public double generate(ObjectPropertyGeneratorContext context) { return 0.0d; } - if (Types.getActualType(context.getProperty().getType()) == String.class) { + if (context.getProperty().getJvmType().getRawType() == String.class) { if (annotations.contains(NotBlank.class) || annotations.contains(NotEmpty.class)) { return 0.0d; } diff --git a/fixture-monkey-javax-validation/src/test/java/com/navercorp/fixturemonkey/javax/validation/JavaxValidationFixtureMonkeyTest.java b/fixture-monkey-javax-validation/src/test/java/com/navercorp/fixturemonkey/javax/validation/JavaxValidationFixtureMonkeyTest.java index e4a0ea5192..2ab44c1351 100644 --- a/fixture-monkey-javax-validation/src/test/java/com/navercorp/fixturemonkey/javax/validation/JavaxValidationFixtureMonkeyTest.java +++ b/fixture-monkey-javax-validation/src/test/java/com/navercorp/fixturemonkey/javax/validation/JavaxValidationFixtureMonkeyTest.java @@ -39,10 +39,9 @@ import java.util.Date; import java.util.regex.Pattern; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledIf; -import net.jqwik.api.Example; - import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.exception.RetryableFilterMissException; import com.navercorp.fixturemonkey.javax.validation.plugin.JavaxValidationPlugin; @@ -80,7 +79,7 @@ static boolean isFirstDayOfYear() { return MonthDay.now().equals(FIRST_DAY_OF_YEAR); } - @Example + @Test void sampleBigDecimal() { BigDecimalIntrospectorSpec actual = SUT.giveMeOne(BigDecimalIntrospectorSpec.class); @@ -95,7 +94,7 @@ void sampleBigDecimal() { then(actual.getPositiveOrZero()).isGreaterThanOrEqualTo(BigDecimal.ZERO); } - @Example + @Test void sampleBigInteger() { BigIntegerIntrospectorSpec actual = SUT.giveMeOne(BigIntegerIntrospectorSpec.class); @@ -110,7 +109,7 @@ void sampleBigInteger() { then(actual.getPositiveOrZero()).isGreaterThanOrEqualTo(BigInteger.ZERO); } - @Example + @Test void sampleBoolean() { BooleanIntrospectorSpec actual = SUT.giveMeOne(BooleanIntrospectorSpec.class); @@ -119,7 +118,7 @@ void sampleBoolean() { then(actual.isAssertTrue()).isTrue(); } - @Example + @Test void sampleByte() { ByteIntrospectorSpec actual = SUT.giveMeOne(ByteIntrospectorSpec.class); @@ -135,14 +134,14 @@ void sampleByte() { then(actual.getPositiveOrZero()).isGreaterThanOrEqualTo((byte)0); } - @Example + @Test void sampleCharacter() { CharacterIntrospectorSpec actual = SUT.giveMeOne(CharacterIntrospectorSpec.class); then(actual.getCharacter()).isBetween(Character.MIN_VALUE, Character.MAX_VALUE); } - @Example + @Test void sampleDouble() { DoubleIntrospectorSpec actual = SUT.giveMeOne(DoubleIntrospectorSpec.class); @@ -158,7 +157,7 @@ void sampleDouble() { then(actual.getPositiveOrZero()).isGreaterThanOrEqualTo(0); } - @Example + @Test void sampleFloat() { FloatIntrospectorSpec actual = SUT.giveMeOne(FloatIntrospectorSpec.class); @@ -174,7 +173,7 @@ void sampleFloat() { then(actual.getPositiveOrZero()).isGreaterThanOrEqualTo(0); } - @Example + @Test void sampleInt() { IntIntrospectorSpec actual = SUT.giveMeOne(IntIntrospectorSpec.class); @@ -190,7 +189,7 @@ void sampleInt() { then(actual.getPositiveOrZero()).isGreaterThanOrEqualTo(0); } - @Example + @Test void sampleLong() { LongIntrospectorSpec actual = SUT.giveMeOne(LongIntrospectorSpec.class); @@ -206,7 +205,7 @@ void sampleLong() { then(actual.getPositiveOrZero()).isGreaterThanOrEqualTo(0); } - @Example + @Test void sampleShort() { ShortIntrospectorSpec actual = SUT.giveMeOne(ShortIntrospectorSpec.class); @@ -222,7 +221,7 @@ void sampleShort() { then(actual.getPositiveOrZero()).isGreaterThanOrEqualTo((short)0); } - @Example + @Test void sampleString() { StringIntrospectorSpec actual = SUT.giveMeOne(StringIntrospectorSpec.class); @@ -242,7 +241,7 @@ void sampleString() { then(actual.getStr()).doesNotMatch(controlCharacters); } - @Example + @Test void samplePastCalendar() { TimePastIntrospectorSpec actual = SUT.giveMeOne(TimePastIntrospectorSpec.class); @@ -252,7 +251,7 @@ void samplePastCalendar() { } @DisabledIf("isLastDayOfYear") - @Example + @Test void sampleFutureCalendar() { Calendar now = Calendar.getInstance(); TimeFutureIntrospectorSpec actual = SUT.giveMeOne(TimeFutureIntrospectorSpec.class); @@ -262,7 +261,7 @@ void sampleFutureCalendar() { .isGreaterThanOrEqualTo(now.toInstant().toEpochMilli()); } - @Example + @Test void samplePastDate() { TimePastIntrospectorSpec actual = SUT.giveMeOne(TimePastIntrospectorSpec.class); @@ -272,7 +271,7 @@ void samplePastDate() { } @DisabledIf("isLastDayOfYear") - @Example + @Test void sampleFutureDate() { Date now = new Date(); TimeFutureIntrospectorSpec actual = SUT.giveMeOne(TimeFutureIntrospectorSpec.class); @@ -281,7 +280,7 @@ void sampleFutureDate() { then(actual.getDateFutureOrPresent().getTime()).isGreaterThanOrEqualTo(now.getTime()); } - @Example + @Test void samplePastInstant() { TimePastIntrospectorSpec actual = SUT.giveMeOne(TimePastIntrospectorSpec.class); @@ -291,7 +290,7 @@ void samplePastInstant() { } @DisabledIf("isLastDayOfYear") - @Example + @Test void sampleFutureInstant() { Instant now = Instant.now(); TimeFutureIntrospectorSpec actual = SUT.giveMeOne(TimeFutureIntrospectorSpec.class); @@ -300,7 +299,7 @@ void sampleFutureInstant() { then(actual.getInstantFutureOrPresent()).isAfterOrEqualTo(now); } - @Example + @Test void samplePastLocalDate() { TimePastIntrospectorSpec actual = SUT.giveMeOne(TimePastIntrospectorSpec.class); @@ -310,7 +309,7 @@ void samplePastLocalDate() { } @DisabledIf("isLastDayOfYear") - @Example + @Test void sampleFutureLocalDate() { LocalDate now = LocalDate.now(); TimeFutureIntrospectorSpec actual = SUT.giveMeOne(TimeFutureIntrospectorSpec.class); @@ -319,7 +318,7 @@ void sampleFutureLocalDate() { then(actual.getLocalDateFutureOrPresent()).isAfterOrEqualTo(now); } - @Example + @Test void samplePastLocalDateTime() { TimePastIntrospectorSpec actual = SUT.giveMeOne(TimePastIntrospectorSpec.class); @@ -329,7 +328,7 @@ void samplePastLocalDateTime() { } @DisabledIf("isLastDayOfYear") - @Example + @Test void sampleFutureLocalDateTime() { LocalDateTime now = LocalDateTime.now(); TimeFutureIntrospectorSpec actual = SUT.giveMeOne(TimeFutureIntrospectorSpec.class); @@ -338,7 +337,7 @@ void sampleFutureLocalDateTime() { then(actual.getLocalDateTimeFutureOrPresent()).isAfterOrEqualTo(now); } - @Example + @Test void samplePastLocalTime() { TimePastIntrospectorSpec actual = SUT.giveMeOne(TimePastIntrospectorSpec.class); @@ -348,7 +347,7 @@ void samplePastLocalTime() { } @DisabledIf("isLastDayOfYear") - @Example + @Test void sampleFutureLocalTime() { LocalTime now = LocalTime.now(); TimeFutureIntrospectorSpec actual = SUT.giveMeOne(TimeFutureIntrospectorSpec.class); @@ -357,7 +356,7 @@ void sampleFutureLocalTime() { then(actual.getLocalTimeFutureOrPresent()).isAfterOrEqualTo(now); } - @Example + @Test void samplePastZonedDateTime() { TimePastIntrospectorSpec actual = SUT.giveMeOne(TimePastIntrospectorSpec.class); @@ -367,7 +366,7 @@ void samplePastZonedDateTime() { } @DisabledIf("isLastDayOfYear") - @Example + @Test void sampleFutureZonedDateTime() { ZonedDateTime now = ZonedDateTime.now().withZoneSameLocal(ZONED_ID); TimeFutureIntrospectorSpec actual = SUT.giveMeOne(TimeFutureIntrospectorSpec.class); @@ -377,7 +376,7 @@ void sampleFutureZonedDateTime() { } @DisabledIf("isFirstDayOfYear") - @Example + @Test void samplePastMonthDay() { MonthDay now = MonthDay.now(); TimePastIntrospectorSpec actual = SUT.giveMeOne(TimePastIntrospectorSpec.class); @@ -387,7 +386,7 @@ void samplePastMonthDay() { } @DisabledIf("isLastDayOfYear") - @Example + @Test void sampleFutureMonthDay() { MonthDay now = MonthDay.now(); TimeFutureIntrospectorSpec actual = SUT.giveMeOne(TimeFutureIntrospectorSpec.class); @@ -396,7 +395,7 @@ void sampleFutureMonthDay() { then(actual.getMonthDayFutureOrPresent()).isGreaterThanOrEqualTo(now); } - @Example + @Test void samplePastOffsetDateTime() { TimePastIntrospectorSpec actual = SUT.giveMeOne(TimePastIntrospectorSpec.class); @@ -406,7 +405,7 @@ void samplePastOffsetDateTime() { } @DisabledIf("isLastDayOfYear") - @Example + @Test void sampleFutureOffsetDateTime() { OffsetDateTime now = OffsetDateTime.now(); @@ -416,7 +415,7 @@ void sampleFutureOffsetDateTime() { then(actual.getOffsetDateTimeFutureOrPresent()).isAfterOrEqualTo(now); } - @Example + @Test void samplePastOffsetTime() { TimePastIntrospectorSpec actual = SUT.giveMeOne(TimePastIntrospectorSpec.class); @@ -426,7 +425,7 @@ void samplePastOffsetTime() { } @DisabledIf("isLastDayOfYear") - @Example + @Test void sampleFutureOffsetTime() { OffsetTime now = OffsetTime.now(); @@ -436,7 +435,7 @@ void sampleFutureOffsetTime() { then(actual.getOffsetTimeFutureOrPresent()).isAfterOrEqualTo(now); } - @Example + @Test void samplePastYear() { TimePastIntrospectorSpec actual = SUT.giveMeOne(TimePastIntrospectorSpec.class); @@ -446,7 +445,7 @@ void samplePastYear() { } @DisabledIf("isLastDayOfYear") - @Example + @Test void sampleFutureYear() { Year now = Year.now(); TimeFutureIntrospectorSpec actual = SUT.giveMeOne(TimeFutureIntrospectorSpec.class); @@ -455,7 +454,7 @@ void sampleFutureYear() { then(actual.getYearFutureOrPresent()).isGreaterThanOrEqualTo(now); } - @Example + @Test void samplePastYearMonth() { TimePastIntrospectorSpec actual = SUT.giveMeOne(TimePastIntrospectorSpec.class); @@ -465,7 +464,7 @@ void samplePastYearMonth() { } @DisabledIf("isLastDayOfYear") - @Example + @Test void sampleFutureYearMonth() { YearMonth now = YearMonth.now(); @@ -475,7 +474,7 @@ void sampleFutureYearMonth() { then(actual.getYearMonthFutureOrPresent()).isGreaterThanOrEqualTo(now); } - @Example + @Test void sampleNullAnnotations() { NullAnnotationIntrospectorSpec actual = SUT.giveMeOne(NullAnnotationIntrospectorSpec.class); @@ -486,7 +485,7 @@ void sampleNullAnnotations() { then(actual.getNotEmptyContainer()).isNotEmpty(); } - @Example + @Test void sampleContainerAnnotations() { ContainerAnnotationIntrospectorSpec actual = SUT.giveMeOne(ContainerAnnotationIntrospectorSpec.class); @@ -498,7 +497,7 @@ void sampleContainerAnnotations() { then(actual.getNotEmptyAndMaxSizeContainer()).hasSizeBetween(1, 5); } - @Example + @Test void logFailedProperties() { thenThrownBy( () -> SUT.giveMeBuilder(NullAnnotationIntrospectorSpec.class) diff --git a/fixture-monkey-junit-jupiter/src/main/java/com/navercorp/fixturemonkey/junit/jupiter/extension/FixtureMonkeySeedExtension.java b/fixture-monkey-junit-jupiter/src/main/java/com/navercorp/fixturemonkey/junit/jupiter/extension/FixtureMonkeySeedExtension.java index 3d5086050c..92cc177f1e 100644 --- a/fixture-monkey-junit-jupiter/src/main/java/com/navercorp/fixturemonkey/junit/jupiter/extension/FixtureMonkeySeedExtension.java +++ b/fixture-monkey-junit-jupiter/src/main/java/com/navercorp/fixturemonkey/junit/jupiter/extension/FixtureMonkeySeedExtension.java @@ -22,10 +22,14 @@ import org.junit.jupiter.api.extension.AfterTestExecutionCallback; import org.junit.jupiter.api.extension.BeforeTestExecutionCallback; import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ExtensionContext.Namespace; +import org.junit.jupiter.api.extension.ExtensionContext.Store; +import org.junit.jupiter.api.extension.ExtensionContext.Store.CloseableResource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.navercorp.fixturemonkey.api.random.Randoms; +import com.navercorp.fixturemonkey.api.random.SeedClaim; import com.navercorp.fixturemonkey.junit.jupiter.annotation.Seed; /** @@ -40,24 +44,25 @@ */ public final class FixtureMonkeySeedExtension implements BeforeTestExecutionCallback, AfterTestExecutionCallback { private static final Logger LOGGER = LoggerFactory.getLogger(FixtureMonkeySeedExtension.class); + private static final Namespace NAMESPACE = Namespace.create(FixtureMonkeySeedExtension.class); + private static final String CLAIM_KEY = "seedClaim"; @Override public void beforeTestExecution(ExtensionContext context) { Seed seed = context.getRequiredTestMethod().getAnnotation(Seed.class); if (seed != null) { - setSeed(seed.value()); + establishClaim(context, seed.value()); return; } Method testMethod = context.getRequiredTestMethod(); - int methodHashCode = testMethod.hashCode(); - setSeed(methodHashCode); + establishClaim(context, testMethod.hashCode()); } /** - * Logs the seed used for the test if the test fails. - * This method is called after a test method has executed. - * If the test failed, it logs the seed used for the test. + * Logs the seed used for the test if the test fails. The seed claim + * established in {@code beforeTestExecution} is released automatically + * by JUnit when this extension's {@link Store} is closed. **/ @Override public void afterTestExecution(ExtensionContext context) { @@ -67,10 +72,13 @@ public void afterTestExecution(ExtensionContext context) { } /** - * Sets the seed for generating random numbers. + * Applies the seed and stores the resulting claim in the JUnit + * {@link Store} so it is released when the test scope ends, even + * if the test or other extensions throw. **/ - private void setSeed(long seed) { - Randoms.newGlobalSeed(seed); + private void establishClaim(ExtensionContext context, long seed) { + SeedClaim claim = SeedClaim.establish(seed); + context.getStore(NAMESPACE).put(CLAIM_KEY, (CloseableResource)claim::close); } /** diff --git a/fixture-monkey-junit-jupiter/src/test/java/com/navercorp/fixturemonkey/junit/jupiter/extension/FixtureMonkeyBuilderSeedTest.java b/fixture-monkey-junit-jupiter/src/test/java/com/navercorp/fixturemonkey/junit/jupiter/extension/FixtureMonkeyBuilderSeedTest.java new file mode 100644 index 0000000000..6d0d22f700 --- /dev/null +++ b/fixture-monkey-junit-jupiter/src/test/java/com/navercorp/fixturemonkey/junit/jupiter/extension/FixtureMonkeyBuilderSeedTest.java @@ -0,0 +1,84 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ +package com.navercorp.fixturemonkey.junit.jupiter.extension; + +import static org.assertj.core.api.BDDAssertions.then; + +import org.junit.jupiter.api.Test; + +import com.navercorp.fixturemonkey.FixtureMonkey; + +/** + * Verifies that {@code FixtureMonkeyBuilder.seed(long)} produces the same canonical values + * as the {@code @Seed} annotation in {@link FixtureMonkeySeedExtensionTest}. + * + *

This class intentionally does not register {@link FixtureMonkeySeedExtension}, + * so the seed configured on the builder is the only source of randomness control. + */ +class FixtureMonkeyBuilderSeedTest { + + @Test + void builderSeedOneProducesCanonicalSeedOneFirstString() { + // given — a FixtureMonkey configured with seed=1 via FixtureMonkeyBuilder + FixtureMonkey sut = FixtureMonkey.builder().seed(1L).build(); + + // when + String actual = sut.giveMeOne(String.class); + + // then — must match the canonical first String of seed-1 verified by + // FixtureMonkeySeedExtensionTest.seedReturnsSame / arbitraryBuilderSampleReturnsSame + then(actual).isEqualTo("㼌✠섨ꝓ仛禦催ᘓ蓊類౺阹瞻"); + } + + @Test + void builderSeedOneSecondCallProducesCanonicalSeedOneSecondString() { + // given + FixtureMonkey sut = FixtureMonkey.builder().seed(1L).build(); + + // when + sut.giveMeOne(String.class); + String actual = sut.giveMeOne(String.class); + + // then — must match FixtureMonkeySeedExtensionTest.latterValue + then(actual).isEqualTo("婵얎⽒竻·俌欕悳잸횑ٻ킐結㗗蜵ꓣ몒둡塸聩"); + } + + @Test + void builderSeedOneIntegerMatchesAnnotationSeedOneInteger() { + // given + FixtureMonkey sut = FixtureMonkey.builder().seed(1L).build(); + + // when + Integer actual = sut.giveMeOne(Integer.class); + + // then — must match FixtureMonkeySeedExtensionTest.integerReturnsSame + then(actual).isEqualTo(86904); + } + + @Test + void builderSeedOneLongMatchesAnnotationSeedOneLong() { + // given + FixtureMonkey sut = FixtureMonkey.builder().seed(1L).build(); + + // when + Long actual = sut.giveMeOne(Long.class); + + // then — must match FixtureMonkeySeedExtensionTest.longReturnsSame + then(actual).isEqualTo(-1555898L); + } +} diff --git a/fixture-monkey-junit-jupiter/src/test/java/com/navercorp/fixturemonkey/junit/jupiter/extension/FixtureMonkeySeedExtensionTest.java b/fixture-monkey-junit-jupiter/src/test/java/com/navercorp/fixturemonkey/junit/jupiter/extension/FixtureMonkeySeedExtensionTest.java index cf1ec284f9..0f9f754c20 100644 --- a/fixture-monkey-junit-jupiter/src/test/java/com/navercorp/fixturemonkey/junit/jupiter/extension/FixtureMonkeySeedExtensionTest.java +++ b/fixture-monkey-junit-jupiter/src/test/java/com/navercorp/fixturemonkey/junit/jupiter/extension/FixtureMonkeySeedExtensionTest.java @@ -21,13 +21,17 @@ import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.extension.ExtendWith; +import lombok.Data; + import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.type.TypeReference; import com.navercorp.fixturemonkey.junit.jupiter.annotation.Seed; @@ -36,10 +40,14 @@ class FixtureMonkeySeedExtensionTest { private static final FixtureMonkey SUT = FixtureMonkey.create(); + private static String noSeedAnnotationFirstValue; + private static boolean noSeedAnnotationFirstValueCaptured; + + @Seed(1) @RepeatedTest(100) void seedReturnsSame() { - String expected = "✠섨ꝓ仛禦催ᘓ蓊類౺阹瞻塢飖獾ࠒ⒐፨"; + String expected = "㼌✠섨ꝓ仛禦催ᘓ蓊類౺阹瞻"; String actual = SUT.giveMeOne(String.class); @@ -49,7 +57,7 @@ void seedReturnsSame() { @Seed(1) @RepeatedTest(100) void latterValue() { - String expected = "欕悳잸"; + String expected = "婵얎⽒竻·俌欕悳잸횑ٻ킐結㗗蜵ꓣ몒둡塸聩"; SUT.giveMeOne(String.class); String actual = SUT.giveMeOne(String.class); @@ -60,7 +68,7 @@ void latterValue() { @Seed(1) @RepeatedTest(100) void containerReturnsSame() { - List expected = Collections.singletonList("仛禦催ᘓ蓊類౺阹瞻塢飖獾ࠒ⒐፨婵얎⽒竻·俌欕悳잸횑ٻ킐結"); + List expected = Collections.emptyList(); List actual = SUT.giveMeOne(new TypeReference>() { }); @@ -71,7 +79,7 @@ void containerReturnsSame() { @Seed(1) @RepeatedTest(100) void containerMattersOrder() { - Set expected = new HashSet<>(Collections.singletonList("仛禦催ᘓ蓊類౺阹瞻塢飖獾ࠒ⒐፨婵얎⽒竻·俌欕悳잸횑ٻ킐結")); + Set expected = new HashSet<>(Collections.singletonList("㼌✠섨ꝓ仛禦催ᘓ蓊類౺阹瞻")); Set actual = SUT.giveMeOne(new TypeReference>() { }); @@ -95,8 +103,8 @@ void multipleContainerReturnsDiff() { @RepeatedTest(100) void multipleFixtureMonkeyInstancesReturnsAsOneInstance() { List expected = Arrays.asList( - "✠섨ꝓ仛禦催ᘓ蓊類౺阹瞻塢飖獾ࠒ⒐፨", - "欕悳잸" + "㼌✠섨ꝓ仛禦催ᘓ蓊類౺阹瞻", + "婵얎⽒竻·俌欕悳잸횑ٻ킐結㗗蜵ꓣ몒둡塸聩" ); FixtureMonkey firstFixtureMonkey = FixtureMonkey.create(); FixtureMonkey secondFixtureMonkey = FixtureMonkey.create(); @@ -108,4 +116,161 @@ void multipleFixtureMonkeyInstancesReturnsAsOneInstance() { then(actual).isEqualTo(expected); } + + @Seed(2) + @RepeatedTest(100) + void differentSeedReturnsDifferentValue() { + String seedOneFirstValue = "㼌✠섨ꝓ仛禦催ᘓ蓊類౺阹瞻"; + + String actual = SUT.giveMeOne(String.class); + + then(actual).isNotEqualTo(seedOneFirstValue); + } + + @Seed(1) + @RepeatedTest(100) + void thirdSequentialStringReturnsSame() { + String expected = "ᣮ鎊熇捺셾壍Ꜻꌩ垅凗❉償粐믩࠱哠횛䄻㹦䤔᫿琬梅䨊"; + SUT.giveMeOne(String.class); + SUT.giveMeOne(String.class); + + String actual = SUT.giveMeOne(String.class); + + then(actual).isEqualTo(expected); + } + + @Seed(1) + @RepeatedTest(100) + void integerReturnsSame() { + Integer expected = 86904; + Integer actual = SUT.giveMeOne(Integer.class); + + then(actual).isEqualTo(expected); + } + + @Seed(1) + @RepeatedTest(100) + void longReturnsSame() { + Long expected = -1555898L; + Long actual = SUT.giveMeOne(Long.class); + + then(actual).isEqualTo(expected); + } + + @Seed(1) + @RepeatedTest(100) + void giveMeListReturnsSame() { + List expected = Arrays.asList( + "㼌✠섨ꝓ仛禦催ᘓ蓊類౺阹瞻", + "婵얎⽒竻·俌欕悳잸횑ٻ킐結㗗蜵ꓣ몒둡塸聩", + "ᣮ鎊熇捺셾壍Ꜻꌩ垅凗❉償粐믩࠱哠횛䄻㹦䤔᫿琬梅䨊" + ); + + List actual = SUT.giveMe(String.class, 3); + + then(actual).isEqualTo(expected); + } + + @Seed(1) + @RepeatedTest(100) + void arbitraryBuilderSampleReturnsSame() { + String expected = "㼌✠섨ꝓ仛禦催ᘓ蓊類౺阹瞻"; + + String actual = SUT.giveMeBuilder(String.class).sample(); + + then(actual).isEqualTo(expected); + } + + @Seed(1) + @RepeatedTest(100) + void builderSetPreservesDeterminism() { + String fixedValue = "fixed"; + + String actual = SUT.giveMeBuilder(String.class).set("$", fixedValue).sample(); + + then(actual).isEqualTo(fixedValue); + } + + @RepeatedTest(100) + void noSeedAnnotationFallsBackToMethodHashDeterministically() { + String actual = SUT.giveMeOne(String.class); + + if (!noSeedAnnotationFirstValueCaptured) { + noSeedAnnotationFirstValue = actual; + noSeedAnnotationFirstValueCaptured = true; + return; + } + then(actual).isEqualTo(noSeedAnnotationFirstValue); + } + + @Seed(1) + @RepeatedTest(100) + void pojoReturnsSame() { + Person expected = new Person(); + expected.setName("㼌✠섨ꝓ仛禦催ᘓ蓊類౺阹瞻"); + expected.setAge(-3336); + + Person actual = SUT.giveMeOne(Person.class); + + then(actual).isEqualTo(expected); + } + + @Seed(1) + @RepeatedTest(100) + void mapReturnsSame() { + Map expected = new HashMap<>(); + expected.put("⽒竻·俌欕悳잸횑ٻ킐結㗗蜵", 286); + expected.put("㼌✠섨ꝓ仛禦催ᘓ蓊類౺阹瞻", 29413); + + Map actual = SUT.giveMeOne(new TypeReference>() { + }); + + then(actual).isEqualTo(expected); + } + + @Seed(1) + @RepeatedTest(100) + void seedResetsBetweenInvocationsDespitePollution() { + String expected = "㼌✠섨ꝓ仛禦催ᘓ蓊類౺阹瞻"; + + String actual = SUT.giveMeOne(String.class); + for (int i = 0; i < 50; i++) { + SUT.giveMeOne(String.class); + } + + then(actual).isEqualTo(expected); + } + + @Seed(1) + @RepeatedTest(100) + void thenApplyWithChildSampleIsDeterministic() { + // given — a builder that uses thenApply to inject a separately-sampled child + Parent actual = SUT.giveMeBuilder(Parent.class) + .thenApply((parent, b) -> b.set("child", SUT.giveMeBuilder(Child.class).sample())) + .sample(); + + // then — under @Seed(1), every iteration must produce this exact child + Child expected = new Child(); + expected.setLabel("ၤ鰁뎖㨭芣쬋瑅肽躣鮡臮祡눻촯⿅䕗ﵢ洞꙱ζ䓎⽟寙တ铓"); + expected.setOptions(Collections.emptyList()); + then(actual.getChild()).isEqualTo(expected); + } + + @Data + public static class Person { + private String name; + private Integer age; + } + + @Data + public static class Parent { + private String name; + private Child child; + } + + @Data + public static class Child { + private String label; + private List options; + } } diff --git a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/ExpressionGenerators.kt b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/ExpressionGenerators.kt index 049ebd706e..8bdd2e204b 100644 --- a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/ExpressionGenerators.kt +++ b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/ExpressionGenerators.kt @@ -10,9 +10,9 @@ import com.navercorp.fixturemonkey.api.type.Types import com.navercorp.fixturemonkey.kotlin.type.actualType import com.navercorp.fixturemonkey.kotlin.type.getPropertyName import com.navercorp.fixturemonkey.kotlin.type.toTypeReference -import java.lang.reflect.AnnotatedType +import com.navercorp.objectfarm.api.type.JavaType +import com.navercorp.objectfarm.api.type.JvmType import java.lang.reflect.Field -import java.lang.reflect.Type import kotlin.reflect.KFunction1 import kotlin.reflect.KProperty import kotlin.reflect.KProperty1 @@ -477,38 +477,29 @@ private class KotlinProperty(private val property: KProperty1) : Pro property.javaField?.annotations?.toList() ?: listOf() /** - * If backed only by a getter, {@code javaProperty} or {@code javaField} may be null and cause NPE. - * To avoid this, returns {@link Types.UnidentifiableType} when the type cannot be identified. - * - * @see com.navercorp.fixturemonkey.kotlin.expression.root + * If backed only by a getter, the field may be null. Returns + * [Types.UnidentifiableType] when the type cannot be identified. */ - override fun getType(): Class<*> = property.javaField?.type ?: Types.UnidentifiableType::class.java - - /** - * If backed only by a getter, {@code javaProperty} or {@code javaField} may be null and cause NPE. - * To avoid this, returns {@link Types.UnidentifiableType} when the type cannot be identified. - * - * @see com.navercorp.fixturemonkey.kotlin.expression.root - */ - override fun getAnnotatedType(): AnnotatedType = - property.javaField?.annotatedType ?: object : AnnotatedType { - override fun getType(): Type = Types.UnidentifiableType::class.java - - override fun getAnnotations(): Array = emptyArray() - - override fun getAnnotation(annotationClass: Class): T? = null - - override fun getDeclaredAnnotations(): Array = emptyArray() + private val cachedJvmType: JvmType = run { + val fieldAnnotatedType = property.javaField?.annotatedType + if (fieldAnnotatedType != null) { + Types.toJvmType( + fieldAnnotatedType, + getAnnotations(), + property.returnType.isMarkedNullable, + ) + } else { + JavaType(Types.UnidentifiableType::class.java) } + } + + override fun getJvmType(): JvmType = cachedJvmType override fun getName(): String = property.name override fun getAnnotations(): List = (propertyAnnotations + getterAnnotations + fieldAnnotations).distinct() - @Suppress("UNCHECKED_CAST") - override fun getValue(instance: Any): Any? = property.get(instance as V) - override fun isNullable(): Boolean = property.returnType.isMarkedNullable } @@ -535,18 +526,21 @@ private class KotlinGetterProperty(private val getter: KFunction1) : private val fieldAnnotations: List = javaField?.annotations?.toList() ?: listOf() - override fun getType(): Class<*> = type + private val cachedJvmType: JvmType = run { + val fieldAnnotatedType = property?.javaField?.annotatedType ?: javaField?.annotatedType + if (fieldAnnotatedType != null) { + Types.toJvmType(fieldAnnotatedType, getAnnotations(), getter.returnType.isMarkedNullable) + } else { + JavaType(type, emptyList(), getAnnotations(), getter.returnType.isMarkedNullable) + } + } - override fun getAnnotatedType(): AnnotatedType? = - property?.javaField?.annotatedType ?: javaField?.annotatedType + override fun getJvmType(): JvmType = cachedJvmType override fun getName(): String = propertyName override fun getAnnotations(): List = (propertyAnnotations + getterAnnotations + fieldAnnotations).distinct() - @Suppress("UNCHECKED_CAST") - override fun getValue(instance: Any?): Any? = getter.invoke(instance as V) - override fun isNullable(): Boolean = getter.returnType.isMarkedNullable } diff --git a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/KotlinNodeTreeAdapterPlugin.kt b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/KotlinNodeTreeAdapterPlugin.kt deleted file mode 100644 index cb1202ed47..0000000000 --- a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/KotlinNodeTreeAdapterPlugin.kt +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.kotlin - -import com.navercorp.fixturemonkey.adapter.DefaultNodeTreeAdapter -import com.navercorp.fixturemonkey.adapter.tracing.AdapterTracer -import com.navercorp.fixturemonkey.api.option.FixtureMonkeyOptionsBuilder -import com.navercorp.fixturemonkey.api.plugin.Plugin -import com.navercorp.fixturemonkey.kotlin.generator.KotlinNullInjectGenerator -import com.navercorp.fixturemonkey.kotlin.node.KotlinLeafTypeResolver -import com.navercorp.fixturemonkey.kotlin.node.KotlinNodeCandidateGenerator -import com.navercorp.fixturemonkey.kotlin.node.KotlinNodePromoters -import com.navercorp.objectfarm.api.tree.JvmNodeCandidateTreeContext -import org.apiguardian.api.API -import org.apiguardian.api.API.Status.EXPERIMENTAL - -/** - * A plugin for configuring the node tree adapter for Kotlin types in FixtureMonkey. - * - * This plugin enables the adapter layer for Kotlin types, which provides - * an alternative object generation path using JvmNodeTree. - * - * Usage: - * ```kotlin - * FixtureMonkey.builder() - * .plugin(KotlinPlugin()) - * .plugin(KotlinNodeTreeAdapterPlugin() - * .seed(12345L) - * .tracer(AdapterTracer.console())) - * .build() - * ``` - * - * @since 1.1.17 - */ -@API(since = "1.1.17", status = EXPERIMENTAL) -class KotlinNodeTreeAdapterPlugin : Plugin { - private var enabled = true - private var seed = System.nanoTime() - private var tracer: AdapterTracer = AdapterTracer.noOp() - - /** - * Enables or disables the node tree adapter. - * - * When enabled, the [DefaultNodeTreeAdapter] will be used - * for object generation using JvmNodeTree. - * - * @param enabled true to enable the adapter, false to disable - * @return this plugin for method chaining - */ - fun enabled(enabled: Boolean): KotlinNodeTreeAdapterPlugin { - this.enabled = enabled - return this - } - - /** - * Sets the seed for random value generation in the adapter. - * - * Using a fixed seed value ensures reproducible test results. - * - * @param seed the seed value for random generation - * @return this plugin for method chaining - */ - fun seed(seed: Long): KotlinNodeTreeAdapterPlugin { - this.seed = seed - return this - } - - /** - * Sets the tracer for debugging resolution process. - * - * The tracer receives detailed information about how values are resolved - * during fixture generation, including manipulator analysis and assembly steps. - * - * @param tracer the tracer to use for debugging - * @return this plugin for method chaining - * @see AdapterTracer.console - * @see AdapterTracer.consoleJson - */ - fun tracer(tracer: AdapterTracer): KotlinNodeTreeAdapterPlugin { - this.tracer = tracer - return this - } - - override fun accept(optionsBuilder: FixtureMonkeyOptionsBuilder) { - if (enabled) { - optionsBuilder.nodeTreeAdapter( - DefaultNodeTreeAdapter( - seed, - JvmNodeCandidateTreeContext(), - KotlinNodePromoters.all(), - listOf(KotlinLeafTypeResolver.INSTANCE), - { delegate -> KotlinNodeCandidateGenerator(delegate) } - ) - ) - optionsBuilder.defaultNullInjectGeneratorOperator { delegate -> - KotlinNullInjectGenerator(delegate) - } - } - optionsBuilder.adapterTracer(tracer) - } -} diff --git a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/KotlinPlugin.kt b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/KotlinPlugin.kt index 7bc2df062f..9bfe0a363f 100644 --- a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/KotlinPlugin.kt +++ b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/KotlinPlugin.kt @@ -18,6 +18,7 @@ package com.navercorp.fixturemonkey.kotlin +import com.navercorp.fixturemonkey.planner.AssemblyPlanner import com.navercorp.fixturemonkey.api.generator.FunctionalInterfaceContainerPropertyGenerator import com.navercorp.fixturemonkey.api.generator.MatchPropertyGenerator import com.navercorp.fixturemonkey.api.generator.NullInjectGenerator @@ -26,6 +27,8 @@ import com.navercorp.fixturemonkey.api.introspector.MatchArbitraryIntrospector import com.navercorp.fixturemonkey.api.matcher.MatcherOperator import com.navercorp.fixturemonkey.api.option.FixtureMonkeyOptionsBuilder import com.navercorp.fixturemonkey.api.plugin.Plugin +import com.navercorp.fixturemonkey.plugin.JvmTypeSystem +import com.navercorp.fixturemonkey.plugin.JvmTypeSystemPlugin import com.navercorp.fixturemonkey.api.property.CandidateConcretePropertyResolver import com.navercorp.fixturemonkey.api.property.ConcreteTypeCandidateConcretePropertyResolver import com.navercorp.fixturemonkey.api.property.DefaultPropertyGenerator @@ -42,18 +45,22 @@ import com.navercorp.fixturemonkey.kotlin.introspector.TripleIntrospector import com.navercorp.fixturemonkey.kotlin.matcher.Matchers.DURATION_TYPE_MATCHER import com.navercorp.fixturemonkey.kotlin.matcher.Matchers.PAIR_TYPE_MATCHER import com.navercorp.fixturemonkey.kotlin.matcher.Matchers.TRIPLE_TYPE_MATCHER +import com.navercorp.fixturemonkey.kotlin.generator.KotlinNullInjectGenerator +import com.navercorp.fixturemonkey.kotlin.node.KotlinLeafTypeResolver +import com.navercorp.fixturemonkey.kotlin.node.KotlinNodeCandidateGenerator +import com.navercorp.fixturemonkey.kotlin.node.KotlinNodePromoters import com.navercorp.fixturemonkey.kotlin.property.KotlinPropertyGenerator import com.navercorp.fixturemonkey.kotlin.type.KotlinNullabilityUtils -import com.navercorp.fixturemonkey.kotlin.type.actualType import com.navercorp.fixturemonkey.kotlin.type.cachedKotlin import com.navercorp.fixturemonkey.kotlin.type.isKotlinLambda import com.navercorp.fixturemonkey.kotlin.type.isKotlinType +import com.navercorp.objectfarm.api.tree.JvmNodeCandidateTreeContext import org.apiguardian.api.API import org.apiguardian.api.API.Status.MAINTAINED import java.lang.reflect.Modifier @API(since = "0.4.0", status = MAINTAINED) -class KotlinPlugin : Plugin { +class KotlinPlugin : Plugin, JvmTypeSystemPlugin { override fun accept(optionsBuilder: FixtureMonkeyOptionsBuilder) { optionsBuilder.objectIntrospector { MatchArbitraryIntrospector( @@ -67,7 +74,7 @@ class KotlinPlugin : Plugin { MatchPropertyGenerator( listOf( MatcherOperator( - { property -> property.type.actualType().isKotlinType() }, + { property -> property.jvmType.rawType.isKotlinType() }, KotlinPropertyGenerator() ), MatcherOperator({ true }, DefaultPropertyGenerator()) @@ -75,18 +82,18 @@ class KotlinPlugin : Plugin { ) ) .insertFirstArbitraryContainerPropertyGenerator( - { property -> property.type.actualType().cachedKotlin().isKotlinLambda() } + { property -> property.jvmType.rawType.cachedKotlin().isKotlinLambda() } ) { FunctionalInterfaceContainerPropertyGenerator.INSTANCE.generate(it) } .insertFirstArbitraryIntrospector( - { property -> property.type.actualType().cachedKotlin().isKotlinLambda() }, + { property -> property.jvmType.rawType.cachedKotlin().isKotlinLambda() }, FunctionalInterfaceArbitraryIntrospector() ) .insertFirstCandidateConcretePropertyResolvers( MatcherOperator( - { it.type.actualType().cachedKotlin().isSealed }, + { it.jvmType.rawType.cachedKotlin().isSealed }, CandidateConcretePropertyResolver { property -> ConcreteTypeCandidateConcretePropertyResolver( - property.type.actualType().cachedKotlin().sealedSubclasses + property.jvmType.rawType.cachedKotlin().sealedSubclasses .map { it.java } ) .resolve(property) @@ -95,7 +102,7 @@ class KotlinPlugin : Plugin { ) .insertFirstPropertyGenerator( MatcherOperator( - { p -> Modifier.isInterface(p.type.actualType().modifiers) }, + { p -> Modifier.isInterface(p.jvmType.rawType.modifiers) }, InterfaceKFunctionPropertyGenerator(), ), ) @@ -136,6 +143,21 @@ class KotlinPlugin : Plugin { NullInjectGenerator { 0.0 } ) ) + .defaultNullInjectGeneratorOperator { delegate -> + KotlinNullInjectGenerator(delegate) + } + } + + override fun configure(typeSystem: JvmTypeSystem) { + typeSystem.assemblyPlanner( + AssemblyPlanner( + System.nanoTime(), + JvmNodeCandidateTreeContext(), + KotlinNodePromoters.all(), + listOf(KotlinLeafTypeResolver.INSTANCE), + { delegate -> KotlinNodeCandidateGenerator(delegate) } + ) + ) } private fun isKotlinNonNullableProperty(property: com.navercorp.fixturemonkey.api.property.Property): Boolean { diff --git a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/generator/InterfaceKFunctionPropertyGenerator.kt b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/generator/InterfaceKFunctionPropertyGenerator.kt index b110cdec90..45bb9cc726 100644 --- a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/generator/InterfaceKFunctionPropertyGenerator.kt +++ b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/generator/InterfaceKFunctionPropertyGenerator.kt @@ -22,7 +22,6 @@ import com.navercorp.fixturemonkey.api.generator.NoArgumentInterfaceJavaMethodPr import com.navercorp.fixturemonkey.api.property.InterfaceJavaMethodProperty import com.navercorp.fixturemonkey.api.property.Property import com.navercorp.fixturemonkey.api.property.PropertyGenerator -import com.navercorp.fixturemonkey.api.type.Types import com.navercorp.fixturemonkey.kotlin.property.InterfaceKFunctionProperty import com.navercorp.fixturemonkey.kotlin.type.actualType import com.navercorp.fixturemonkey.kotlin.type.getPropertyName @@ -42,7 +41,7 @@ import kotlin.reflect.jvm.javaMethod @API(since = "0.5.5", status = Status.MAINTAINED) class InterfaceKFunctionPropertyGenerator : PropertyGenerator { override fun generateChildProperties(property: Property): List { - val type = Types.getActualType(property.type) + val type = property.jvmType.rawType if (type.isKotlinType()) { val methods = type.kotlinMemberFunctions() diff --git a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/generator/KotlinNullInjectGenerator.kt b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/generator/KotlinNullInjectGenerator.kt index adbf5a2a44..bab0fb3f90 100644 --- a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/generator/KotlinNullInjectGenerator.kt +++ b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/generator/KotlinNullInjectGenerator.kt @@ -83,8 +83,8 @@ class KotlinNullInjectGenerator( if (nullable == null) { val ownerProperty = context.ownerProperty if (ownerProperty != null) { - val ownerType = ownerProperty.objectProperty?.property?.type - if (ownerType is Class<*> && KotlinTypeDetector.isKotlinType(ownerType)) { + val ownerType = ownerProperty.objectProperty?.property?.jvmType?.rawType + if (ownerType != null && KotlinTypeDetector.isKotlinType(ownerType)) { val ownerNullable = KotlinNullabilityUtils.isNullableByOwnerType(ownerType, property.name) if (ownerNullable == false) { return NOT_NULL_INJECT diff --git a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/generator/PairContainerPropertyGenerator.kt b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/generator/PairContainerPropertyGenerator.kt index df0b927547..8158f804e1 100644 --- a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/generator/PairContainerPropertyGenerator.kt +++ b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/generator/PairContainerPropertyGenerator.kt @@ -24,7 +24,6 @@ import com.navercorp.fixturemonkey.api.generator.ContainerPropertyGenerator import com.navercorp.fixturemonkey.api.generator.ContainerPropertyGeneratorContext import com.navercorp.fixturemonkey.api.property.DefaultContainerElementProperty import com.navercorp.fixturemonkey.api.property.TypeParameterProperty -import com.navercorp.fixturemonkey.api.type.Types import org.apiguardian.api.API import org.apiguardian.api.API.Status @@ -32,17 +31,18 @@ import org.apiguardian.api.API.Status class PairContainerPropertyGenerator : ContainerPropertyGenerator { override fun generate(context: ContainerPropertyGeneratorContext): ContainerProperty { val property = context.property - val genericsTypes = Types.getGenericsTypes(property.annotatedType) - if (genericsTypes.size != 2) { + val typeVariables = property.jvmType.typeVariables + if (typeVariables.size != 2) { throw IllegalArgumentException( """ - Pair genericsTypes must have 2 generics types for the first and second values. - "propertyType: ${property.type}, genericsTypes: $genericsTypes + Pair typeVariables must have 2 generics types for the first and second values. + "propertyType: ${property.jvmType.rawType}, typeVariables: $typeVariables """.trimIndent() ) } - val (firstElementType, secondElementType) = genericsTypes + val firstElementType = typeVariables[0] + val secondElementType = typeVariables[1] return ContainerProperty( listOf( diff --git a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/generator/TripleContainerPropertyGenerator.kt b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/generator/TripleContainerPropertyGenerator.kt index b4c975a511..cba9d56628 100644 --- a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/generator/TripleContainerPropertyGenerator.kt +++ b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/generator/TripleContainerPropertyGenerator.kt @@ -24,7 +24,6 @@ import com.navercorp.fixturemonkey.api.generator.ContainerPropertyGenerator import com.navercorp.fixturemonkey.api.generator.ContainerPropertyGeneratorContext import com.navercorp.fixturemonkey.api.property.DefaultContainerElementProperty import com.navercorp.fixturemonkey.api.property.TypeParameterProperty -import com.navercorp.fixturemonkey.api.type.Types import org.apiguardian.api.API import org.apiguardian.api.API.Status @@ -32,17 +31,19 @@ import org.apiguardian.api.API.Status class TripleContainerPropertyGenerator : ContainerPropertyGenerator { override fun generate(context: ContainerPropertyGeneratorContext): ContainerProperty { val property = context.property - val genericsTypes = Types.getGenericsTypes(property.annotatedType) - if (genericsTypes.size != 3) { + val typeVariables = property.jvmType.typeVariables + if (typeVariables.size != 3) { throw IllegalArgumentException( """ - Triple genericsTypes must have 3 generics types for the first, second, and third values. - "propertyType: ${property.type}, genericsTypes: $genericsTypes + Triple typeVariables must have 3 generics types for the first, second, and third values. + "propertyType: ${property.jvmType.rawType}, typeVariables: $typeVariables """.trimIndent() ) } - val (firstElementType, secondElementType, thirdElementType) = genericsTypes + val firstElementType = typeVariables[0] + val secondElementType = typeVariables[1] + val thirdElementType = typeVariables[2] return ContainerProperty( listOf( diff --git a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/instantiator/KotlinInstantiator.kt b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/instantiator/KotlinInstantiator.kt index 053f36e08d..6842a7515a 100644 --- a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/instantiator/KotlinInstantiator.kt +++ b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/instantiator/KotlinInstantiator.kt @@ -219,7 +219,11 @@ class KotlinInstantiatorProcessor : .filter { parameter -> parameter.kind != KParameter.Kind.INSTANCE } .mapIndexed { index, kParameter -> TypeNameProperty( - resolvedParameterTypes[index].annotatedType, + Types.toJvmType( + resolvedParameterTypes[index].annotatedType, + emptyList(), + kParameter.type.isMarkedNullable, + ), resolvedParameterNames[index], kParameter.type.isMarkedNullable, ) diff --git a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/introspector/PrimaryConstructorArbitraryIntrospector.kt b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/introspector/PrimaryConstructorArbitraryIntrospector.kt index dd2157b411..42d3671aae 100644 --- a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/introspector/PrimaryConstructorArbitraryIntrospector.kt +++ b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/introspector/PrimaryConstructorArbitraryIntrospector.kt @@ -25,9 +25,7 @@ import com.navercorp.fixturemonkey.api.introspector.ArbitraryIntrospectorResult import com.navercorp.fixturemonkey.api.matcher.Matcher import com.navercorp.fixturemonkey.api.property.Property import com.navercorp.fixturemonkey.api.property.PropertyGenerator -import com.navercorp.fixturemonkey.api.type.Types import com.navercorp.fixturemonkey.kotlin.property.KotlinConstructorParameterPropertyGenerator -import com.navercorp.fixturemonkey.kotlin.type.actualType import com.navercorp.fixturemonkey.kotlin.type.cachedKotlin import com.navercorp.fixturemonkey.kotlin.type.isKotlinLambda import com.navercorp.fixturemonkey.kotlin.type.isKotlinType @@ -41,13 +39,13 @@ import kotlin.reflect.KParameter @API(since = "0.4.0", status = MAINTAINED) class PrimaryConstructorArbitraryIntrospector : ArbitraryIntrospector, Matcher { override fun match(property: Property): Boolean = - property.type.actualType().isKotlinType() && - !property.type.actualType().cachedKotlin().isKotlinLambda() && - property.type.actualType().cachedKotlin() != Unit::class && - property.type.actualType().cachedKotlin().objectInstance == null + property.jvmType.rawType.isKotlinType() && + !property.jvmType.rawType.cachedKotlin().isKotlinLambda() && + property.jvmType.rawType.cachedKotlin() != Unit::class && + property.jvmType.rawType.cachedKotlin().objectInstance == null override fun introspect(context: ArbitraryGeneratorContext): ArbitraryIntrospectorResult { - val type = Types.getActualType(context.resolvedType) + val type = context.resolvedType if (Modifier.isAbstract(type.modifiers)) { return ArbitraryIntrospectorResult.NOT_INTROSPECTED } @@ -85,7 +83,7 @@ class PrimaryConstructorArbitraryIntrospector : ArbitraryIntrospector, Matcher { val INSTANCE = PrimaryConstructorArbitraryIntrospector() private val LOGGER = LoggerFactory.getLogger(PrimaryConstructorArbitraryIntrospector::class.java) internal val PROPERTY_GENERATOR = KotlinConstructorParameterPropertyGenerator({ property -> - property.type.actualType().kotlinPrimaryConstructor() + property.jvmType.rawType.kotlinPrimaryConstructor() }) } } diff --git a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/introspector/TripleIntrospector.kt b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/introspector/TripleIntrospector.kt index 1cd600e4df..96d1e8506c 100644 --- a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/introspector/TripleIntrospector.kt +++ b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/introspector/TripleIntrospector.kt @@ -34,7 +34,9 @@ class TripleIntrospector : ArbitraryIntrospector, Matcher { return ArbitraryIntrospectorResult( CombinableArbitrary.containerBuilder() .elements(elementCombinableArbitraryList) - .build { Triple(it[0], it[1], it[2]) }, + .build { + Triple(it[0], it[1], it[2]) + }, ) } } diff --git a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/property/InterfaceKFunctionProperty.kt b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/property/InterfaceKFunctionProperty.kt index 84a4a6035a..fb5ddddf4b 100644 --- a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/property/InterfaceKFunctionProperty.kt +++ b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/property/InterfaceKFunctionProperty.kt @@ -19,11 +19,12 @@ package com.navercorp.fixturemonkey.kotlin.property import com.navercorp.fixturemonkey.api.property.MethodProperty +import com.navercorp.fixturemonkey.api.type.Types +import com.navercorp.fixturemonkey.api.type.Types.generateAnnotatedTypeWithoutAnnotation import com.navercorp.fixturemonkey.kotlin.type.toTypeReference +import com.navercorp.objectfarm.api.type.JvmType import org.apiguardian.api.API import org.apiguardian.api.API.Status -import java.lang.reflect.AnnotatedType -import java.lang.reflect.Type import java.util.Optional import kotlin.reflect.KType @@ -37,18 +38,13 @@ data class InterfaceKFunctionProperty( private val methodName: String, private val annotations: List, ) : MethodProperty { - override fun getType(): Type = type.toTypeReference().type + private val cachedJvmType: JvmType = Types.toJvmType( + generateAnnotatedTypeWithoutAnnotation(type.toTypeReference().type), + annotations, + type.isMarkedNullable, + ) - override fun getAnnotatedType(): AnnotatedType = object : AnnotatedType { - override fun getType(): Type = this@InterfaceKFunctionProperty.getType() - - override fun getAnnotation(annotationClass: Class): T = - this@InterfaceKFunctionProperty.getAnnotation(annotationClass).orElse(null) - - override fun getAnnotations(): Array = this@InterfaceKFunctionProperty.annotations.toTypedArray() - - override fun getDeclaredAnnotations(): Array = annotations - } + override fun getJvmType(): JvmType = cachedJvmType override fun getName(): String = propertyName @@ -56,10 +52,6 @@ data class InterfaceKFunctionProperty( override fun getAnnotations(): List = annotations - override fun getValue(obj: Any?): Any? { - throw UnsupportedOperationException("Interface method should not be called.") - } - override fun getAnnotation(annotationClass: Class?): Optional { return super.getAnnotation(annotationClass) } diff --git a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/property/KPropertyProperty.kt b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/property/KPropertyProperty.kt index 458ca2c09f..10d0d6aaa5 100644 --- a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/property/KPropertyProperty.kt +++ b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/property/KPropertyProperty.kt @@ -19,46 +19,30 @@ package com.navercorp.fixturemonkey.kotlin.property import com.navercorp.fixturemonkey.api.property.Property +import com.navercorp.fixturemonkey.api.type.Types +import com.navercorp.objectfarm.api.type.JvmType import org.apiguardian.api.API import org.slf4j.LoggerFactory import java.lang.reflect.AnnotatedType -import java.lang.reflect.Type import kotlin.reflect.KProperty -import kotlin.reflect.jvm.isAccessible -import kotlin.reflect.jvm.javaField -import kotlin.reflect.jvm.javaMethod @API(since = "0.4.0", status = API.Status.MAINTAINED) data class KPropertyProperty( private val annotatedType: AnnotatedType, val kProperty: KProperty<*>, ) : Property { - override fun getType(): Type = this.annotatedType.type + private val cachedJvmType: JvmType = Types.toJvmType( + annotatedType, + emptyList(), + kProperty.returnType.isMarkedNullable, + ) - override fun getAnnotatedType(): AnnotatedType = this.annotatedType + override fun getJvmType(): JvmType = cachedJvmType override fun getName(): String = this.kProperty.name override fun getAnnotations(): List = this.annotatedType.annotations.toList() - override fun getValue(instance: Any): Any? { - val javaMethod = this.kProperty.getter.javaMethod - - if (javaMethod != null) { - javaMethod.isAccessible = true - return javaMethod.invoke(instance) - } - - val javaField = this.kProperty.javaField - if (javaField != null) { - javaField.isAccessible = true - return javaField.get(instance) - } - - LOGGER.warn("Failed to get value of property {} in instance {}.", this.kProperty.name, instance) - return null - } - override fun equals(other: Any?): Boolean { if (this === other) { return true @@ -68,10 +52,10 @@ data class KPropertyProperty( } val that = other as Property - return type == that.type + return jvmType == that.jvmType } - override fun hashCode(): Int = type.hashCode() + override fun hashCode(): Int = jvmType.hashCode() override fun isNullable(): Boolean = this.kProperty.returnType.isMarkedNullable diff --git a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/property/KotlinConstructorParameterProperty.kt b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/property/KotlinConstructorParameterProperty.kt index 93224f0513..7b3beb6f47 100644 --- a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/property/KotlinConstructorParameterProperty.kt +++ b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/property/KotlinConstructorParameterProperty.kt @@ -19,10 +19,9 @@ package com.navercorp.fixturemonkey.kotlin.property import com.navercorp.fixturemonkey.api.property.Property -import com.navercorp.fixturemonkey.kotlin.type.actualType -import com.navercorp.fixturemonkey.kotlin.type.toTypeReference +import com.navercorp.fixturemonkey.api.type.Types +import com.navercorp.objectfarm.api.type.JvmType import java.lang.reflect.AnnotatedType -import java.lang.reflect.Type import java.util.Optional import kotlin.reflect.KFunction import kotlin.reflect.KParameter @@ -33,20 +32,18 @@ internal data class KotlinConstructorParameterProperty( private val parameterName: String?, private val constructor: KFunction<*>, ) : Property { - override fun getType(): Type = annotatedType.type + private val cachedJvmType: JvmType = Types.toJvmType( + annotatedType, + kParameter.annotations, + kParameter.type.isMarkedNullable, + ) - override fun getAnnotatedType(): AnnotatedType = annotatedType + override fun getJvmType(): JvmType = cachedJvmType override fun getName(): String? = parameterName override fun getAnnotations(): List = kParameter.annotations - override fun getValue(obj: Any?): Any? { - return getKotlinMemberProperties(constructor.returnType.toTypeReference().type.actualType()) - .firstOrNull { it.name == parameterName } - ?.call(obj) - } - @Suppress("UNCHECKED_CAST") override fun getAnnotation(annotationClass: Class): Optional = annotations .find { it.annotationClass.java == annotationClass } diff --git a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/property/KotlinPropertyCache.kt b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/property/KotlinPropertyCache.kt index d5fe71136d..f9e622d1bf 100644 --- a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/property/KotlinPropertyCache.kt +++ b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/property/KotlinPropertyCache.kt @@ -34,11 +34,12 @@ fun getMemberProperties( property: Property, propertyFilter: (KProperty<*>) -> Boolean = { true }, ): List { - val actualType = Types.getActualType(property.type) + val actualType = property.jvmType.rawType + val parentAnnotatedType = Types.toAnnotatedType(property.jvmType) return getKotlinMemberProperties(actualType) .filter(propertyFilter) .map { - val propertyAnnotatedType = getAnnotatedType(property.annotatedType, it) + val propertyAnnotatedType = getAnnotatedType(parentAnnotatedType, it) KPropertyProperty(propertyAnnotatedType, it) } } diff --git a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/type/KotlinTypes.kt b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/type/KotlinTypes.kt index f8dbf1c078..f14063c3c9 100644 --- a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/type/KotlinTypes.kt +++ b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/type/KotlinTypes.kt @@ -81,7 +81,7 @@ fun getAnnotatedType(ownerType: AnnotatedType, kProperty: KProperty<*>): Annotat for (i in propertyGenericsTypes.indices) { val generics = propertyGenericsTypes[i] if (generics is ParameterizedType || generics::class.java == Class::class.java) { - resolvedGenericsTypes.add(i, KotlinAnnotatedType(type, arrayOf())) + resolvedGenericsTypes.add(i, KotlinAnnotatedType(generics, arrayOf())) resolvedTypes.add(i, generics) continue } diff --git a/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/FixtureMonkeyJavaTest.kt b/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/FixtureMonkeyJavaTest.kt index 2dc781e7ec..c87f329df9 100644 --- a/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/FixtureMonkeyJavaTest.kt +++ b/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/FixtureMonkeyJavaTest.kt @@ -18,10 +18,10 @@ package com.navercorp.fixturemonkey.kotlin +import org.junit.jupiter.api.Test import com.navercorp.fixturemonkey.FixtureMonkey import com.navercorp.fixturemonkey.api.introspector.BeanArbitraryIntrospector import com.navercorp.fixturemonkey.kotlin.spec.JavaObject -import net.jqwik.api.Example import org.assertj.core.api.BDDAssertions.then import org.assertj.core.api.BDDAssertions.thenNoException @@ -31,7 +31,7 @@ class FixtureMonkeyJavaTest { .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) .build() - @Example + @Test fun sampleJavaObject() { // when val actual = sut.giveMeOne() @@ -39,7 +39,7 @@ class FixtureMonkeyJavaTest { then(actual).isNotNull } - @Example + @Test fun fixedJavaObject() { thenNoException() .isThrownBy { diff --git a/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/FixtureMonkeyKotlinJacksonTest.kt b/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/FixtureMonkeyKotlinJacksonTest.kt index e0842053dc..b0f7880016 100644 --- a/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/FixtureMonkeyKotlinJacksonTest.kt +++ b/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/FixtureMonkeyKotlinJacksonTest.kt @@ -18,9 +18,9 @@ package com.navercorp.fixturemonkey.kotlin +import org.junit.jupiter.api.Test import com.navercorp.fixturemonkey.FixtureMonkey import com.navercorp.fixturemonkey.jackson.plugin.JacksonPlugin -import net.jqwik.api.Example import org.assertj.core.api.BDDAssertions.then import java.util.UUID @@ -30,7 +30,7 @@ class FixtureMonkeyKotlinJacksonTest { .plugin(JacksonPlugin()) .build() - @Example + @Test fun setParentPrivateValue() { val actual = this.sut.giveMeBuilder() .set("id", "id") diff --git a/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/KotlinContainerTest.kt b/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/KotlinContainerTest.kt index e1b0d70cf2..d03761fc3c 100644 --- a/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/KotlinContainerTest.kt +++ b/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/KotlinContainerTest.kt @@ -18,13 +18,13 @@ package com.navercorp.fixturemonkey.kotlin +import org.junit.jupiter.api.Test import com.navercorp.fixturemonkey.FixtureMonkey -import net.jqwik.api.Example import org.assertj.core.api.BDDAssertions.then import java.util.function.Consumer class KotlinContainerTest { - @Example + @Test fun samplePair() { val actual = SUT.giveMeOne>() @@ -32,7 +32,7 @@ class KotlinContainerTest { then(actual.second).isInstanceOf(java.lang.Long::class.java) } - @Example + @Test fun samplePairList() { val actual = SUT.giveMeOne>>() @@ -44,7 +44,7 @@ class KotlinContainerTest { ) } - @Example + @Test fun decomposePair() { val builder = SUT.giveMeBuilder>() .fixed() @@ -55,7 +55,7 @@ class KotlinContainerTest { then(actual1).isEqualTo(actual2) } - @Example + @Test fun sampleTriple() { val actual = SUT.giveMeOne>() @@ -64,7 +64,7 @@ class KotlinContainerTest { then(actual.third).isInstanceOf(java.lang.Long::class.java) } - @Example + @Test fun sampleTripleList() { val actual = SUT.giveMeOne>>() @@ -77,7 +77,7 @@ class KotlinContainerTest { ) } - @Example + @Test fun decomposeTriple() { val builder = SUT.giveMeBuilder>() .fixed() diff --git a/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/property/KPropertyPropertyTest.kt b/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/property/KPropertyPropertyTest.kt deleted file mode 100644 index 947d351bf6..0000000000 --- a/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/property/KPropertyPropertyTest.kt +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.kotlin.property - -import com.navercorp.fixturemonkey.api.type.TypeReference -import com.navercorp.fixturemonkey.kotlin.type.getAnnotatedType -import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.Test -import java.time.Instant -import kotlin.reflect.full.memberProperties - -class KPropertyPropertyTest { - @Test - fun kPropertyPropertyValue() { - // given - val typeReference = object : TypeReference() {} - val properties = PropertySample::class.memberProperties.toList() - - // when - val actual = properties - .map { KPropertyProperty(getAnnotatedType(typeReference.annotatedType, it), it) } - .associateBy { it.name } - - then(actual["str"]!!.type).isEqualTo(String::class.java) - then(actual["str"]!!.isNullable).isFalse - then(actual["str"]!!.annotations).hasSize(1) - then(actual["nullable"]!!.type).isEqualTo(String::class.java) - then(actual["nullable"]!!.isNullable).isTrue - then(actual["nullable"]!!.annotations).hasSize(1) - then(actual["integer"]!!.type).isEqualTo(Int::class.java) - then(actual["integer"]!!.isNullable).isFalse - then(actual["integer"]!!.annotations).hasSize(1) - then(actual["list"]!!.type.typeName).isEqualTo("java.util.List") - then(actual["list"]!!.isNullable).isFalse - then(actual["list"]!!.annotations).isEmpty() - then(actual["instant"]!!.type).isEqualTo(Instant::class.java) - then(actual["instant"]!!.isNullable).isFalse - then(actual["instant"]!!.annotations).hasSize(1) - } - - @Test - fun getValueOfPropertyWithoutBackingField() { - // given - val typeReference = object : TypeReference() {} - val property = PropertyWithoutBackingFieldClass::class.memberProperties.first() - val kPropertyProperty = KPropertyProperty(getAnnotatedType(typeReference.annotatedType, property), property) - val propertyWithoutBackingFieldClass = PropertyWithoutBackingFieldClass() - - // when - val actual = kPropertyProperty.getValue(propertyWithoutBackingFieldClass) - - // then - then(actual).isEqualTo("test") - } -} - -data class PropertySample( - val str: String, - - val nullable: String?, - - val integer: Int, - - val list: List, -) { - val instant: Instant = Instant.now() -} - -class PropertyWithoutBackingFieldClass { - val str: String - get() = "test" -} diff --git a/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/property/KotlinPropertyCacheTest.kt b/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/property/KotlinPropertyCacheTest.kt index 1b61c8d9f4..c123cb0de6 100644 --- a/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/property/KotlinPropertyCacheTest.kt +++ b/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/property/KotlinPropertyCacheTest.kt @@ -19,11 +19,13 @@ package com.navercorp.fixturemonkey.kotlin.property import com.navercorp.fixturemonkey.api.property.RootProperty +import com.navercorp.fixturemonkey.api.property.TypeParameterProperty import com.navercorp.fixturemonkey.api.type.TypeReference +import com.navercorp.fixturemonkey.api.type.Types import org.assertj.core.api.BDDAssertions.then import org.junit.jupiter.api.Test -import java.lang.reflect.ParameterizedType import java.time.Instant +import java.util.Collections import javax.annotation.Nullable class KotlinPropertyCacheTest { @@ -33,10 +35,14 @@ class KotlinPropertyCacheTest { val typeReference = object : TypeReference() {} // when - val actual = getMemberProperties(RootProperty(typeReference.annotatedType)) + val actual = getMemberProperties( + RootProperty( + TypeParameterProperty(Types.toJvmType(typeReference.annotatedType, Collections.emptyList())) + ) + ) then(actual).hasSize(1) - then(actual[0].type).isEqualTo(String::class.java) + then(actual[0].jvmType.rawType).isEqualTo(String::class.java) then(actual[0].name).isEqualTo("name") then(actual[0].annotations).hasSize(1) then(actual[0].annotations[0].annotationClass).isEqualTo(Nullable::class) @@ -49,49 +55,41 @@ class KotlinPropertyCacheTest { val typeReference = object : TypeReference>() {} // when - val actual = getMemberProperties(RootProperty(typeReference.annotatedType)) + val actual = getMemberProperties( + RootProperty( + TypeParameterProperty(Types.toJvmType(typeReference.annotatedType, Collections.emptyList())) + ) + ) then(actual).hasSize(6) val sorted = actual.sortedBy { it.name } then(sorted[0].name).isEqualTo("list") then(sorted[0].isNullable).isFalse - then(sorted[0].type).isInstanceOf(ParameterizedType::class.java) - with(sorted[0].type as ParameterizedType) { - then(rawType).isEqualTo(List::class.java) - then(actualTypeArguments).hasSize(1) - then(actualTypeArguments[0]).isEqualTo(String::class.java) - } + then(sorted[0].jvmType.rawType).isEqualTo(List::class.java) + then(sorted[0].jvmType.typeVariables.map { it.rawType }).containsExactly(String::class.java) then(sorted[1].name).isEqualTo("name") then(sorted[1].isNullable).isFalse - then(sorted[1].type).isEqualTo(String::class.java) + then(sorted[1].jvmType.rawType).isEqualTo(String::class.java) then(sorted[2].name).isEqualTo("property") then(sorted[2].isNullable).isTrue - then(sorted[2].type).isEqualTo(Instant::class.java) + then(sorted[2].jvmType.rawType).isEqualTo(Instant::class.java) then(sorted[3].name).isEqualTo("sample2") then(sorted[3].isNullable).isTrue - then(sorted[3].type).isInstanceOf(ParameterizedType::class.java) - with(sorted[3].type as ParameterizedType) { - then(rawType).isEqualTo(GenericSample2::class.java) - then(actualTypeArguments).hasSize(1) - then(actualTypeArguments[0]).isEqualTo(String::class.java) - } + then(sorted[3].jvmType.rawType).isEqualTo(GenericSample2::class.java) + then(sorted[3].jvmType.typeVariables.map { it.rawType }).containsExactly(String::class.java) then(sorted[4].name).isEqualTo("samples") then(sorted[4].isNullable).isFalse - then(sorted[4].type).isInstanceOf(ParameterizedType::class.java) - with(sorted[4].type as ParameterizedType) { - then(rawType).isEqualTo(List::class.java) - then(actualTypeArguments).hasSize(1) - then(actualTypeArguments[0]).isEqualTo(SampleValue::class.java) - } + then(sorted[4].jvmType.rawType).isEqualTo(List::class.java) + then(sorted[4].jvmType.typeVariables.map { it.rawType }).containsExactly(SampleValue::class.java) then(sorted[5].name).isEqualTo("test") then(sorted[5].isNullable).isFalse - then(sorted[5].type).isEqualTo(SampleValue::class.java) + then(sorted[5].jvmType.rawType).isEqualTo(SampleValue::class.java) } } diff --git a/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/test/KotlinAndJavaCompositeArbitraryIntrospectorTest.kt b/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/test/KotlinAndJavaCompositeArbitraryIntrospectorTest.kt index ab70131dbe..f0423d90c4 100644 --- a/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/test/KotlinAndJavaCompositeArbitraryIntrospectorTest.kt +++ b/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/test/KotlinAndJavaCompositeArbitraryIntrospectorTest.kt @@ -18,16 +18,16 @@ package com.navercorp.fixturemonkey.kotlin.test +import org.junit.jupiter.api.Test import com.navercorp.fixturemonkey.FixtureMonkey import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector import com.navercorp.fixturemonkey.kotlin.KotlinPlugin import com.navercorp.fixturemonkey.kotlin.giveMeOne import com.navercorp.fixturemonkey.kotlin.introspector.KotlinAndJavaCompositeArbitraryIntrospector -import net.jqwik.api.Example import org.assertj.core.api.BDDAssertions.then class KotlinAndJavaCompositeArbitraryIntrospectorTest { - @Example + @Test fun kotlinClassWithJavaClass() { // given val sut: FixtureMonkey = FixtureMonkey.builder() @@ -42,7 +42,7 @@ class KotlinAndJavaCompositeArbitraryIntrospectorTest { then(actual.javaObject).isNotNull } - @Example + @Test fun kotlinClassWithJavaClassUsingOtherIntrospector() { // given val sut: FixtureMonkey = FixtureMonkey.builder() @@ -61,7 +61,7 @@ class KotlinAndJavaCompositeArbitraryIntrospectorTest { then(actual.javaObject).isNotNull } - @Example + @Test fun sampleMapValue() { // given val sut: FixtureMonkey = FixtureMonkey.builder() diff --git a/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/test/KotlinExpJacksonPropertyTest.kt b/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/test/KotlinExpJacksonPropertyTest.kt index a066dba008..8ae05fd8c3 100644 --- a/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/test/KotlinExpJacksonPropertyTest.kt +++ b/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/test/KotlinExpJacksonPropertyTest.kt @@ -18,6 +18,7 @@ package com.navercorp.fixturemonkey.kotlin.test +import org.junit.jupiter.api.Test import com.fasterxml.jackson.annotation.JsonProperty import com.navercorp.fixturemonkey.FixtureMonkey import com.navercorp.fixturemonkey.jackson.plugin.JacksonPlugin @@ -26,7 +27,6 @@ import com.navercorp.fixturemonkey.kotlin.giveMeBuilder import com.navercorp.fixturemonkey.kotlin.giveMeOne import com.navercorp.fixturemonkey.kotlin.setExp import com.navercorp.fixturemonkey.kotlin.setExpGetter -import net.jqwik.api.Example import org.assertj.core.api.BDDAssertions.then class KotlinExpJacksonPropertyTest { @@ -35,7 +35,7 @@ class KotlinExpJacksonPropertyTest { .plugin(KotlinPlugin()) .build() - @Example + @Test fun setExpJsonPropertyName() { val stringValue: String = sut.giveMeOne() val actual = sut.giveMeBuilder() @@ -44,7 +44,7 @@ class KotlinExpJacksonPropertyTest { then(actual.stringValue).isEqualTo(stringValue) } - @Example + @Test fun setExpGetterJsonPropertyName() { val intValue: Int = sut.giveMeOne() val actual = sut.giveMeBuilder() diff --git a/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/test/PrimaryConstructorArbitraryIntrospectorTest.kt b/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/test/PrimaryConstructorArbitraryIntrospectorTest.kt index de341740f7..17f6298760 100644 --- a/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/test/PrimaryConstructorArbitraryIntrospectorTest.kt +++ b/fixture-monkey-kotlin/src/test/kotlin/com/navercorp/fixturemonkey/kotlin/test/PrimaryConstructorArbitraryIntrospectorTest.kt @@ -18,12 +18,12 @@ package com.navercorp.fixturemonkey.kotlin.test +import org.junit.jupiter.api.Test import com.navercorp.fixturemonkey.FixtureMonkey import com.navercorp.fixturemonkey.kotlin.KotlinPlugin import com.navercorp.fixturemonkey.kotlin.giveMeBuilder import com.navercorp.fixturemonkey.kotlin.giveMeOne import com.navercorp.fixturemonkey.kotlin.set -import net.jqwik.api.Example import org.assertj.core.api.BDDAssertions.then import org.assertj.core.api.BDDAssertions.thenNoException import org.junit.jupiter.api.assertAll @@ -37,32 +37,32 @@ class PrimaryConstructorArbitraryIntrospectorTest { .plugin(KotlinPlugin()) .build() - @Example + @Test fun samplePrimaryConstructor() { thenNoException().isThrownBy { sut.giveMeOne() } } - @Example + @Test fun sampleNested() { thenNoException().isThrownBy { sut.giveMeOne().nested.intValue } } - @Example + @Test fun sampleDataClass() { thenNoException().isThrownBy { sut.giveMeOne() } } - @Example + @Test fun sampleVarValue() { thenNoException().isThrownBy { sut.giveMeOne() } } - @Example + @Test fun sampleNullableValue() { thenNoException().isThrownBy { sut.giveMeOne() } } - @Example + @Test fun sampleDefaultValue() { // when val actual = sut.giveMeOne().stringValue @@ -70,14 +70,14 @@ class PrimaryConstructorArbitraryIntrospectorTest { then(actual).isNotEqualTo("default_value") } - @Example + @Test fun sampleDuration() { // when val duration = sut.giveMeOne() then(duration).isNotNull() } - @Example + @Test fun sampleDurationValue() { // when val durationValue = sut.giveMeBuilder() @@ -86,7 +86,7 @@ class PrimaryConstructorArbitraryIntrospectorTest { then(durationValue.duration).isNotNull() } - @Example + @Test fun setDurationValue() { // given val duration = Random().nextLong().toDuration(DurationUnit.values().random()) @@ -100,7 +100,7 @@ class PrimaryConstructorArbitraryIntrospectorTest { then(one.duration).isEqualTo(duration) } - @Example + @Test fun sampleGenericDuration() { // when val one = sut.giveMeOne>() @@ -111,7 +111,7 @@ class PrimaryConstructorArbitraryIntrospectorTest { ) } - @Example + @Test fun sampleSecondaryConstructor() { // when val actual = sut.giveMeOne().stringValue @@ -119,7 +119,7 @@ class PrimaryConstructorArbitraryIntrospectorTest { then(actual).isNotEqualTo("default_value") } - @Example + @Test fun sampleInterface() { // when val actual: InterfaceClass = sut.giveMeOne() diff --git a/fixture-monkey-mockito/build.gradle.kts b/fixture-monkey-mockito/build.gradle.kts index c5eeda0f0b..ada9c41b7e 100644 --- a/fixture-monkey-mockito/build.gradle.kts +++ b/fixture-monkey-mockito/build.gradle.kts @@ -7,6 +7,8 @@ dependencies { api(projects.fixtureMonkey) api(libs.mockito.core) + testImplementation(libs.junit.jupiter.engine) + testImplementation(libs.junit.platform.engine) testImplementation(libs.assertj.core) testImplementation(libs.lombok) testAnnotationProcessor(libs.lombok) diff --git a/fixture-monkey-mockito/src/main/java/com/navercorp/fixturemonkey/mockito/introspector/MockitoIntrospector.java b/fixture-monkey-mockito/src/main/java/com/navercorp/fixturemonkey/mockito/introspector/MockitoIntrospector.java index 3b1a9d2b37..4145dbd029 100644 --- a/fixture-monkey-mockito/src/main/java/com/navercorp/fixturemonkey/mockito/introspector/MockitoIntrospector.java +++ b/fixture-monkey-mockito/src/main/java/com/navercorp/fixturemonkey/mockito/introspector/MockitoIntrospector.java @@ -32,7 +32,6 @@ import com.navercorp.fixturemonkey.api.jqwik.ArbitraryUtils; import com.navercorp.fixturemonkey.api.matcher.Matcher; import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.api.type.Types; @API(since = "0.4.0", status = Status.MAINTAINED) public final class MockitoIntrospector implements ArbitraryIntrospector, Matcher { @@ -40,13 +39,13 @@ public final class MockitoIntrospector implements ArbitraryIntrospector, Matcher @Override public boolean match(Property property) { - Class actualType = Types.getActualType(property.getType()); + Class actualType = property.getJvmType().getRawType(); return Modifier.isAbstract(actualType.getModifiers()); } @Override public ArbitraryIntrospectorResult introspect(ArbitraryGeneratorContext context) { - Class actualType = Types.getActualType(context.getResolvedType()); + Class actualType = context.getResolvedType(); return new ArbitraryIntrospectorResult( ArbitraryUtils.toCombinableArbitrary(Arbitraries.of(Mockito.mock(actualType))) ); diff --git a/fixture-monkey-mockito/src/test/java/com/navercorp/fixturemonkey/mockito/plugin/MockitoPluginTest.java b/fixture-monkey-mockito/src/test/java/com/navercorp/fixturemonkey/mockito/plugin/MockitoPluginTest.java index c1b0bd356b..3e619d9aec 100644 --- a/fixture-monkey-mockito/src/test/java/com/navercorp/fixturemonkey/mockito/plugin/MockitoPluginTest.java +++ b/fixture-monkey-mockito/src/test/java/com/navercorp/fixturemonkey/mockito/plugin/MockitoPluginTest.java @@ -23,8 +23,9 @@ import java.util.Collections; +import org.junit.jupiter.api.Test; + import net.jqwik.api.Arbitraries; -import net.jqwik.api.Example; import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.plugin.InterfacePlugin; @@ -35,7 +36,7 @@ import com.navercorp.fixturemonkey.mockito.plugin.MockitoPluginTestSpecs.Sample; class MockitoPluginTest { - @Example + @Test void mockitoAbstractInterface() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -59,7 +60,7 @@ void mockitoAbstractInterface() { then(actual.getInterfaceSample().getValue()).isEqualTo(mockIntValue); } - @Example + @Test void interfaceImplementsAndMockitoInterface() { FixtureMonkey sut = FixtureMonkey.builder() .plugin(new MockitoPlugin()) @@ -75,7 +76,7 @@ void interfaceImplementsAndMockitoInterface() { then(actual).isNotNull(); } - @Example + @Test void interfaceImplementsAndMockitoAbstract() { FixtureMonkey sut = FixtureMonkey.builder() .plugin(new MockitoPlugin()) diff --git a/fixture-monkey-tests/doc-examples/build.gradle.kts b/fixture-monkey-tests/doc-examples/build.gradle.kts index db2b2d33c6..315dab5063 100644 --- a/fixture-monkey-tests/doc-examples/build.gradle.kts +++ b/fixture-monkey-tests/doc-examples/build.gradle.kts @@ -20,3 +20,7 @@ subprojects { useJUnitPlatform() } } + +tasks.named("test") { + dependsOn(subprojects.map { "${it.path}:test" }) +} diff --git a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/ConstructorPropertiesRecordTest.java b/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/ConstructorPropertiesRecordTest.java index 16c023bfbf..fc017f20e4 100644 --- a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/ConstructorPropertiesRecordTest.java +++ b/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/ConstructorPropertiesRecordTest.java @@ -19,10 +19,9 @@ package com.navercorp.fixturemonkey.tests.java17; import static com.navercorp.fixturemonkey.api.experimental.JavaGetterMethodPropertySelector.javaGetter; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; import static org.assertj.core.api.BDDAssertions.then; -import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; @@ -43,14 +42,14 @@ class ConstructorPropertiesRecordTest { .defaultNotNull(true) .build(); - @RepeatedTest(TEST_COUNT) + @Test void sampleJavaType() { JavaTypeRecord actual = SUT.giveMeOne(JavaTypeRecord.class); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedJavaType() { JavaTypeRecord actual = SUT.giveMeBuilder(JavaTypeRecord.class) .fixed() @@ -59,14 +58,14 @@ void fixedJavaType() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleDateTime() { DateTimeRecord actual = SUT.giveMeOne(DateTimeRecord.class); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedDateTime() { DateTimeRecord actual = SUT.giveMeBuilder(DateTimeRecord.class) .fixed() @@ -75,14 +74,14 @@ void fixedDateTime() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleContainer() { ContainerRecord actual = SUT.giveMeOne(ContainerRecord.class); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedContainer() { ContainerRecord actual = SUT.giveMeBuilder(ContainerRecord.class) .fixed() @@ -91,14 +90,14 @@ void fixedContainer() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleInterfaceContainer() { ComplexContainerRecord actual = SUT.giveMeOne(ComplexContainerRecord.class); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedInterfaceContainer() { ComplexContainerRecord actual = SUT.giveMeBuilder(ComplexContainerRecord.class) .fixed() @@ -107,7 +106,7 @@ void fixedInterfaceContainer() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleTwoConstructorsRecord() { String actual = SUT.giveMeBuilder(TwoConstructorsRecord.class) .setNotNull("string") @@ -117,7 +116,7 @@ void sampleTwoConstructorsRecord() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void recordShouldUseCanonicalConstructor() { String expected = "expected"; @@ -129,7 +128,7 @@ void recordShouldUseCanonicalConstructor() { then(actual).isEqualTo(expected); } - @RepeatedTest(TEST_COUNT) + @Test void recordUseCompactConstructor() { String expected = "expected"; @@ -141,7 +140,7 @@ void recordUseCompactConstructor() { then(actual).isEqualTo("12345"); } - @RepeatedTest(TEST_COUNT) + @Test void fixedTwoConstructorsRecord() { String actual = SUT.giveMeBuilder(TwoConstructorsRecord.class) .setNotNull("string") @@ -152,14 +151,14 @@ void fixedTwoConstructorsRecord() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleNoArgsConstructorRecord() { NoArgsConstructorRecord actual = SUT.giveMeOne(NoArgsConstructorRecord.class); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedNoArgsConstructorRecord() { NoArgsConstructorRecord actual = SUT.giveMeBuilder(NoArgsConstructorRecord.class) .fixed() @@ -168,7 +167,7 @@ void fixedNoArgsConstructorRecord() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void setIsPrefixPrimitiveBoolean() { boolean actual = SUT.giveMeBuilder(IsPrefixBooleanRecord.class) .set(javaGetter(IsPrefixBooleanRecord::isPrimitive), false) @@ -178,7 +177,7 @@ void setIsPrefixPrimitiveBoolean() { then(actual).isFalse(); } - @RepeatedTest(TEST_COUNT) + @Test void setIsPrefixWrapperBoolean() { boolean actual = SUT.giveMeBuilder(IsPrefixBooleanRecord.class) .set(javaGetter(IsPrefixBooleanRecord::isWrapper), false) @@ -188,7 +187,7 @@ void setIsPrefixWrapperBoolean() { then(actual).isFalse(); } - @RepeatedTest(TEST_COUNT) + @Test void setPrimitiveBoolean() { boolean actual = SUT.giveMeBuilder(BooleanRecord.class) .set(javaGetter(BooleanRecord::primitive), false) @@ -198,7 +197,7 @@ void setPrimitiveBoolean() { then(actual).isFalse(); } - @RepeatedTest(TEST_COUNT) + @Test void setWrapperBoolean() { boolean actual = SUT.giveMeBuilder(BooleanRecord.class) .set(javaGetter(BooleanRecord::wrapper), false) @@ -208,7 +207,7 @@ void setWrapperBoolean() { then(actual).isFalse(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleCanonicalConstructorRecord() { String actual = SUT.giveMeOne(CanonicalConstructorRecord.class).string(); diff --git a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/adapter/FieldExtractorJavaTypeAdapterTest.java b/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/FieldExtractorJavaTypeTest.java similarity index 89% rename from fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/adapter/FieldExtractorJavaTypeAdapterTest.java rename to fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/FieldExtractorJavaTypeTest.java index 9067cb65f7..05330c923b 100644 --- a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/adapter/FieldExtractorJavaTypeAdapterTest.java +++ b/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/FieldExtractorJavaTypeTest.java @@ -16,17 +16,16 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.tests.java17.adapter; +package com.navercorp.fixturemonkey.tests.java17; import static org.assertj.core.api.BDDAssertions.thenNoException; import java.time.LocalDate; import java.util.List; -import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; /** * Tests that FieldExtractor does not call setAccessible on Java standard library types @@ -37,11 +36,10 @@ * triggering extractFieldsRecursively(LocalDate.class, ...) which attempts * setAccessible(true) on LocalDate's private fields. */ -class FieldExtractorJavaTypeAdapterTest { +class FieldExtractorJavaTypeTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); /** @@ -51,7 +49,7 @@ class FieldExtractorJavaTypeAdapterTest { * with the LocalDate value, which triggers extractFieldsRecursively(LocalDate.class). * On Java 17+, this throws InaccessibleObjectException. */ - @RepeatedTest(10) + @Test void thenApplyWithJavaStandardTypeFieldShouldNotThrow() { thenNoException().isThrownBy(() -> SUT.giveMeBuilder(ObjectWithLocalDateAndList.class) diff --git a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/JacksonRecordTest.java b/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/JacksonRecordTest.java index 027a864a17..992196d12c 100644 --- a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/JacksonRecordTest.java +++ b/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/JacksonRecordTest.java @@ -18,11 +18,10 @@ package com.navercorp.fixturemonkey.tests.java17; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; import static org.assertj.core.api.BDDAssertions.then; import static org.assertj.core.api.BDDAssertions.thenNoException; -import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.jackson.plugin.JacksonPlugin; @@ -36,14 +35,14 @@ class JacksonRecordTest { .plugin(new JacksonPlugin()) .build(); - @RepeatedTest(TEST_COUNT) + @Test void sampleJavaType() { JavaTypeRecord actual = SUT.giveMeOne(JavaTypeRecord.class); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedJavaType() { JavaTypeRecord actual = SUT.giveMeBuilder(JavaTypeRecord.class) .fixed() @@ -52,14 +51,14 @@ void fixedJavaType() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleDateTime() { DateTimeRecord actual = SUT.giveMeOne(DateTimeRecord.class); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedDateTime() { DateTimeRecord actual = SUT.giveMeBuilder(DateTimeRecord.class) .fixed() @@ -68,14 +67,14 @@ void fixedDateTime() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleContainer() { ContainerRecord actual = SUT.giveMeOne(ContainerRecord.class); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedContainer() { ContainerRecord actual = SUT.giveMeBuilder(ContainerRecord.class) .fixed() @@ -84,7 +83,7 @@ void fixedContainer() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleEnum() { thenNoException().isThrownBy(() -> SUT.giveMeOne(EnumClass.class)); } diff --git a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/MultiLevelSealedClassTest.java b/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/MultiLevelSealedClassTest.java index a8cfb42034..23504a1456 100644 --- a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/MultiLevelSealedClassTest.java +++ b/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/MultiLevelSealedClassTest.java @@ -18,10 +18,9 @@ package com.navercorp.fixturemonkey.tests.java17; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; import static org.assertj.core.api.BDDAssertions.then; -import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; @@ -37,7 +36,7 @@ class MultiLevelSealedClassTest { .defaultNotNull(true) .build(); - @RepeatedTest(TEST_COUNT) + @Test void sampleSealedClass() { // when BaseSealedClass actual = SUT.giveMeOne(BaseSealedClass.class); @@ -45,7 +44,7 @@ void sampleSealedClass() { then(actual).isInstanceOf(SealedClassImpl.class); } - @RepeatedTest(TEST_COUNT) + @Test void sampleSealedInterface() { // when BaseSealedInterface actual = SUT.giveMeOne(BaseSealedInterface.class); @@ -53,7 +52,7 @@ void sampleSealedInterface() { then(actual).isInstanceOf(BaseSealedInterface.class); } - @RepeatedTest(TEST_COUNT) + @Test void sampleSealedClassProperty() { // when BaseSealedClassProperty actual = SUT.giveMeOne(BaseSealedClassProperty.class); @@ -62,7 +61,7 @@ void sampleSealedClassProperty() { then(actual.sealedClass()).isInstanceOf(SealedClassImpl.class); } - @RepeatedTest(TEST_COUNT) + @Test void fixedSealedClassProperty() { // when BaseSealedClassProperty actual = SUT.giveMeBuilder(BaseSealedClassProperty.class) diff --git a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/SealedClassTest.java b/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/SealedClassTest.java index c7f095ff98..495c52f563 100644 --- a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/SealedClassTest.java +++ b/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/SealedClassTest.java @@ -18,15 +18,15 @@ package com.navercorp.fixturemonkey.tests.java17; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; import static org.assertj.core.api.BDDAssertions.then; import static org.assertj.core.api.BDDAssertions.thenNoException; -import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; import com.navercorp.fixturemonkey.tests.java17.RecordTestSpecs.EnumClass; +import com.navercorp.fixturemonkey.tests.java17.SealedClassTestSpecs.GenericSealedShapeContainer; import com.navercorp.fixturemonkey.tests.java17.SealedClassTestSpecs.SealedClass; import com.navercorp.fixturemonkey.tests.java17.SealedClassTestSpecs.SealedClassImpl; import com.navercorp.fixturemonkey.tests.java17.SealedClassTestSpecs.SealedClassProperty; @@ -34,12 +34,13 @@ import com.navercorp.fixturemonkey.tests.java17.SealedClassTestSpecs.SealedInterfaceImpl; class SealedClassTest { + private static final FixtureMonkey SUT = FixtureMonkey.builder() .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) .defaultNotNull(true) .build(); - @RepeatedTest(TEST_COUNT) + @Test void sampleSealedClass() { // when SealedClass actual = SUT.giveMeOne(SealedClass.class); @@ -47,7 +48,7 @@ void sampleSealedClass() { then(actual).isInstanceOf(SealedClassImpl.class); } - @RepeatedTest(TEST_COUNT) + @Test void sampleSealedInterface() { // when SealedInterface actual = SUT.giveMeOne(SealedInterface.class); @@ -55,7 +56,7 @@ void sampleSealedInterface() { then(actual).isInstanceOf(SealedInterfaceImpl.class); } - @RepeatedTest(TEST_COUNT) + @Test void sampleSealedClassProperty() { // when SealedClassProperty actual = SUT.giveMeOne(SealedClassProperty.class); @@ -64,19 +65,30 @@ void sampleSealedClassProperty() { then(actual.sealedClass()).isInstanceOf(SealedClassImpl.class); } - @RepeatedTest(TEST_COUNT) + @Test void fixedSealedClassProperty() { // when - SealedClassProperty actual = SUT.giveMeBuilder(SealedClassProperty.class) - .fixed() - .sample(); + SealedClassProperty actual = SUT.giveMeBuilder(SealedClassProperty.class).fixed().sample(); then(actual.sealedInterface()).isInstanceOf(SealedInterfaceImpl.class); then(actual.sealedClass()).isInstanceOf(SealedClassImpl.class); } - @RepeatedTest(TEST_COUNT) + @Test void sampleEnum() { thenNoException().isThrownBy(() -> SUT.giveMeOne(EnumClass.class)); } + + @Test + void sampleGenericSealedInterface() { + // when + GenericSealedShapeContainer actual = SUT.giveMeOne(GenericSealedShapeContainer.class); + + // then + then(actual).isNotNull(); + then(actual.stringShape()).isNotNull(); + then(actual.stringShape().getLabel()).isInstanceOf(String.class); + then(actual.intShape()).isNotNull(); + then(actual.intShape().getLabel()).isInstanceOf(Integer.class); + } } diff --git a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/adapter/ConstructorPropertiesRecordAdapterTest.java b/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/adapter/ConstructorPropertiesRecordAdapterTest.java deleted file mode 100644 index af87c0e539..0000000000 --- a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/adapter/ConstructorPropertiesRecordAdapterTest.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.java17.adapter; - -import static com.navercorp.fixturemonkey.api.experimental.JavaGetterMethodPropertySelector.javaGetter; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; -import static org.assertj.core.api.BDDAssertions.then; - -import org.junit.jupiter.api.RepeatedTest; - -import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; -import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; -import com.navercorp.fixturemonkey.tests.java17.RecordTestSpecs.BooleanRecord; -import com.navercorp.fixturemonkey.tests.java17.RecordTestSpecs.CanonicalConstructorRecord; -import com.navercorp.fixturemonkey.tests.java17.RecordTestSpecs.CompactConstructorRecord; -import com.navercorp.fixturemonkey.tests.java17.RecordTestSpecs.ComplexContainerRecord; -import com.navercorp.fixturemonkey.tests.java17.RecordTestSpecs.ContainerRecord; -import com.navercorp.fixturemonkey.tests.java17.RecordTestSpecs.DateTimeRecord; -import com.navercorp.fixturemonkey.tests.java17.RecordTestSpecs.IsPrefixBooleanRecord; -import com.navercorp.fixturemonkey.tests.java17.RecordTestSpecs.JavaTypeRecord; -import com.navercorp.fixturemonkey.tests.java17.RecordTestSpecs.NoArgsConstructorRecord; -import com.navercorp.fixturemonkey.tests.java17.RecordTestSpecs.TwoConstructorsRecord; - -class ConstructorPropertiesRecordAdapterTest { - - private static final FixtureMonkey SUT = FixtureMonkey.builder() - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - @RepeatedTest(TEST_COUNT) - void sampleJavaType() { - JavaTypeRecord actual = SUT.giveMeOne(JavaTypeRecord.class); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedJavaType() { - JavaTypeRecord actual = SUT.giveMeBuilder(JavaTypeRecord.class).fixed().sample(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleDateTime() { - DateTimeRecord actual = SUT.giveMeOne(DateTimeRecord.class); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedDateTime() { - DateTimeRecord actual = SUT.giveMeBuilder(DateTimeRecord.class).fixed().sample(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleContainer() { - ContainerRecord actual = SUT.giveMeOne(ContainerRecord.class); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedContainer() { - ContainerRecord actual = SUT.giveMeBuilder(ContainerRecord.class).fixed().sample(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleInterfaceContainer() { - ComplexContainerRecord actual = SUT.giveMeOne(ComplexContainerRecord.class); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedInterfaceContainer() { - ComplexContainerRecord actual = SUT.giveMeBuilder(ComplexContainerRecord.class).fixed().sample(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleTwoConstructorsRecord() { - String actual = SUT.giveMeBuilder(TwoConstructorsRecord.class).setNotNull("string").sample().string(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void recordShouldUseCanonicalConstructor() { - String expected = "expected"; - - String actual = SUT.giveMeBuilder(TwoConstructorsRecord.class).set("string", expected).sample().string(); - - then(actual).isEqualTo(expected); - } - - @RepeatedTest(TEST_COUNT) - void recordUseCompactConstructor() { - String expected = "expected"; - - String actual = SUT.giveMeBuilder(CompactConstructorRecord.class).set("string", expected).sample().string(); - - then(actual).isEqualTo("12345"); - } - - @RepeatedTest(TEST_COUNT) - void fixedTwoConstructorsRecord() { - String actual = SUT.giveMeBuilder(TwoConstructorsRecord.class).setNotNull("string").fixed().sample().string(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleNoArgsConstructorRecord() { - NoArgsConstructorRecord actual = SUT.giveMeOne(NoArgsConstructorRecord.class); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedNoArgsConstructorRecord() { - NoArgsConstructorRecord actual = SUT.giveMeBuilder(NoArgsConstructorRecord.class).fixed().sample(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void setIsPrefixPrimitiveBoolean() { - boolean actual = SUT.giveMeBuilder(IsPrefixBooleanRecord.class) - .set(javaGetter(IsPrefixBooleanRecord::isPrimitive), false) - .sample() - .isPrimitive(); - - then(actual).isFalse(); - } - - @RepeatedTest(TEST_COUNT) - void setIsPrefixWrapperBoolean() { - boolean actual = SUT.giveMeBuilder(IsPrefixBooleanRecord.class) - .set(javaGetter(IsPrefixBooleanRecord::isWrapper), false) - .sample() - .isWrapper(); - - then(actual).isFalse(); - } - - @RepeatedTest(TEST_COUNT) - void setPrimitiveBoolean() { - boolean actual = SUT.giveMeBuilder(BooleanRecord.class) - .set(javaGetter(BooleanRecord::primitive), false) - .sample() - .primitive(); - - then(actual).isFalse(); - } - - @RepeatedTest(TEST_COUNT) - void setWrapperBoolean() { - boolean actual = SUT.giveMeBuilder(BooleanRecord.class) - .set(javaGetter(BooleanRecord::wrapper), false) - .sample() - .wrapper(); - - then(actual).isFalse(); - } - - @RepeatedTest(TEST_COUNT) - void sampleCanonicalConstructorRecord() { - String actual = SUT.giveMeOne(CanonicalConstructorRecord.class).string(); - - then(actual).isNotNull(); - } -} diff --git a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/adapter/InterfaceDefaultMethodAdapterTest.java b/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/adapter/InterfaceDefaultMethodAdapterTest.java deleted file mode 100644 index 6fddc08b76..0000000000 --- a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/adapter/InterfaceDefaultMethodAdapterTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.java17.adapter; - -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; -import static org.assertj.core.api.BDDAssertions.then; - -import org.junit.jupiter.api.RepeatedTest; - -import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; -import com.navercorp.fixturemonkey.api.plugin.InterfacePlugin; - -class InterfaceDefaultMethodAdapterTest { - - private static final FixtureMonkey SUT = FixtureMonkey.builder() - .plugin(new InterfacePlugin()) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - @RepeatedTest(TEST_COUNT) - void defaultMethod() { - String actual = SUT.giveMeOne(DefaultMethodInterface.class).defaultMethod(); - - then(actual).isEqualTo("test"); - } - - public interface DefaultMethodInterface { - default String defaultMethod() { - return "test"; - } - } -} diff --git a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/adapter/JacksonRecordAdapterTest.java b/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/adapter/JacksonRecordAdapterTest.java deleted file mode 100644 index 3b9b5ae134..0000000000 --- a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/adapter/JacksonRecordAdapterTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.java17.adapter; - -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; -import static org.assertj.core.api.BDDAssertions.then; -import static org.assertj.core.api.BDDAssertions.thenNoException; - -import org.junit.jupiter.api.RepeatedTest; - -import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; -import com.navercorp.fixturemonkey.jackson.plugin.JacksonPlugin; -import com.navercorp.fixturemonkey.tests.java17.RecordTestSpecs.ContainerRecord; -import com.navercorp.fixturemonkey.tests.java17.RecordTestSpecs.DateTimeRecord; -import com.navercorp.fixturemonkey.tests.java17.RecordTestSpecs.EnumClass; -import com.navercorp.fixturemonkey.tests.java17.RecordTestSpecs.JavaTypeRecord; - -class JacksonRecordAdapterTest { - - private static final FixtureMonkey SUT = FixtureMonkey.builder() - .plugin(new JacksonPlugin()) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - @RepeatedTest(TEST_COUNT) - void sampleJavaType() { - JavaTypeRecord actual = SUT.giveMeOne(JavaTypeRecord.class); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedJavaType() { - JavaTypeRecord actual = SUT.giveMeBuilder(JavaTypeRecord.class).fixed().sample(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleDateTime() { - DateTimeRecord actual = SUT.giveMeOne(DateTimeRecord.class); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedDateTime() { - DateTimeRecord actual = SUT.giveMeBuilder(DateTimeRecord.class).fixed().sample(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleContainer() { - ContainerRecord actual = SUT.giveMeOne(ContainerRecord.class); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedContainer() { - ContainerRecord actual = SUT.giveMeBuilder(ContainerRecord.class).fixed().sample(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleEnum() { - thenNoException().isThrownBy(() -> SUT.giveMeOne(EnumClass.class)); - } -} diff --git a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/adapter/MultiLevelSealedClassAdapterTest.java b/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/adapter/MultiLevelSealedClassAdapterTest.java deleted file mode 100644 index 2082db5017..0000000000 --- a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/adapter/MultiLevelSealedClassAdapterTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.java17.adapter; - -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; -import static org.assertj.core.api.BDDAssertions.then; - -import org.junit.jupiter.api.RepeatedTest; - -import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; -import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; -import com.navercorp.fixturemonkey.tests.java17.SealedClassTestSpecs.BaseSealedClass; -import com.navercorp.fixturemonkey.tests.java17.SealedClassTestSpecs.BaseSealedClassProperty; -import com.navercorp.fixturemonkey.tests.java17.SealedClassTestSpecs.BaseSealedInterface; -import com.navercorp.fixturemonkey.tests.java17.SealedClassTestSpecs.SealedClassImpl; -import com.navercorp.fixturemonkey.tests.java17.SealedClassTestSpecs.SealedInterfaceImpl; - -class MultiLevelSealedClassAdapterTest { - - private static final FixtureMonkey SUT = FixtureMonkey.builder() - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - @RepeatedTest(TEST_COUNT) - void sampleSealedClass() { - // when - BaseSealedClass actual = SUT.giveMeOne(BaseSealedClass.class); - - then(actual).isInstanceOf(SealedClassImpl.class); - } - - @RepeatedTest(TEST_COUNT) - void sampleSealedInterface() { - // when - BaseSealedInterface actual = SUT.giveMeOne(BaseSealedInterface.class); - - then(actual).isInstanceOf(BaseSealedInterface.class); - } - - @RepeatedTest(TEST_COUNT) - void sampleSealedClassProperty() { - // when - BaseSealedClassProperty actual = SUT.giveMeOne(BaseSealedClassProperty.class); - - then(actual.sealedInterface()).isInstanceOf(SealedInterfaceImpl.class); - then(actual.sealedClass()).isInstanceOf(SealedClassImpl.class); - } - - @RepeatedTest(TEST_COUNT) - void fixedSealedClassProperty() { - // when - BaseSealedClassProperty actual = SUT.giveMeBuilder(BaseSealedClassProperty.class).fixed().sample(); - - then(actual.sealedInterface()).isInstanceOf(SealedInterfaceImpl.class); - then(actual.sealedClass()).isInstanceOf(SealedClassImpl.class); - } -} diff --git a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/adapter/SealedClassAdapterTest.java b/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/adapter/SealedClassAdapterTest.java deleted file mode 100644 index 929d04275d..0000000000 --- a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/adapter/SealedClassAdapterTest.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.java17.adapter; - -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; -import static org.assertj.core.api.BDDAssertions.then; -import static org.assertj.core.api.BDDAssertions.thenNoException; - -import org.junit.jupiter.api.RepeatedTest; - -import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; -import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; -import com.navercorp.fixturemonkey.tests.java17.RecordTestSpecs.EnumClass; -import com.navercorp.fixturemonkey.tests.java17.SealedClassTestSpecs.GenericSealedShapeContainer; -import com.navercorp.fixturemonkey.tests.java17.SealedClassTestSpecs.SealedClass; -import com.navercorp.fixturemonkey.tests.java17.SealedClassTestSpecs.SealedClassImpl; -import com.navercorp.fixturemonkey.tests.java17.SealedClassTestSpecs.SealedClassProperty; -import com.navercorp.fixturemonkey.tests.java17.SealedClassTestSpecs.SealedInterface; -import com.navercorp.fixturemonkey.tests.java17.SealedClassTestSpecs.SealedInterfaceImpl; - -class SealedClassAdapterTest { - - private static final FixtureMonkey SUT = FixtureMonkey.builder() - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - @RepeatedTest(TEST_COUNT) - void sampleSealedClass() { - // when - SealedClass actual = SUT.giveMeOne(SealedClass.class); - - then(actual).isInstanceOf(SealedClassImpl.class); - } - - @RepeatedTest(TEST_COUNT) - void sampleSealedInterface() { - // when - SealedInterface actual = SUT.giveMeOne(SealedInterface.class); - - then(actual).isInstanceOf(SealedInterfaceImpl.class); - } - - @RepeatedTest(TEST_COUNT) - void sampleSealedClassProperty() { - // when - SealedClassProperty actual = SUT.giveMeOne(SealedClassProperty.class); - - then(actual.sealedInterface()).isInstanceOf(SealedInterfaceImpl.class); - then(actual.sealedClass()).isInstanceOf(SealedClassImpl.class); - } - - @RepeatedTest(TEST_COUNT) - void fixedSealedClassProperty() { - // when - SealedClassProperty actual = SUT.giveMeBuilder(SealedClassProperty.class).fixed().sample(); - - then(actual.sealedInterface()).isInstanceOf(SealedInterfaceImpl.class); - then(actual.sealedClass()).isInstanceOf(SealedClassImpl.class); - } - - @RepeatedTest(TEST_COUNT) - void sampleEnum() { - thenNoException().isThrownBy(() -> SUT.giveMeOne(EnumClass.class)); - } - - @RepeatedTest(TEST_COUNT) - void sampleGenericSealedInterface() { - // when - GenericSealedShapeContainer actual = SUT.giveMeOne(GenericSealedShapeContainer.class); - - // then - then(actual).isNotNull(); - then(actual.stringShape()).isNotNull(); - then(actual.stringShape().getLabel()).isInstanceOf(String.class); - then(actual.intShape()).isNotNull(); - then(actual.intShape().getLabel()).isInstanceOf(Integer.class); - } -} diff --git a/fixture-monkey-tests/java-concurrent-tests/src/test/java/com/navercorp/fixturemonkey/tests/concurrent/ConcurrentTest.java b/fixture-monkey-tests/java-concurrent-tests/src/test/java/com/navercorp/fixturemonkey/tests/concurrent/ConcurrentTest.java index b8d0887057..e35487984d 100644 --- a/fixture-monkey-tests/java-concurrent-tests/src/test/java/com/navercorp/fixturemonkey/tests/concurrent/ConcurrentTest.java +++ b/fixture-monkey-tests/java-concurrent-tests/src/test/java/com/navercorp/fixturemonkey/tests/concurrent/ConcurrentTest.java @@ -1,12 +1,11 @@ package com.navercorp.fixturemonkey.tests.concurrent; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; import static org.assertj.core.api.BDDAssertions.then; import java.util.Map; import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; @@ -17,21 +16,21 @@ class ConcurrentTest { .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) .build(); - @RepeatedTest(TEST_COUNT) + @Test void test1() { JavaObject actual = SUT.giveMeOne(JavaObject.class); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void test2() { JavaObject actual = SUT.giveMeOne(JavaObject.class); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void test3() { JavaObject actual = SUT.giveMeOne(JavaObject.class); diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/AnnotationTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/AnnotationTest.java index 214afa55a3..184a97db70 100644 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/AnnotationTest.java +++ b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/AnnotationTest.java @@ -18,10 +18,9 @@ package com.navercorp.fixturemonkey.tests.java; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; import static org.assertj.core.api.BDDAssertions.then; -import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; @@ -35,7 +34,7 @@ class AnnotationTest { .plugin(new JavaxValidationPlugin()) .build(); - @RepeatedTest(TEST_COUNT) + @Test void sampleCustomAnnotation() { String actual = SUT.giveMeOne(CustomAnnotationStringObject.class) .getNullOrLessThan5String(); @@ -43,7 +42,7 @@ void sampleCustomAnnotation() { then(actual).matches(it -> it == null || it.length() < 5); } - @RepeatedTest(TEST_COUNT) + @Test void sampleNotValidAnnotation() { String actual = SUT.giveMeBuilder(StringNotNullAnnotationObject.class) .set("value", null) @@ -54,7 +53,7 @@ void sampleNotValidAnnotation() { then(actual).isNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleNotValidAnnotationWithCopy() { String actual = SUT.giveMeBuilder(StringNotNullAnnotationObject.class) .set("value", null) diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/AnonymousInstanceTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/AnonymousInstanceTest.java index 34be924450..39adaa3ad6 100644 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/AnonymousInstanceTest.java +++ b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/AnonymousInstanceTest.java @@ -18,14 +18,12 @@ package com.navercorp.fixturemonkey.tests.java; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; import static org.assertj.core.api.BDDAssertions.then; import java.util.List; import java.util.Set; import java.util.stream.Collectors; -import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; @@ -53,7 +51,7 @@ class AnonymousInstanceTest { ) .build(); - @RepeatedTest(TEST_COUNT) + @Test void sampleInterface() { Interface actual = SUT.giveMeOne(Interface.class); @@ -62,7 +60,7 @@ void sampleInterface() { then(actual.integer()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void objectBaseMethods() { Interface actual = SUT.giveMeOne(Interface.class); @@ -71,7 +69,7 @@ void objectBaseMethods() { then(actual.toString()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void equalsOnSimilarInterface() { Interface one = SUT.giveMeBuilder(Interface.class) .set("string", "test") @@ -85,7 +83,7 @@ void equalsOnSimilarInterface() { then(one).isNotEqualTo(another); } - @RepeatedTest(TEST_COUNT) + @Test void setInterface() { String expected = "test"; @@ -97,21 +95,21 @@ void setInterface() { then(actual).isEqualTo(expected); } - @RepeatedTest(TEST_COUNT) + @Test void sampleInterfaceWithParamReturnsNullProperties() { InterfaceWithParams actual = SUT.giveMeOne(InterfaceWithParams.class); then(actual).isNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleInterfaceWithConstant() { String actual = SUT.giveMeOne(InterfaceWithConstant.class).value; then(actual).isEqualTo("constant"); } - @RepeatedTest(TEST_COUNT) + @Test void setConstantNotWorks() { String actual = SUT.giveMeBuilder(InterfaceWithConstant.class) .set("value", "changed") @@ -121,7 +119,7 @@ void setConstantNotWorks() { then(actual).isEqualTo("constant"); } - @RepeatedTest(TEST_COUNT) + @Test void sampleContainerInterface() { ContainerInterface actual = SUT.giveMeOne(ContainerInterface.class); @@ -129,7 +127,7 @@ void sampleContainerInterface() { then(actual.map()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void setContainerInterfaceList() { List actual = SUT.giveMeBuilder(ContainerInterface.class) .size("list", 3) @@ -141,7 +139,7 @@ void setContainerInterfaceList() { then(actual.get(0)).isEqualTo("test"); } - @RepeatedTest(TEST_COUNT) + @Test void sampleAnnotatedInterface() { String actual = SUT.giveMeOne(AnnotatedInterface.class) .string(); @@ -149,7 +147,7 @@ void sampleAnnotatedInterface() { then(actual).isNotEmpty(); } - @RepeatedTest(TEST_COUNT) + @Test void setPropertyName() { String expected = "test"; @@ -161,7 +159,7 @@ void setPropertyName() { then(actual).isEqualTo(expected); } - @RepeatedTest(TEST_COUNT) + @Test void setMethodNameNotWorks() { String notExpected = "test"; @@ -173,7 +171,7 @@ void setMethodNameNotWorks() { then(actual).isNotEqualTo(notExpected); } - @RepeatedTest(TEST_COUNT) + @Test void sampleInheritedInterface() { InheritedInterface actual = SUT.giveMeOne(InheritedInterface.class); @@ -182,7 +180,7 @@ void sampleInheritedInterface() { then(actual.integer()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void setInheritedInterface() { String expected = "test"; @@ -194,14 +192,14 @@ void setInheritedInterface() { then(actual).isEqualTo(expected); } - @RepeatedTest(TEST_COUNT) + @Test void sampleInheritedInterfaceWithSameNameMethod() { String actual = SUT.giveMeOne(InheritedInterfaceWithSameNameMethod.class).string(); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void setInheritedInterfaceWithSameNameMethod() { String expected = "test"; @@ -213,7 +211,7 @@ void setInheritedInterfaceWithSameNameMethod() { then(actual).isEqualTo(expected); } - @RepeatedTest(TEST_COUNT) + @Test void sampleInheritedTwoInterface() { InheritedTwoInterface actual = SUT.giveMeOne(InheritedTwoInterface.class); @@ -223,14 +221,14 @@ void sampleInheritedTwoInterface() { then(actual.map()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleNestedInheritedInterface() { String actual = SUT.giveMeOne(NestedInheritedInterface.class).string(); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void setNestedInheritedInterface() { String expected = "test"; diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/BeanArbitraryIntrospectorTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/BeanArbitraryIntrospectorTest.java index 44eb289e63..7e39e6f84a 100644 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/BeanArbitraryIntrospectorTest.java +++ b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/BeanArbitraryIntrospectorTest.java @@ -1,9 +1,8 @@ package com.navercorp.fixturemonkey.tests.java; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; import static org.assertj.core.api.BDDAssertions.then; -import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.introspector.BeanArbitraryIntrospector; @@ -18,28 +17,28 @@ class BeanArbitraryIntrospectorTest { .defaultNotNull(true) .build(); - @RepeatedTest(TEST_COUNT) + @Test void sampleJavaType() { JavaTypeObject actual = SUT.giveMeOne(JavaTypeObject.class); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleDateTime() { DateTimeObject actual = SUT.giveMeOne(DateTimeObject.class); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleContainer() { ContainerObject actual = SUT.giveMeOne(ContainerObject.class); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void setPropertyPostCondition() { String actual = SUT.giveMeBuilder(JavaTypeObject.class) .setPostCondition("string", String.class, str -> str.length() > 5) @@ -49,7 +48,7 @@ void setPropertyPostCondition() { then(actual).hasSizeGreaterThan(5); } - @RepeatedTest(TEST_COUNT) + @Test void objectGenerationShouldWorkWithoutSetter() { NoSetterSpecs.StringObject actual = SUT.giveMeOne(NoSetterSpecs.StringObject.class); diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/BuilderArbitraryIntrospectorAdapterTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/BuilderArbitraryIntrospectorTest.java similarity index 91% rename from fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/BuilderArbitraryIntrospectorAdapterTest.java rename to fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/BuilderArbitraryIntrospectorTest.java index a9f4677a47..6505c81c3c 100644 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/BuilderArbitraryIntrospectorAdapterTest.java +++ b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/BuilderArbitraryIntrospectorTest.java @@ -16,21 +16,18 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.tests.java.adapter; +package com.navercorp.fixturemonkey.tests.java; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; import static org.assertj.core.api.BDDAssertions.then; import java.util.Arrays; import java.util.Map; -import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import net.jqwik.api.Arbitraries; import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; import com.navercorp.fixturemonkey.api.introspector.BuilderArbitraryIntrospector; import com.navercorp.fixturemonkey.api.introspector.FailoverIntrospector; import com.navercorp.fixturemonkey.api.introspector.FieldReflectionArbitraryIntrospector; @@ -42,36 +39,35 @@ import com.navercorp.fixturemonkey.tests.java.specs.MixedIntrospectorsSpecs.BuilderWithMutableFieldObject; import com.navercorp.fixturemonkey.tests.java.specs.MutableSpecs; -class BuilderArbitraryIntrospectorAdapterTest { +class BuilderArbitraryIntrospectorTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .objectIntrospector(BuilderArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @RepeatedTest(TEST_COUNT) + @Test void sampleJavaType() { JavaTypeObject actual = SUT.giveMeOne(JavaTypeObject.class); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleDateTime() { DateTimeObject actual = SUT.giveMeOne(DateTimeObject.class); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleContainer() { ContainerObject actual = SUT.giveMeOne(ContainerObject.class); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleNestedObject() { RootJavaTypeObject actual = SUT.giveMeOne(RootJavaTypeObject.class); @@ -79,7 +75,7 @@ void sampleNestedObject() { then(actual.getValue()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void setString() { // given String expected = "test"; @@ -91,7 +87,7 @@ void setString() { then(actual).isEqualTo(expected); } - @RepeatedTest(TEST_COUNT) + @Test void setPostCondition() { String actual = SUT.giveMeBuilder(JavaTypeObject.class) .setPostCondition("string", String.class, str -> str.length() > 5) @@ -101,7 +97,7 @@ void setPostCondition() { then(actual).hasSizeGreaterThan(5); } - @RepeatedTest(TEST_COUNT) + @Test void setContainerSize() { // when ContainerObject actual = SUT.giveMeBuilder(ContainerObject.class).size("list", 3).sample(); @@ -110,7 +106,7 @@ void setContainerSize() { then(actual.getList()).hasSize(3); } - @RepeatedTest(TEST_COUNT) + @Test void setContainerElement() { // given String expected = "fixed"; @@ -125,7 +121,7 @@ void setContainerElement() { then(actual.getList().get(0)).isEqualTo(expected); } - @RepeatedTest(TEST_COUNT) + @Test void sampleTwiceResultNotMutated() { // given JavaTypeObject first = SUT.giveMeOne(JavaTypeObject.class); @@ -138,7 +134,7 @@ void sampleTwiceResultNotMutated() { then(first.getString()).isEqualTo(firstString); } - @RepeatedTest(TEST_COUNT) + @Test void thenApply() { // when JavaTypeObject actual = SUT.giveMeBuilder(JavaTypeObject.class) @@ -149,7 +145,7 @@ void thenApply() { then(actual.getString()).isEqualTo("applied"); } - @RepeatedTest(TEST_COUNT) + @Test void setRootObject() { // given JavaTypeObject expected = SUT.giveMeOne(JavaTypeObject.class); @@ -161,7 +157,7 @@ void setRootObject() { then(actual).isEqualTo(expected); } - @RepeatedTest(TEST_COUNT) + @Test void setNestedObjectField() { // given JavaTypeObject expected = SUT.giveMeOne(JavaTypeObject.class); @@ -173,7 +169,7 @@ void setNestedObjectField() { then(actual.getValue()).isEqualTo(expected); } - @RepeatedTest(TEST_COUNT) + @Test void setNestedObjectInnerField() { // given String expected = "innerValue"; @@ -185,7 +181,7 @@ void setNestedObjectInnerField() { then(actual.getValue().getString()).isEqualTo(expected); } - @RepeatedTest(TEST_COUNT) + @Test void setContainerObjectField() { // given JavaTypeObject expected = SUT.giveMeOne(JavaTypeObject.class); @@ -200,7 +196,7 @@ void setContainerObjectField() { then(actual.getComplexList().get(0)).isEqualTo(expected); } - @RepeatedTest(TEST_COUNT) + @Test void failoverWithBuilderAndFieldReflection() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -210,7 +206,6 @@ void failoverWithBuilderAndFieldReflection() { ) ) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); // when @@ -223,7 +218,7 @@ void failoverWithBuilderAndFieldReflection() { then(actual.getMutableObject().getString()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void failoverSetMutableFieldInBuilderObject() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -233,7 +228,6 @@ void failoverSetMutableFieldInBuilderObject() { ) ) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); String expected = "mutableString"; @@ -247,7 +241,7 @@ void failoverSetMutableFieldInBuilderObject() { then(actual.getMutableObject().getString()).isEqualTo(expected); } - @RepeatedTest(TEST_COUNT) + @Test void failoverSetMutableObjectInBuilderObject() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -257,7 +251,6 @@ void failoverSetMutableObjectInBuilderObject() { ) ) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); MutableSpecs.JavaTypeObject expected = sut.giveMeOne(MutableSpecs.JavaTypeObject.class); @@ -271,7 +264,7 @@ void failoverSetMutableObjectInBuilderObject() { then(actual.getMutableObject()).isEqualTo(expected); } - @RepeatedTest(TEST_COUNT) + @Test void failoverWithMutableContainerInBuilderObject() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -281,7 +274,6 @@ void failoverWithMutableContainerInBuilderObject() { ) ) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); // when @@ -296,7 +288,7 @@ void failoverWithMutableContainerInBuilderObject() { then(actual.getMutableList().get(0).getString()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void failoverSetMutableContainerElementField() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -306,7 +298,6 @@ void failoverSetMutableContainerElementField() { ) ) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); String expected = "elementField"; @@ -321,7 +312,7 @@ void failoverSetMutableContainerElementField() { then(actual.getMutableList().get(0).getString()).isEqualTo(expected); } - @RepeatedTest(TEST_COUNT) + @Test void pushExactTypeIntrospectorForNestedField() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -331,7 +322,6 @@ void pushExactTypeIntrospectorForNestedField() { FieldReflectionArbitraryIntrospector.INSTANCE ) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); // when @@ -371,7 +361,6 @@ void complexDualRegisterWithAllOperations() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(BuilderArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) // register ContainerObject: size + set + thenApply .register(ContainerObject.class, fm -> fm diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/CombinableArbitraryTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/CombinableArbitraryTest.java index 732bcf77a3..18051be202 100644 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/CombinableArbitraryTest.java +++ b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/CombinableArbitraryTest.java @@ -1,9 +1,7 @@ package com.navercorp.fixturemonkey.tests.java; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; import static org.assertj.core.api.BDDAssertions.then; -import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary; @@ -23,77 +21,77 @@ void integerCombinableArbitraryIsJqwik() { then(actual).isInstanceOf(JqwikIntegerCombinableArbitrary.class); } - @RepeatedTest(TEST_COUNT) + @Test void integerCombinableArbitraryInjectNull() { Integer actual = CombinableArbitrary.integers().injectNull(1).combined(); then(actual).isNull(); } - @RepeatedTest(TEST_COUNT) + @Test void integerCombinableArbitraryFilter() { Integer actual = CombinableArbitrary.integers().filter(it -> it > 10000).combined(); then(actual).isGreaterThan(10000); } - @RepeatedTest(TEST_COUNT) + @Test void integerCombinableArbitraryPositive() { Integer actual = CombinableArbitrary.integers().positive().combined(); then(actual).isPositive(); } - @RepeatedTest(TEST_COUNT) + @Test void integerCombinableArbitraryNegative() { Integer actual = CombinableArbitrary.integers().negative().combined(); then(actual).isNegative(); } - @RepeatedTest(TEST_COUNT) + @Test void integerCombinableArbitraryWithRange() { Integer actual = CombinableArbitrary.integers().withRange(10, 100).combined(); then(actual).isBetween(10, 100); } - @RepeatedTest(TEST_COUNT) + @Test void integerCombinableArbitraryWithRangeAndFilter() { Integer actual = CombinableArbitrary.integers().withRange(10, 100).filter(it -> 75 <= it).combined(); then(actual).isBetween(75, 100); } - @RepeatedTest(TEST_COUNT) + @Test void integerCombinableArbitraryEven() { Integer actual = CombinableArbitrary.integers().even().combined(); then(actual).isEven(); } - @RepeatedTest(TEST_COUNT) + @Test void integerCombinableArbitraryOdd() { Integer actual = CombinableArbitrary.integers().odd().combined(); then(actual).isOdd(); } - @RepeatedTest(TEST_COUNT) + @Test void integerCombinableArbitraryLastOperationWinsWithPositiveAndNegative() { Integer actual = CombinableArbitrary.integers().positive().negative().combined(); then(actual).isNegative(); } - @RepeatedTest(TEST_COUNT) + @Test void integerCombinableArbitraryLastOperationWinsWithEvenAndOdd() { Integer actual = CombinableArbitrary.integers().even().odd().combined(); then(actual).isOdd(); } - @RepeatedTest(TEST_COUNT) + @Test void integerCombinableArbitraryLastOperationWinsWithNegativeAndRange() { Integer actual = CombinableArbitrary.integers().negative().withRange(100, 1000).combined(); @@ -107,77 +105,77 @@ void longCombinableArbitraryIsJqwik() { then(actual).isInstanceOf(JqwikLongCombinableArbitrary.class); } - @RepeatedTest(TEST_COUNT) + @Test void longCombinableArbitraryInjectNull() { Long actual = CombinableArbitrary.longs().injectNull(1).combined(); then(actual).isNull(); } - @RepeatedTest(TEST_COUNT) + @Test void longCombinableArbitraryFilter() { Long actual = CombinableArbitrary.longs().filter(it -> it > 10000L).combined(); then(actual).isGreaterThan(10000L); } - @RepeatedTest(TEST_COUNT) + @Test void longCombinableArbitraryPositive() { Long actual = CombinableArbitrary.longs().positive().combined(); then(actual).isPositive(); } - @RepeatedTest(TEST_COUNT) + @Test void longCombinableArbitraryNegative() { Long actual = CombinableArbitrary.longs().negative().combined(); then(actual).isNegative(); } - @RepeatedTest(TEST_COUNT) + @Test void longCombinableArbitraryWithRange() { Long actual = CombinableArbitrary.longs().withRange(10L, 100L).combined(); then(actual).isBetween(10L, 100L); } - @RepeatedTest(TEST_COUNT) + @Test void longCombinableArbitraryWithRangeAndFilter() { Long actual = CombinableArbitrary.longs().withRange(10L, 100L).filter(it -> 75L <= it).combined(); then(actual).isBetween(75L, 100L); } - @RepeatedTest(TEST_COUNT) + @Test void longCombinableArbitraryEven() { Long actual = CombinableArbitrary.longs().even().combined(); then(actual % 2).isEqualTo(0); } - @RepeatedTest(TEST_COUNT) + @Test void longCombinableArbitraryOdd() { Long actual = CombinableArbitrary.longs().odd().combined(); then(actual % 2 != 0).isTrue(); } - @RepeatedTest(TEST_COUNT) + @Test void longCombinableArbitraryLastOperationWinsWithPositiveAndNegative() { Long actual = CombinableArbitrary.longs().positive().negative().combined(); then(actual).isNegative(); } - @RepeatedTest(TEST_COUNT) + @Test void longCombinableArbitraryLastOperationWinsWithEvenAndOdd() { Long actual = CombinableArbitrary.longs().even().odd().combined(); then(actual % 2 != 0).isTrue(); } - @RepeatedTest(TEST_COUNT) + @Test void longCombinableArbitraryLastOperationWinsWithNegativeAndRange() { Long actual = CombinableArbitrary.longs().negative().withRange(100L, 1000L).combined(); @@ -191,70 +189,70 @@ void byteCombinableArbitraryIsJqwik() { then(actual).isInstanceOf(JqwikByteCombinableArbitrary.class); } - @RepeatedTest(TEST_COUNT) + @Test void byteCombinableArbitraryInjectNull() { Byte actual = CombinableArbitrary.bytes().injectNull(1).combined(); then(actual).isNull(); } - @RepeatedTest(TEST_COUNT) + @Test void byteCombinableArbitraryFilter() { Byte actual = CombinableArbitrary.bytes().filter(it -> it > 50).combined(); then(actual).isGreaterThan((byte)50); } - @RepeatedTest(TEST_COUNT) + @Test void byteCombinableArbitraryPositive() { Byte actual = CombinableArbitrary.bytes().positive().combined(); then(actual).isPositive(); } - @RepeatedTest(TEST_COUNT) + @Test void byteCombinableArbitraryNegative() { Byte actual = CombinableArbitrary.bytes().negative().combined(); then(actual).isNegative(); } - @RepeatedTest(TEST_COUNT) + @Test void byteCombinableArbitraryWithRange() { Byte actual = CombinableArbitrary.bytes().withRange((byte)10, (byte)100).combined(); then(actual).isBetween((byte)10, (byte)100); } - @RepeatedTest(TEST_COUNT) + @Test void byteCombinableArbitraryWithRangeAndFilter() { Byte actual = CombinableArbitrary.bytes().withRange((byte)10, (byte)100).filter(it -> 75 <= it).combined(); then(actual).isBetween((byte)75, (byte)100); } - @RepeatedTest(TEST_COUNT) + @Test void byteCombinableArbitraryEven() { Byte actual = CombinableArbitrary.bytes().even().combined(); then(actual % 2).isEqualTo(0); } - @RepeatedTest(TEST_COUNT) + @Test void byteCombinableArbitraryOdd() { Byte actual = CombinableArbitrary.bytes().odd().combined(); then(actual % 2 != 0).isTrue(); } - @RepeatedTest(TEST_COUNT) + @Test void byteCombinableArbitraryAscii() { Byte actual = CombinableArbitrary.bytes().ascii().combined(); then(actual).isBetween((byte)0, (byte)127); } - @RepeatedTest(TEST_COUNT) + @Test void byteCombinableArbitraryLastOperationWinsWithPositiveAndNegative() { // positive().negative() => negative() Byte actual = CombinableArbitrary.bytes().positive().negative().combined(); @@ -262,7 +260,7 @@ void byteCombinableArbitraryLastOperationWinsWithPositiveAndNegative() { then(actual).isNegative(); } - @RepeatedTest(TEST_COUNT) + @Test void byteCombinableArbitraryLastOperationWinsWithEvenAndOdd() { // even().odd() => odd() Byte actual = CombinableArbitrary.bytes().even().odd().combined(); @@ -270,7 +268,7 @@ void byteCombinableArbitraryLastOperationWinsWithEvenAndOdd() { then(actual % 2 != 0).isTrue(); } - @RepeatedTest(TEST_COUNT) + @Test void byteCombinableArbitraryLastOperationWinsWithNegativeAndRange() { // negative().withRange() => withRange() Byte actual = CombinableArbitrary.bytes().negative().withRange((byte)100, (byte)127).combined(); @@ -278,7 +276,7 @@ void byteCombinableArbitraryLastOperationWinsWithNegativeAndRange() { then(actual).isBetween((byte)100, (byte)127); } - @RepeatedTest(TEST_COUNT) + @Test void byteCombinableArbitraryLastOperationWinsWithAsciiAndPositive() { // ascii().positive() => positive() Byte actual = CombinableArbitrary.bytes().ascii().positive().combined(); @@ -286,7 +284,7 @@ void byteCombinableArbitraryLastOperationWinsWithAsciiAndPositive() { then(actual).isPositive(); } - @RepeatedTest(TEST_COUNT) + @Test void byteCombinableArbitraryLastOperationWinsWithPositiveAndAscii() { // positive().ascii() => ascii() Byte actual = CombinableArbitrary.bytes().positive().ascii().combined(); @@ -294,7 +292,7 @@ void byteCombinableArbitraryLastOperationWinsWithPositiveAndAscii() { then(actual).isBetween((byte)0, (byte)127); } - @RepeatedTest(TEST_COUNT) + @Test void byteCombinableArbitraryLastOperationWinsWithAsciiAndEven() { // ascii().even() => even() Byte actual = CombinableArbitrary.bytes().ascii().even().combined(); @@ -302,7 +300,7 @@ void byteCombinableArbitraryLastOperationWinsWithAsciiAndEven() { then(actual % 2).isEqualTo(0); } - @RepeatedTest(TEST_COUNT) + @Test void byteCombinableArbitraryLastOperationWinsWithEvenAndAscii() { // even().ascii() => ascii() Byte actual = CombinableArbitrary.bytes().even().ascii().combined(); @@ -310,7 +308,7 @@ void byteCombinableArbitraryLastOperationWinsWithEvenAndAscii() { then(actual).isBetween((byte)0, (byte)127); } - @RepeatedTest(TEST_COUNT) + @Test void byteCombinableArbitraryLastOperationWinsWithAsciiAndNegative() { // ascii().negative() => negative() Byte actual = CombinableArbitrary.bytes().ascii().negative().combined(); @@ -328,84 +326,84 @@ void characterCombinableArbitraryIsJqwik() { then(actual).isInstanceOf(JqwikCharacterCombinableArbitrary.class); } - @RepeatedTest(TEST_COUNT) + @Test void characterCombinableArbitraryInjectNull() { Character actual = CombinableArbitrary.chars().injectNull(1).combined(); then(actual).isNull(); } - @RepeatedTest(TEST_COUNT) + @Test void characterCombinableArbitraryFilter() { Character actual = CombinableArbitrary.chars().filter(it -> it > 'A').combined(); then(actual).isGreaterThan('A'); } - @RepeatedTest(TEST_COUNT) + @Test void characterCombinableArbitraryWithRange() { Character actual = CombinableArbitrary.chars().withRange('A', 'Z').combined(); then(actual).isBetween('A', 'Z'); } - @RepeatedTest(TEST_COUNT) + @Test void characterCombinableArbitraryAlpha() { Character actual = CombinableArbitrary.chars().alphabetic().combined(); then(Character.isLetter(actual)).isTrue(); } - @RepeatedTest(TEST_COUNT) + @Test void characterCombinableArbitraryNumeric() { Character actual = CombinableArbitrary.chars().numeric().combined(); then(Character.isDigit(actual)).isTrue(); } - @RepeatedTest(TEST_COUNT) + @Test void characterCombinableArbitraryAlphaNumeric() { Character actual = CombinableArbitrary.chars().alphaNumeric().combined(); then(Character.isLetterOrDigit(actual)).isTrue(); } - @RepeatedTest(TEST_COUNT) + @Test void characterCombinableArbitraryAscii() { Character actual = CombinableArbitrary.chars().ascii().combined(); then((int)actual).isLessThanOrEqualTo(127); } - @RepeatedTest(TEST_COUNT) + @Test void characterCombinableArbitraryUppercase() { Character actual = CombinableArbitrary.chars().uppercase().combined(); then(Character.isUpperCase(actual)).isTrue(); } - @RepeatedTest(TEST_COUNT) + @Test void characterCombinableArbitraryLowercase() { Character actual = CombinableArbitrary.chars().lowercase().combined(); then(Character.isLowerCase(actual)).isTrue(); } - @RepeatedTest(TEST_COUNT) + @Test void characterCombinableArbitraryKorean() { Character actual = CombinableArbitrary.chars().korean().combined(); then(actual).isBetween('가', '힣'); } - @RepeatedTest(TEST_COUNT) + @Test void characterCombinableArbitraryWhitespace() { Character actual = CombinableArbitrary.chars().whitespace().combined(); then(Character.isWhitespace(actual)).isTrue(); } - @RepeatedTest(TEST_COUNT) + @Test void characterCombinableArbitraryLastOperationWinsWithAlphaAndNumeric() { Character actual = CombinableArbitrary.chars().alphabetic().numeric().combined(); @@ -499,42 +497,42 @@ void shortCombinableArbitraryIsJqwik() { then(actual).isInstanceOf(JqwikShortCombinableArbitrary.class); } - @RepeatedTest(TEST_COUNT) + @Test void shortCombinableArbitraryInjectNull() { Short actual = CombinableArbitrary.shorts().injectNull(1).combined(); then(actual).isNull(); } - @RepeatedTest(TEST_COUNT) + @Test void shortCombinableArbitraryFilter() { Short actual = CombinableArbitrary.shorts().filter(it -> it > 100).combined(); then(actual).isGreaterThan((short) 100); } - @RepeatedTest(TEST_COUNT) + @Test void shortCombinableArbitraryPositive() { Short actual = CombinableArbitrary.shorts().positive().combined(); then(actual).isPositive(); } - @RepeatedTest(TEST_COUNT) + @Test void shortCombinableArbitraryNegative() { Short actual = CombinableArbitrary.shorts().negative().combined(); then(actual).isNegative(); } - @RepeatedTest(TEST_COUNT) + @Test void shortCombinableArbitraryWithRange() { Short actual = CombinableArbitrary.shorts().withRange((short) 10, (short) 100).combined(); then(actual).isBetween((short) 10, (short) 100); } - @RepeatedTest(TEST_COUNT) + @Test void shortCombinableArbitraryWithRangeAndFilter() { Short actual = CombinableArbitrary.shorts() .withRange((short) 10, (short) 100) @@ -544,35 +542,35 @@ void shortCombinableArbitraryWithRangeAndFilter() { then(actual).isBetween((short) 75, (short) 100); } - @RepeatedTest(TEST_COUNT) + @Test void shortCombinableArbitraryEven() { Short actual = CombinableArbitrary.shorts().even().combined(); then(actual % 2).isEqualTo(0); } - @RepeatedTest(TEST_COUNT) + @Test void shortCombinableArbitraryOdd() { Short actual = CombinableArbitrary.shorts().odd().combined(); then(actual % 2 != 0).isTrue(); } - @RepeatedTest(TEST_COUNT) + @Test void shortCombinableArbitraryLastOperationWinsWithPositiveAndNegative() { Short actual = CombinableArbitrary.shorts().positive().negative().combined(); then(actual).isNegative(); } - @RepeatedTest(TEST_COUNT) + @Test void shortCombinableArbitraryLastOperationWinsWithEvenAndOdd() { Short actual = CombinableArbitrary.shorts().even().odd().combined(); then(actual % 2 != 0).isTrue(); } - @RepeatedTest(TEST_COUNT) + @Test void shortCombinableArbitraryLastOperationWinsWithNegativeAndRange() { Short actual = CombinableArbitrary.shorts().negative().withRange((short) 100, (short) 1000).combined(); diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/ContainerTypeTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/ContainerTypeTest.java index a444f983a0..358842cd24 100644 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/ContainerTypeTest.java +++ b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/ContainerTypeTest.java @@ -18,7 +18,6 @@ package com.navercorp.fixturemonkey.tests.java; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; import static org.assertj.core.api.BDDAssertions.then; import static org.assertj.core.api.BDDAssertions.thenNoException; @@ -29,7 +28,6 @@ import java.util.Optional; import java.util.Set; -import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import net.jqwik.api.Arbitraries; @@ -50,7 +48,7 @@ class ContainerTypeTest { .defaultNotNull(true) .build(); - @RepeatedTest(TEST_COUNT) + @Test void sampleContainerType() { ContainerObject actual = SUT.giveMeOne(ContainerObject.class); @@ -71,7 +69,7 @@ void sampleContainerType() { then(actual.getOptionalDouble()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleListType() { List actual = SUT.giveMeOne(new TypeReference>() { }); @@ -79,7 +77,7 @@ void sampleListType() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedListType() { List actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -89,7 +87,7 @@ void fixedListType() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleSetType() { Set actual = SUT.giveMeOne(new TypeReference>() { }); @@ -97,7 +95,7 @@ void sampleSetType() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedSetType() { Set actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -107,7 +105,7 @@ void fixedSetType() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleArrayType() { JavaTypeObject[] actual = SUT.giveMeOne(new TypeReference() { }); @@ -115,7 +113,7 @@ void sampleArrayType() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedArrayType() { JavaTypeObject[] actual = SUT.giveMeBuilder(new TypeReference() { }) @@ -125,7 +123,7 @@ void fixedArrayType() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleOptionalType() { Optional actual = SUT.giveMeOne(new TypeReference>() { }); @@ -133,7 +131,7 @@ void sampleOptionalType() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedOptionalType() { Optional actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -143,7 +141,7 @@ void fixedOptionalType() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleMapType() { Map actual = SUT.giveMeOne(new TypeReference>() { }); @@ -151,7 +149,7 @@ void sampleMapType() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedMapType() { Map actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -161,7 +159,7 @@ void fixedMapType() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleMapEntryType() { Map.Entry actual = SUT.giveMeOne( new TypeReference>() { @@ -170,7 +168,7 @@ void sampleMapEntryType() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedMapEntryType() { Map.Entry actual = SUT.giveMeBuilder( new TypeReference>() { @@ -191,7 +189,7 @@ void sampleUniqueSet() { then(actual).hasSize(200); } - @RepeatedTest(TEST_COUNT) + @Test void setEnumSet() { Set set = new HashSet<>(); set.add(Enum.ONE); @@ -206,7 +204,7 @@ void setEnumSet() { then(actual).hasSize(3); } - @RepeatedTest(TEST_COUNT) + @Test void sampleUniqueList() { List actual = SUT.giveMeBuilder(new TypeReference>() { }) diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/CustomizationTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/CustomizationTest.java index a1285093cd..8aacc88a90 100644 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/CustomizationTest.java +++ b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/CustomizationTest.java @@ -20,11 +20,11 @@ import static com.navercorp.fixturemonkey.api.experimental.TypedExpressionGenerator.typedRoot; import static com.navercorp.fixturemonkey.api.experimental.TypedExpressionGenerator.typedString; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; import static org.assertj.core.api.BDDAssertions.then; import static org.assertj.core.api.BDDAssertions.thenNoException; import static org.assertj.core.api.BDDAssertions.thenThrownBy; +import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -33,7 +33,6 @@ import java.util.function.Function; import java.util.function.Supplier; -import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import net.jqwik.api.Arbitraries; @@ -42,6 +41,7 @@ import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary; import com.navercorp.fixturemonkey.api.exception.RetryableFilterMissException; +import com.navercorp.fixturemonkey.api.introspector.BeanArbitraryIntrospector; import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; import com.navercorp.fixturemonkey.api.matcher.MatcherOperator; import com.navercorp.fixturemonkey.api.type.TypeReference; @@ -50,8 +50,11 @@ import com.navercorp.fixturemonkey.tests.java.specs.FunctionalInterfaceSpecs.FunctionObject; import com.navercorp.fixturemonkey.tests.java.specs.FunctionalInterfaceSpecs.SupplierObject; import com.navercorp.fixturemonkey.tests.java.specs.MutableSpecs.ConstantObject; +import com.navercorp.fixturemonkey.tests.java.specs.MutableSpecs.ContainerObject; +import com.navercorp.fixturemonkey.tests.java.specs.MutableSpecs.JavaTypeObject; class CustomizationTest { + private static final FixtureMonkey SUT = FixtureMonkey.builder() .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) .defaultNotNull(true) @@ -69,8 +72,8 @@ void sampleJavaTypeReturnsDiff() { @Test void setPostConditionFailed() { - thenThrownBy( - () -> SUT.giveMeBuilder(String.class) + thenThrownBy(() -> + SUT.giveMeBuilder(String.class) .setPostCondition(it -> it.equals("test")) .sample() ) @@ -78,33 +81,27 @@ void setPostConditionFailed() { .isExactlyInstanceOf(RetryableFilterMissException.class); } - @RepeatedTest(TEST_COUNT) + @Test void thenApplyAndSizeMap() { Map actual = SUT.giveMeBuilder(new TypeReference>>() { }) - .setInner(new InnerSpec() - .size(1) - .value(m -> m.size(0)) - ) - .thenApply((it, builder) -> - builder.setInner(new InnerSpec() - .size(1) - .value(m -> m.size(1)) - ) - ) + .setInner(new InnerSpec().size(1).value(m -> m.size(0))) + .thenApply((it, builder) -> builder.setInner(new InnerSpec().size(1).value(m -> m.size(1)))) .sample() .values() - .stream().findFirst() + .stream() + .findFirst() .orElse(null); then(actual).hasSize(1); } - @RepeatedTest(TEST_COUNT) + @Test void setLazyJust() { AtomicInteger atomicInteger = new AtomicInteger(); - ArbitraryBuilder builder = SUT.giveMeBuilder(Integer.class) - .setLazy("$", () -> Values.just(atomicInteger.getAndIncrement())); + ArbitraryBuilder builder = SUT.giveMeBuilder(Integer.class).setLazy("$", () -> + Values.just(atomicInteger.getAndIncrement()) + ); int actual = builder.sample(); @@ -112,29 +109,26 @@ void setLazyJust() { then(actual).isNotEqualTo(notExpected); } - @RepeatedTest(TEST_COUNT) + @Test void setArbitraryJust() { int expected = 1; - int actual = SUT.giveMeBuilder(Integer.class) - .set("$", Arbitraries.just(Values.just(expected))) - .sample(); + int actual = SUT.giveMeBuilder(Integer.class).set("$", Arbitraries.just(Values.just(expected))).sample(); then(actual).isEqualTo(expected); } @Test void constant() { - thenNoException().isThrownBy( - () -> SUT.giveMeOne(ConstantObject.class) - ); + thenNoException().isThrownBy(() -> SUT.giveMeOne(ConstantObject.class)); } @Test void sampleFunction() { - Function actual = SUT.giveMeBuilder(new TypeReference>() { - }) - .sample(); + Function actual = SUT.giveMeBuilder( + new TypeReference>() { + } + ).sample(); then(actual.apply(1)).isNotNull(); } @@ -161,7 +155,7 @@ void decomposeSupplierObject() { then(actual.get()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void unique() { List actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -173,14 +167,11 @@ void unique() { then(actual).hasSize(expected.size()); } - @RepeatedTest(TEST_COUNT) + @Test void customizePropertyUnique() { List actual = SUT.giveMeExperimentalBuilder(new TypeReference>() { }) - .customizeProperty( - typedString("$[*]"), - it -> it.filter(integer -> 0 <= integer && integer < 4) - ) + .customizeProperty(typedString("$[*]"), it -> it.filter(integer -> 0 <= integer && integer < 4)) .>customizeProperty(typedRoot(), CombinableArbitrary::unique) .size("$", 3) .sample(); @@ -201,16 +192,16 @@ void registerJavaTypebuilder() { then(actual).isEqualTo(expected); } - @RepeatedTest(TEST_COUNT) + @Test void registerSizeLessThanThree() { FixtureMonkey sut = FixtureMonkey.builder() .register( new MatcherOperator<>( - it -> it.getType().equals(new TypeReference>() { - }.getType()), + it -> it.getJvmType().getRawType().equals(List.class) + && it.getJvmType().getTypeVariables().size() == 1 + && it.getJvmType().getTypeVariables().get(0).getRawType().equals(String.class), fixture -> fixture.giveMeBuilder(new TypeReference>() { - }) - .maxSize("$", 2) + }).maxSize("$", 2) ) ) .build(); @@ -220,4 +211,1419 @@ void registerSizeLessThanThree() { then(actual).hasSizeLessThan(3); } + + @Test + void nestedMapSetInnerValue() { + // given + Map> actual = SUT.giveMeBuilder( + new TypeReference>>() { + } + ) + .setInner(new InnerSpec().size(1).entry("outerKey", inner -> inner.size(1).entry("innerKey", 42))) + .sample(); + + // when + Map innerMap = actual.get("outerKey"); + + // then + then(actual).hasSize(1); + then(actual).containsKey("outerKey"); + then(innerMap).isNotNull(); + then(innerMap).hasSize(1); + then(innerMap).containsEntry("innerKey", 42); + } + + @Test + void nestedMapSetInnerSize() { + // given + Map> actual = SUT.giveMeBuilder( + new TypeReference>>() { + } + ) + .setInner(new InnerSpec().size(2).allValue(inner -> inner.size(3))) + .sample(); + + // then + then(actual).hasSize(2); + for (Map innerMap : actual.values()) { + then(innerMap).hasSize(3); + } + } + + @Test + void nestedMapSize() { + // given + Map> actual = SUT.giveMeBuilder( + new TypeReference>>() { + } + ) + .setInner(new InnerSpec().size(5).allValue(inner -> inner.size(5))) + .sample(); + + // then + then(actual).hasSize(5); + for (Map innerMap : actual.values()) { + then(innerMap).hasSize(5); + } + } + + @Test + void thenApplyAndSizeFieldContainer() { + // given + FixtureMonkey sut = FixtureMonkey.builder() + .defaultNotNull(true) + .build(); + + ContainerObject actual = sut + .giveMeBuilder(ContainerObject.class) + .size("$.list", 1) + .thenApply((it, builder) -> builder.size("$.list", 3)) + .sample(); + + // then + then(actual.getList()).hasSize(3); + } + + @Test + void thenApplyAndSizeNestedFieldContainer() { + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector( + com.navercorp.fixturemonkey.api.introspector.FieldReflectionArbitraryIntrospector.INSTANCE + ) + .defaultNotNull(true) + .build(); + + NestedListObject actual = sut + .giveMeBuilder(NestedListObject.class) + .size("$.nestedList", 2) + .size("$.nestedList[*]", 1) + .thenApply((it, builder) -> builder.size("$.nestedList", 2).size("$.nestedList[*]", 3)) + .sample(); + + // then + then(actual.getNestedList()).hasSize(2); + for (List inner : actual.getNestedList()) { + then(inner).hasSize(3); + } + } + + @Test + void setListValueOverridesRegisteredList() { + // given + JavaTypeObject registered = new JavaTypeObject(); + registered.setString("x"); + + JavaTypeObject expectedElement1 = new JavaTypeObject(); + expectedElement1.setString("a"); + JavaTypeObject expectedElement2 = new JavaTypeObject(); + expectedElement2.setString("b"); + JavaTypeObject expectedElement3 = new JavaTypeObject(); + expectedElement3.setString("c"); + JavaTypeObject expectedElement4 = new JavaTypeObject(); + expectedElement4.setString("d"); + JavaTypeObject expectedElement5 = new JavaTypeObject(); + expectedElement5.setString("e"); + + List expected = new java.util.ArrayList<>(Arrays.asList( + expectedElement1, expectedElement2, expectedElement3, expectedElement4, expectedElement5 + )); + + FixtureMonkey registerSut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> + fm + .giveMeBuilder(ContainerObject.class) + .set("complexList", new java.util.ArrayList<>(Arrays.asList(registered))) + ) + .build(); + + // when + ContainerObject actual = registerSut.giveMeBuilder(ContainerObject.class).set("complexList", expected).sample(); + + // then + then(actual.getComplexList()).hasSize(5); + } + + @Test + void setScalarFieldOverridesRegisteredScalarField() { + // given + String expected = "overridden"; + + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).set("string", "registered")) + .build(); + + // when + JavaTypeObject actual = sut.giveMeBuilder(JavaTypeObject.class).set("string", expected).sample(); + + // then + then(actual.getString()).isEqualTo(expected); + } + + @Test + void setNestedObjectFieldOverridesRegistered() { + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> + fm.giveMeBuilder(ContainerObject.class).set("complexList[0].string", "registered") + ) + .build(); + + // when + ContainerObject actual = sut + .giveMeBuilder(ContainerObject.class) + .size("complexList", 1) + .set("complexList[0].string", "overridden") + .sample(); + + // then + then(actual.getComplexList()).hasSize(1); + then(actual.getComplexList().get(0).getString()).isEqualTo("overridden"); + } + + @Test + void setContainerSmallerThanRegistered() { + // given + JavaTypeObject registeredElement1 = new JavaTypeObject(); + registeredElement1.setString("r1"); + JavaTypeObject registeredElement2 = new JavaTypeObject(); + registeredElement2.setString("r2"); + JavaTypeObject registeredElement3 = new JavaTypeObject(); + registeredElement3.setString("r3"); + + JavaTypeObject userElement = new JavaTypeObject(); + userElement.setString("u1"); + + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> + fm + .giveMeBuilder(ContainerObject.class) + .set("complexList", new java.util.ArrayList<>(Arrays.asList( + registeredElement1, registeredElement2, registeredElement3 + ))) + ) + .build(); + + // when + ContainerObject actual = sut + .giveMeBuilder(ContainerObject.class) + .set("complexList", new java.util.ArrayList<>(Arrays.asList(userElement))) + .sample(); + + // then + then(actual.getComplexList()).hasSize(1); + then(actual.getComplexList().get(0).getString()).isEqualTo("u1"); + } + + @Test + void setNonOverlappingFieldsWithRegister() { + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).set("string", "fromRegister")) + .build(); + + // when + JavaTypeObject actual = sut.giveMeBuilder(JavaTypeObject.class).set("wrapperInteger", 42).sample(); + + // then + then(actual.getString()).isEqualTo("fromRegister"); + then(actual.getWrapperInteger()).isEqualTo(42); + } + + @Test + void setElementOverridesRegisteredContainer() { + // given + JavaTypeObject registeredElement1 = new JavaTypeObject(); + registeredElement1.setString("r1"); + JavaTypeObject registeredElement2 = new JavaTypeObject(); + registeredElement2.setString("r2"); + + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> + fm + .giveMeBuilder(ContainerObject.class) + .set("complexList", + new java.util.ArrayList<>(Arrays.asList(registeredElement1, registeredElement2))) + ) + .build(); + + JavaTypeObject overriddenElement = new JavaTypeObject(); + overriddenElement.setString("overridden"); + + // when + ContainerObject actual = sut + .giveMeBuilder(ContainerObject.class) + .size("complexList", 2) + .set("complexList[0]", overriddenElement) + .sample(); + + // then + then(actual.getComplexList()).hasSize(2); + then(actual.getComplexList().get(0).getString()).isEqualTo("overridden"); + } + + @Test + void setWholeContainerOverridesRegisteredElement() { + // given + JavaTypeObject userElement1 = new JavaTypeObject(); + userElement1.setString("u1"); + JavaTypeObject userElement2 = new JavaTypeObject(); + userElement2.setString("u2"); + JavaTypeObject userElement3 = new JavaTypeObject(); + userElement3.setString("u3"); + + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> + fm + .giveMeBuilder(ContainerObject.class) + .size("complexList", 1) + .set("complexList[0].string", "registered") + ) + .build(); + + // when + ContainerObject actual = sut + .giveMeBuilder(ContainerObject.class) + .set("complexList", new java.util.ArrayList<>(Arrays.asList(userElement1, userElement2, userElement3))) + .sample(); + + // then + then(actual.getComplexList()).hasSize(3); + then(actual.getComplexList().get(0).getString()).isEqualTo("u1"); + then(actual.getComplexList().get(1).getString()).isEqualTo("u2"); + then(actual.getComplexList().get(2).getString()).isEqualTo("u3"); + } + + @Test + void setOverridesRegisteredThenApply() { + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(JavaTypeObject.class, fm -> + fm + .giveMeBuilder(JavaTypeObject.class) + .set("string", "initial") + .thenApply((it, builder) -> builder.set("string", "fromThenApply")) + ) + .build(); + + // when + JavaTypeObject actual = sut.giveMeBuilder(JavaTypeObject.class).set("string", "overridden").sample(); + + // then + then(actual.getString()).isEqualTo("overridden"); + } + + @Test + void setMapOverridesRegisteredMap() { + // given + Map registered = new java.util.HashMap<>(); + registered.put("regKey", 1); + + Map expected = new java.util.HashMap<>(); + expected.put("key1", 10); + expected.put("key2", 20); + expected.put("key3", 30); + + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).set("map", registered)) + .build(); + + // when + ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).set("map", expected).sample(); + + // then + then(actual.getMap()).hasSize(3); + then(actual.getMap()).containsEntry("key1", 10); + then(actual.getMap()).containsEntry("key2", 20); + then(actual.getMap()).containsEntry("key3", 30); + } + + @Test + void setNullOverridesRegisteredSet() { + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).set("string", "registered")) + .build(); + + // when + JavaTypeObject actual = sut.giveMeBuilder(JavaTypeObject.class).setNull("string").sample(); + + // then + then(actual.getString()).isNull(); + } + + @Test + void setOverridesRegisteredSetNull() { + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).setNull("string")) + .build(); + + // when + JavaTypeObject actual = sut.giveMeBuilder(JavaTypeObject.class).set("string", "overridden").sample(); + + // then + then(actual.getString()).isEqualTo("overridden"); + } + + @Test + void setLazyOverridesRegisteredSet() { + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).set("string", "registered")) + .build(); + + // when + JavaTypeObject actual = sut + .giveMeBuilder(JavaTypeObject.class) + .setLazy("string", () -> "lazy") + .sample(); + + // then + then(actual.getString()).isEqualTo("lazy"); + } + + @Test + void setPostConditionAppliesOnRegisteredSet() { + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).set("wrapperInteger", 10)) + .build(); + + // when + JavaTypeObject actual = sut + .giveMeBuilder(JavaTypeObject.class) + .setPostCondition("wrapperInteger", Integer.class, i -> i > 5) + .sample(); + + // then + then(actual.getWrapperInteger()).isGreaterThan(5); + } + + @Test + void setContainerOverridesRegisteredSize() { + // given + JavaTypeObject userElement1 = new JavaTypeObject(); + userElement1.setString("u1"); + JavaTypeObject userElement2 = new JavaTypeObject(); + userElement2.setString("u2"); + + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).size("complexList", 5)) + .build(); + + // when + ContainerObject actual = sut + .giveMeBuilder(ContainerObject.class) + .set("complexList", new java.util.ArrayList<>(Arrays.asList(userElement1, userElement2))) + .sample(); + + // then + then(actual.getComplexList()).hasSize(2); + then(actual.getComplexList().get(0).getString()).isEqualTo("u1"); + then(actual.getComplexList().get(1).getString()).isEqualTo("u2"); + } + + @Test + void sizeOverridesRegisteredSetContainer() { + // given + JavaTypeObject registeredElement = new JavaTypeObject(); + registeredElement.setString("r1"); + + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> + fm.giveMeBuilder(ContainerObject.class) + .set("complexList", new java.util.ArrayList<>(Arrays.asList(registeredElement))) + ) + .build(); + + // when + ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).size("complexList", 3).sample(); + + // then + then(actual.getComplexList()).hasSize(3); + } + + @Test + void thenApplySetOverridesRegisteredSet() { + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).set("string", "registered")) + .build(); + + // when + JavaTypeObject actual = sut + .giveMeBuilder(JavaTypeObject.class) + .thenApply((it, builder) -> builder.set("string", "fromThenApply")) + .sample(); + + // then + then(actual.getString()).isEqualTo("fromThenApply"); + } + + @Test + void setInnerOverridesRegisteredMap() { + // given + Map registered = new java.util.HashMap<>(); + registered.put("regKey", 1); + + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).set("map", registered)) + .build(); + + // when + ContainerObject actual = sut + .giveMeBuilder(ContainerObject.class) + .setInner(new InnerSpec().property("map", m -> m.size(2).entry("k1", 100).entry("k2", 200))) + .sample(); + + // then + then(actual.getMap()).hasSize(2); + then(actual.getMap()).containsEntry("k1", 100); + then(actual.getMap()).containsEntry("k2", 200); + } + + @Test + void setOverridesRegisteredSetLazy() { + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(JavaTypeObject.class, fm -> + fm.giveMeBuilder(JavaTypeObject.class).setLazy("string", () -> "fromLazy") + ) + .build(); + + // when + JavaTypeObject actual = sut.giveMeBuilder(JavaTypeObject.class).set("string", "eager").sample(); + + // then + then(actual.getString()).isEqualTo("eager"); + } + + @Test + void setOverridesRegisteredSetInner() { + // given + JavaTypeObject userElement1 = new JavaTypeObject(); + userElement1.setString("u1"); + JavaTypeObject userElement2 = new JavaTypeObject(); + userElement2.setString("u2"); + + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> + fm + .giveMeBuilder(ContainerObject.class) + .setInner(new InnerSpec().property("complexList", l -> l.size(5))) + ) + .build(); + + // when + ContainerObject actual = sut + .giveMeBuilder(ContainerObject.class) + .set("complexList", new java.util.ArrayList<>(Arrays.asList(userElement1, userElement2))) + .sample(); + + // then + then(actual.getComplexList()).hasSize(2); + then(actual.getComplexList().get(0).getString()).isEqualTo("u1"); + then(actual.getComplexList().get(1).getString()).isEqualTo("u2"); + } + + @Test + void sizeOverridesRegisteredSetInner() { + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> + fm + .giveMeBuilder(ContainerObject.class) + .setInner(new InnerSpec().property("complexList", l -> l.size(5))) + ) + .build(); + + // when + ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).size("complexList", 2).sample(); + + // then + then(actual.getComplexList()).hasSize(2); + } + + @Test + void setLazyOverridesRegisteredSetNull() { + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).setNull("string")) + .build(); + + // when + JavaTypeObject actual = sut + .giveMeBuilder(JavaTypeObject.class) + .setLazy("string", () -> "fromLazy") + .sample(); + + // then + then(actual.getString()).isEqualTo("fromLazy"); + } + + @Test + void setNullOverridesRegisteredSetNotNull() { + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).setNotNull("string")) + .build(); + + // when + JavaTypeObject actual = sut.giveMeBuilder(JavaTypeObject.class).setNull("string").sample(); + + // then + then(actual.getString()).isNull(); + } + + @Test + void userSizeOverridesRegisteredSize() { + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).size("complexList", 5)) + .build(); + + // when + ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).size("complexList", 2).sample(); + + // then + then(actual.getComplexList()).hasSize(2); + } + + @Test + void registerOnlyAppliesWithoutUserOverride() { + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(JavaTypeObject.class, fm -> + fm.giveMeBuilder(JavaTypeObject.class).set("string", "fromRegister").set("wrapperInteger", 99) + ) + .build(); + + // when + JavaTypeObject actual = sut.giveMeOne(JavaTypeObject.class); + + // then + then(actual.getString()).isEqualTo("fromRegister"); + then(actual.getWrapperInteger()).isEqualTo(99); + } + + @Test + void setSpecificElementOverridesRegisteredWildcard() { + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> + fm.giveMeBuilder(ContainerObject.class).size("list", 3).set("list[*]", "registered") + ) + .build(); + + // when + ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).set("list[1]", "overridden").sample(); + + // then + then(actual.getList()).hasSize(3); + then(actual.getList().get(1)).isEqualTo("overridden"); + } + + @Test + void setRootObjectOverridesRegisteredField() { + // register sets a field, user sets the whole root object via "$" + // given + JavaTypeObject wholeObject = new JavaTypeObject(); + wholeObject.setString("fromRootSet"); + wholeObject.setWrapperInteger(77); + + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).set("string", "registered")) + .build(); + + // when + JavaTypeObject actual = sut.giveMeBuilder(JavaTypeObject.class).set("$", wholeObject).sample(); + + // then + then(actual.getString()).isEqualTo("fromRootSet"); + then(actual.getWrapperInteger()).isEqualTo(77); + } + + @Test + void setFieldOverridesRegisteredRootObject() { + // register sets the whole root object via "$", user sets a specific field + // given + JavaTypeObject registered = new JavaTypeObject(); + registered.setString("fromRegisterRoot"); + registered.setWrapperInteger(99); + + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).set("$", registered)) + .build(); + + // when + JavaTypeObject actual = sut.giveMeBuilder(JavaTypeObject.class).set("string", "overridden").sample(); + + // then + then(actual.getString()).isEqualTo("overridden"); + } + + @Test + void setRootObjectOverridesRegisteredRootObject() { + // both register and user set whole root object via "$" + // given + JavaTypeObject registered = new JavaTypeObject(); + registered.setString("fromRegister"); + registered.setWrapperInteger(1); + + JavaTypeObject userObj = new JavaTypeObject(); + userObj.setString("fromUser"); + userObj.setWrapperInteger(2); + + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).set("$", registered)) + .build(); + + // when + JavaTypeObject actual = sut.giveMeBuilder(JavaTypeObject.class).set("$", userObj).sample(); + + // then + then(actual.getString()).isEqualTo("fromUser"); + then(actual.getWrapperInteger()).isEqualTo(2); + } + + @Test + void setElementObjectOverridesRegisteredElementField() { + // register sets a field inside a list element, user sets the whole element as object + // given + JavaTypeObject userElement = new JavaTypeObject(); + userElement.setString("userObj"); + userElement.setWrapperInteger(55); + + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> + fm + .giveMeBuilder(ContainerObject.class) + .size("complexList", 2) + .set("complexList[0].string", "registered") + ) + .build(); + + // when + ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).set("complexList[0]", userElement).sample(); + + // then + then(actual.getComplexList().get(0).getString()).isEqualTo("userObj"); + then(actual.getComplexList().get(0).getWrapperInteger()).isEqualTo(55); + } + + @Test + void setElementFieldOverridesRegisteredElementObject() { + // register sets the whole element as object, user sets a field inside it + // given + JavaTypeObject registeredElement = new JavaTypeObject(); + registeredElement.setString("regObj"); + registeredElement.setWrapperInteger(33); + + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> + fm.giveMeBuilder(ContainerObject.class).size("complexList", 2).set("complexList[0]", registeredElement) + ) + .build(); + + // when + ContainerObject actual = sut + .giveMeBuilder(ContainerObject.class) + .set("complexList[0].string", "overridden") + .sample(); + + // then + then(actual.getComplexList().get(0).getString()).isEqualTo("overridden"); + } + + @Test + void setParentObjectOverridesRegisteredContainerField() { + // register sets a container field, user sets the parent object containing that field + // given + JavaTypeObject childElement = new JavaTypeObject(); + childElement.setString("e1"); + + ContainerObject userParent = new ContainerObject(); + userParent.setList(Arrays.asList("x", "y")); + userParent.setComplexList(new java.util.ArrayList<>(Arrays.asList(childElement))); + + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> + fm.giveMeBuilder(ContainerObject.class).size("list", 5).set("list[*]", "registered") + ) + .build(); + + // when + ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).set("$", userParent).sample(); + + // then + then(actual.getList()).hasSize(2); + then(actual.getList()).containsExactly("x", "y"); + then(actual.getComplexList()).hasSize(1); + then(actual.getComplexList().get(0).getString()).isEqualTo("e1"); + } + + // ================================ + // Container setNull combinations + // ================================ + + @Test + void setNullContainerOverridesRegisteredSetContainer() { + // given + JavaTypeObject registeredElement = new JavaTypeObject(); + registeredElement.setString("r1"); + + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> + fm.giveMeBuilder(ContainerObject.class) + .set("complexList", new java.util.ArrayList<>(Arrays.asList(registeredElement))) + ) + .build(); + + // when + ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).setNull("complexList").sample(); + + // then + then(actual.getComplexList()).isNull(); + } + + @Test + void setNullContainerOverridesRegisteredSize() { + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).size("complexList", 5)) + .build(); + + // when + ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).setNull("complexList").sample(); + + // then + then(actual.getComplexList()).isNull(); + } + + @Test + void setContainerOverridesRegisteredSetNull() { + // given + JavaTypeObject userElement = new JavaTypeObject(); + userElement.setString("u1"); + + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).setNull("complexList")) + .build(); + + // when + ContainerObject actual = sut + .giveMeBuilder(ContainerObject.class) + .set("complexList", new java.util.ArrayList<>(Arrays.asList(userElement))) + .sample(); + + // then + then(actual.getComplexList()).hasSize(1); + then(actual.getComplexList().get(0).getString()).isEqualTo("u1"); + } + + @Test + void sizeOverridesRegisteredSetNullContainer() { + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).setNull("complexList")) + .build(); + + // when + ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).size("complexList", 3).sample(); + + // then + then(actual.getComplexList()).hasSize(3); + } + + // ================================ + // Container setLazy combinations + // ================================ + + @Test + void setContainerOverridesRegisteredSetLazyContainer() { + // given + JavaTypeObject userElement = new JavaTypeObject(); + userElement.setString("u1"); + + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> + fm.giveMeBuilder(ContainerObject.class).setLazy("list", () -> Arrays.asList("lazy1", "lazy2", "lazy3")) + ) + .build(); + + // when + ContainerObject actual = sut + .giveMeBuilder(ContainerObject.class) + .set("list", new java.util.ArrayList<>(Arrays.asList("eager"))) + .sample(); + + // then + then(actual.getList()).hasSize(1); + then(actual.getList().get(0)).isEqualTo("eager"); + } + + @Test + void setLazyContainerOverridesRegisteredSetContainer() { + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> + fm + .giveMeBuilder(ContainerObject.class) + .set("list", new java.util.ArrayList<>(Arrays.asList("reg1", "reg2"))) + ) + .build(); + + // when + ContainerObject actual = sut + .giveMeBuilder(ContainerObject.class) + .setLazy("list", () -> Arrays.asList("lazy1")) + .sample(); + + // then + then(actual.getList()).hasSize(1); + then(actual.getList().get(0)).isEqualTo("lazy1"); + } + + // ================================ + // Wildcard field path combinations + // ================================ + + @Test + void setSpecificElementFieldOverridesRegisteredWildcardField() { + // register sets all elements' field via wildcard, user sets specific element's field + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> + fm.giveMeBuilder(ContainerObject.class).size("complexList", 3).set("complexList[*].string", "wildcard") + ) + .build(); + + // when + ContainerObject actual = sut + .giveMeBuilder(ContainerObject.class) + .set("complexList[1].string", "specific") + .sample(); + + // then + then(actual.getComplexList()).hasSize(3); + then(actual.getComplexList().get(1).getString()).isEqualTo("specific"); + } + + @Test + void setWildcardFieldOverridesRegisteredSpecificElementField() { + // register sets specific element's field, user sets all via wildcard + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> + fm.giveMeBuilder(ContainerObject.class).size("complexList", 3).set("complexList[0].string", "specific") + ) + .build(); + + // when + ContainerObject actual = sut + .giveMeBuilder(ContainerObject.class) + .set("complexList[*].string", "wildcard") + .sample(); + + // then + then(actual.getComplexList()).hasSize(3); + for (JavaTypeObject elem : actual.getComplexList()) { + then(elem.getString()).isEqualTo("wildcard"); + } + } + + // ================================ + // setInner vs setInner + // ================================ + + @Test + void setInnerOverridesRegisteredSetInner() { + // both register and user use setInner on same container + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> + fm + .giveMeBuilder(ContainerObject.class) + .setInner(new InnerSpec().property("map", m -> m.size(5).entry("regKey", 999))) + ) + .build(); + + // when + ContainerObject actual = sut + .giveMeBuilder(ContainerObject.class) + .setInner(new InnerSpec().property("map", m -> m.size(2).entry("userKey", 1))) + .sample(); + + // then + then(actual.getMap()).hasSize(2); + then(actual.getMap()).containsKey("userKey"); + } + + // ================================ + // Size range combinations + // ================================ + + @Test + void exactSizeOverridesRegisteredSizeRange() { + // register uses size range, user uses exact size + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).size("list", 1, 10)) + .build(); + + // when + ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).size("list", 3).sample(); + + // then + then(actual.getList()).hasSize(3); + } + + // ================================ + // Edge cases: empty container, size 0 + // ================================ + + @Test + void sizeExpandsRegisteredEmptyContainer() { + // register sets empty container, user expands with size + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> + fm.giveMeBuilder(ContainerObject.class).set("list", new java.util.ArrayList<>()) + ) + .build(); + + // when + ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).size("list", 3).sample(); + + // then + then(actual.getList()).hasSize(3); + } + + @Test + void setNonEmptyContainerOverridesRegisteredSizeZero() { + // register sets size to 0, user sets non-empty container + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).size("list", 0)) + .build(); + + // when + ContainerObject actual = sut + .giveMeBuilder(ContainerObject.class) + .set("list", new java.util.ArrayList<>(Arrays.asList("a", "b"))) + .sample(); + + // then + then(actual.getList()).hasSize(2); + then(actual.getList()).containsExactly("a", "b"); + } + + // ================================ + // Dual register: parent + child type + // ================================ + + @Test + void dualRegisterBothApplyWithoutUserOverride() { + // register ContainerObject (size) + register JavaTypeObject (field) + // both should apply when no user override + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).size("complexList", 3)) + .register(JavaTypeObject.class, fm -> + fm.giveMeBuilder(JavaTypeObject.class).set("string", "fromInnerRegister") + ) + .build(); + + // when + ContainerObject actual = sut.giveMeOne(ContainerObject.class); + + // then + then(actual.getComplexList()).hasSize(3); + for (JavaTypeObject elem : actual.getComplexList()) { + then(elem.getString()).isEqualTo("fromInnerRegister"); + } + } + + @Test + void dualRegisterUserOverridesElementField() { + // register ContainerObject (size) + register JavaTypeObject (field) + // user overrides specific element's field + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).size("complexList", 3)) + .register(JavaTypeObject.class, fm -> + fm.giveMeBuilder(JavaTypeObject.class).set("string", "fromInnerRegister") + ) + .build(); + + // when + ContainerObject actual = sut + .giveMeBuilder(ContainerObject.class) + .set("complexList[0].string", "userOverride") + .sample(); + + // then + then(actual.getComplexList()).hasSize(3); + then(actual.getComplexList().get(0).getString()).isEqualTo("userOverride"); + then(actual.getComplexList().get(1).getString()).isEqualTo("fromInnerRegister"); + then(actual.getComplexList().get(2).getString()).isEqualTo("fromInnerRegister"); + } + + @Test + void dualRegisterUserOverridesElementObject() { + // register ContainerObject (size) + register JavaTypeObject (field) + // user overrides a whole element object — should bypass inner register + // given + JavaTypeObject userObj = new JavaTypeObject(); + userObj.setString("userObj"); + userObj.setWrapperInteger(77); + + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).size("complexList", 3)) + .register(JavaTypeObject.class, fm -> + fm.giveMeBuilder(JavaTypeObject.class).set("string", "fromInnerRegister") + ) + .build(); + + // when + ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).set("complexList[0]", userObj).sample(); + + // then + then(actual.getComplexList()).hasSize(3); + then(actual.getComplexList().get(0).getString()).isEqualTo("userObj"); + then(actual.getComplexList().get(0).getWrapperInteger()).isEqualTo(77); + then(actual.getComplexList().get(1).getString()).isEqualTo("fromInnerRegister"); + } + + @Test + void dualRegisterUserOverridesWholeContainer() { + // register ContainerObject (container set) + register JavaTypeObject (field) + // user overrides whole container — should bypass both registers + // given + JavaTypeObject userElement = new JavaTypeObject(); + userElement.setString("u1"); + + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).size("complexList", 5)) + .register(JavaTypeObject.class, fm -> + fm.giveMeBuilder(JavaTypeObject.class).set("string", "fromInnerRegister") + ) + .build(); + + // when + ContainerObject actual = sut + .giveMeBuilder(ContainerObject.class) + .set("complexList", new java.util.ArrayList<>(Arrays.asList(userElement))) + .sample(); + + // then + then(actual.getComplexList()).hasSize(1); + then(actual.getComplexList().get(0).getString()).isEqualTo("u1"); + } + + @Test + void dualRegisterUserOverridesContainerSize() { + // register ContainerObject (size=5) + register JavaTypeObject (field) + // user overrides only size — inner register should still apply + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).size("complexList", 5)) + .register(JavaTypeObject.class, fm -> + fm.giveMeBuilder(JavaTypeObject.class).set("string", "fromInnerRegister") + ) + .build(); + + // when + ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).size("complexList", 2).sample(); + + // then + then(actual.getComplexList()).hasSize(2); + for (JavaTypeObject elem : actual.getComplexList()) { + then(elem.getString()).isEqualTo("fromInnerRegister"); + } + } + + @Test + void dualRegisterParentSetAndChildRootSet() { + // register ContainerObject (set container field) + register JavaTypeObject (set "$" root) + // given + JavaTypeObject registeredRoot = new JavaTypeObject(); + registeredRoot.setString("rootObj"); + registeredRoot.setWrapperInteger(42); + + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).size("complexList", 2)) + .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).set("$", registeredRoot)) + .build(); + + // when + ContainerObject actual = sut.giveMeOne(ContainerObject.class); + + // then + then(actual.getComplexList()).hasSize(2); + for (JavaTypeObject elem : actual.getComplexList()) { + then(elem.getString()).isEqualTo("rootObj"); + then(elem.getWrapperInteger()).isEqualTo(42); + } + } + + // ================================ + // Arbitrary set combinations + // ================================ + + @Test + void setValueOverridesRegisteredArbitrary() { + // register sets field via Arbitrary, user sets plain value + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(JavaTypeObject.class, fm -> + fm.giveMeBuilder(JavaTypeObject.class).set("wrapperInteger", Arbitraries.integers().between(100, 200)) + ) + .build(); + + // when + JavaTypeObject actual = sut.giveMeBuilder(JavaTypeObject.class).set("wrapperInteger", 42).sample(); + + // then + then(actual.getWrapperInteger()).isEqualTo(42); + } + + @Test + void setArbitraryOverridesRegisteredValue() { + // register sets plain value, user sets via Arbitrary + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).set("wrapperInteger", 999)) + .build(); + + // when + JavaTypeObject actual = sut + .giveMeBuilder(JavaTypeObject.class) + .set("wrapperInteger", Arbitraries.integers().between(1, 5)) + .sample(); + + // then + then(actual.getWrapperInteger()).isBetween(1, 5); + } + + @Test + void setArbitraryOverridesRegisteredArbitrary() { + // both register and user set via Arbitrary + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(JavaTypeObject.class, fm -> + fm.giveMeBuilder(JavaTypeObject.class).set("wrapperInteger", Arbitraries.integers().between(100, 200)) + ) + .build(); + + // when + JavaTypeObject actual = sut + .giveMeBuilder(JavaTypeObject.class) + .set("wrapperInteger", Arbitraries.integers().between(1, 5)) + .sample(); + + // then + then(actual.getWrapperInteger()).isBetween(1, 5); + } + + @Test + void registeredArbitraryAppliesWithoutUserOverride() { + // register sets via Arbitrary, no user override — Arbitrary should generate + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(JavaTypeObject.class, fm -> + fm.giveMeBuilder(JavaTypeObject.class).set("wrapperInteger", Arbitraries.integers().between(100, 200)) + ) + .build(); + + // when + JavaTypeObject actual = sut.giveMeOne(JavaTypeObject.class); + + // then + then(actual.getWrapperInteger()).isBetween(100, 200); + } + + @Test + void dualRegisterUserSetsArbitraryOnElement() { + // dual register + user sets Arbitrary on a specific element field + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).size("complexList", 3)) + .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).set("wrapperInteger", 999)) + .build(); + + // when + ContainerObject actual = sut + .giveMeBuilder(ContainerObject.class) + .set("complexList[0].wrapperInteger", Arbitraries.integers().between(1, 5)) + .sample(); + + // then + then(actual.getComplexList()).hasSize(3); + then(actual.getComplexList().get(0).getWrapperInteger()).isBetween(1, 5); + then(actual.getComplexList().get(1).getWrapperInteger()).isEqualTo(999); + then(actual.getComplexList().get(2).getWrapperInteger()).isEqualTo(999); + } + + @Test + void setElementOverridesRegisteredArbitraryOnWildcard() { + // register sets Arbitrary via wildcard, user sets specific element + // given + JavaTypeObject userObj = new JavaTypeObject(); + userObj.setString("userObj"); + + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> + fm + .giveMeBuilder(ContainerObject.class) + .size("complexList", 3) + .set("complexList[*].string", Arbitraries.strings().alpha().ofLength(10)) + ) + .build(); + + // when + ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).set("complexList[1]", userObj).sample(); + + // then + then(actual.getComplexList()).hasSize(3); + then(actual.getComplexList().get(1).getString()).isEqualTo("userObj"); + } + + @Test + void sizeOverridesRegisteredArbitraryContainer() { + // register sets container via Arbitrary.just(list), user overrides with size + // given + FixtureMonkey sut = FixtureMonkey.builder() + .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) + .register(ContainerObject.class, fm -> + fm + .giveMeBuilder(ContainerObject.class) + .set("list", Arbitraries.just(new java.util.ArrayList<>(Arrays.asList("a")))) + ) + .build(); + + // when + ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).size("list", 4).sample(); + + // then + then(actual.getList()).hasSize(4); + } + + @lombok.Data + static class NestedListObject { + + private List> nestedList; + } } diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/DataFakerArbitraryTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/DataFakerArbitraryTest.java index 2ebfe18d50..53ad331899 100644 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/DataFakerArbitraryTest.java +++ b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/DataFakerArbitraryTest.java @@ -1,81 +1,80 @@ package com.navercorp.fixturemonkey.tests.java; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; import static org.assertj.core.api.BDDAssertions.then; -import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.datafaker.arbitrary.DataFakerStringArbitrary; class DataFakerArbitraryTest { - @RepeatedTest(TEST_COUNT) + @Test void fullNameShouldNotBeBlank() { String value = DataFakerStringArbitrary.name().fullName(); then(value).isNotBlank(); } - @RepeatedTest(TEST_COUNT) + @Test void firstNameShouldNotBeBlank() { String value = DataFakerStringArbitrary.name().firstName(); then(value).isNotBlank(); } - @RepeatedTest(TEST_COUNT) + @Test void lastNameShouldNotBeBlank() { String value = DataFakerStringArbitrary.name().lastName(); then(value).isNotBlank(); } - @RepeatedTest(TEST_COUNT) + @Test void fullAddressShouldNotBeBlank() { String value = DataFakerStringArbitrary.address().fullAddress(); then(value).isNotBlank(); } - @RepeatedTest(TEST_COUNT) + @Test void cityShouldNotBeBlank() { String value = DataFakerStringArbitrary.address().city(); then(value).isNotBlank(); } - @RepeatedTest(TEST_COUNT) + @Test void countryShouldNotBeBlank() { String value = DataFakerStringArbitrary.address().country(); then(value).isNotBlank(); } - @RepeatedTest(TEST_COUNT) + @Test void zipCodeShouldNotBeBlank() { String value = DataFakerStringArbitrary.address().zipCode(); then(value).isNotBlank(); } - @RepeatedTest(TEST_COUNT) + @Test void emailAddressShouldContainAtSymbol() { String value = DataFakerStringArbitrary.internet().emailAddress(); then(value).contains("@"); } - @RepeatedTest(TEST_COUNT) + @Test void domainNameShouldNotBeBlank() { String value = DataFakerStringArbitrary.internet().domainName(); then(value).isNotBlank(); } - @RepeatedTest(TEST_COUNT) + @Test void urlShouldStartWithHttpOrHttps() { String value = DataFakerStringArbitrary.internet().url(); then(value).startsWith("www"); } - @RepeatedTest(TEST_COUNT) + @Test void phoneNumberShouldNotBeBlank() { String value = DataFakerStringArbitrary.phoneNumber().cellPhone(); then(value).isNotBlank(); } - @RepeatedTest(TEST_COUNT) + @Test void creditCardShouldNotBeBlank() { String value = DataFakerStringArbitrary.finance().creditCard(); then(value).isNotBlank(); diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/DefaultNullInjectGeneratorTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/DefaultNullInjectGeneratorTest.java index 46d98e71e4..44ce9203e6 100644 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/DefaultNullInjectGeneratorTest.java +++ b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/DefaultNullInjectGeneratorTest.java @@ -21,12 +21,11 @@ import static com.navercorp.fixturemonkey.api.generator.DefaultNullInjectGenerator.ALWAYS_NULL_INJECT; import static com.navercorp.fixturemonkey.api.generator.DefaultNullInjectGenerator.DEFAULT_NOTNULL_ANNOTATION_TYPES; import static com.navercorp.fixturemonkey.api.generator.DefaultNullInjectGenerator.DEFAULT_NULLABLE_ANNOTATION_TYPES; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; import static org.assertj.core.api.BDDAssertions.then; import java.util.HashSet; -import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.generator.DefaultNullInjectGenerator; @@ -35,7 +34,7 @@ import com.navercorp.fixturemonkey.tests.java.specs.DefaultNullInjectGeneratorSpecs.NullableAnnotationObject; class DefaultNullInjectGeneratorTest { - @RepeatedTest(TEST_COUNT) + @Test void nonNullAnnotations() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) @@ -58,7 +57,7 @@ void nonNullAnnotations() { then(actual.getCheckerNonNullField()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void nullableAnnotations() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/GenericTypeTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/GenericTypeTest.java index b62b8a447a..d492156134 100644 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/GenericTypeTest.java +++ b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/GenericTypeTest.java @@ -18,12 +18,11 @@ package com.navercorp.fixturemonkey.tests.java; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; import static org.assertj.core.api.BDDAssertions.then; import java.time.Instant; -import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; @@ -43,7 +42,7 @@ class GenericTypeTest { .defaultNotNull(true) .build(); - @RepeatedTest(TEST_COUNT) + @Test void sampleGenericObjectWithoutGeneric() { GenericObject actual = SUT.giveMeOne(GenericObject.class); @@ -51,7 +50,7 @@ void sampleGenericObjectWithoutGeneric() { then(actual.getValue()).isInstanceOf(Object.class); } - @RepeatedTest(TEST_COUNT) + @Test void fixedGenericObjectWithoutGeneric() { GenericObject actual = SUT.giveMeBuilder(GenericObject.class) .fixed() @@ -61,7 +60,7 @@ void fixedGenericObjectWithoutGeneric() { then(actual.getValue()).isInstanceOf(Object.class); } - @RepeatedTest(TEST_COUNT) + @Test void sampleGenericObject() { String actual = SUT.giveMeOne(new TypeReference>() { }) @@ -70,7 +69,7 @@ void sampleGenericObject() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedGenericObject() { String actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -81,14 +80,14 @@ void fixedGenericObject() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleGenericImplementationObjectWithoutGeneric() { GenericImplementationObject actual = SUT.giveMeOne(GenericImplementationObject.class); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedGenericImplementationObjectWithoutGeneric() { GenericImplementationObject actual = SUT.giveMeBuilder(GenericImplementationObject.class) .fixed() @@ -97,7 +96,7 @@ void fixedGenericImplementationObjectWithoutGeneric() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleGenericImplementationObject() { String actual = SUT.giveMeOne(new TypeReference>() { }) @@ -106,7 +105,7 @@ void sampleGenericImplementationObject() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedGenericImplementationObject() { String actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -117,14 +116,14 @@ void fixedGenericImplementationObject() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleTwoGenericImplementationObjectWithoutGeneric() { TwoGenericImplementationObject actual = SUT.giveMeOne(TwoGenericImplementationObject.class); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedTwoGenericImplementationObjectWithoutGeneric() { TwoGenericImplementationObject actual = SUT.giveMeBuilder(TwoGenericImplementationObject.class) .fixed() @@ -133,7 +132,7 @@ void fixedTwoGenericImplementationObjectWithoutGeneric() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleTwoGenericImplementationObject() { TwoGenericImplementationObject actual = SUT.giveMeOne( new TypeReference>() { @@ -144,7 +143,7 @@ void sampleTwoGenericImplementationObject() { then(actual.getTValue()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedTwoGenericImplementationObject() { TwoGenericImplementationObject actual = SUT.giveMeBuilder( new TypeReference>() { @@ -157,7 +156,7 @@ void fixedTwoGenericImplementationObject() { then(actual.getTValue()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleSetImplementationWithoutGeneric() { String actual = SUT.giveMeOne(SetImplementationWithoutGeneric.class) .getValue(); @@ -165,7 +164,7 @@ void sampleSetImplementationWithoutGeneric() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedSetImplementationWithoutGeneric() { String actual = SUT.giveMeBuilder(SetImplementationWithoutGeneric.class) .fixed() @@ -175,7 +174,7 @@ void fixedSetImplementationWithoutGeneric() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleGenericArrayType() { GenericImplementationObject[] values = SUT.giveMeOne(new TypeReference>() { }) @@ -184,7 +183,7 @@ void sampleGenericArrayType() { then(values).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedGenericArrayType() { GenericImplementationObject[] values = SUT.giveMeBuilder( new TypeReference>() { @@ -196,7 +195,7 @@ void fixedGenericArrayType() { then(values).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleTwoGenericObject() { TwoGenericObject actual = SUT.giveMeOne( new TypeReference>() { @@ -206,7 +205,7 @@ void sampleTwoGenericObject() { then(actual.getValue2()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedTwoGenericObject() { TwoGenericObject actual = SUT.giveMeBuilder( new TypeReference>() { @@ -219,7 +218,7 @@ void fixedTwoGenericObject() { then(actual.getValue2()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleTwoGenericObjectProperty() { TwoGenericObject actual = SUT.giveMeOne( new TypeReference>>() { @@ -230,7 +229,7 @@ void sampleTwoGenericObjectProperty() { then(actual.getValue2()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedTwoGenericObjectProperty() { TwoGenericObject actual = SUT.giveMeOne( new TypeReference>>() { @@ -241,7 +240,7 @@ void fixedTwoGenericObjectProperty() { then(actual.getValue2()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleThreeGenericObjectProperty() { ThreeGenericObject actual = SUT.giveMeOne( new TypeReference>>() { @@ -253,7 +252,7 @@ void sampleThreeGenericObjectProperty() { then(actual.getValue3()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedThreeGenericObjectProperty() { ThreeGenericObject actual = SUT.giveMeOne( new TypeReference>>() { diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/InstantiatorTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/InstantiatorTest.java index 8f032d019e..2d9a1974af 100644 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/InstantiatorTest.java +++ b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/InstantiatorTest.java @@ -20,7 +20,6 @@ import static com.navercorp.fixturemonkey.api.instantiator.Instantiator.constructor; import static com.navercorp.fixturemonkey.api.instantiator.Instantiator.factoryMethod; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; import static org.assertj.core.api.BDDAssertions.then; import java.lang.reflect.Modifier; @@ -31,7 +30,7 @@ import java.util.OptionalInt; import java.util.OptionalLong; -import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; @@ -46,7 +45,7 @@ class InstantiatorTest { .defaultNotNull(true) .build(); - @RepeatedTest(TEST_COUNT) + @Test void instantiateParametersInOrder() { String actual = SUT.giveMeBuilder(ConstructorSpecs.JavaTypeObject.class) .instantiate( @@ -67,7 +66,7 @@ void instantiateParametersInOrder() { then(actual).isEqualTo("first"); } - @RepeatedTest(TEST_COUNT) + @Test void instantiateNoArgsConstructor() { String actual = SUT.giveMeBuilder(ConstructorSpecs.JavaTypeObject.class) .instantiate( @@ -80,7 +79,7 @@ void instantiateNoArgsConstructor() { then(actual).isEqualTo("second"); } - @RepeatedTest(TEST_COUNT) + @Test void instantiateParameterNameHint() { String actual = SUT.giveMeBuilder(ConstructorSpecs.JavaTypeObject.class) .instantiate( @@ -95,7 +94,7 @@ void instantiateParameterNameHint() { then(actual).isEqualTo("third"); } - @RepeatedTest(TEST_COUNT) + @Test void instantiateConstructorContainer() { List actual = SUT.giveMeBuilder(SimpleContainerObject.class) .instantiate( @@ -123,7 +122,7 @@ void instantiateConstructorContainer() { then(actual).hasSize(1); } - @RepeatedTest(TEST_COUNT) + @Test void instantiateConstructorGenericContainer() { String actual = SUT.giveMeBuilder(ConstructorSpecs.ContainerObject.class) .instantiate( @@ -172,7 +171,7 @@ void instantiateConstructorGenericContainer() { then(actual).isEqualTo("test"); } - @RepeatedTest(TEST_COUNT) + @Test void instantiateGenericObjectByConstructor() { ConstructorSpecs.GenericObject actual = SUT.giveMeBuilder( new TypeReference>() { @@ -189,7 +188,7 @@ void instantiateGenericObjectByConstructor() { then(actual.getValue()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void instantiateTwoGenericObjectByConstructor() { ConstructorSpecs.TwoGenericObject actual = SUT.giveMeBuilder( new TypeReference>() { @@ -208,7 +207,7 @@ void instantiateTwoGenericObjectByConstructor() { then(actual.getUValue()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void instantiateGenericObjectWithHintByConstructor() { ConstructorSpecs.GenericObject actual = SUT.giveMeBuilder( new TypeReference>() { @@ -225,7 +224,7 @@ void instantiateGenericObjectWithHintByConstructor() { then(actual.getValue()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void instantiateByFactoryMethod() { String actual = SUT.giveMeBuilder(ConstructorSpecs.JavaTypeObject.class) .instantiate( @@ -237,7 +236,7 @@ void instantiateByFactoryMethod() { then(actual).isEqualTo("factory"); } - @RepeatedTest(TEST_COUNT) + @Test void instantiateByFactoryMethodWithParameter() { String actual = SUT.giveMeBuilder(ConstructorSpecs.JavaTypeObject.class) .instantiate( @@ -250,7 +249,7 @@ void instantiateByFactoryMethodWithParameter() { then(actual).isEqualTo("factory"); } - @RepeatedTest(TEST_COUNT) + @Test void instantiateFactoryMethodAndField() { Integer actual = SUT.giveMeBuilder(ConstructorSpecs.JavaTypeObject.class) .instantiate( @@ -264,7 +263,7 @@ void instantiateFactoryMethodAndField() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void instantiateConstructorField() { String actual = SUT.giveMeBuilder(MutableSpecs.JavaTypeObject.class) .instantiate(constructor().field()) @@ -274,7 +273,7 @@ void instantiateConstructorField() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void instantiateConstructorJavaBeansProperty() { String actual = SUT.giveMeBuilder(MutableSpecs.JavaTypeObject.class) .instantiate(constructor().javaBeansProperty()) @@ -284,7 +283,7 @@ void instantiateConstructorJavaBeansProperty() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void instantiateConstructorFieldFilter() { MutableSpecs.JavaTypeObject actual = SUT.giveMeBuilder(MutableSpecs.JavaTypeObject.class) @@ -298,7 +297,7 @@ void instantiateConstructorFieldFilter() { then(actual.getWrapperBoolean()).isNull(); } - @RepeatedTest(TEST_COUNT) + @Test void instantiateConstructorJavaBeansPropertyFilter() { MutableSpecs.JavaTypeObject actual = SUT.giveMeBuilder(MutableSpecs.JavaTypeObject.class) diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/IntrospectorTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/IntrospectorTest.java index ad3a5d5701..bb758a3afe 100644 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/IntrospectorTest.java +++ b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/IntrospectorTest.java @@ -18,7 +18,6 @@ package com.navercorp.fixturemonkey.tests.java; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; import static org.assertj.core.api.BDDAssertions.then; import static org.assertj.core.api.BDDAssertions.thenNoException; @@ -27,7 +26,6 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; -import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import net.jqwik.api.Arbitraries; @@ -50,7 +48,7 @@ import com.navercorp.fixturemonkey.tests.java.specs.NoArgsConstructorSpecs.NestedObject; class IntrospectorTest { - @RepeatedTest(TEST_COUNT) + @Test void registerListWouldNotCached() { AtomicInteger sequence = new AtomicInteger(); FixtureMonkey sut = FixtureMonkey.builder() @@ -112,7 +110,7 @@ void failoverIntrospectorMixed() { thenNoException().isThrownBy(() -> sut.giveMeOne(MixedJavaTypeObject.class)); } - @RepeatedTest(TEST_COUNT) + @Test void compositeArbitraryIntrospector() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector( diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/JacksonTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/JacksonTest.java index 4dfad707a4..55be52e41c 100644 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/JacksonTest.java +++ b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/JacksonTest.java @@ -1,6 +1,23 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + package com.navercorp.fixturemonkey.tests.java; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; import static org.assertj.core.api.BDDAssertions.then; import static org.assertj.core.api.BDDAssertions.thenNoException; @@ -9,7 +26,7 @@ import java.util.Optional; import java.util.Set; -import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.type.TypeReference; @@ -18,68 +35,84 @@ import com.navercorp.fixturemonkey.tests.java.specs.ImmutableSpecs.Enum; import com.navercorp.fixturemonkey.tests.java.specs.ImmutableSpecs.JavaTypeObject; import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.ConstructorObject; +import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonEnum; +import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonFormatObject; +import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonNodeWrapper; +import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonPropertyConstructor; +import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonPropertyContainerOuter; +import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonPropertyInner; +import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonPropertyMultipleFields; +import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonPropertyOuter; +import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonPropertyWithNormalField; +import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonPropertyWithOuter; +import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonTypeInfoFieldOuter; import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonTypeInfoIdClass; import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonTypeInfoIdName; import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonTypeInfoList; import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonTypeInfoListInSetter; import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonTypeInfoListInSetterIncludeWrapperObject; import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonTypeInfoListIncludeWrapperObject; +import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.PayPreApproval; +import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.Type; +import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.TypeWithAnnotations; import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.TypeWithAnnotationsIncludeWrapperObjectList; import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.TypeWithAnnotationsList; import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.TypeWithAnnotationsValue; +import com.navercorp.fixturemonkey.tracing.AssemblyTracer; class JacksonTest { + private static final FixtureMonkey SUT = FixtureMonkey.builder() .plugin(new JacksonPlugin()) .defaultNotNull(true) .build(); - @RepeatedTest(TEST_COUNT) + @Test void jsonTypeInfoName() { thenNoException().isThrownBy(() -> SUT.giveMeOne(JsonTypeInfoIdName.class)); } - @RepeatedTest(TEST_COUNT) + @Test void jsonTypeInfoList() { thenNoException().isThrownBy(() -> SUT.giveMeOne(JsonTypeInfoList.class)); } - @RepeatedTest(TEST_COUNT) + @Test void jsonTypeInfoIdClass() { thenNoException().isThrownBy(() -> SUT.giveMeOne(JsonTypeInfoIdClass.class)); } - @RepeatedTest(TEST_COUNT) + @Test void jsonTypeWithAnnotations() { thenNoException().isThrownBy(() -> SUT.giveMeOne(TypeWithAnnotationsValue.class)); } - @RepeatedTest(TEST_COUNT) + @Test void jsonTypeWithAnnotationsList() { thenNoException().isThrownBy(() -> SUT.giveMeOne(TypeWithAnnotationsList.class)); } - @RepeatedTest(TEST_COUNT) + @Test void jsonTypeInfoListInSetter() { thenNoException().isThrownBy(() -> SUT.giveMeOne(JsonTypeInfoListInSetter.class)); } - @RepeatedTest(TEST_COUNT) + @Test void jsonTypeInfoListIncludeWrapperObject() { thenNoException().isThrownBy(() -> SUT.giveMeOne(JsonTypeInfoListIncludeWrapperObject.class)); } - @RepeatedTest(TEST_COUNT) + @Test void jsonTypeInfoListInSetterIncludeWrapperObject() { thenNoException().isThrownBy(() -> SUT.giveMeOne(JsonTypeInfoListInSetterIncludeWrapperObject.class)); } - @RepeatedTest(TEST_COUNT) + @Test void jsonTypeWithAnnotationsIncludeWrapperObjectList() { thenNoException().isThrownBy(() -> SUT.giveMeOne(TypeWithAnnotationsIncludeWrapperObjectList.class)); } - @RepeatedTest(TEST_COUNT) + @Test void sampleContainerType() { ContainerObject actual = SUT.giveMeOne(ContainerObject.class); @@ -100,7 +133,7 @@ void sampleContainerType() { then(actual.getOptionalDouble()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleListType() { List actual = SUT.giveMeOne(new TypeReference>() { }); @@ -108,17 +141,15 @@ void sampleListType() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedListType() { List actual = SUT.giveMeBuilder(new TypeReference>() { - }) - .fixed() - .sample(); + }).fixed().sample(); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleSetType() { Set actual = SUT.giveMeOne(new TypeReference>() { }); @@ -126,17 +157,15 @@ void sampleSetType() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedSetType() { Set actual = SUT.giveMeBuilder(new TypeReference>() { - }) - .fixed() - .sample(); + }).fixed().sample(); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleArrayType() { JavaTypeObject[] actual = SUT.giveMeOne(new TypeReference() { }); @@ -144,17 +173,15 @@ void sampleArrayType() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedArrayType() { JavaTypeObject[] actual = SUT.giveMeBuilder(new TypeReference() { - }) - .fixed() - .sample(); + }).fixed().sample(); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleOptionalType() { Optional actual = SUT.giveMeOne(new TypeReference>() { }); @@ -162,7 +189,7 @@ void sampleOptionalType() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedOptionalType() { Optional actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -172,7 +199,7 @@ void fixedOptionalType() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleMapType() { Map actual = SUT.giveMeOne(new TypeReference>() { }); @@ -180,7 +207,7 @@ void sampleMapType() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedMapType() { Map actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -190,42 +217,450 @@ void fixedMapType() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleMapEntryType() { Map.Entry actual = SUT.giveMeOne( new TypeReference>() { - }); + } + ); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedMapEntryType() { Map.Entry actual = SUT.giveMeBuilder( new TypeReference>() { - }) + } + ) .fixed() .sample(); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleEnumKeyMap() { - thenNoException() - .isThrownBy(() -> SUT.giveMeBuilder( - new TypeReference>>() { - } - ) - .size("$", 2) - .sample() - ); + thenNoException().isThrownBy(() -> + SUT.giveMeBuilder(new TypeReference>>() { + }).size("$", 2).sample() + ); } - @RepeatedTest(TEST_COUNT) + @Test void sampleConstructorObject() { ConstructorObject actual = SUT.giveMeOne(ConstructorObject.class); then(actual).isNotNull(); } + + @Test + void setDecomposedValueShouldRespectJsonProperty() { + // when + JsonPropertyOuter actual = SUT.giveMeBuilder(JsonPropertyOuter.class) + .set("inner", new JsonPropertyInner("expected")) + .sample(); + + // then + then(actual.getInner()).isNotNull(); + then(actual.getInner().getOriginalField()).isEqualTo("expected"); + } + + @Test + void setDecomposedValueJsonPropertyShouldRespectJsonProperty() { + // when + JsonPropertyWithOuter actual = SUT.giveMeBuilder(JsonPropertyWithOuter.class) + .set("outer", new JsonPropertyInner("expected")) + .sample(); + + // then + then(actual.getInner()).isNotNull(); + then(actual.getInner().getOriginalField()).isEqualTo("expected"); + } + + @Test + void setDecomposedValueShouldRespectInnerJsonProperty() { + // given + String expected = "expected"; + + // when + String actual = SUT.giveMeBuilder(JsonPropertyOuter.class) + .set("inner.renamed", expected) + .sample() + .getInner() + .getOriginalField(); + + // then + then(actual).isEqualTo(expected); + } + + @Test + void setDecomposedValueShouldRespectJsonPropertyDiff() { + // when + String actual = SUT.giveMeBuilder(JsonPropertyInner.class) + .set("renamed", "expected") + .sample() + .getOriginalField(); + + // then + then(actual).isEqualTo("expected"); + } + + @Test + void sizeByJsonPropertyNameShouldWork() { + // when + JsonPropertyContainerOuter actual = SUT.giveMeBuilder(JsonPropertyContainerOuter.class) + .size("body", 0) + .sample(); + + // then + then(actual.getContents()).isEmpty(); + } + + // A. @JsonProperty + 조작자 + + @Test + void setNullByJsonPropertyName() { + // when + JsonPropertyWithNormalField actual = SUT.giveMeBuilder(JsonPropertyWithNormalField.class) + .setNull("renamed") + .sample(); + + // then + then(actual.getOriginalField()).isNull(); + } + + @Test + void setNotNullByJsonPropertyName() { + // when + JsonPropertyWithNormalField actual = SUT.giveMeBuilder(JsonPropertyWithNormalField.class) + .setNotNull("renamed") + .sample(); + + // then + then(actual.getOriginalField()).isNotNull(); + } + + @Test + void setLazyByJsonPropertyName() { + // when + String actual = SUT.giveMeBuilder(JsonPropertyInner.class) + .setLazy("renamed", () -> "lazy") + .sample() + .getOriginalField(); + + // then + then(actual).isEqualTo("lazy"); + } + + @Test + void setPostConditionByJsonPropertyName() { + // when + String actual = SUT.giveMeBuilder(JsonPropertyInner.class) + .setPostCondition("renamed", String.class, it -> it != null && it.startsWith("a")) + .sample() + .getOriginalField(); + + // then + then(actual).startsWith("a"); + } + + @Test + void setNullNestedJsonPropertyPath() { + // when + JsonPropertyOuter actual = SUT.giveMeBuilder(JsonPropertyOuter.class).setNull("inner.renamed").sample(); + + // then + then(actual.getInner()).isNotNull(); + then(actual.getInner().getOriginalField()).isNull(); + } + + @Test + void setNotNullNestedJsonPropertyPath() { + // when + JsonPropertyOuter actual = SUT.giveMeBuilder(JsonPropertyOuter.class).setNotNull("inner.renamed").sample(); + + // then + then(actual.getInner()).isNotNull(); + then(actual.getInner().getOriginalField()).isNotNull(); + } + + @Test + void setNullContainerByJsonPropertyName() { + // when + JsonPropertyContainerOuter actual = SUT.giveMeBuilder(JsonPropertyContainerOuter.class) + .setNull("body") + .sample(); + + // then + then(actual.getContents()).isNull(); + } + + @Test + void setNotNullContainerByJsonPropertyName() { + // when + JsonPropertyContainerOuter actual = SUT.giveMeBuilder(JsonPropertyContainerOuter.class) + .setNotNull("body") + .sample(); + + // then + then(actual.getContents()).isNotNull(); + } + + @Test + void setMultipleJsonPropertyFields() { + // when + JsonPropertyMultipleFields actual = SUT.giveMeBuilder(JsonPropertyMultipleFields.class) + .set("name", "testName") + .set("age", 25) + .set("active", true) + .sample(); + + // then + then(actual.getOriginalName()).isEqualTo("testName"); + then(actual.getOriginalAge()).isEqualTo(25); + then(actual.isOriginalActive()).isTrue(); + } + + @Test + void thenApplySetByJsonPropertyName() { + // when + JsonPropertyWithNormalField actual = SUT.giveMeBuilder(JsonPropertyWithNormalField.class) + .thenApply((it, builder) -> builder.set("renamed", "applied")) + .sample(); + + // then + then(actual.getOriginalField()).isEqualTo("applied"); + } + + @Test + void acceptIfSetByJsonPropertyName() { + // when + JsonPropertyWithNormalField actual = SUT.giveMeBuilder(JsonPropertyWithNormalField.class) + .acceptIf(it -> true, builder -> builder.set("renamed", "accepted")) + .sample(); + + // then + then(actual.getOriginalField()).isEqualTo("accepted"); + } + + @Test + void registerWithJsonPropertyFields() { + // given + FixtureMonkey sut = FixtureMonkey.builder() + .plugin(new JacksonPlugin()) + .defaultNotNull(true) + .register(JsonPropertyWithNormalField.class, fixture -> + fixture.giveMeBuilder(JsonPropertyWithNormalField.class).set("renamed", "registered") + ) + .build(); + + // when + JsonPropertyWithNormalField actual = sut.giveMeOne(JsonPropertyWithNormalField.class); + + // then + then(actual.getOriginalField()).isEqualTo("registered"); + } + + @Test + void registerThenUserOverrideByJsonPropertyName() { + // given + FixtureMonkey sut = FixtureMonkey.builder() + .plugin(new JacksonPlugin()) + .defaultNotNull(true) + .register(JsonPropertyWithNormalField.class, fixture -> + fixture.giveMeBuilder(JsonPropertyWithNormalField.class).set("renamed", "registered") + ) + .build(); + + // when + JsonPropertyWithNormalField actual = sut + .giveMeBuilder(JsonPropertyWithNormalField.class) + .set("renamed", "overridden") + .sample(); + + // then + then(actual.getOriginalField()).isEqualTo("overridden"); + } + + @Test + void setLazyNestedJsonPropertyPath() { + // when + String actual = SUT.giveMeBuilder(JsonPropertyOuter.class) + .setLazy("inner.renamed", () -> "lazyNested") + .sample() + .getInner() + .getOriginalField(); + + // then + then(actual).isEqualTo("lazyNested"); + } + + @Test + void sizeAndSetElementByJsonPropertyName() { + // when + JsonPropertyContainerOuter actual = SUT.giveMeBuilder(JsonPropertyContainerOuter.class) + .size("body", 2) + .set("body[0]", "first") + .sample(); + + // then + then(actual.getContents()).hasSize(2); + then(actual.getContents().get(0)).isEqualTo("first"); + } + + // B. @JsonTypeInfo + adapter + + @Test + void jsonTypeInfoSetSiblingField() { + // when + JsonTypeInfoFieldOuter actual = SUT.giveMeBuilder(JsonTypeInfoFieldOuter.class).set("name", "hello").sample(); + + // then + then(actual.getName()).isEqualTo("hello"); + then(actual.getType()).isInstanceOf(Type.class); + } + + @Test + void jsonTypeInfoSetNull() { + // when + JsonTypeInfoFieldOuter actual = SUT.giveMeBuilder(JsonTypeInfoFieldOuter.class).setNull("type").sample(); + + // then + then(actual.getType()).isNull(); + } + + @Test + void jsonTypeInfoSetNotNull() { + // when + JsonTypeInfoFieldOuter actual = SUT.giveMeBuilder(JsonTypeInfoFieldOuter.class).setNotNull("type").sample(); + + // then + then(actual.getType()).isNotNull(); + } + + @Test + void jsonTypeInfoListSize() { + // when + JsonTypeInfoFieldOuter actual = SUT.giveMeBuilder(JsonTypeInfoFieldOuter.class).size("types", 3).sample(); + + // then + then(actual.getTypes()).hasSize(3); + then(actual.getTypes()).allSatisfy(it -> then(it).isInstanceOf(Type.class)); + } + + @Test + void jsonTypeInfoSetSiblingFieldAndSetNotNull() { + // when + JsonTypeInfoFieldOuter actual = SUT.giveMeBuilder(JsonTypeInfoFieldOuter.class) + .set("name", "hello") + .setNotNull("type") + .sample(); + + // then + then(actual.getName()).isEqualTo("hello"); + then(actual.getType()).isNotNull(); + then(actual.getType()).isInstanceOf(Type.class); + } + + @Test + void jsonTypeInfoRegister() { + // given + FixtureMonkey sut = FixtureMonkey.builder() + .plugin(new JacksonPlugin()) + .defaultNotNull(true) + .register(JsonTypeInfoFieldOuter.class, fixture -> + fixture.giveMeBuilder(JsonTypeInfoFieldOuter.class).set("name", "registered") + ) + .build(); + + // when + JsonTypeInfoFieldOuter actual = sut.giveMeOne(JsonTypeInfoFieldOuter.class); + + // then + then(actual.getName()).isEqualTo("registered"); + then(actual.getType()).isInstanceOf(Type.class); + } + + @Test + void jsonTypeInfoInterfaceAnnotationsSetNotNull() { + // when + TypeWithAnnotationsValue actual = SUT.giveMeBuilder(TypeWithAnnotationsValue.class).setNotNull("type").sample(); + + // then + then(actual.getType()).isNotNull(); + then(actual.getType()).isInstanceOf(TypeWithAnnotations.class); + } + + // C. @JsonFormat + adapter + + @Test + void jsonFormatGeneration() { + thenNoException().isThrownBy(() -> SUT.giveMeOne(JsonFormatObject.class)); + } + + @Test + void jsonFormatSetEnumField() { + // when + JsonFormatObject actual = SUT.giveMeBuilder(JsonFormatObject.class).set("enumValue", JsonEnum.TWO).sample(); + + // then + then(actual.getEnumValue()).isEqualTo(JsonEnum.TWO); + } + + // D. JsonNode + adapter + + @Test + void jsonNodeFieldGeneration() { + thenNoException().isThrownBy(() -> SUT.giveMeOne(JsonNodeWrapper.class)); + } + + @Test + void jsonNodeFieldSetNull() { + // when + JsonNodeWrapper actual = SUT.giveMeBuilder(JsonNodeWrapper.class).setNull("value").sample(); + + // then + then(actual.getValue()).isNull(); + } + + // E. Constructor + @JsonProperty + + @Test + void constructorJsonPropertySet() { + // when + JsonPropertyConstructor actual = SUT.giveMeBuilder(JsonPropertyConstructor.class).set("id", "test").sample(); + + // then + then(actual.getIdentifier()).isEqualTo("test"); + } + + @Test + void constructorJsonPropertySetNull() { + // when + JsonPropertyConstructor actual = SUT.giveMeBuilder(JsonPropertyConstructor.class).setNull("id").sample(); + + // then + then(actual.getIdentifier()).isNull(); + } + + @Test + void sampleNestedValueTypeWithDefaultNotNull() { + // given + FixtureMonkey sut = FixtureMonkey.builder() + .plugin(new JacksonPlugin()) + .defaultNotNull(true) + .tracer(AssemblyTracer.console()) + .build(); + + // when + PayPreApproval actual = sut.giveMeOne(PayPreApproval.class); + + // then + then(actual).isNotNull(); + then(actual.getPayMethod()).isNotNull(); + then(actual.getPayMethod().getFirstPayMethod()).isNotNull(); + then(actual.getPayMethod().getFirstPayMethod().getPayMethodType()).isNotNull(); + } + } diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/JavaGetterPropertyFieldNameResolverTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/JavaGetterPropertyFieldNameResolverTest.java index c9b52a7554..92c51700db 100644 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/JavaGetterPropertyFieldNameResolverTest.java +++ b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/JavaGetterPropertyFieldNameResolverTest.java @@ -19,10 +19,9 @@ package com.navercorp.fixturemonkey.tests.java; import static com.navercorp.fixturemonkey.api.expression.JavaGetterMethodPropertySelector.javaGetter; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; import static org.assertj.core.api.BDDAssertions.then; -import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Test; import lombok.AllArgsConstructor; import lombok.Getter; @@ -35,7 +34,7 @@ class JavaGetterPropertyFieldNameResolverTest { .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) .build(); - @RepeatedTest(TEST_COUNT) + @Test void nonBooleanFieldWithIsPrefixReturns() { JavaGetterObject actual = SUT.giveMeBuilder(JavaGetterObject.class) .set(javaGetter(JavaGetterObject::getIsStatus), "javaGetterStringStatus") @@ -44,7 +43,7 @@ void nonBooleanFieldWithIsPrefixReturns() { then(actual.getIsStatus()).isEqualTo("javaGetterStringStatus"); } - @RepeatedTest(TEST_COUNT) + @Test void primitiveTypeBooleanFieldWithIsPrefixReturns() { JavaGetterObject actual = SUT.giveMeBuilder(JavaGetterObject.class) .set(javaGetter(JavaGetterObject::isActive), true) @@ -53,7 +52,7 @@ void primitiveTypeBooleanFieldWithIsPrefixReturns() { then(actual.isActive).isTrue(); } - @RepeatedTest(TEST_COUNT) + @Test void booleanFieldWithoutIsPrefixReturns() { JavaGetterObject actual = SUT.giveMeBuilder(JavaGetterObject.class) .set(javaGetter(JavaGetterObject::isEnabled), true) @@ -62,7 +61,7 @@ void booleanFieldWithoutIsPrefixReturns() { then(actual.isEnabled()).isTrue(); } - @RepeatedTest(TEST_COUNT) + @Test void nonBooleanFieldWithoutIsPrefixReturns() { JavaGetterObject actual = SUT.giveMeBuilder(JavaGetterObject.class) .set(javaGetter(JavaGetterObject::getName), "javaGetterObjectName") @@ -71,7 +70,7 @@ void nonBooleanFieldWithoutIsPrefixReturns() { then(actual.getName()).isEqualTo("javaGetterObjectName"); } - @RepeatedTest(TEST_COUNT) + @Test void wrapperTypeBooleanFieldWithIsPrefixReturns() { JavaGetterObject actual = SUT.giveMeBuilder(JavaGetterObject.class) .set(javaGetter(JavaGetterObject::getIsDeleted), true) diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/PluginTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/PluginTest.java index 7f37349f35..6063cd5424 100644 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/PluginTest.java +++ b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/PluginTest.java @@ -18,7 +18,6 @@ package com.navercorp.fixturemonkey.tests.java; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; import static org.assertj.core.api.BDDAssertions.then; import static org.assertj.core.api.BDDAssertions.thenThrownBy; @@ -27,7 +26,6 @@ import java.util.List; import java.util.stream.Collectors; -import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; @@ -48,7 +46,7 @@ import com.navercorp.fixturemonkey.tests.java.specs.InterfaceSpecs.InterfaceWrapperObject; class PluginTest { - @RepeatedTest(TEST_COUNT) + @Test void setListRecursiveImplementations() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -77,7 +75,7 @@ void setListRecursiveImplementations() { then(actual.getValue()).isEqualTo(expected); } - @RepeatedTest(TEST_COUNT) + @Test void constructorValidator() { FixtureMonkey sut = FixtureMonkey.builder() .plugin(new JavaxValidationPlugin()) @@ -90,7 +88,7 @@ void constructorValidator() { then(actual.getValue()).isEqualTo(100); } - @RepeatedTest(TEST_COUNT) + @Test void abstractClassExtends() { FixtureMonkey sut = FixtureMonkey.builder() .plugin( @@ -200,7 +198,7 @@ void simpleValueJqwikPluginMinusDaysFromTodayGreaterThanDefault() { then(actual).isBetween(expectedMinDate, expectedMaxDate); } - @RepeatedTest(TEST_COUNT) + @Test void dataFakerPluginGeneratesUserFields() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -217,7 +215,7 @@ void dataFakerPluginGeneratesUserFields() { then(actual.getPhoneNumber()).isNotBlank(); } - @RepeatedTest(TEST_COUNT) + @Test void dataFakerPluginGeneratesFinanceFields() { // given FixtureMonkey sut = FixtureMonkey.builder() diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/PriorityConstructorArbitraryIntrospectorTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/PriorityConstructorArbitraryIntrospectorTest.java index a81dae9e1b..0ce664f170 100644 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/PriorityConstructorArbitraryIntrospectorTest.java +++ b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/PriorityConstructorArbitraryIntrospectorTest.java @@ -18,13 +18,11 @@ package com.navercorp.fixturemonkey.tests.java; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; import static org.assertj.core.api.BDDAssertions.then; import java.sql.Timestamp; import java.util.Arrays; -import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; @@ -41,7 +39,7 @@ class PriorityConstructorArbitraryIntrospectorTest { .defaultNotNull(true) .build(); - @RepeatedTest(TEST_COUNT) + @Test void sample() { Timestamp actual = SUT.giveMeOne(Timestamp.class); @@ -58,7 +56,7 @@ void setWithoutName() { then(actual).isNotEqualTo(expected); } - @RepeatedTest(TEST_COUNT) + @Test void set() { // given PriorityConstructorArbitraryIntrospector priorityConstructorArbitraryIntrospector = @@ -80,7 +78,7 @@ void set() { then(actual).isEqualTo(expected); } - @RepeatedTest(TEST_COUNT) + @Test void genericType() { String actual = SUT.giveMeOne(new TypeReference>() { }).getValue(); @@ -88,7 +86,7 @@ void genericType() { then(actual).isExactlyInstanceOf(String.class); } - @RepeatedTest(TEST_COUNT) + @Test void twoGenericType() { TwoGenericObject actual = SUT.giveMeOne( new TypeReference>() { @@ -98,7 +96,7 @@ void twoGenericType() { then(actual.getValue2()).isExactlyInstanceOf(Integer.class); } - @RepeatedTest(TEST_COUNT) + @Test void twoGenericObjectConstructorParameterOrderDiff() { TwoGenericObjectConstructorParameterOrderDiff actual = SUT.giveMeOne( new TypeReference>() { @@ -108,7 +106,7 @@ void twoGenericObjectConstructorParameterOrderDiff() { then(actual.getValue2()).isExactlyInstanceOf(Integer.class); } - @RepeatedTest(TEST_COUNT) + @Test void twoGenericObjectConstructorParameterOrderDiffNameDiff() { TwoGenericObjectConstructorParameterOrderDiffNameDiff actual = SUT.giveMeOne( new TypeReference>() { diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/PropertySelectorTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/PropertySelectorTest.java index a3a36043bb..3d33f70bc9 100644 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/PropertySelectorTest.java +++ b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/PropertySelectorTest.java @@ -19,13 +19,11 @@ package com.navercorp.fixturemonkey.tests.java; import static com.navercorp.fixturemonkey.api.experimental.JavaGetterMethodPropertySelector.javaGetter; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; import static org.assertj.core.api.BDDAssertions.then; import java.util.List; import java.util.stream.Collectors; -import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; @@ -41,14 +39,14 @@ class PropertySelectorTest { .defaultNotNull(true) .build(); - @RepeatedTest(TEST_COUNT) + @Test void nestedObject() { Inner actual = SUT.giveMeOne(Inner.class); then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void setJavaGetter() { String actual = SUT.giveMeBuilder(JavaTypeObject.class) .set(javaGetter(JavaTypeObject::getString), "test") @@ -58,7 +56,7 @@ void setJavaGetter() { then(actual).isEqualTo("test"); } - @RepeatedTest(TEST_COUNT) + @Test void setJavaGetterInto() { String actual = SUT.giveMeBuilder(RootJavaTypeObject.class) .set(javaGetter(RootJavaTypeObject::getValue).into(JavaTypeObject::getString), "test") @@ -69,7 +67,7 @@ void setJavaGetterInto() { then(actual).isEqualTo("test"); } - @RepeatedTest(TEST_COUNT) + @Test void setJavaGetterCollection() { String actual = SUT.giveMeBuilder(ContainerObject.class) .size("list", 1) @@ -81,7 +79,7 @@ void setJavaGetterCollection() { then(actual).isEqualTo("test"); } - @RepeatedTest(TEST_COUNT) + @Test void setJavaGetterCollectionElement() { String actual = SUT.giveMeBuilder(ContainerObject.class) .size("complexList", 1) @@ -98,7 +96,7 @@ void setJavaGetterCollectionElement() { then(actual).isEqualTo("test"); } - @RepeatedTest(TEST_COUNT) + @Test void setJavaGetterCollectionAllElement() { String expected = "test"; @@ -159,7 +157,7 @@ void indexTypedJavaGetter() { then(actual).isEqualTo(expected); } - @RepeatedTest(TEST_COUNT) + @Test void setExp() { String actual = SUT.giveMeJavaBuilder(JavaTypeObject.class) .setExpGetter(JavaTypeObject::getString, "test") @@ -169,7 +167,7 @@ void setExp() { then(actual).isEqualTo("test"); } - @RepeatedTest(TEST_COUNT) + @Test void setExpCollectionElement() { String actual = SUT.giveMeJavaBuilder(ContainerObject.class) .size("complexList", 1) diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/RecursiveTypeTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/RecursiveTypeTest.java index 25019414fa..9f6655e926 100644 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/RecursiveTypeTest.java +++ b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/RecursiveTypeTest.java @@ -18,13 +18,12 @@ package com.navercorp.fixturemonkey.tests.java; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; import static org.assertj.core.api.BDDAssertions.then; import java.util.List; import java.util.Map; -import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; @@ -39,7 +38,7 @@ class RecursiveTypeTest { .defaultNotNull(true) .build(); - @RepeatedTest(TEST_COUNT) + @Test void sampleSelfRecursiveObject() { SelfRecursiveObject actual = SUT.giveMeOne(SelfRecursiveObject.class); @@ -47,7 +46,7 @@ void sampleSelfRecursiveObject() { then(actual.getSelfRecursiveObject()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedSelfRecursiveObject() { SelfRecursiveObject actual = SUT.giveMeBuilder(SelfRecursiveObject.class) .fixed() @@ -57,7 +56,7 @@ void fixedSelfRecursiveObject() { then(actual.getSelfRecursiveObject()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleSelfRecursiveListObject() { SelfRecursiveListObject actual = SUT.giveMeOne(SelfRecursiveListObject.class); @@ -65,7 +64,7 @@ void sampleSelfRecursiveListObject() { then(actual.getSelfRecursiveListObjects()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedSelfRecursiveListObject() { SelfRecursiveListObject actual = SUT.giveMeBuilder(SelfRecursiveListObject.class) .fixed() @@ -75,7 +74,7 @@ void fixedSelfRecursiveListObject() { then(actual.getSelfRecursiveListObjects()).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void sampleSelfRecursiveMapObject() { Map actual = SUT.giveMeOne( new TypeReference>() { @@ -84,7 +83,7 @@ void sampleSelfRecursiveMapObject() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void fixedSelfRecursiveMapObject() { Map actual = SUT.giveMeBuilder( new TypeReference>() { @@ -95,7 +94,7 @@ void fixedSelfRecursiveMapObject() { then(actual).isNotNull(); } - @RepeatedTest(TEST_COUNT) + @Test void setSelfRecursiveObjectList() { List expected = SUT.giveMeOne( new TypeReference>() { @@ -112,7 +111,7 @@ void setSelfRecursiveObjectList() { then(actual).isEqualTo(expected); } - @RepeatedTest(TEST_COUNT) + @Test void setNestedSelfRecursiveObjectList() { List expected = SUT.giveMeBuilder( new TypeReference>() { @@ -134,7 +133,7 @@ void setNestedSelfRecursiveObjectList() { then(actual).isEqualTo(expected); } - @RepeatedTest(TEST_COUNT) + @Test void setSelfRecursiveObject() { SelfRecursiveObject actual = SUT.giveMeOne(SelfRecursiveObject.class); diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/SizeAnnotationTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/SizeAnnotationTest.java new file mode 100644 index 0000000000..c41d78e7e8 --- /dev/null +++ b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/SizeAnnotationTest.java @@ -0,0 +1,43 @@ +package com.navercorp.fixturemonkey.tests.java; + +import static org.assertj.core.api.BDDAssertions.then; + +import java.util.Map; + +import javax.validation.constraints.Size; + +import org.junit.jupiter.api.Test; + +import lombok.Value; + +import com.navercorp.fixturemonkey.FixtureMonkey; +import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; +import com.navercorp.fixturemonkey.javax.validation.plugin.JavaxValidationPlugin; + +class SizeAnnotationTest { + + private static final FixtureMonkey SUT = FixtureMonkey.builder() + .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) + .plugin(new JavaxValidationPlugin()) + .build(); + + @Value + public static class SizeAnnotatedMapObject { + + String id; + + @Size(min = 1, max = 1) + Map values; + } + + @Test + void sampleSizeAnnotatedMapWithThenApply() { + SizeAnnotatedMapObject actual = SUT.giveMeBuilder(SizeAnnotatedMapObject.class) + .set("id", "base") + .thenApply((obj, builder) -> builder.set("id", obj.getId() + "-applied")) + .sample(); + + then(actual.getId()).isEqualTo("base-applied"); + then(actual.getValues()).hasSize(1); + } +} diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/AnnotationAdapterTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/AnnotationAdapterTest.java deleted file mode 100644 index 77eb12068c..0000000000 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/AnnotationAdapterTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.java.adapter; - -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; -import static org.assertj.core.api.BDDAssertions.then; - -import org.junit.jupiter.api.RepeatedTest; - -import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; -import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; -import com.navercorp.fixturemonkey.javax.validation.plugin.JavaxValidationPlugin; -import com.navercorp.fixturemonkey.tests.java.specs.ValidationSpecs.CustomAnnotationStringObject; -import com.navercorp.fixturemonkey.tests.java.specs.ValidationSpecs.StringNotNullAnnotationObject; - -class AnnotationAdapterTest { - private static final FixtureMonkey SUT = FixtureMonkey.builder() - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .plugin(new JavaxValidationPlugin()) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - @RepeatedTest(TEST_COUNT) - void sampleCustomAnnotation() { - String actual = SUT.giveMeOne(CustomAnnotationStringObject.class) - .getNullOrLessThan5String(); - - then(actual).matches(it -> it == null || it.length() < 5); - } - - @RepeatedTest(TEST_COUNT) - void sampleNotValidAnnotation() { - String actual = SUT.giveMeBuilder(StringNotNullAnnotationObject.class) - .set("value", null) - .validOnly(false) - .sample() - .getValue(); - - then(actual).isNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleNotValidAnnotationWithCopy() { - String actual = SUT.giveMeBuilder(StringNotNullAnnotationObject.class) - .set("value", null) - .validOnly(false) - .copy() - .sample() - .getValue(); - - then(actual).isNull(); - } -} diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/AnonymousInstanceAdapterTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/AnonymousInstanceAdapterTest.java deleted file mode 100644 index 12a0dbfc59..0000000000 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/AnonymousInstanceAdapterTest.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.java.adapter; - -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; -import static org.assertj.core.api.BDDAssertions.then; - -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -import org.junit.jupiter.api.RepeatedTest; -import org.junit.jupiter.api.Test; - -import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; -import com.navercorp.fixturemonkey.api.plugin.InterfacePlugin; -import com.navercorp.fixturemonkey.javax.validation.plugin.JavaxValidationPlugin; -import com.navercorp.fixturemonkey.tests.java.specs.AnonymousInstanceSpecs.AnnotatedInterface; -import com.navercorp.fixturemonkey.tests.java.specs.AnonymousInstanceSpecs.ContainerInterface; -import com.navercorp.fixturemonkey.tests.java.specs.AnonymousInstanceSpecs.GetterInterface; -import com.navercorp.fixturemonkey.tests.java.specs.AnonymousInstanceSpecs.InheritedInterface; -import com.navercorp.fixturemonkey.tests.java.specs.AnonymousInstanceSpecs.InheritedInterfaceWithSameNameMethod; -import com.navercorp.fixturemonkey.tests.java.specs.AnonymousInstanceSpecs.InheritedTwoInterface; -import com.navercorp.fixturemonkey.tests.java.specs.AnonymousInstanceSpecs.Interface; -import com.navercorp.fixturemonkey.tests.java.specs.AnonymousInstanceSpecs.InterfaceWithConstant; -import com.navercorp.fixturemonkey.tests.java.specs.AnonymousInstanceSpecs.InterfaceWithParams; -import com.navercorp.fixturemonkey.tests.java.specs.AnonymousInstanceSpecs.NestedInheritedInterface; -import com.navercorp.fixturemonkey.tests.java.specs.AnonymousInstanceSpecs.SimilarInterface; - -class AnonymousInstanceAdapterTest { - private static final FixtureMonkey SUT = FixtureMonkey.builder() - .defaultNotNull(true) - .plugin(new JavaxValidationPlugin()) - .plugin( - new InterfacePlugin() - .useAnonymousArbitraryIntrospector(true) - ) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - @RepeatedTest(TEST_COUNT) - void sampleInterface() { - Interface actual = SUT.giveMeOne(Interface.class); - - then(actual).isNotNull(); - then(actual.string()).isNotNull(); - then(actual.integer()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void objectBaseMethods() { - Interface actual = SUT.giveMeOne(Interface.class); - - then(actual.hashCode()).isNotNull(); - then(actual).isEqualTo(actual); - then(actual.toString()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void equalsOnSimilarInterface() { - Interface one = SUT.giveMeBuilder(Interface.class) - .set("string", "test") - .set("integer", 123) - .sample(); - SimilarInterface another = SUT.giveMeBuilder(SimilarInterface.class) - .set("string", "test") - .set("integer", 123) - .sample(); - - then(one).isNotEqualTo(another); - } - - @RepeatedTest(TEST_COUNT) - void setInterface() { - String expected = "test"; - - String actual = SUT.giveMeBuilder(Interface.class) - .set("string", expected) - .sample() - .string(); - - then(actual).isEqualTo(expected); - } - - @RepeatedTest(TEST_COUNT) - void sampleInterfaceWithParamReturnsNullProperties() { - InterfaceWithParams actual = SUT.giveMeOne(InterfaceWithParams.class); - - then(actual).isNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleInterfaceWithConstant() { - String actual = SUT.giveMeOne(InterfaceWithConstant.class).value; - - then(actual).isEqualTo("constant"); - } - - @RepeatedTest(TEST_COUNT) - void setConstantNotWorks() { - String actual = SUT.giveMeBuilder(InterfaceWithConstant.class) - .set("value", "changed") - .sample() - .value; - - then(actual).isEqualTo("constant"); - } - - @RepeatedTest(TEST_COUNT) - void sampleContainerInterface() { - ContainerInterface actual = SUT.giveMeOne(ContainerInterface.class); - - then(actual.list()).isNotNull(); - then(actual.map()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void setContainerInterfaceList() { - List actual = SUT.giveMeBuilder(ContainerInterface.class) - .size("list", 3) - .set("list[0]", "test") - .sample() - .list(); - - then(actual).hasSize(3); - then(actual.get(0)).isEqualTo("test"); - } - - @RepeatedTest(TEST_COUNT) - void sampleAnnotatedInterface() { - String actual = SUT.giveMeOne(AnnotatedInterface.class) - .string(); - - then(actual).isNotEmpty(); - } - - @RepeatedTest(TEST_COUNT) - void setPropertyName() { - String expected = "test"; - - String actual = SUT.giveMeBuilder(GetterInterface.class) - .set("value", expected) - .sample() - .getValue(); - - then(actual).isEqualTo(expected); - } - - @RepeatedTest(TEST_COUNT) - void setMethodNameNotWorks() { - String notExpected = "test"; - - String actual = SUT.giveMeBuilder(GetterInterface.class) - .set("getValue", notExpected) - .sample() - .getValue(); - - then(actual).isNotEqualTo(notExpected); - } - - @RepeatedTest(TEST_COUNT) - void sampleInheritedInterface() { - InheritedInterface actual = SUT.giveMeOne(InheritedInterface.class); - - then(actual.value()).isNotNull(); - then(actual.string()).isNotNull(); - then(actual.integer()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void setInheritedInterface() { - String expected = "test"; - - String actual = SUT.giveMeBuilder(InheritedInterface.class) - .set("value", expected) - .sample() - .value(); - - then(actual).isEqualTo(expected); - } - - @RepeatedTest(TEST_COUNT) - void sampleInheritedInterfaceWithSameNameMethod() { - String actual = SUT.giveMeOne(InheritedInterfaceWithSameNameMethod.class).string(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void setInheritedInterfaceWithSameNameMethod() { - String expected = "test"; - - String actual = SUT.giveMeBuilder(InheritedInterfaceWithSameNameMethod.class) - .set("string", expected) - .sample() - .string(); - - then(actual).isEqualTo(expected); - } - - @RepeatedTest(TEST_COUNT) - void sampleInheritedTwoInterface() { - InheritedTwoInterface actual = SUT.giveMeOne(InheritedTwoInterface.class); - - then(actual.integer()).isNotNull(); - then(actual.string()).isNotNull(); - then(actual.list()).isNotNull(); - then(actual.map()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleNestedInheritedInterface() { - String actual = SUT.giveMeOne(NestedInheritedInterface.class).string(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void setNestedInheritedInterface() { - String expected = "test"; - - String actual = SUT.giveMeBuilder(NestedInheritedInterface.class) - .set("string", expected) - .sample() - .string(); - - then(actual).isEqualTo(expected); - } - - @Test - void sampleListWouldReturnDiff() { - Set actual = SUT.giveMeBuilder(Interface.class) - .sampleList(2) - .stream() - .map(Interface::integer) - .collect(Collectors.toSet()); - - then(actual).hasSize(2); - } -} diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/BeanArbitraryIntrospectorAdapterTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/BeanArbitraryIntrospectorAdapterTest.java deleted file mode 100644 index 9567d6dacf..0000000000 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/BeanArbitraryIntrospectorAdapterTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.java.adapter; - -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; -import static org.assertj.core.api.BDDAssertions.then; - -import org.junit.jupiter.api.RepeatedTest; - -import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; -import com.navercorp.fixturemonkey.api.introspector.BeanArbitraryIntrospector; -import com.navercorp.fixturemonkey.tests.java.specs.MutableSpecs.ContainerObject; -import com.navercorp.fixturemonkey.tests.java.specs.MutableSpecs.DateTimeObject; -import com.navercorp.fixturemonkey.tests.java.specs.MutableSpecs.JavaTypeObject; -import com.navercorp.fixturemonkey.tests.java.specs.NoSetterSpecs; - -class BeanArbitraryIntrospectorAdapterTest { - private static final FixtureMonkey SUT = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - @RepeatedTest(TEST_COUNT) - void sampleJavaType() { - JavaTypeObject actual = SUT.giveMeOne(JavaTypeObject.class); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleDateTime() { - DateTimeObject actual = SUT.giveMeOne(DateTimeObject.class); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleContainer() { - ContainerObject actual = SUT.giveMeOne(ContainerObject.class); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void setPropertyPostCondition() { - String actual = SUT.giveMeBuilder(JavaTypeObject.class) - .setPostCondition("string", String.class, str -> str.length() > 5) - .sample() - .getString(); - - then(actual).hasSizeGreaterThan(5); - } - - @RepeatedTest(TEST_COUNT) - void objectGenerationShouldWorkWithoutSetter() { - NoSetterSpecs.StringObject actual = SUT.giveMeOne(NoSetterSpecs.StringObject.class); - - then(actual).isNotNull(); - } -} diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/ContainerTypeAdapterTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/ContainerTypeAdapterTest.java deleted file mode 100644 index b7b1321c69..0000000000 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/ContainerTypeAdapterTest.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.java.adapter; - -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; -import static org.assertj.core.api.BDDAssertions.then; -import static org.assertj.core.api.BDDAssertions.thenNoException; - -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.RepeatedTest; -import org.junit.jupiter.api.Test; - -import net.jqwik.api.Arbitraries; - -import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; -import com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary; -import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; -import com.navercorp.fixturemonkey.api.lazy.LazyArbitrary; -import com.navercorp.fixturemonkey.api.type.TypeReference; -import com.navercorp.fixturemonkey.customizer.Values; -import com.navercorp.fixturemonkey.tests.java.specs.ImmutableSpecs.ContainerObject; -import com.navercorp.fixturemonkey.tests.java.specs.ImmutableSpecs.Enum; -import com.navercorp.fixturemonkey.tests.java.specs.ImmutableSpecs.JavaTypeObject; - -class ContainerTypeAdapterTest { - private static final FixtureMonkey SUT = FixtureMonkey.builder() - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - @Disabled("ContainerObject contains Map.Entry fields not yet supported in Adapter") - @RepeatedTest(TEST_COUNT) - void sampleContainerType() { - ContainerObject actual = SUT.giveMeOne(ContainerObject.class); - - then(actual.getPrimitiveArray()).isNotNull(); - then(actual.getArray()).isNotNull(); - then(actual.getComplexArray()).isNotNull(); - then(actual.getList()).isNotNull(); - then(actual.getComplexList()).isNotNull(); - then(actual.getSet()).isNotNull(); - then(actual.getComplexSet()).isNotNull(); - then(actual.getMap()).isNotNull(); - then(actual.getComplexMap()).isNotNull(); - then(actual.getOptional()).isNotNull(); - then(actual.getOptionalInt()).isNotNull(); - then(actual.getOptionalLong()).isNotNull(); - then(actual.getOptionalDouble()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleListType() { - List actual = SUT.giveMeOne(new TypeReference>() { - }); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedListType() { - List actual = SUT.giveMeBuilder(new TypeReference>() { - }) - .fixed() - .sample(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleSetType() { - Set actual = SUT.giveMeOne(new TypeReference>() { - }); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedSetType() { - Set actual = SUT.giveMeBuilder(new TypeReference>() { - }) - .fixed() - .sample(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleArrayType() { - JavaTypeObject[] actual = SUT.giveMeOne(new TypeReference() { - }); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedArrayType() { - JavaTypeObject[] actual = SUT.giveMeBuilder(new TypeReference() { - }) - .fixed() - .sample(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleOptionalType() { - Optional actual = SUT.giveMeOne(new TypeReference>() { - }); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedOptionalType() { - Optional actual = SUT.giveMeBuilder(new TypeReference>() { - }) - .fixed() - .sample(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleMapType() { - Map actual = SUT.giveMeOne(new TypeReference>() { - }); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedMapType() { - Map actual = SUT.giveMeBuilder(new TypeReference>() { - }) - .fixed() - .sample(); - - then(actual).isNotNull(); - } - - @Disabled("Map.Entry root type with ConstructorPropertiesArbitraryIntrospector not yet supported in Adapter") - @RepeatedTest(TEST_COUNT) - void sampleMapEntryType() { - Map.Entry actual = SUT.giveMeOne( - new TypeReference>() { - }); - - then(actual).isNotNull(); - } - - @Disabled("Map.Entry root type with ConstructorPropertiesArbitraryIntrospector not yet supported in Adapter") - @RepeatedTest(TEST_COUNT) - void fixedMapEntryType() { - Map.Entry actual = SUT.giveMeBuilder( - new TypeReference>() { - }) - .fixed() - .sample(); - - then(actual).isNotNull(); - } - - @Test - void sampleUniqueSet() { - Set actual = SUT.giveMeBuilder(new TypeReference>() { - }) - .size("$", 200) - .sample(); - - then(actual).hasSize(200); - } - - @RepeatedTest(TEST_COUNT) - void setEnumSet() { - Set set = new HashSet<>(); - set.add(Enum.ONE); - set.add(Enum.TWO); - set.add(Enum.THREE); - - Set actual = SUT.giveMeBuilder(new TypeReference>() { - }) - .set("$", set) - .sample(); - - then(actual).hasSize(3); - } - - @RepeatedTest(TEST_COUNT) - void sampleUniqueList() { - List actual = SUT.giveMeBuilder(new TypeReference>() { - }) - .size("$", 100) - .set( - "$[*]", - Values.just(CombinableArbitrary.from(LazyArbitrary.lazy(() -> Arbitraries.strings().sample())).unique()) - ) - .sample(); - - Set expected = new HashSet<>(actual); - then(actual).hasSameSizeAs(expected); - } - - @Test - void collectionNotThrows() { - thenNoException().isThrownBy( - () -> SUT.giveMeOne(new TypeReference>() { - }) - ); - } -} diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/CustomizationAdapterTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/CustomizationAdapterTest.java deleted file mode 100644 index 0c2e351d1f..0000000000 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/CustomizationAdapterTest.java +++ /dev/null @@ -1,1692 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.java.adapter; - -import static com.navercorp.fixturemonkey.api.experimental.TypedExpressionGenerator.typedRoot; -import static com.navercorp.fixturemonkey.api.experimental.TypedExpressionGenerator.typedString; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; -import static org.assertj.core.api.BDDAssertions.then; -import static org.assertj.core.api.BDDAssertions.thenNoException; -import static org.assertj.core.api.BDDAssertions.thenThrownBy; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Function; -import java.util.function.Supplier; - -import org.junit.jupiter.api.RepeatedTest; -import org.junit.jupiter.api.Test; - -import net.jqwik.api.Arbitraries; - -import com.navercorp.fixturemonkey.ArbitraryBuilder; -import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; -import com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary; -import com.navercorp.fixturemonkey.api.exception.RetryableFilterMissException; -import com.navercorp.fixturemonkey.api.introspector.BeanArbitraryIntrospector; -import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; -import com.navercorp.fixturemonkey.api.matcher.MatcherOperator; -import com.navercorp.fixturemonkey.api.type.TypeReference; -import com.navercorp.fixturemonkey.customizer.InnerSpec; -import com.navercorp.fixturemonkey.customizer.Values; -import com.navercorp.fixturemonkey.tests.java.specs.FunctionalInterfaceSpecs.FunctionObject; -import com.navercorp.fixturemonkey.tests.java.specs.FunctionalInterfaceSpecs.SupplierObject; -import com.navercorp.fixturemonkey.tests.java.specs.MutableSpecs.ConstantObject; -import com.navercorp.fixturemonkey.tests.java.specs.MutableSpecs.ContainerObject; -import com.navercorp.fixturemonkey.tests.java.specs.MutableSpecs.JavaTypeObject; - -class CustomizationAdapterTest { - - private static final FixtureMonkey SUT = FixtureMonkey.builder() - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - @Test - void sampleJavaTypeReturnsDiff() { - ArbitraryBuilder builder = SUT.giveMeBuilder(String.class); - - String actual = builder.sample(); - - String notExpected = builder.sample(); - then(actual).isNotEqualTo(notExpected); - } - - @Test - void setPostConditionFailed() { - thenThrownBy(() -> - SUT.giveMeBuilder(String.class) - .setPostCondition(it -> it.equals("test")) - .sample() - ) - .getCause() - .isExactlyInstanceOf(RetryableFilterMissException.class); - } - - @Test - void thenApplyAndSizeMap() { - Map actual = SUT.giveMeBuilder(new TypeReference>>() { - }) - .setInner(new InnerSpec().size(1).value(m -> m.size(0))) - .thenApply((it, builder) -> builder.setInner(new InnerSpec().size(1).value(m -> m.size(1)))) - .sample() - .values() - .stream() - .findFirst() - .orElse(null); - - then(actual).hasSize(1); - } - - @RepeatedTest(TEST_COUNT) - void setLazyJust() { - AtomicInteger atomicInteger = new AtomicInteger(); - ArbitraryBuilder builder = SUT.giveMeBuilder(Integer.class).setLazy("$", () -> - Values.just(atomicInteger.getAndIncrement()) - ); - - int actual = builder.sample(); - - int notExpected = builder.sample(); - then(actual).isNotEqualTo(notExpected); - } - - @RepeatedTest(TEST_COUNT) - void setArbitraryJust() { - int expected = 1; - - int actual = SUT.giveMeBuilder(Integer.class).set("$", Arbitraries.just(Values.just(expected))).sample(); - - then(actual).isEqualTo(expected); - } - - @Test - void constant() { - thenNoException().isThrownBy(() -> SUT.giveMeOne(ConstantObject.class)); - } - - @Test - void sampleFunction() { - Function actual = SUT.giveMeBuilder( - new TypeReference>() { - } - ).sample(); - - then(actual.apply(1)).isNotNull(); - } - - @Test - void decomposeFunctionObject() { - Function actual = SUT.giveMeBuilder(FunctionObject.class) - .thenApply((function, builder) -> { - }) - .sample() - .getValue(); - - then(actual.apply(1)).isNotNull(); - } - - @Test - void decomposeSupplierObject() { - Supplier actual = SUT.giveMeBuilder(SupplierObject.class) - .thenApply((function, builder) -> { - }) - .sample() - .getValue(); - - then(actual.get()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void unique() { - List actual = SUT.giveMeBuilder(new TypeReference>() { - }) - .size("$", 3) - .set("$[*]", Values.unique(() -> Arbitraries.integers().between(0, 3).sample())) - .sample(); - - Set expected = new HashSet<>(actual); - then(actual).hasSize(expected.size()); - } - - @RepeatedTest(TEST_COUNT) - void customizePropertyUnique() { - List actual = SUT.giveMeExperimentalBuilder(new TypeReference>() { - }) - .customizeProperty(typedString("$[*]"), it -> it.filter(integer -> 0 <= integer && integer < 4)) - .>customizeProperty(typedRoot(), CombinableArbitrary::unique) - .size("$", 3) - .sample(); - - Set expected = new HashSet<>(actual); - then(actual).hasSize(expected.size()); - } - - @Test - void registerJavaTypebuilder() { - String expected = "test"; - FixtureMonkey sut = FixtureMonkey.builder() - .register(String.class, it -> it.giveMeJavaBuilder(expected)) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - String actual = sut.giveMeOne(String.class); - - then(actual).isEqualTo(expected); - } - - @RepeatedTest(TEST_COUNT) - void registerSizeLessThanThree() { - FixtureMonkey sut = FixtureMonkey.builder() - .register( - new MatcherOperator<>( - it -> it.getType().equals(new TypeReference>() { - }.getType()), - fixture -> fixture.giveMeBuilder(new TypeReference>() { - }).maxSize("$", 2) - ) - ) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - List actual = sut.giveMeOne(new TypeReference>() { - }); - - then(actual).hasSizeLessThan(3); - } - - @Test - void nestedMapSetInnerValue() { - // given - Map> actual = SUT.giveMeBuilder( - new TypeReference>>() { - } - ) - .setInner(new InnerSpec().size(1).entry("outerKey", inner -> inner.size(1).entry("innerKey", 42))) - .sample(); - - // when - Map innerMap = actual.get("outerKey"); - - // then - then(actual).hasSize(1); - then(actual).containsKey("outerKey"); - then(innerMap).isNotNull(); - then(innerMap).hasSize(1); - then(innerMap).containsEntry("innerKey", 42); - } - - @Test - void nestedMapSetInnerSize() { - // given - Map> actual = SUT.giveMeBuilder( - new TypeReference>>() { - } - ) - .setInner(new InnerSpec().size(2).allValue(inner -> inner.size(3))) - .sample(); - - // then - then(actual).hasSize(2); - for (Map innerMap : actual.values()) { - then(innerMap).hasSize(3); - } - } - - @Test - void nestedMapSize() { - // given - Map> actual = SUT.giveMeBuilder( - new TypeReference>>() { - } - ) - .setInner(new InnerSpec().size(5).allValue(inner -> inner.size(5))) - .sample(); - - // then - then(actual).hasSize(5); - for (Map innerMap : actual.values()) { - then(innerMap).hasSize(5); - } - } - - @Test - void thenApplyAndSizeFieldContainer() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - ContainerObject actual = sut - .giveMeBuilder(ContainerObject.class) - .size("$.list", 1) - .thenApply((it, builder) -> builder.size("$.list", 3)) - .sample(); - - // then - then(actual.getList()).hasSize(3); - } - - @Test - void thenApplyAndSizeNestedFieldContainer() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector( - com.navercorp.fixturemonkey.api.introspector.FieldReflectionArbitraryIntrospector.INSTANCE - ) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - NestedListObject actual = sut - .giveMeBuilder(NestedListObject.class) - .size("$.nestedList", 2) - .size("$.nestedList[*]", 1) - .thenApply((it, builder) -> builder.size("$.nestedList", 2).size("$.nestedList[*]", 3)) - .sample(); - - // then - then(actual.getNestedList()).hasSize(2); - for (List inner : actual.getNestedList()) { - then(inner).hasSize(3); - } - } - - @Test - void setListValueOverridesRegisteredList() { - // given - JavaTypeObject registered = new JavaTypeObject(); - registered.setString("x"); - - JavaTypeObject expectedElement1 = new JavaTypeObject(); - expectedElement1.setString("a"); - JavaTypeObject expectedElement2 = new JavaTypeObject(); - expectedElement2.setString("b"); - JavaTypeObject expectedElement3 = new JavaTypeObject(); - expectedElement3.setString("c"); - JavaTypeObject expectedElement4 = new JavaTypeObject(); - expectedElement4.setString("d"); - JavaTypeObject expectedElement5 = new JavaTypeObject(); - expectedElement5.setString("e"); - - List expected = new java.util.ArrayList<>(Arrays.asList( - expectedElement1, expectedElement2, expectedElement3, expectedElement4, expectedElement5 - )); - - FixtureMonkey registerSut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> - fm - .giveMeBuilder(ContainerObject.class) - .set("complexList", new java.util.ArrayList<>(Arrays.asList(registered))) - ) - .build(); - - // when - ContainerObject actual = registerSut.giveMeBuilder(ContainerObject.class).set("complexList", expected).sample(); - - // then - then(actual.getComplexList()).hasSize(5); - } - - @Test - void setScalarFieldOverridesRegisteredScalarField() { - // given - String expected = "overridden"; - - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).set("string", "registered")) - .build(); - - // when - JavaTypeObject actual = sut.giveMeBuilder(JavaTypeObject.class).set("string", expected).sample(); - - // then - then(actual.getString()).isEqualTo(expected); - } - - @Test - void setNestedObjectFieldOverridesRegistered() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> - fm.giveMeBuilder(ContainerObject.class).set("complexList[0].string", "registered") - ) - .build(); - - // when - ContainerObject actual = sut - .giveMeBuilder(ContainerObject.class) - .size("complexList", 1) - .set("complexList[0].string", "overridden") - .sample(); - - // then - then(actual.getComplexList()).hasSize(1); - then(actual.getComplexList().get(0).getString()).isEqualTo("overridden"); - } - - @Test - void setContainerSmallerThanRegistered() { - // given - JavaTypeObject registeredElement1 = new JavaTypeObject(); - registeredElement1.setString("r1"); - JavaTypeObject registeredElement2 = new JavaTypeObject(); - registeredElement2.setString("r2"); - JavaTypeObject registeredElement3 = new JavaTypeObject(); - registeredElement3.setString("r3"); - - JavaTypeObject userElement = new JavaTypeObject(); - userElement.setString("u1"); - - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> - fm - .giveMeBuilder(ContainerObject.class) - .set("complexList", new java.util.ArrayList<>(Arrays.asList( - registeredElement1, registeredElement2, registeredElement3 - ))) - ) - .build(); - - // when - ContainerObject actual = sut - .giveMeBuilder(ContainerObject.class) - .set("complexList", new java.util.ArrayList<>(Arrays.asList(userElement))) - .sample(); - - // then - then(actual.getComplexList()).hasSize(1); - then(actual.getComplexList().get(0).getString()).isEqualTo("u1"); - } - - @Test - void setNonOverlappingFieldsWithRegister() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).set("string", "fromRegister")) - .build(); - - // when - JavaTypeObject actual = sut.giveMeBuilder(JavaTypeObject.class).set("wrapperInteger", 42).sample(); - - // then - then(actual.getString()).isEqualTo("fromRegister"); - then(actual.getWrapperInteger()).isEqualTo(42); - } - - @Test - void setElementOverridesRegisteredContainer() { - // given - JavaTypeObject registeredElement1 = new JavaTypeObject(); - registeredElement1.setString("r1"); - JavaTypeObject registeredElement2 = new JavaTypeObject(); - registeredElement2.setString("r2"); - - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> - fm - .giveMeBuilder(ContainerObject.class) - .set("complexList", - new java.util.ArrayList<>(Arrays.asList(registeredElement1, registeredElement2))) - ) - .build(); - - JavaTypeObject overriddenElement = new JavaTypeObject(); - overriddenElement.setString("overridden"); - - // when - ContainerObject actual = sut - .giveMeBuilder(ContainerObject.class) - .size("complexList", 2) - .set("complexList[0]", overriddenElement) - .sample(); - - // then - then(actual.getComplexList()).hasSize(2); - then(actual.getComplexList().get(0).getString()).isEqualTo("overridden"); - } - - @Test - void setWholeContainerOverridesRegisteredElement() { - // given - JavaTypeObject userElement1 = new JavaTypeObject(); - userElement1.setString("u1"); - JavaTypeObject userElement2 = new JavaTypeObject(); - userElement2.setString("u2"); - JavaTypeObject userElement3 = new JavaTypeObject(); - userElement3.setString("u3"); - - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> - fm - .giveMeBuilder(ContainerObject.class) - .size("complexList", 1) - .set("complexList[0].string", "registered") - ) - .build(); - - // when - ContainerObject actual = sut - .giveMeBuilder(ContainerObject.class) - .set("complexList", new java.util.ArrayList<>(Arrays.asList(userElement1, userElement2, userElement3))) - .sample(); - - // then - then(actual.getComplexList()).hasSize(3); - then(actual.getComplexList().get(0).getString()).isEqualTo("u1"); - then(actual.getComplexList().get(1).getString()).isEqualTo("u2"); - then(actual.getComplexList().get(2).getString()).isEqualTo("u3"); - } - - @Test - void setOverridesRegisteredThenApply() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(JavaTypeObject.class, fm -> - fm - .giveMeBuilder(JavaTypeObject.class) - .set("string", "initial") - .thenApply((it, builder) -> builder.set("string", "fromThenApply")) - ) - .build(); - - // when - JavaTypeObject actual = sut.giveMeBuilder(JavaTypeObject.class).set("string", "overridden").sample(); - - // then - then(actual.getString()).isEqualTo("overridden"); - } - - @Test - void setMapOverridesRegisteredMap() { - // given - Map registered = new java.util.HashMap<>(); - registered.put("regKey", 1); - - Map expected = new java.util.HashMap<>(); - expected.put("key1", 10); - expected.put("key2", 20); - expected.put("key3", 30); - - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).set("map", registered)) - .build(); - - // when - ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).set("map", expected).sample(); - - // then - then(actual.getMap()).hasSize(3); - then(actual.getMap()).containsEntry("key1", 10); - then(actual.getMap()).containsEntry("key2", 20); - then(actual.getMap()).containsEntry("key3", 30); - } - - @Test - void setNullOverridesRegisteredSet() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).set("string", "registered")) - .build(); - - // when - JavaTypeObject actual = sut.giveMeBuilder(JavaTypeObject.class).setNull("string").sample(); - - // then - then(actual.getString()).isNull(); - } - - @Test - void setOverridesRegisteredSetNull() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).setNull("string")) - .build(); - - // when - JavaTypeObject actual = sut.giveMeBuilder(JavaTypeObject.class).set("string", "overridden").sample(); - - // then - then(actual.getString()).isEqualTo("overridden"); - } - - @RepeatedTest(TEST_COUNT) - void setLazyOverridesRegisteredSet() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).set("string", "registered")) - .build(); - - // when - JavaTypeObject actual = sut - .giveMeBuilder(JavaTypeObject.class) - .setLazy("string", () -> "lazy") - .sample(); - - // then - then(actual.getString()).isEqualTo("lazy"); - } - - @RepeatedTest(TEST_COUNT) - void setPostConditionAppliesOnRegisteredSet() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).set("wrapperInteger", 10)) - .build(); - - // when - JavaTypeObject actual = sut - .giveMeBuilder(JavaTypeObject.class) - .setPostCondition("wrapperInteger", Integer.class, i -> i > 5) - .sample(); - - // then - then(actual.getWrapperInteger()).isGreaterThan(5); - } - - @Test - void setContainerOverridesRegisteredSize() { - // given - JavaTypeObject userElement1 = new JavaTypeObject(); - userElement1.setString("u1"); - JavaTypeObject userElement2 = new JavaTypeObject(); - userElement2.setString("u2"); - - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).size("complexList", 5)) - .build(); - - // when - ContainerObject actual = sut - .giveMeBuilder(ContainerObject.class) - .set("complexList", new java.util.ArrayList<>(Arrays.asList(userElement1, userElement2))) - .sample(); - - // then - then(actual.getComplexList()).hasSize(2); - then(actual.getComplexList().get(0).getString()).isEqualTo("u1"); - then(actual.getComplexList().get(1).getString()).isEqualTo("u2"); - } - - @Test - void sizeOverridesRegisteredSetContainer() { - // given - JavaTypeObject registeredElement = new JavaTypeObject(); - registeredElement.setString("r1"); - - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> - fm.giveMeBuilder(ContainerObject.class) - .set("complexList", new java.util.ArrayList<>(Arrays.asList(registeredElement))) - ) - .build(); - - // when - ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).size("complexList", 3).sample(); - - // then - then(actual.getComplexList()).hasSize(3); - } - - @Test - void thenApplySetOverridesRegisteredSet() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).set("string", "registered")) - .build(); - - // when - JavaTypeObject actual = sut - .giveMeBuilder(JavaTypeObject.class) - .thenApply((it, builder) -> builder.set("string", "fromThenApply")) - .sample(); - - // then - then(actual.getString()).isEqualTo("fromThenApply"); - } - - @Test - void setInnerOverridesRegisteredMap() { - // given - Map registered = new java.util.HashMap<>(); - registered.put("regKey", 1); - - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).set("map", registered)) - .build(); - - // when - ContainerObject actual = sut - .giveMeBuilder(ContainerObject.class) - .setInner(new InnerSpec().property("map", m -> m.size(2).entry("k1", 100).entry("k2", 200))) - .sample(); - - // then - then(actual.getMap()).hasSize(2); - then(actual.getMap()).containsEntry("k1", 100); - then(actual.getMap()).containsEntry("k2", 200); - } - - @RepeatedTest(TEST_COUNT) - void setOverridesRegisteredSetLazy() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(JavaTypeObject.class, fm -> - fm.giveMeBuilder(JavaTypeObject.class).setLazy("string", () -> "fromLazy") - ) - .build(); - - // when - JavaTypeObject actual = sut.giveMeBuilder(JavaTypeObject.class).set("string", "eager").sample(); - - // then - then(actual.getString()).isEqualTo("eager"); - } - - @Test - void setOverridesRegisteredSetInner() { - // given - JavaTypeObject userElement1 = new JavaTypeObject(); - userElement1.setString("u1"); - JavaTypeObject userElement2 = new JavaTypeObject(); - userElement2.setString("u2"); - - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> - fm - .giveMeBuilder(ContainerObject.class) - .setInner(new InnerSpec().property("complexList", l -> l.size(5))) - ) - .build(); - - // when - ContainerObject actual = sut - .giveMeBuilder(ContainerObject.class) - .set("complexList", new java.util.ArrayList<>(Arrays.asList(userElement1, userElement2))) - .sample(); - - // then - then(actual.getComplexList()).hasSize(2); - then(actual.getComplexList().get(0).getString()).isEqualTo("u1"); - then(actual.getComplexList().get(1).getString()).isEqualTo("u2"); - } - - @Test - void sizeOverridesRegisteredSetInner() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> - fm - .giveMeBuilder(ContainerObject.class) - .setInner(new InnerSpec().property("complexList", l -> l.size(5))) - ) - .build(); - - // when - ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).size("complexList", 2).sample(); - - // then - then(actual.getComplexList()).hasSize(2); - } - - @Test - void setLazyOverridesRegisteredSetNull() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).setNull("string")) - .build(); - - // when - JavaTypeObject actual = sut - .giveMeBuilder(JavaTypeObject.class) - .setLazy("string", () -> "fromLazy") - .sample(); - - // then - then(actual.getString()).isEqualTo("fromLazy"); - } - - @Test - void setNullOverridesRegisteredSetNotNull() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).setNotNull("string")) - .build(); - - // when - JavaTypeObject actual = sut.giveMeBuilder(JavaTypeObject.class).setNull("string").sample(); - - // then - then(actual.getString()).isNull(); - } - - @Test - void userSizeOverridesRegisteredSize() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).size("complexList", 5)) - .build(); - - // when - ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).size("complexList", 2).sample(); - - // then - then(actual.getComplexList()).hasSize(2); - } - - @Test - void registerOnlyAppliesWithoutUserOverride() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(JavaTypeObject.class, fm -> - fm.giveMeBuilder(JavaTypeObject.class).set("string", "fromRegister").set("wrapperInteger", 99) - ) - .build(); - - // when - JavaTypeObject actual = sut.giveMeOne(JavaTypeObject.class); - - // then - then(actual.getString()).isEqualTo("fromRegister"); - then(actual.getWrapperInteger()).isEqualTo(99); - } - - @Test - void setSpecificElementOverridesRegisteredWildcard() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> - fm.giveMeBuilder(ContainerObject.class).size("list", 3).set("list[*]", "registered") - ) - .build(); - - // when - ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).set("list[1]", "overridden").sample(); - - // then - then(actual.getList()).hasSize(3); - then(actual.getList().get(1)).isEqualTo("overridden"); - } - - @Test - void setRootObjectOverridesRegisteredField() { - // register sets a field, user sets the whole root object via "$" - // given - JavaTypeObject wholeObject = new JavaTypeObject(); - wholeObject.setString("fromRootSet"); - wholeObject.setWrapperInteger(77); - - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).set("string", "registered")) - .build(); - - // when - JavaTypeObject actual = sut.giveMeBuilder(JavaTypeObject.class).set("$", wholeObject).sample(); - - // then - then(actual.getString()).isEqualTo("fromRootSet"); - then(actual.getWrapperInteger()).isEqualTo(77); - } - - @Test - void setFieldOverridesRegisteredRootObject() { - // register sets the whole root object via "$", user sets a specific field - // given - JavaTypeObject registered = new JavaTypeObject(); - registered.setString("fromRegisterRoot"); - registered.setWrapperInteger(99); - - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).set("$", registered)) - .build(); - - // when - JavaTypeObject actual = sut.giveMeBuilder(JavaTypeObject.class).set("string", "overridden").sample(); - - // then - then(actual.getString()).isEqualTo("overridden"); - } - - @Test - void setRootObjectOverridesRegisteredRootObject() { - // both register and user set whole root object via "$" - // given - JavaTypeObject registered = new JavaTypeObject(); - registered.setString("fromRegister"); - registered.setWrapperInteger(1); - - JavaTypeObject userObj = new JavaTypeObject(); - userObj.setString("fromUser"); - userObj.setWrapperInteger(2); - - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).set("$", registered)) - .build(); - - // when - JavaTypeObject actual = sut.giveMeBuilder(JavaTypeObject.class).set("$", userObj).sample(); - - // then - then(actual.getString()).isEqualTo("fromUser"); - then(actual.getWrapperInteger()).isEqualTo(2); - } - - @Test - void setElementObjectOverridesRegisteredElementField() { - // register sets a field inside a list element, user sets the whole element as object - // given - JavaTypeObject userElement = new JavaTypeObject(); - userElement.setString("userObj"); - userElement.setWrapperInteger(55); - - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> - fm - .giveMeBuilder(ContainerObject.class) - .size("complexList", 2) - .set("complexList[0].string", "registered") - ) - .build(); - - // when - ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).set("complexList[0]", userElement).sample(); - - // then - then(actual.getComplexList().get(0).getString()).isEqualTo("userObj"); - then(actual.getComplexList().get(0).getWrapperInteger()).isEqualTo(55); - } - - @Test - void setElementFieldOverridesRegisteredElementObject() { - // register sets the whole element as object, user sets a field inside it - // given - JavaTypeObject registeredElement = new JavaTypeObject(); - registeredElement.setString("regObj"); - registeredElement.setWrapperInteger(33); - - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> - fm.giveMeBuilder(ContainerObject.class).size("complexList", 2).set("complexList[0]", registeredElement) - ) - .build(); - - // when - ContainerObject actual = sut - .giveMeBuilder(ContainerObject.class) - .set("complexList[0].string", "overridden") - .sample(); - - // then - then(actual.getComplexList().get(0).getString()).isEqualTo("overridden"); - } - - @Test - void setParentObjectOverridesRegisteredContainerField() { - // register sets a container field, user sets the parent object containing that field - // given - JavaTypeObject childElement = new JavaTypeObject(); - childElement.setString("e1"); - - ContainerObject userParent = new ContainerObject(); - userParent.setList(Arrays.asList("x", "y")); - userParent.setComplexList(new java.util.ArrayList<>(Arrays.asList(childElement))); - - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> - fm.giveMeBuilder(ContainerObject.class).size("list", 5).set("list[*]", "registered") - ) - .build(); - - // when - ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).set("$", userParent).sample(); - - // then - then(actual.getList()).hasSize(2); - then(actual.getList()).containsExactly("x", "y"); - then(actual.getComplexList()).hasSize(1); - then(actual.getComplexList().get(0).getString()).isEqualTo("e1"); - } - - // ================================ - // Container setNull combinations - // ================================ - - @Test - void setNullContainerOverridesRegisteredSetContainer() { - // given - JavaTypeObject registeredElement = new JavaTypeObject(); - registeredElement.setString("r1"); - - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> - fm.giveMeBuilder(ContainerObject.class) - .set("complexList", new java.util.ArrayList<>(Arrays.asList(registeredElement))) - ) - .build(); - - // when - ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).setNull("complexList").sample(); - - // then - then(actual.getComplexList()).isNull(); - } - - @Test - void setNullContainerOverridesRegisteredSize() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).size("complexList", 5)) - .build(); - - // when - ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).setNull("complexList").sample(); - - // then - then(actual.getComplexList()).isNull(); - } - - @Test - void setContainerOverridesRegisteredSetNull() { - // given - JavaTypeObject userElement = new JavaTypeObject(); - userElement.setString("u1"); - - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).setNull("complexList")) - .build(); - - // when - ContainerObject actual = sut - .giveMeBuilder(ContainerObject.class) - .set("complexList", new java.util.ArrayList<>(Arrays.asList(userElement))) - .sample(); - - // then - then(actual.getComplexList()).hasSize(1); - then(actual.getComplexList().get(0).getString()).isEqualTo("u1"); - } - - @Test - void sizeOverridesRegisteredSetNullContainer() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).setNull("complexList")) - .build(); - - // when - ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).size("complexList", 3).sample(); - - // then - then(actual.getComplexList()).hasSize(3); - } - - // ================================ - // Container setLazy combinations - // ================================ - - @Test - void setContainerOverridesRegisteredSetLazyContainer() { - // given - JavaTypeObject userElement = new JavaTypeObject(); - userElement.setString("u1"); - - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> - fm.giveMeBuilder(ContainerObject.class).setLazy("list", () -> Arrays.asList("lazy1", "lazy2", "lazy3")) - ) - .build(); - - // when - ContainerObject actual = sut - .giveMeBuilder(ContainerObject.class) - .set("list", new java.util.ArrayList<>(Arrays.asList("eager"))) - .sample(); - - // then - then(actual.getList()).hasSize(1); - then(actual.getList().get(0)).isEqualTo("eager"); - } - - @RepeatedTest(TEST_COUNT) - void setLazyContainerOverridesRegisteredSetContainer() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> - fm - .giveMeBuilder(ContainerObject.class) - .set("list", new java.util.ArrayList<>(Arrays.asList("reg1", "reg2"))) - ) - .build(); - - // when - ContainerObject actual = sut - .giveMeBuilder(ContainerObject.class) - .setLazy("list", () -> Arrays.asList("lazy1")) - .sample(); - - // then - then(actual.getList()).hasSize(1); - then(actual.getList().get(0)).isEqualTo("lazy1"); - } - - // ================================ - // Wildcard field path combinations - // ================================ - - @Test - void setSpecificElementFieldOverridesRegisteredWildcardField() { - // register sets all elements' field via wildcard, user sets specific element's field - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> - fm.giveMeBuilder(ContainerObject.class).size("complexList", 3).set("complexList[*].string", "wildcard") - ) - .build(); - - // when - ContainerObject actual = sut - .giveMeBuilder(ContainerObject.class) - .set("complexList[1].string", "specific") - .sample(); - - // then - then(actual.getComplexList()).hasSize(3); - then(actual.getComplexList().get(1).getString()).isEqualTo("specific"); - } - - @Test - void setWildcardFieldOverridesRegisteredSpecificElementField() { - // register sets specific element's field, user sets all via wildcard - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> - fm.giveMeBuilder(ContainerObject.class).size("complexList", 3).set("complexList[0].string", "specific") - ) - .build(); - - // when - ContainerObject actual = sut - .giveMeBuilder(ContainerObject.class) - .set("complexList[*].string", "wildcard") - .sample(); - - // then - then(actual.getComplexList()).hasSize(3); - for (JavaTypeObject elem : actual.getComplexList()) { - then(elem.getString()).isEqualTo("wildcard"); - } - } - - // ================================ - // setInner vs setInner - // ================================ - - @Test - void setInnerOverridesRegisteredSetInner() { - // both register and user use setInner on same container - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> - fm - .giveMeBuilder(ContainerObject.class) - .setInner(new InnerSpec().property("map", m -> m.size(5).entry("regKey", 999))) - ) - .build(); - - // when - ContainerObject actual = sut - .giveMeBuilder(ContainerObject.class) - .setInner(new InnerSpec().property("map", m -> m.size(2).entry("userKey", 1))) - .sample(); - - // then - then(actual.getMap()).hasSize(2); - then(actual.getMap()).containsKey("userKey"); - } - - // ================================ - // Size range combinations - // ================================ - - @RepeatedTest(TEST_COUNT) - void exactSizeOverridesRegisteredSizeRange() { - // register uses size range, user uses exact size - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).size("list", 1, 10)) - .build(); - - // when - ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).size("list", 3).sample(); - - // then - then(actual.getList()).hasSize(3); - } - - // ================================ - // Edge cases: empty container, size 0 - // ================================ - - @Test - void sizeExpandsRegisteredEmptyContainer() { - // register sets empty container, user expands with size - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> - fm.giveMeBuilder(ContainerObject.class).set("list", new java.util.ArrayList<>()) - ) - .build(); - - // when - ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).size("list", 3).sample(); - - // then - then(actual.getList()).hasSize(3); - } - - @Test - void setNonEmptyContainerOverridesRegisteredSizeZero() { - // register sets size to 0, user sets non-empty container - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).size("list", 0)) - .build(); - - // when - ContainerObject actual = sut - .giveMeBuilder(ContainerObject.class) - .set("list", new java.util.ArrayList<>(Arrays.asList("a", "b"))) - .sample(); - - // then - then(actual.getList()).hasSize(2); - then(actual.getList()).containsExactly("a", "b"); - } - - // ================================ - // Dual register: parent + child type - // ================================ - - @Test - void dualRegisterBothApplyWithoutUserOverride() { - // register ContainerObject (size) + register JavaTypeObject (field) - // both should apply when no user override - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).size("complexList", 3)) - .register(JavaTypeObject.class, fm -> - fm.giveMeBuilder(JavaTypeObject.class).set("string", "fromInnerRegister") - ) - .build(); - - // when - ContainerObject actual = sut.giveMeOne(ContainerObject.class); - - // then - then(actual.getComplexList()).hasSize(3); - for (JavaTypeObject elem : actual.getComplexList()) { - then(elem.getString()).isEqualTo("fromInnerRegister"); - } - } - - @Test - void dualRegisterUserOverridesElementField() { - // register ContainerObject (size) + register JavaTypeObject (field) - // user overrides specific element's field - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).size("complexList", 3)) - .register(JavaTypeObject.class, fm -> - fm.giveMeBuilder(JavaTypeObject.class).set("string", "fromInnerRegister") - ) - .build(); - - // when - ContainerObject actual = sut - .giveMeBuilder(ContainerObject.class) - .set("complexList[0].string", "userOverride") - .sample(); - - // then - then(actual.getComplexList()).hasSize(3); - then(actual.getComplexList().get(0).getString()).isEqualTo("userOverride"); - then(actual.getComplexList().get(1).getString()).isEqualTo("fromInnerRegister"); - then(actual.getComplexList().get(2).getString()).isEqualTo("fromInnerRegister"); - } - - @Test - void dualRegisterUserOverridesElementObject() { - // register ContainerObject (size) + register JavaTypeObject (field) - // user overrides a whole element object — should bypass inner register - // given - JavaTypeObject userObj = new JavaTypeObject(); - userObj.setString("userObj"); - userObj.setWrapperInteger(77); - - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).size("complexList", 3)) - .register(JavaTypeObject.class, fm -> - fm.giveMeBuilder(JavaTypeObject.class).set("string", "fromInnerRegister") - ) - .build(); - - // when - ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).set("complexList[0]", userObj).sample(); - - // then - then(actual.getComplexList()).hasSize(3); - then(actual.getComplexList().get(0).getString()).isEqualTo("userObj"); - then(actual.getComplexList().get(0).getWrapperInteger()).isEqualTo(77); - then(actual.getComplexList().get(1).getString()).isEqualTo("fromInnerRegister"); - } - - @Test - void dualRegisterUserOverridesWholeContainer() { - // register ContainerObject (container set) + register JavaTypeObject (field) - // user overrides whole container — should bypass both registers - // given - JavaTypeObject userElement = new JavaTypeObject(); - userElement.setString("u1"); - - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).size("complexList", 5)) - .register(JavaTypeObject.class, fm -> - fm.giveMeBuilder(JavaTypeObject.class).set("string", "fromInnerRegister") - ) - .build(); - - // when - ContainerObject actual = sut - .giveMeBuilder(ContainerObject.class) - .set("complexList", new java.util.ArrayList<>(Arrays.asList(userElement))) - .sample(); - - // then - then(actual.getComplexList()).hasSize(1); - then(actual.getComplexList().get(0).getString()).isEqualTo("u1"); - } - - @Test - void dualRegisterUserOverridesContainerSize() { - // register ContainerObject (size=5) + register JavaTypeObject (field) - // user overrides only size — inner register should still apply - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).size("complexList", 5)) - .register(JavaTypeObject.class, fm -> - fm.giveMeBuilder(JavaTypeObject.class).set("string", "fromInnerRegister") - ) - .build(); - - // when - ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).size("complexList", 2).sample(); - - // then - then(actual.getComplexList()).hasSize(2); - for (JavaTypeObject elem : actual.getComplexList()) { - then(elem.getString()).isEqualTo("fromInnerRegister"); - } - } - - @Test - void dualRegisterParentSetAndChildRootSet() { - // register ContainerObject (set container field) + register JavaTypeObject (set "$" root) - // given - JavaTypeObject registeredRoot = new JavaTypeObject(); - registeredRoot.setString("rootObj"); - registeredRoot.setWrapperInteger(42); - - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).size("complexList", 2)) - .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).set("$", registeredRoot)) - .build(); - - // when - ContainerObject actual = sut.giveMeOne(ContainerObject.class); - - // then - then(actual.getComplexList()).hasSize(2); - for (JavaTypeObject elem : actual.getComplexList()) { - then(elem.getString()).isEqualTo("rootObj"); - then(elem.getWrapperInteger()).isEqualTo(42); - } - } - - // ================================ - // Arbitrary set combinations - // ================================ - - @RepeatedTest(TEST_COUNT) - void setValueOverridesRegisteredArbitrary() { - // register sets field via Arbitrary, user sets plain value - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(JavaTypeObject.class, fm -> - fm.giveMeBuilder(JavaTypeObject.class).set("wrapperInteger", Arbitraries.integers().between(100, 200)) - ) - .build(); - - // when - JavaTypeObject actual = sut.giveMeBuilder(JavaTypeObject.class).set("wrapperInteger", 42).sample(); - - // then - then(actual.getWrapperInteger()).isEqualTo(42); - } - - @RepeatedTest(TEST_COUNT) - void setArbitraryOverridesRegisteredValue() { - // register sets plain value, user sets via Arbitrary - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).set("wrapperInteger", 999)) - .build(); - - // when - JavaTypeObject actual = sut - .giveMeBuilder(JavaTypeObject.class) - .set("wrapperInteger", Arbitraries.integers().between(1, 5)) - .sample(); - - // then - then(actual.getWrapperInteger()).isBetween(1, 5); - } - - @RepeatedTest(TEST_COUNT) - void setArbitraryOverridesRegisteredArbitrary() { - // both register and user set via Arbitrary - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(JavaTypeObject.class, fm -> - fm.giveMeBuilder(JavaTypeObject.class).set("wrapperInteger", Arbitraries.integers().between(100, 200)) - ) - .build(); - - // when - JavaTypeObject actual = sut - .giveMeBuilder(JavaTypeObject.class) - .set("wrapperInteger", Arbitraries.integers().between(1, 5)) - .sample(); - - // then - then(actual.getWrapperInteger()).isBetween(1, 5); - } - - @RepeatedTest(TEST_COUNT) - void registeredArbitraryAppliesWithoutUserOverride() { - // register sets via Arbitrary, no user override — Arbitrary should generate - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(JavaTypeObject.class, fm -> - fm.giveMeBuilder(JavaTypeObject.class).set("wrapperInteger", Arbitraries.integers().between(100, 200)) - ) - .build(); - - // when - JavaTypeObject actual = sut.giveMeOne(JavaTypeObject.class); - - // then - then(actual.getWrapperInteger()).isBetween(100, 200); - } - - @RepeatedTest(TEST_COUNT) - void dualRegisterUserSetsArbitraryOnElement() { - // dual register + user sets Arbitrary on a specific element field - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> fm.giveMeBuilder(ContainerObject.class).size("complexList", 3)) - .register(JavaTypeObject.class, fm -> fm.giveMeBuilder(JavaTypeObject.class).set("wrapperInteger", 999)) - .build(); - - // when - ContainerObject actual = sut - .giveMeBuilder(ContainerObject.class) - .set("complexList[0].wrapperInteger", Arbitraries.integers().between(1, 5)) - .sample(); - - // then - then(actual.getComplexList()).hasSize(3); - then(actual.getComplexList().get(0).getWrapperInteger()).isBetween(1, 5); - then(actual.getComplexList().get(1).getWrapperInteger()).isEqualTo(999); - then(actual.getComplexList().get(2).getWrapperInteger()).isEqualTo(999); - } - - @Test - void setElementOverridesRegisteredArbitraryOnWildcard() { - // register sets Arbitrary via wildcard, user sets specific element - // given - JavaTypeObject userObj = new JavaTypeObject(); - userObj.setString("userObj"); - - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> - fm - .giveMeBuilder(ContainerObject.class) - .size("complexList", 3) - .set("complexList[*].string", Arbitraries.strings().alpha().ofLength(10)) - ) - .build(); - - // when - ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).set("complexList[1]", userObj).sample(); - - // then - then(actual.getComplexList()).hasSize(3); - then(actual.getComplexList().get(1).getString()).isEqualTo("userObj"); - } - - @Test - void sizeOverridesRegisteredArbitraryContainer() { - // register sets container via Arbitrary.just(list), user overrides with size - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(ContainerObject.class, fm -> - fm - .giveMeBuilder(ContainerObject.class) - .set("list", Arbitraries.just(new java.util.ArrayList<>(Arrays.asList("a")))) - ) - .build(); - - // when - ContainerObject actual = sut.giveMeBuilder(ContainerObject.class).size("list", 4).sample(); - - // then - then(actual.getList()).hasSize(4); - } - - @lombok.Data - static class NestedListObject { - - private List> nestedList; - } -} diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/DataFakerArbitraryAdapterTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/DataFakerArbitraryAdapterTest.java deleted file mode 100644 index 624632528a..0000000000 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/DataFakerArbitraryAdapterTest.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.java.adapter; - -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; -import static org.assertj.core.api.BDDAssertions.then; - -import org.junit.jupiter.api.RepeatedTest; - -import com.navercorp.fixturemonkey.datafaker.arbitrary.DataFakerStringArbitrary; - -class DataFakerArbitraryAdapterTest { - - @RepeatedTest(TEST_COUNT) - void fullNameShouldNotBeBlank() { - String value = DataFakerStringArbitrary.name().fullName(); - then(value).isNotBlank(); - } - - @RepeatedTest(TEST_COUNT) - void firstNameShouldNotBeBlank() { - String value = DataFakerStringArbitrary.name().firstName(); - then(value).isNotBlank(); - } - - @RepeatedTest(TEST_COUNT) - void lastNameShouldNotBeBlank() { - String value = DataFakerStringArbitrary.name().lastName(); - then(value).isNotBlank(); - } - - @RepeatedTest(TEST_COUNT) - void fullAddressShouldNotBeBlank() { - String value = DataFakerStringArbitrary.address().fullAddress(); - then(value).isNotBlank(); - } - - @RepeatedTest(TEST_COUNT) - void cityShouldNotBeBlank() { - String value = DataFakerStringArbitrary.address().city(); - then(value).isNotBlank(); - } - - @RepeatedTest(TEST_COUNT) - void countryShouldNotBeBlank() { - String value = DataFakerStringArbitrary.address().country(); - then(value).isNotBlank(); - } - - @RepeatedTest(TEST_COUNT) - void zipCodeShouldNotBeBlank() { - String value = DataFakerStringArbitrary.address().zipCode(); - then(value).isNotBlank(); - } - - @RepeatedTest(TEST_COUNT) - void emailAddressShouldContainAtSymbol() { - String value = DataFakerStringArbitrary.internet().emailAddress(); - then(value).contains("@"); - } - - @RepeatedTest(TEST_COUNT) - void domainNameShouldNotBeBlank() { - String value = DataFakerStringArbitrary.internet().domainName(); - then(value).isNotBlank(); - } - - @RepeatedTest(TEST_COUNT) - void urlShouldStartWithHttpOrHttps() { - String value = DataFakerStringArbitrary.internet().url(); - then(value).startsWith("www"); - } - - @RepeatedTest(TEST_COUNT) - void phoneNumberShouldNotBeBlank() { - String value = DataFakerStringArbitrary.phoneNumber().cellPhone(); - then(value).isNotBlank(); - } - - @RepeatedTest(TEST_COUNT) - void creditCardShouldNotBeBlank() { - String value = DataFakerStringArbitrary.finance().creditCard(); - then(value).isNotBlank(); - } -} diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/DefaultNullInjectGeneratorAdapterTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/DefaultNullInjectGeneratorAdapterTest.java deleted file mode 100644 index c114b2a351..0000000000 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/DefaultNullInjectGeneratorAdapterTest.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.java.adapter; - -import static com.navercorp.fixturemonkey.api.generator.DefaultNullInjectGenerator.ALWAYS_NULL_INJECT; -import static com.navercorp.fixturemonkey.api.generator.DefaultNullInjectGenerator.DEFAULT_NOTNULL_ANNOTATION_TYPES; -import static com.navercorp.fixturemonkey.api.generator.DefaultNullInjectGenerator.DEFAULT_NULLABLE_ANNOTATION_TYPES; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; -import static org.assertj.core.api.BDDAssertions.then; - -import java.util.HashSet; - -import org.junit.jupiter.api.RepeatedTest; - -import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; -import com.navercorp.fixturemonkey.api.generator.DefaultNullInjectGenerator; -import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; -import com.navercorp.fixturemonkey.tests.java.specs.DefaultNullInjectGeneratorSpecs.NonNullAnnotationObject; -import com.navercorp.fixturemonkey.tests.java.specs.DefaultNullInjectGeneratorSpecs.NullableAnnotationObject; - -class DefaultNullInjectGeneratorAdapterTest { - @RepeatedTest(TEST_COUNT) - void nonNullAnnotations() { - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .defaultNullInjectGenerator( - new DefaultNullInjectGenerator( - ALWAYS_NULL_INJECT, - false, - false, - false, - new HashSet<>(DEFAULT_NULLABLE_ANNOTATION_TYPES), - new HashSet<>(DEFAULT_NOTNULL_ANNOTATION_TYPES) - ) - ) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - NonNullAnnotationObject actual = sut.giveMeOne(NonNullAnnotationObject.class); - - then(actual.getJavaxNonNullField()).isNotNull(); - then(actual.getJspecifyNonNullField()).isNotNull(); - then(actual.getCheckerNonNullField()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void nullableAnnotations() { - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .defaultNullInjectGenerator( - new DefaultNullInjectGenerator( - ALWAYS_NULL_INJECT, - false, - true, - false, - new HashSet<>(DEFAULT_NULLABLE_ANNOTATION_TYPES), - new HashSet<>(DEFAULT_NOTNULL_ANNOTATION_TYPES) - ) - ) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - NullableAnnotationObject actual = sut.giveMeOne(NullableAnnotationObject.class); - - then(actual.getJavaxNullableField()).isNull(); - then(actual.getJspecifyNullableField()).isNull(); - then(actual.getCheckerNullableField()).isNull(); - } -} diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/GenericTypeAdapterTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/GenericTypeAdapterTest.java deleted file mode 100644 index 40fa664eac..0000000000 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/GenericTypeAdapterTest.java +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.java.adapter; - -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; -import static org.assertj.core.api.BDDAssertions.then; - -import java.time.Instant; - -import org.junit.jupiter.api.RepeatedTest; - -import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; -import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; -import com.navercorp.fixturemonkey.api.type.TypeReference; -import com.navercorp.fixturemonkey.tests.java.specs.GenericTypeSpecs.GenericArrayObject; -import com.navercorp.fixturemonkey.tests.java.specs.GenericTypeSpecs.GenericImplementationObject; -import com.navercorp.fixturemonkey.tests.java.specs.GenericTypeSpecs.GenericObject; -import com.navercorp.fixturemonkey.tests.java.specs.GenericTypeSpecs.ThreeGenericObject; -import com.navercorp.fixturemonkey.tests.java.specs.GenericTypeSpecs.TwoGenericImplementationObject; -import com.navercorp.fixturemonkey.tests.java.specs.GenericTypeSpecs.TwoGenericObject; -import com.navercorp.fixturemonkey.tests.java.specs.ImmutableSpecs.SetImplementationWithoutGeneric; - -@SuppressWarnings("rawtypes") -class GenericTypeAdapterTest { - private static final FixtureMonkey SUT = FixtureMonkey.builder() - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - @RepeatedTest(TEST_COUNT) - void sampleGenericObjectWithoutGeneric() { - GenericObject actual = SUT.giveMeOne(GenericObject.class); - - then(actual).isNotNull(); - then(actual.getValue()).isInstanceOf(Object.class); - } - - @RepeatedTest(TEST_COUNT) - void fixedGenericObjectWithoutGeneric() { - GenericObject actual = SUT.giveMeBuilder(GenericObject.class) - .fixed() - .sample(); - - then(actual).isNotNull(); - then(actual.getValue()).isInstanceOf(Object.class); - } - - @RepeatedTest(TEST_COUNT) - void sampleGenericObject() { - String actual = SUT.giveMeOne(new TypeReference>() { - }) - .getValue(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedGenericObject() { - String actual = SUT.giveMeBuilder(new TypeReference>() { - }) - .fixed() - .sample() - .getValue(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleGenericImplementationObjectWithoutGeneric() { - GenericImplementationObject actual = SUT.giveMeOne(GenericImplementationObject.class); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedGenericImplementationObjectWithoutGeneric() { - GenericImplementationObject actual = SUT.giveMeBuilder(GenericImplementationObject.class) - .fixed() - .sample(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleGenericImplementationObject() { - String actual = SUT.giveMeOne(new TypeReference>() { - }) - .getValue(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedGenericImplementationObject() { - String actual = SUT.giveMeBuilder(new TypeReference>() { - }) - .fixed() - .sample() - .getValue(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleTwoGenericImplementationObjectWithoutGeneric() { - TwoGenericImplementationObject actual = SUT.giveMeOne(TwoGenericImplementationObject.class); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedTwoGenericImplementationObjectWithoutGeneric() { - TwoGenericImplementationObject actual = SUT.giveMeBuilder(TwoGenericImplementationObject.class) - .fixed() - .sample(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleTwoGenericImplementationObject() { - TwoGenericImplementationObject actual = SUT.giveMeOne( - new TypeReference>() { - } - ); - - then(actual.getUValue()).isNotNull(); - then(actual.getTValue()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedTwoGenericImplementationObject() { - TwoGenericImplementationObject actual = SUT.giveMeBuilder( - new TypeReference>() { - } - ) - .fixed() - .sample(); - - then(actual.getUValue()).isNotNull(); - then(actual.getTValue()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleSetImplementationWithoutGeneric() { - String actual = SUT.giveMeOne(SetImplementationWithoutGeneric.class) - .getValue(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedSetImplementationWithoutGeneric() { - String actual = SUT.giveMeBuilder(SetImplementationWithoutGeneric.class) - .fixed() - .sample() - .getValue(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleGenericArrayType() { - GenericImplementationObject[] values = SUT.giveMeOne(new TypeReference>() { - }) - .getValues(); - - then(values).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedGenericArrayType() { - GenericImplementationObject[] values = SUT.giveMeBuilder( - new TypeReference>() { - }) - .fixed() - .sample() - .getValues(); - - then(values).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleTwoGenericObject() { - TwoGenericObject actual = SUT.giveMeOne( - new TypeReference>() { - }); - - then(actual.getValue1()).isNotNull(); - then(actual.getValue2()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedTwoGenericObject() { - TwoGenericObject actual = SUT.giveMeBuilder( - new TypeReference>() { - - }) - .fixed() - .sample(); - - then(actual.getValue1()).isNotNull(); - then(actual.getValue2()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleTwoGenericObjectProperty() { - TwoGenericObject actual = SUT.giveMeOne( - new TypeReference>>() { - }) - .getValue(); - - then(actual.getValue1()).isNotNull(); - then(actual.getValue2()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedTwoGenericObjectProperty() { - TwoGenericObject actual = SUT.giveMeOne( - new TypeReference>>() { - }) - .getValue(); - - then(actual.getValue1()).isNotNull(); - then(actual.getValue2()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleThreeGenericObjectProperty() { - ThreeGenericObject actual = SUT.giveMeOne( - new TypeReference>>() { - }) - .getValue(); - - then(actual.getValue1()).isNotNull(); - then(actual.getValue2()).isNotNull(); - then(actual.getValue3()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedThreeGenericObjectProperty() { - ThreeGenericObject actual = SUT.giveMeOne( - new TypeReference>>() { - }) - .getValue(); - - then(actual.getValue1()).isNotNull(); - then(actual.getValue2()).isNotNull(); - then(actual.getValue3()).isNotNull(); - } -} diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/InstantiatorAdapterTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/InstantiatorAdapterTest.java deleted file mode 100644 index a22e428134..0000000000 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/InstantiatorAdapterTest.java +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.java.adapter; - -import static com.navercorp.fixturemonkey.api.instantiator.Instantiator.constructor; -import static com.navercorp.fixturemonkey.api.instantiator.Instantiator.factoryMethod; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; -import static org.assertj.core.api.BDDAssertions.then; - -import java.lang.reflect.Modifier; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.OptionalDouble; -import java.util.OptionalInt; -import java.util.OptionalLong; - -import org.junit.jupiter.api.RepeatedTest; - -import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; -import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; -import com.navercorp.fixturemonkey.api.type.TypeReference; -import com.navercorp.fixturemonkey.tests.java.specs.ConstructorSpecs; -import com.navercorp.fixturemonkey.tests.java.specs.ConstructorSpecs.SimpleContainerObject; -import com.navercorp.fixturemonkey.tests.java.specs.MutableSpecs; - -class InstantiatorAdapterTest { - private static final FixtureMonkey SUT = FixtureMonkey.builder() - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - @RepeatedTest(TEST_COUNT) - void instantiateParametersInOrder() { - String actual = SUT.giveMeBuilder(ConstructorSpecs.JavaTypeObject.class) - .instantiate( - ConstructorSpecs.JavaTypeObject.class, - constructor() - .parameter(int.class) - .parameter(float.class) - .parameter(long.class) - .parameter(double.class) - .parameter(byte.class) - .parameter(char.class) - .parameter(short.class) - .parameter(boolean.class) - ) - .sample() - .getString(); - - then(actual).isEqualTo("first"); - } - - @RepeatedTest(TEST_COUNT) - void instantiateNoArgsConstructor() { - String actual = SUT.giveMeBuilder(ConstructorSpecs.JavaTypeObject.class) - .instantiate( - ConstructorSpecs.JavaTypeObject.class, - constructor() - ) - .sample() - .getString(); - - then(actual).isEqualTo("second"); - } - - @RepeatedTest(TEST_COUNT) - void instantiateParameterNameHint() { - String actual = SUT.giveMeBuilder(ConstructorSpecs.JavaTypeObject.class) - .instantiate( - ConstructorSpecs.JavaTypeObject.class, - constructor() - .parameter(String.class, "str") - ) - .set("str", "third") - .sample() - .getString(); - - then(actual).isEqualTo("third"); - } - - @RepeatedTest(TEST_COUNT) - void instantiateConstructorContainer() { - List actual = SUT.giveMeBuilder(SimpleContainerObject.class) - .instantiate( - SimpleContainerObject.class, - constructor() - .parameter(new TypeReference>() { - }, "list") - ) - .instantiate( - ConstructorSpecs.JavaTypeObject.class, - constructor() - .parameter(int.class) - .parameter(float.class) - .parameter(long.class) - .parameter(double.class) - .parameter(byte.class) - .parameter(char.class) - .parameter(short.class) - .parameter(boolean.class) - ) - .size("list", 1) - .sample() - .getList(); - - then(actual).hasSize(1); - } - - @RepeatedTest(TEST_COUNT) - void instantiateConstructorGenericContainer() { - String actual = SUT.giveMeBuilder(ConstructorSpecs.ContainerObject.class) - .instantiate( - ConstructorSpecs.ContainerObject.class, - constructor() - .parameter(new TypeReference>() { - }) - .parameter(new TypeReference>() { - }) - .parameter(new TypeReference>() { - }) - .parameter(new TypeReference>() { - }) - .parameter(new TypeReference>() { - }) - .parameter(new TypeReference>() { - }) - .parameter(new TypeReference>() { - }) - .parameter(new TypeReference>() { - }) - .parameter(new TypeReference>() { - }) - .parameter(new TypeReference() { - }) - .parameter(new TypeReference() { - }) - .parameter(new TypeReference() { - }) - ) - .instantiate( - ConstructorSpecs.JavaTypeObject.class, - constructor() - .parameter(int.class) - .parameter(float.class) - .parameter(long.class) - .parameter(double.class) - .parameter(byte.class) - .parameter(char.class) - .parameter(short.class) - .parameter(boolean.class) - ) - .sample() - .getArray()[0]; - - then(actual).isEqualTo("test"); - } - - @RepeatedTest(TEST_COUNT) - void instantiateGenericObjectByConstructor() { - ConstructorSpecs.GenericObject actual = SUT.giveMeBuilder( - new TypeReference>() { - }) - .instantiate( - new TypeReference>() { - }, - constructor() - .parameter(String.class) - ) - .sample(); - - then(actual).isNotNull(); - then(actual.getValue()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void instantiateTwoGenericObjectByConstructor() { - ConstructorSpecs.TwoGenericObject actual = SUT.giveMeBuilder( - new TypeReference>() { - }) - .instantiate( - new TypeReference>() { - }, - constructor() - .parameter(String.class) - .parameter(Integer.class) - ) - .sample(); - - then(actual).isNotNull(); - then(actual.getTValue()).isNotNull(); - then(actual.getUValue()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void instantiateGenericObjectWithHintByConstructor() { - ConstructorSpecs.GenericObject actual = SUT.giveMeBuilder( - new TypeReference>() { - }) - .instantiate( - new TypeReference>() { - }, - constructor() - .parameter(String.class) - ) - .sample(); - - then(actual).isNotNull(); - then(actual.getValue()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void instantiateByFactoryMethod() { - String actual = SUT.giveMeBuilder(ConstructorSpecs.JavaTypeObject.class) - .instantiate( - factoryMethod("from") - ) - .sample() - .getString(); - - then(actual).isEqualTo("factory"); - } - - @RepeatedTest(TEST_COUNT) - void instantiateByFactoryMethodWithParameter() { - String actual = SUT.giveMeBuilder(ConstructorSpecs.JavaTypeObject.class) - .instantiate( - factoryMethod("from") - .parameter(String.class) - ) - .sample() - .getString(); - - then(actual).isEqualTo("factory"); - } - - @RepeatedTest(TEST_COUNT) - void instantiateFactoryMethodAndField() { - Integer actual = SUT.giveMeBuilder(ConstructorSpecs.JavaTypeObject.class) - .instantiate( - factoryMethod("from") - .parameter(String.class) - .field() - ) - .sample() - .getWrapperInteger(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void instantiateConstructorField() { - String actual = SUT.giveMeBuilder(MutableSpecs.JavaTypeObject.class) - .instantiate(constructor().field()) - .sample() - .getString(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void instantiateConstructorJavaBeansProperty() { - String actual = SUT.giveMeBuilder(MutableSpecs.JavaTypeObject.class) - .instantiate(constructor().javaBeansProperty()) - .sample() - .getString(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void instantiateConstructorFieldFilter() { - MutableSpecs.JavaTypeObject actual = - SUT.giveMeBuilder(MutableSpecs.JavaTypeObject.class) - .instantiate( - constructor() - .field(it -> it.filter(field -> !Modifier.isPrivate(field.getModifiers()))) - ) - .sample(); - - then(actual.getString()).isNull(); - then(actual.getWrapperBoolean()).isNull(); - } - - @RepeatedTest(TEST_COUNT) - void instantiateConstructorJavaBeansPropertyFilter() { - MutableSpecs.JavaTypeObject actual = - SUT.giveMeBuilder(MutableSpecs.JavaTypeObject.class) - .instantiate( - constructor() - .javaBeansProperty(it -> it.filter(property -> !"string".equals(property.getName()))) - ) - .sample(); - - then(actual.getString()).isNull(); - then(actual.getWrapperBoolean()).isNotNull(); - } -} diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/IntrospectorAdapterTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/IntrospectorAdapterTest.java deleted file mode 100644 index 9db5947fe7..0000000000 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/IntrospectorAdapterTest.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.java.adapter; - -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; -import static org.assertj.core.api.BDDAssertions.then; -import static org.assertj.core.api.BDDAssertions.thenNoException; - -import java.util.Arrays; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; - -import org.junit.jupiter.api.RepeatedTest; -import org.junit.jupiter.api.Test; - -import net.jqwik.api.Arbitraries; - -import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; -import com.navercorp.fixturemonkey.api.introspector.BeanArbitraryIntrospector; -import com.navercorp.fixturemonkey.api.introspector.CompositeArbitraryIntrospector; -import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; -import com.navercorp.fixturemonkey.api.introspector.FailoverIntrospector; -import com.navercorp.fixturemonkey.api.introspector.FieldReflectionArbitraryIntrospector; -import com.navercorp.fixturemonkey.resolver.ArbitraryBuilderCandidateFactory; -import com.navercorp.fixturemonkey.resolver.ArbitraryBuilderCandidateList; -import com.navercorp.fixturemonkey.tests.java.specs.ConstructorPropertySpecs.ConsturctorAndProperty; -import com.navercorp.fixturemonkey.tests.java.specs.ConstructorSpecs.FieldAndConstructorParameterMismatchObject; -import com.navercorp.fixturemonkey.tests.java.specs.DepthSpecs.DepthStringValueList; -import com.navercorp.fixturemonkey.tests.java.specs.DepthSpecs.OneDepthStringValue; -import com.navercorp.fixturemonkey.tests.java.specs.DepthSpecs.TwoDepthStringValue; -import com.navercorp.fixturemonkey.tests.java.specs.ImmutableSpecs.JavaTypeObject; -import com.navercorp.fixturemonkey.tests.java.specs.MixedIntrospectorsSpecs.MixedJavaTypeObject; -import com.navercorp.fixturemonkey.tests.java.specs.NoArgsConstructorSpecs.NestedObject; - -class IntrospectorAdapterTest { - @RepeatedTest(TEST_COUNT) - void registerListWouldNotCached() { - AtomicInteger sequence = new AtomicInteger(); - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .registerGroup(() -> ArbitraryBuilderCandidateList.create() - .add( - ArbitraryBuilderCandidateFactory - .of(DepthStringValueList.class) - .builder(builder -> builder.size("twoDepthList", 3)) - ) - .add( - ArbitraryBuilderCandidateFactory - .of(OneDepthStringValue.class) - .builder(builder -> builder.set( - "value", - Arbitraries.ofSuppliers(() -> String.valueOf(sequence.getAndIncrement())) - )) - ) - ) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - Set actual = sut.giveMe(DepthStringValueList.class, 3).stream() - .flatMap(it -> it.getTwoDepthList().stream()) - .map(TwoDepthStringValue::getValue) - .map(OneDepthStringValue::getValue) - .collect(Collectors.toSet()); - - then(actual).hasSize(9); - } - - @Test - void failoverIntrospector() { - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(new FailoverIntrospector( - Arrays.asList( - FieldReflectionArbitraryIntrospector.INSTANCE, - ConstructorPropertiesArbitraryIntrospector.INSTANCE - ) - ) - ) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - thenNoException().isThrownBy(() -> sut.giveMeOne(JavaTypeObject.class)); - } - - @Test - void failoverIntrospectorMixed() { - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(new FailoverIntrospector( - Arrays.asList( - FieldReflectionArbitraryIntrospector.INSTANCE, - ConstructorPropertiesArbitraryIntrospector.INSTANCE - ) - ) - ) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - thenNoException().isThrownBy(() -> sut.giveMeOne(MixedJavaTypeObject.class)); - } - - @RepeatedTest(TEST_COUNT) - void compositeArbitraryIntrospector() { - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector( - new CompositeArbitraryIntrospector( - Arrays.asList( - ConstructorPropertiesArbitraryIntrospector.INSTANCE, - FieldReflectionArbitraryIntrospector.INSTANCE - ) - ) - ) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - ConsturctorAndProperty actual = - sut.giveMeOne(ConsturctorAndProperty.class); - - then(actual.getValue()).isNotNull(); - then(actual.getPropertyNotInConstructor()).isNotNull(); - } - - @Test - void beanArbitraryIntrospectorSampleTwiceResultNotMutated() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - NestedObject stringObject = sut.giveMeOne(NestedObject.class); - String actual = stringObject.getObject().getValue(); - - // when - sut.giveMeOne(NestedObject.class); - - // then - String expected = stringObject.getObject().getValue(); - then(actual).isEqualTo(expected); - } - - @Test - void fieldReflectionArbitraryIntrospectorSampleTwiceResultNotMutated() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - NestedObject stringObject = sut.giveMeOne(NestedObject.class); - String actual = stringObject.getObject().getValue(); - - // when - sut.giveMeOne(NestedObject.class); - - // then - String expected = stringObject.getObject().getValue(); - then(actual).isEqualTo(expected); - } - - @Test - void fieldAndConstructorParameterMismatch() { - FixtureMonkey sut = FixtureMonkey.builder() - .pushExactTypeArbitraryIntrospector( - FieldAndConstructorParameterMismatchObject.class, - ConstructorPropertiesArbitraryIntrospector.INSTANCE - ) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - String actual = sut.giveMeOne(FieldAndConstructorParameterMismatchObject.class).getValue(); - - then(actual).isNotNull(); - } -} diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/JacksonAdapterTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/JacksonAdapterTest.java deleted file mode 100644 index 7f0dae6185..0000000000 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/JacksonAdapterTest.java +++ /dev/null @@ -1,673 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.java.adapter; - -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; -import static org.assertj.core.api.BDDAssertions.then; -import static org.assertj.core.api.BDDAssertions.thenNoException; - -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; - -import org.junit.jupiter.api.RepeatedTest; - -import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; -import com.navercorp.fixturemonkey.adapter.tracing.AdapterTracer; -import com.navercorp.fixturemonkey.api.type.TypeReference; -import com.navercorp.fixturemonkey.jackson.plugin.JacksonPlugin; -import com.navercorp.fixturemonkey.tests.java.specs.ImmutableSpecs.ContainerObject; -import com.navercorp.fixturemonkey.tests.java.specs.ImmutableSpecs.Enum; -import com.navercorp.fixturemonkey.tests.java.specs.ImmutableSpecs.JavaTypeObject; -import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.ConstructorObject; -import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonEnum; -import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonFormatObject; -import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonNodeWrapper; -import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonPropertyConstructor; -import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonPropertyContainerOuter; -import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonPropertyInner; -import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonPropertyMultipleFields; -import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonPropertyOuter; -import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonPropertyWithNormalField; -import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonPropertyWithOuter; -import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonTypeInfoFieldOuter; -import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonTypeInfoIdClass; -import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonTypeInfoIdName; -import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonTypeInfoList; -import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonTypeInfoListInSetter; -import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonTypeInfoListInSetterIncludeWrapperObject; -import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.JsonTypeInfoListIncludeWrapperObject; -import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.PayPreApproval; -import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.Type; -import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.TypeWithAnnotations; -import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.TypeWithAnnotationsIncludeWrapperObjectList; -import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.TypeWithAnnotationsList; -import com.navercorp.fixturemonkey.tests.java.specs.JacksonSpecs.TypeWithAnnotationsValue; - -class JacksonAdapterTest { - - private static final FixtureMonkey SUT = FixtureMonkey.builder() - .plugin(new JacksonPlugin()) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - @RepeatedTest(TEST_COUNT) - void jsonTypeInfoName() { - thenNoException().isThrownBy(() -> SUT.giveMeOne(JsonTypeInfoIdName.class)); - } - - @RepeatedTest(TEST_COUNT) - void jsonTypeInfoList() { - thenNoException().isThrownBy(() -> SUT.giveMeOne(JsonTypeInfoList.class)); - } - - @RepeatedTest(TEST_COUNT) - void jsonTypeInfoIdClass() { - thenNoException().isThrownBy(() -> SUT.giveMeOne(JsonTypeInfoIdClass.class)); - } - - @RepeatedTest(TEST_COUNT) - void jsonTypeWithAnnotations() { - thenNoException().isThrownBy(() -> SUT.giveMeOne(TypeWithAnnotationsValue.class)); - } - - @RepeatedTest(TEST_COUNT) - void jsonTypeWithAnnotationsList() { - thenNoException().isThrownBy(() -> SUT.giveMeOne(TypeWithAnnotationsList.class)); - } - - @RepeatedTest(TEST_COUNT) - void jsonTypeInfoListInSetter() { - thenNoException().isThrownBy(() -> SUT.giveMeOne(JsonTypeInfoListInSetter.class)); - } - - @RepeatedTest(TEST_COUNT) - void jsonTypeInfoListIncludeWrapperObject() { - thenNoException().isThrownBy(() -> SUT.giveMeOne(JsonTypeInfoListIncludeWrapperObject.class)); - } - - @RepeatedTest(TEST_COUNT) - void jsonTypeInfoListInSetterIncludeWrapperObject() { - thenNoException().isThrownBy(() -> SUT.giveMeOne(JsonTypeInfoListInSetterIncludeWrapperObject.class)); - } - - @RepeatedTest(TEST_COUNT) - void jsonTypeWithAnnotationsIncludeWrapperObjectList() { - thenNoException().isThrownBy(() -> SUT.giveMeOne(TypeWithAnnotationsIncludeWrapperObjectList.class)); - } - - @RepeatedTest(TEST_COUNT) - void sampleContainerType() { - ContainerObject actual = SUT.giveMeOne(ContainerObject.class); - - then(actual.getPrimitiveArray()).isNotNull(); - then(actual.getArray()).isNotNull(); - then(actual.getComplexArray()).isNotNull(); - then(actual.getList()).isNotNull(); - then(actual.getComplexList()).isNotNull(); - then(actual.getSet()).isNotNull(); - then(actual.getComplexSet()).isNotNull(); - then(actual.getMap()).isNotNull(); - then(actual.getComplexMap()).isNotNull(); - then(actual.getMapEntry()).isNotNull(); - then(actual.getComplexMapEntry()).isNotNull(); - then(actual.getOptional()).isNotNull(); - then(actual.getOptionalInt()).isNotNull(); - then(actual.getOptionalLong()).isNotNull(); - then(actual.getOptionalDouble()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleListType() { - List actual = SUT.giveMeOne(new TypeReference>() { - }); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedListType() { - List actual = SUT.giveMeBuilder(new TypeReference>() { - }).fixed().sample(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleSetType() { - Set actual = SUT.giveMeOne(new TypeReference>() { - }); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedSetType() { - Set actual = SUT.giveMeBuilder(new TypeReference>() { - }).fixed().sample(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleArrayType() { - JavaTypeObject[] actual = SUT.giveMeOne(new TypeReference() { - }); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedArrayType() { - JavaTypeObject[] actual = SUT.giveMeBuilder(new TypeReference() { - }).fixed().sample(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleOptionalType() { - Optional actual = SUT.giveMeOne(new TypeReference>() { - }); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedOptionalType() { - Optional actual = SUT.giveMeBuilder(new TypeReference>() { - }) - .fixed() - .sample(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleMapType() { - Map actual = SUT.giveMeOne(new TypeReference>() { - }); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedMapType() { - Map actual = SUT.giveMeBuilder(new TypeReference>() { - }) - .fixed() - .sample(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleMapEntryType() { - Map.Entry actual = SUT.giveMeOne( - new TypeReference>() { - } - ); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedMapEntryType() { - Map.Entry actual = SUT.giveMeBuilder( - new TypeReference>() { - } - ) - .fixed() - .sample(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleEnumKeyMap() { - thenNoException().isThrownBy(() -> - SUT.giveMeBuilder(new TypeReference>>() { - }).size("$", 2).sample() - ); - } - - @RepeatedTest(TEST_COUNT) - void sampleConstructorObject() { - ConstructorObject actual = SUT.giveMeOne(ConstructorObject.class); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void setDecomposedValueShouldRespectJsonProperty() { - // when - JsonPropertyOuter actual = SUT.giveMeBuilder(JsonPropertyOuter.class) - .set("inner", new JsonPropertyInner("expected")) - .sample(); - - // then - then(actual.getInner()).isNotNull(); - then(actual.getInner().getOriginalField()).isEqualTo("expected"); - } - - @RepeatedTest(TEST_COUNT) - void setDecomposedValueJsonPropertyShouldRespectJsonProperty() { - // when - JsonPropertyWithOuter actual = SUT.giveMeBuilder(JsonPropertyWithOuter.class) - .set("outer", new JsonPropertyInner("expected")) - .sample(); - - // then - then(actual.getInner()).isNotNull(); - then(actual.getInner().getOriginalField()).isEqualTo("expected"); - } - - @RepeatedTest(TEST_COUNT) - void setDecomposedValueShouldRespectInnerJsonProperty() { - // given - String expected = "expected"; - - // when - String actual = SUT.giveMeBuilder(JsonPropertyOuter.class) - .set("inner.renamed", expected) - .sample() - .getInner() - .getOriginalField(); - - // then - then(actual).isEqualTo(expected); - } - - @RepeatedTest(TEST_COUNT) - void setDecomposedValueShouldRespectJsonPropertyDiff() { - // when - String actual = SUT.giveMeBuilder(JsonPropertyInner.class) - .set("renamed", "expected") - .sample() - .getOriginalField(); - - // then - then(actual).isEqualTo("expected"); - } - - @RepeatedTest(TEST_COUNT) - void sizeByJsonPropertyNameShouldWork() { - // when - JsonPropertyContainerOuter actual = SUT.giveMeBuilder(JsonPropertyContainerOuter.class) - .size("body", 0) - .sample(); - - // then - then(actual.getContents()).isEmpty(); - } - - // A. @JsonProperty + 조작자 - - @RepeatedTest(TEST_COUNT) - void setNullByJsonPropertyName() { - // when - JsonPropertyWithNormalField actual = SUT.giveMeBuilder(JsonPropertyWithNormalField.class) - .setNull("renamed") - .sample(); - - // then - then(actual.getOriginalField()).isNull(); - } - - @RepeatedTest(TEST_COUNT) - void setNotNullByJsonPropertyName() { - // when - JsonPropertyWithNormalField actual = SUT.giveMeBuilder(JsonPropertyWithNormalField.class) - .setNotNull("renamed") - .sample(); - - // then - then(actual.getOriginalField()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void setLazyByJsonPropertyName() { - // when - String actual = SUT.giveMeBuilder(JsonPropertyInner.class) - .setLazy("renamed", () -> "lazy") - .sample() - .getOriginalField(); - - // then - then(actual).isEqualTo("lazy"); - } - - @RepeatedTest(TEST_COUNT) - void setPostConditionByJsonPropertyName() { - // when - String actual = SUT.giveMeBuilder(JsonPropertyInner.class) - .setPostCondition("renamed", String.class, it -> it != null && it.startsWith("a")) - .sample() - .getOriginalField(); - - // then - then(actual).startsWith("a"); - } - - @RepeatedTest(TEST_COUNT) - void setNullNestedJsonPropertyPath() { - // when - JsonPropertyOuter actual = SUT.giveMeBuilder(JsonPropertyOuter.class).setNull("inner.renamed").sample(); - - // then - then(actual.getInner()).isNotNull(); - then(actual.getInner().getOriginalField()).isNull(); - } - - @RepeatedTest(TEST_COUNT) - void setNotNullNestedJsonPropertyPath() { - // when - JsonPropertyOuter actual = SUT.giveMeBuilder(JsonPropertyOuter.class).setNotNull("inner.renamed").sample(); - - // then - then(actual.getInner()).isNotNull(); - then(actual.getInner().getOriginalField()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void setNullContainerByJsonPropertyName() { - // when - JsonPropertyContainerOuter actual = SUT.giveMeBuilder(JsonPropertyContainerOuter.class) - .setNull("body") - .sample(); - - // then - then(actual.getContents()).isNull(); - } - - @RepeatedTest(TEST_COUNT) - void setNotNullContainerByJsonPropertyName() { - // when - JsonPropertyContainerOuter actual = SUT.giveMeBuilder(JsonPropertyContainerOuter.class) - .setNotNull("body") - .sample(); - - // then - then(actual.getContents()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void setMultipleJsonPropertyFields() { - // when - JsonPropertyMultipleFields actual = SUT.giveMeBuilder(JsonPropertyMultipleFields.class) - .set("name", "testName") - .set("age", 25) - .set("active", true) - .sample(); - - // then - then(actual.getOriginalName()).isEqualTo("testName"); - then(actual.getOriginalAge()).isEqualTo(25); - then(actual.isOriginalActive()).isTrue(); - } - - @RepeatedTest(TEST_COUNT) - void thenApplySetByJsonPropertyName() { - // when - JsonPropertyWithNormalField actual = SUT.giveMeBuilder(JsonPropertyWithNormalField.class) - .thenApply((it, builder) -> builder.set("renamed", "applied")) - .sample(); - - // then - then(actual.getOriginalField()).isEqualTo("applied"); - } - - @RepeatedTest(TEST_COUNT) - void acceptIfSetByJsonPropertyName() { - // when - JsonPropertyWithNormalField actual = SUT.giveMeBuilder(JsonPropertyWithNormalField.class) - .acceptIf(it -> true, builder -> builder.set("renamed", "accepted")) - .sample(); - - // then - then(actual.getOriginalField()).isEqualTo("accepted"); - } - - @RepeatedTest(TEST_COUNT) - void registerWithJsonPropertyFields() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JacksonPlugin()) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(JsonPropertyWithNormalField.class, fixture -> - fixture.giveMeBuilder(JsonPropertyWithNormalField.class).set("renamed", "registered") - ) - .build(); - - // when - JsonPropertyWithNormalField actual = sut.giveMeOne(JsonPropertyWithNormalField.class); - - // then - then(actual.getOriginalField()).isEqualTo("registered"); - } - - @RepeatedTest(TEST_COUNT) - void registerThenUserOverrideByJsonPropertyName() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JacksonPlugin()) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(JsonPropertyWithNormalField.class, fixture -> - fixture.giveMeBuilder(JsonPropertyWithNormalField.class).set("renamed", "registered") - ) - .build(); - - // when - JsonPropertyWithNormalField actual = sut - .giveMeBuilder(JsonPropertyWithNormalField.class) - .set("renamed", "overridden") - .sample(); - - // then - then(actual.getOriginalField()).isEqualTo("overridden"); - } - - @RepeatedTest(TEST_COUNT) - void setLazyNestedJsonPropertyPath() { - // when - String actual = SUT.giveMeBuilder(JsonPropertyOuter.class) - .setLazy("inner.renamed", () -> "lazyNested") - .sample() - .getInner() - .getOriginalField(); - - // then - then(actual).isEqualTo("lazyNested"); - } - - @RepeatedTest(TEST_COUNT) - void sizeAndSetElementByJsonPropertyName() { - // when - JsonPropertyContainerOuter actual = SUT.giveMeBuilder(JsonPropertyContainerOuter.class) - .size("body", 2) - .set("body[0]", "first") - .sample(); - - // then - then(actual.getContents()).hasSize(2); - then(actual.getContents().get(0)).isEqualTo("first"); - } - - // B. @JsonTypeInfo + adapter - - @RepeatedTest(TEST_COUNT) - void jsonTypeInfoSetSiblingField() { - // when - JsonTypeInfoFieldOuter actual = SUT.giveMeBuilder(JsonTypeInfoFieldOuter.class).set("name", "hello").sample(); - - // then - then(actual.getName()).isEqualTo("hello"); - then(actual.getType()).isInstanceOf(Type.class); - } - - @RepeatedTest(TEST_COUNT) - void jsonTypeInfoSetNull() { - // when - JsonTypeInfoFieldOuter actual = SUT.giveMeBuilder(JsonTypeInfoFieldOuter.class).setNull("type").sample(); - - // then - then(actual.getType()).isNull(); - } - - @RepeatedTest(TEST_COUNT) - void jsonTypeInfoSetNotNull() { - // when - JsonTypeInfoFieldOuter actual = SUT.giveMeBuilder(JsonTypeInfoFieldOuter.class).setNotNull("type").sample(); - - // then - then(actual.getType()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void jsonTypeInfoListSize() { - // when - JsonTypeInfoFieldOuter actual = SUT.giveMeBuilder(JsonTypeInfoFieldOuter.class).size("types", 3).sample(); - - // then - then(actual.getTypes()).hasSize(3); - then(actual.getTypes()).allSatisfy(it -> then(it).isInstanceOf(Type.class)); - } - - @RepeatedTest(TEST_COUNT) - void jsonTypeInfoSetSiblingFieldAndSetNotNull() { - // when - JsonTypeInfoFieldOuter actual = SUT.giveMeBuilder(JsonTypeInfoFieldOuter.class) - .set("name", "hello") - .setNotNull("type") - .sample(); - - // then - then(actual.getName()).isEqualTo("hello"); - then(actual.getType()).isNotNull(); - then(actual.getType()).isInstanceOf(Type.class); - } - - @RepeatedTest(TEST_COUNT) - void jsonTypeInfoRegister() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JacksonPlugin()) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .register(JsonTypeInfoFieldOuter.class, fixture -> - fixture.giveMeBuilder(JsonTypeInfoFieldOuter.class).set("name", "registered") - ) - .build(); - - // when - JsonTypeInfoFieldOuter actual = sut.giveMeOne(JsonTypeInfoFieldOuter.class); - - // then - then(actual.getName()).isEqualTo("registered"); - then(actual.getType()).isInstanceOf(Type.class); - } - - @RepeatedTest(TEST_COUNT) - void jsonTypeInfoInterfaceAnnotationsSetNotNull() { - // when - TypeWithAnnotationsValue actual = SUT.giveMeBuilder(TypeWithAnnotationsValue.class).setNotNull("type").sample(); - - // then - then(actual.getType()).isNotNull(); - then(actual.getType()).isInstanceOf(TypeWithAnnotations.class); - } - - // C. @JsonFormat + adapter - - @RepeatedTest(TEST_COUNT) - void jsonFormatGeneration() { - thenNoException().isThrownBy(() -> SUT.giveMeOne(JsonFormatObject.class)); - } - - @RepeatedTest(TEST_COUNT) - void jsonFormatSetEnumField() { - // when - JsonFormatObject actual = SUT.giveMeBuilder(JsonFormatObject.class).set("enumValue", JsonEnum.TWO).sample(); - - // then - then(actual.getEnumValue()).isEqualTo(JsonEnum.TWO); - } - - // D. JsonNode + adapter - - @RepeatedTest(TEST_COUNT) - void jsonNodeFieldGeneration() { - thenNoException().isThrownBy(() -> SUT.giveMeOne(JsonNodeWrapper.class)); - } - - @RepeatedTest(TEST_COUNT) - void jsonNodeFieldSetNull() { - // when - JsonNodeWrapper actual = SUT.giveMeBuilder(JsonNodeWrapper.class).setNull("value").sample(); - - // then - then(actual.getValue()).isNull(); - } - - // E. Constructor + @JsonProperty - - @RepeatedTest(TEST_COUNT) - void constructorJsonPropertySet() { - // when - JsonPropertyConstructor actual = SUT.giveMeBuilder(JsonPropertyConstructor.class).set("id", "test").sample(); - - // then - then(actual.getIdentifier()).isEqualTo("test"); - } - - @RepeatedTest(TEST_COUNT) - void constructorJsonPropertySetNull() { - // when - JsonPropertyConstructor actual = SUT.giveMeBuilder(JsonPropertyConstructor.class).setNull("id").sample(); - - // then - then(actual.getIdentifier()).isNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleNestedValueTypeWithDefaultNotNull() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JacksonPlugin()) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin() - .tracer(AdapterTracer.console())) - .build(); - - // when - PayPreApproval actual = sut.giveMeOne(PayPreApproval.class); - - // then - then(actual).isNotNull(); - then(actual.getPayMethod()).isNotNull(); - then(actual.getPayMethod().getFirstPayMethod()).isNotNull(); - then(actual.getPayMethod().getFirstPayMethod().getPayMethodType()).isNotNull(); - } - -} diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/JavaGetterPropertyFieldNameResolverAdapterTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/JavaGetterPropertyFieldNameResolverAdapterTest.java deleted file mode 100644 index 8c9d28bbdc..0000000000 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/JavaGetterPropertyFieldNameResolverAdapterTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.java.adapter; - -import static com.navercorp.fixturemonkey.api.expression.JavaGetterMethodPropertySelector.javaGetter; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; -import static org.assertj.core.api.BDDAssertions.then; - -import org.junit.jupiter.api.RepeatedTest; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; -import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; - -class JavaGetterPropertyFieldNameResolverAdapterTest { - private static final FixtureMonkey SUT = FixtureMonkey.builder() - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - @RepeatedTest(TEST_COUNT) - void nonBooleanFieldWithIsPrefixReturns() { - JavaGetterObject actual = SUT.giveMeBuilder(JavaGetterObject.class) - .set(javaGetter(JavaGetterObject::getIsStatus), "javaGetterStringStatus") - .sample(); - - then(actual.getIsStatus()).isEqualTo("javaGetterStringStatus"); - } - - @RepeatedTest(TEST_COUNT) - void primitiveTypeBooleanFieldWithIsPrefixReturns() { - JavaGetterObject actual = SUT.giveMeBuilder(JavaGetterObject.class) - .set(javaGetter(JavaGetterObject::isActive), true) - .sample(); - - then(actual.isActive).isTrue(); - } - - @RepeatedTest(TEST_COUNT) - void booleanFieldWithoutIsPrefixReturns() { - JavaGetterObject actual = SUT.giveMeBuilder(JavaGetterObject.class) - .set(javaGetter(JavaGetterObject::isEnabled), true) - .sample(); - - then(actual.isEnabled()).isTrue(); - } - - @RepeatedTest(TEST_COUNT) - void nonBooleanFieldWithoutIsPrefixReturns() { - JavaGetterObject actual = SUT.giveMeBuilder(JavaGetterObject.class) - .set(javaGetter(JavaGetterObject::getName), "javaGetterObjectName") - .sample(); - - then(actual.getName()).isEqualTo("javaGetterObjectName"); - } - - @RepeatedTest(TEST_COUNT) - void wrapperTypeBooleanFieldWithIsPrefixReturns() { - JavaGetterObject actual = SUT.giveMeBuilder(JavaGetterObject.class) - .set(javaGetter(JavaGetterObject::getIsDeleted), true) - .sample(); - - then(actual.isDeleted).isTrue(); - } - - @AllArgsConstructor - @Getter - private static class JavaGetterObject { - private String isStatus; - private boolean isActive; - private boolean enabled; - private String name; - private Boolean isDeleted; - } -} diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/LoggingAdapterTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/LoggingAdapterTest.java deleted file mode 100644 index 1f229ea664..0000000000 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/LoggingAdapterTest.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.java.adapter; - -import static org.assertj.core.api.BDDAssertions.thenThrownBy; - -import org.junit.jupiter.api.Test; - -import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; -import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; -import com.navercorp.fixturemonkey.customizer.InnerSpec; -import com.navercorp.fixturemonkey.tests.java.specs.ImmutableSpecs.ContainerObject; -import com.navercorp.fixturemonkey.tests.java.specs.ImmutableSpecs.JavaTypeObject; -import com.navercorp.fixturemonkey.tests.java.specs.ImmutableSpecs.RootJavaTypeObject; - -class LoggingAdapterTest { - private static final FixtureMonkey SUT = FixtureMonkey.builder() - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - @Test - void logRoot() { - thenThrownBy( - () -> SUT.giveMeBuilder(String.class) - .setPostCondition(it -> it.equals("test")) - .sample() - ) - .getCause() - .hasMessageContaining("\"$\""); - } - - @Test - void logProperty() { - thenThrownBy( - () -> SUT.giveMeBuilder(JavaTypeObject.class) - .setPostCondition("string", String.class, it -> it.equals("test")) - .sample() - ) - .getCause() - .hasMessageContaining("\"string\""); - } - - @Test - void logNestedProperty() { - thenThrownBy( - () -> SUT.giveMeBuilder(RootJavaTypeObject.class) - .setPostCondition("value.string", String.class, it -> it.equals("test")) - .sample() - ) - .getCause() - .hasMessageContaining("\"value.string\""); - } - - @Test - void logArrayElement() { - thenThrownBy( - () -> SUT.giveMeBuilder(ContainerObject.class) - .size("array", 1) - .setPostCondition("array[0]", String.class, it -> it.equals("test")) - .sample() - ) - .getCause() - .hasMessageContaining("\"array[0]\""); - } - - @Test - void logListElement() { - thenThrownBy( - () -> SUT.giveMeBuilder(ContainerObject.class) - .size("list", 1) - .setPostCondition("list[0]", String.class, it -> it.equals("test")) - .sample() - ) - .getCause() - .hasMessageContaining("\"list[0]\""); - } - - @Test - void logListElementProperty() { - thenThrownBy( - () -> SUT.giveMeBuilder(ContainerObject.class) - .size("complexList", 1) - .setPostCondition("complexList[0].string", String.class, it -> it.equals("test")) - .sample() - ) - .getCause() - .hasMessageContaining("\"complexList[0].string\""); - } - - @Test - void logMapElementKeyProperty() { - thenThrownBy( - () -> SUT.giveMeBuilder(ContainerObject.class) - .setInner( - new InnerSpec() - .property("map", m -> - m.size(1) - .key(v -> v.postCondition(String.class, it -> it.equals("test"))) - ) - ) - .sample() - ) - .getCause() - .hasMessageContaining("\"map{key}\""); - } - - @Test - void logMapElementValueProperty() { - thenThrownBy( - () -> SUT.giveMeBuilder(ContainerObject.class) - .setInner( - new InnerSpec() - .property("map", m -> - m.size(1) - .value(v -> v.postCondition(Integer.class, it -> it == -987654321)) - ) - ) - .sample() - ) - .getCause() - .hasMessageContaining("\"map{value}\""); - } -} diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/PluginAdapterTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/PluginAdapterTest.java deleted file mode 100644 index 14f688394e..0000000000 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/PluginAdapterTest.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.java.adapter; - -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; -import static org.assertj.core.api.BDDAssertions.then; -import static org.assertj.core.api.BDDAssertions.thenThrownBy; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -import org.junit.jupiter.api.RepeatedTest; -import org.junit.jupiter.api.Test; - -import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; -import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; -import com.navercorp.fixturemonkey.api.plugin.InterfacePlugin; -import com.navercorp.fixturemonkey.api.plugin.SimpleValueJqwikPlugin; -import com.navercorp.fixturemonkey.api.type.TypeReference; -import com.navercorp.fixturemonkey.datafaker.plugin.DataFakerPlugin; -import com.navercorp.fixturemonkey.javax.validation.plugin.JavaxValidationPlugin; -import com.navercorp.fixturemonkey.tests.java.specs.ConstructorSpecs.JavaxValidationObject; -import com.navercorp.fixturemonkey.tests.java.specs.DataFakerSpecs; -import com.navercorp.fixturemonkey.tests.java.specs.InterfaceSpecs.AbstractClassObject; -import com.navercorp.fixturemonkey.tests.java.specs.InterfaceSpecs.AbstractClassStringChildObject; -import com.navercorp.fixturemonkey.tests.java.specs.InterfaceSpecs.InterfaceIntegerObject; -import com.navercorp.fixturemonkey.tests.java.specs.InterfaceSpecs.InterfaceListObject; -import com.navercorp.fixturemonkey.tests.java.specs.InterfaceSpecs.InterfaceObject; -import com.navercorp.fixturemonkey.tests.java.specs.InterfaceSpecs.InterfaceStringObject; -import com.navercorp.fixturemonkey.tests.java.specs.InterfaceSpecs.InterfaceWrapperObject; - -class PluginAdapterTest { - @RepeatedTest(TEST_COUNT) - void setListRecursiveImplementations() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .plugin(new InterfacePlugin() - .interfaceImplements( - InterfaceObject.class, - Arrays.asList( - InterfaceStringObject.class, - InterfaceIntegerObject.class, - InterfaceListObject.class))) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - List element = sut.giveMeOne( - new com.navercorp.fixturemonkey.api.type.TypeReference>() { - }).stream() - .map(InterfaceObject.class::cast) - .collect(Collectors.toList()); - InterfaceListObject expected = new InterfaceListObject(element); - - // when - InterfaceWrapperObject actual = sut.giveMeBuilder(InterfaceWrapperObject.class) - .set("value", expected) - .sample(); - - then(actual.getValue()).isEqualTo(expected); - } - - @RepeatedTest(TEST_COUNT) - void constructorValidator() { - FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaxValidationPlugin()) - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - JavaxValidationObject actual = sut.giveMeOne(JavaxValidationObject.class); - - then(actual.getValue()).isEqualTo(100); - } - - @RepeatedTest(TEST_COUNT) - void abstractClassExtends() { - FixtureMonkey sut = FixtureMonkey.builder() - .plugin( - new InterfacePlugin() - .abstractClassExtends( - AbstractClassObject.class, - Collections.singletonList(AbstractClassStringChildObject.class))) - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - AbstractClassObject actual = sut.giveMeOne(AbstractClassObject.class); - - then(actual).isExactlyInstanceOf(AbstractClassStringChildObject.class); - } - - @Test - void abstractExtendsInterfaceThrows() { - thenThrownBy( - () -> FixtureMonkey.builder() - .plugin( - new InterfacePlugin() - .abstractClassExtends( - InterfaceObject.class, - Collections.singletonList(InterfaceStringObject.class))) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build()) - .isExactlyInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("should be abstract class"); - } - - @Test - void interfaceImplementsAbstractClassThrows() { - thenThrownBy( - () -> FixtureMonkey.builder() - .plugin( - new InterfacePlugin() - .interfaceImplements( - AbstractClassObject.class, - Collections.singletonList(AbstractClassStringChildObject.class))) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build()) - .isExactlyInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("should be interface"); - } - - @Test - void simpleValueJqwikPluginMinNumberValueGreaterThanDefault() { - // given - long expected = 10001L; - FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new SimpleValueJqwikPlugin() - .minNumberValue(expected)) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - // when - long actual = sut.giveMeOne(Long.class); - - then(actual).isGreaterThanOrEqualTo(expected); - } - - @Test - void simpleValueJqwikPluginMinStringLengthGreaterThanDefault() { - // given - long expected = 10L; - FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new SimpleValueJqwikPlugin() - .minStringLength(expected)) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - // when - String actual = sut.giveMeOne(String.class); - - // then - then(actual.length()).isGreaterThanOrEqualTo((int)expected); - } - - @Test - void simpleValueJqwikPluginMinContainerSizeGreaterThanDefault() { - // given - int expected = 5; - FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new SimpleValueJqwikPlugin() - .minContainerSize(expected)) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - // when - List actual = sut.giveMeOne(new TypeReference>() { - }); - - // then - then(actual.size()).isGreaterThanOrEqualTo(expected); - } - - @Test - void simpleValueJqwikPluginMinusDaysFromTodayGreaterThanDefault() { - // given - long expected = 400L; - FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new SimpleValueJqwikPlugin() - .minusDaysFromToday(expected)) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - // when - java.time.LocalDateTime actual = sut.giveMeOne(java.time.LocalDateTime.class); - - // then - java.time.LocalDateTime expectedMinDate = java.time.LocalDateTime.now().minusDays(expected); - java.time.LocalDateTime expectedMaxDate = java.time.LocalDateTime.now().plusDays(expected + 30L); - then(actual).isBetween(expectedMinDate, expectedMaxDate); - } - - @RepeatedTest(TEST_COUNT) - void dataFakerPluginGeneratesUserFields() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .defaultNotNull(true) - .plugin(new DataFakerPlugin()) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - DataFakerSpecs.User actual = sut.giveMeOne(DataFakerSpecs.User.class); - - // then - then(actual.getFullName()).isNotBlank(); - then(actual.getEmail()).contains("@"); - then(actual.getHomeAddress()).isNotBlank(); - then(actual.getPhoneNumber()).isNotBlank(); - } - - @RepeatedTest(TEST_COUNT) - void dataFakerPluginGeneratesFinanceFields() { - // given - FixtureMonkey sut = FixtureMonkey.builder() - .defaultNotNull(true) - .plugin(new DataFakerPlugin()) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - DataFakerSpecs.Finance actual = sut.giveMeOne(DataFakerSpecs.Finance.class); - - // then - then(actual.getCreditCard()).isNotBlank(); - } -} diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/PriorityConstructorArbitraryIntrospectorAdapterTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/PriorityConstructorArbitraryIntrospectorAdapterTest.java deleted file mode 100644 index d325d4170c..0000000000 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/PriorityConstructorArbitraryIntrospectorAdapterTest.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.java.adapter; - -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; -import static org.assertj.core.api.BDDAssertions.then; - -import java.sql.Timestamp; -import java.util.Arrays; - -import org.junit.jupiter.api.RepeatedTest; -import org.junit.jupiter.api.Test; - -import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; -import com.navercorp.fixturemonkey.api.introspector.PriorityConstructorArbitraryIntrospector; -import com.navercorp.fixturemonkey.api.type.TypeReference; -import com.navercorp.fixturemonkey.tests.java.specs.GenericTypeSpecs.GenericObject; -import com.navercorp.fixturemonkey.tests.java.specs.GenericTypeSpecs.TwoGenericObject; -import com.navercorp.fixturemonkey.tests.java.specs.GenericTypeSpecs.TwoGenericObjectConstructorParameterOrderDiff; -import com.navercorp.fixturemonkey.tests.java.specs.GenericTypeSpecs.TwoGenericObjectConstructorParameterOrderDiffNameDiff; - -class PriorityConstructorArbitraryIntrospectorAdapterTest { - private static final FixtureMonkey SUT = FixtureMonkey.builder() - .objectIntrospector(PriorityConstructorArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - @RepeatedTest(TEST_COUNT) - void sample() { - Timestamp actual = SUT.giveMeOne(Timestamp.class); - - then(actual).isNotNull(); - } - - @Test - void setWithoutName() { - Timestamp actual = SUT.giveMeBuilder(Timestamp.class) - .set("time", 0) - .sample(); - - Timestamp expected = new Timestamp(0); - then(actual).isNotEqualTo(expected); - } - - @RepeatedTest(TEST_COUNT) - void set() { - // given - PriorityConstructorArbitraryIntrospector priorityConstructorArbitraryIntrospector = - PriorityConstructorArbitraryIntrospector.INSTANCE.withParameterNamesResolver( - constructor -> Arrays.asList("time") - ); - - FixtureMonkey sut = FixtureMonkey.builder() - .objectIntrospector(priorityConstructorArbitraryIntrospector) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - // when - Timestamp actual = sut.giveMeBuilder(Timestamp.class) - .set("time", 0) - .sample(); - - // then - Timestamp expected = new Timestamp(0); - then(actual).isEqualTo(expected); - } - - @RepeatedTest(TEST_COUNT) - void genericType() { - String actual = SUT.giveMeOne(new TypeReference>() { - }).getValue(); - - then(actual).isExactlyInstanceOf(String.class); - } - - @RepeatedTest(TEST_COUNT) - void twoGenericType() { - TwoGenericObject actual = SUT.giveMeOne( - new TypeReference>() { - }); - - then(actual.getValue1()).isExactlyInstanceOf(String.class); - then(actual.getValue2()).isExactlyInstanceOf(Integer.class); - } - - @RepeatedTest(TEST_COUNT) - void twoGenericObjectConstructorParameterOrderDiff() { - TwoGenericObjectConstructorParameterOrderDiff actual = SUT.giveMeOne( - new TypeReference>() { - }); - - then(actual.getValue1()).isExactlyInstanceOf(String.class); - then(actual.getValue2()).isExactlyInstanceOf(Integer.class); - } - - @RepeatedTest(TEST_COUNT) - void twoGenericObjectConstructorParameterOrderDiffNameDiff() { - TwoGenericObjectConstructorParameterOrderDiffNameDiff actual = SUT.giveMeOne( - new TypeReference>() { - }); - - then(actual.getValue1()).isExactlyInstanceOf(String.class); - then(actual.getValue2()).isExactlyInstanceOf(Integer.class); - } -} diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/PropertySelectorAdapterTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/PropertySelectorAdapterTest.java deleted file mode 100644 index 67f3b4131e..0000000000 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/PropertySelectorAdapterTest.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.java.adapter; - -import static com.navercorp.fixturemonkey.api.experimental.JavaGetterMethodPropertySelector.javaGetter; -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; -import static org.assertj.core.api.BDDAssertions.then; - -import java.util.List; -import java.util.stream.Collectors; - -import org.junit.jupiter.api.RepeatedTest; -import org.junit.jupiter.api.Test; - -import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; -import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; -import com.navercorp.fixturemonkey.tests.java.specs.ImmutableSpecs.ContainerObject; -import com.navercorp.fixturemonkey.tests.java.specs.ImmutableSpecs.JavaTypeObject; -import com.navercorp.fixturemonkey.tests.java.specs.ImmutableSpecs.RootJavaTypeObject; -import com.navercorp.fixturemonkey.tests.java.specs.NestedClassSpecs.Inner; - -class PropertySelectorAdapterTest { - - private static final FixtureMonkey SUT = FixtureMonkey.builder() - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - @RepeatedTest(TEST_COUNT) - void nestedObject() { - Inner actual = SUT.giveMeOne(Inner.class); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void setJavaGetter() { - String actual = SUT.giveMeBuilder(JavaTypeObject.class) - .set(javaGetter(JavaTypeObject::getString), "test") - .sample() - .getString(); - - then(actual).isEqualTo("test"); - } - - @RepeatedTest(TEST_COUNT) - void setJavaGetterInto() { - String actual = SUT.giveMeBuilder(RootJavaTypeObject.class) - .set(javaGetter(RootJavaTypeObject::getValue).into(JavaTypeObject::getString), "test") - .sample() - .getValue() - .getString(); - - then(actual).isEqualTo("test"); - } - - @RepeatedTest(TEST_COUNT) - void setJavaGetterCollection() { - String actual = SUT.giveMeBuilder(ContainerObject.class) - .size("list", 1) - .set(javaGetter(ContainerObject::getList).index(String.class, 0), "test") - .sample() - .getList() - .get(0); - - then(actual).isEqualTo("test"); - } - - @RepeatedTest(TEST_COUNT) - void setJavaGetterCollectionElement() { - String actual = SUT.giveMeBuilder(ContainerObject.class) - .size("complexList", 1) - .set( - javaGetter(ContainerObject::getComplexList) - .index(JavaTypeObject.class, 0) - .into(JavaTypeObject::getString), - "test" - ) - .sample() - .getComplexList() - .get(0) - .getString(); - - then(actual).isEqualTo("test"); - } - - @RepeatedTest(TEST_COUNT) - void setJavaGetterCollectionAllElement() { - String expected = "test"; - - List actual = SUT.giveMeBuilder(ContainerObject.class) - .size("complexList", 3) - .set( - javaGetter(ContainerObject::getComplexList) - .allIndex(JavaTypeObject.class) - .into(JavaTypeObject::getString), - expected - ) - .sample() - .getComplexList() - .stream() - .map(JavaTypeObject::getString) - .collect(Collectors.toList()); - - then(actual).allMatch(expected::equals); - } - - @Test - void typedJavaGetter() { - String expected = "expected"; - - String actual = SUT.giveMeBuilder(JavaTypeObject.class) - .customizeProperty(javaGetter(JavaTypeObject::getString), arb -> arb.map(it -> expected)) - .sample() - .getString(); - - then(actual).isEqualTo(expected); - } - - @Test - void nestedTypedJavaGetter() { - String expected = "expected"; - - String actual = SUT.giveMeBuilder(RootJavaTypeObject.class) - .customizeProperty(javaGetter(RootJavaTypeObject::getValue).into(JavaTypeObject::getString), arb -> - arb.map(it -> expected) - ) - .sample() - .getValue() - .getString(); - - then(actual).isEqualTo(expected); - } - - @Test - void indexTypedJavaGetter() { - String expected = "expected"; - - String actual = SUT.giveMeBuilder(ContainerObject.class) - .size("list", 1) - .customizeProperty(javaGetter(ContainerObject::getList).index(String.class, 0), arb -> - arb.map(it -> expected) - ) - .sample() - .getList() - .get(0); - - then(actual).isEqualTo(expected); - } - - @RepeatedTest(TEST_COUNT) - void setExp() { - String actual = SUT.giveMeJavaBuilder(JavaTypeObject.class) - .setExpGetter(JavaTypeObject::getString, "test") - .sample() - .getString(); - - then(actual).isEqualTo("test"); - } - - @RepeatedTest(TEST_COUNT) - void setExpCollectionElement() { - String actual = SUT.giveMeJavaBuilder(ContainerObject.class) - .size("complexList", 1) - .setExpGetter( - javaGetter(ContainerObject::getComplexList) - .index(JavaTypeObject.class, 0) - .into(JavaTypeObject::getString), - "test" - ) - .sample() - .getComplexList() - .get(0) - .getString(); - - then(actual).isEqualTo("test"); - } -} diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/RecursiveTypeAdapterTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/RecursiveTypeAdapterTest.java deleted file mode 100644 index 96d1033d19..0000000000 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/RecursiveTypeAdapterTest.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.java.adapter; - -import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; -import static org.assertj.core.api.BDDAssertions.then; - -import java.util.List; -import java.util.Map; - -import org.junit.jupiter.api.RepeatedTest; - -import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; -import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; -import com.navercorp.fixturemonkey.api.type.TypeReference; -import com.navercorp.fixturemonkey.tests.java.specs.RecursiveTypeSpecs.SelfRecursiveListObject; -import com.navercorp.fixturemonkey.tests.java.specs.RecursiveTypeSpecs.SelfRecursiveMapObject; -import com.navercorp.fixturemonkey.tests.java.specs.RecursiveTypeSpecs.SelfRecursiveObject; - -class RecursiveTypeAdapterTest { - private static final FixtureMonkey SUT = FixtureMonkey.builder() - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - @RepeatedTest(TEST_COUNT) - void sampleSelfRecursiveObject() { - SelfRecursiveObject actual = SUT.giveMeOne(SelfRecursiveObject.class); - - then(actual.getValue()).isNotNull(); - then(actual.getSelfRecursiveObject()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedSelfRecursiveObject() { - SelfRecursiveObject actual = SUT.giveMeBuilder(SelfRecursiveObject.class) - .fixed() - .sample(); - - then(actual.getValue()).isNotNull(); - then(actual.getSelfRecursiveObject()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleSelfRecursiveListObject() { - SelfRecursiveListObject actual = SUT.giveMeOne(SelfRecursiveListObject.class); - - then(actual.getValue()).isNotNull(); - then(actual.getSelfRecursiveListObjects()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedSelfRecursiveListObject() { - SelfRecursiveListObject actual = SUT.giveMeBuilder(SelfRecursiveListObject.class) - .fixed() - .sample(); - - then(actual.getValue()).isNotNull(); - then(actual.getSelfRecursiveListObjects()).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void sampleSelfRecursiveMapObject() { - Map actual = SUT.giveMeOne( - new TypeReference>() { - }); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void fixedSelfRecursiveMapObject() { - Map actual = SUT.giveMeBuilder( - new TypeReference>() { - }) - .fixed() - .sample(); - - then(actual).isNotNull(); - } - - @RepeatedTest(TEST_COUNT) - void setSelfRecursiveObjectList() { - List expected = SUT.giveMeOne( - new TypeReference>() { - }); - - List actual = SUT.giveMeBuilder(new TypeReference>() { - }) - .size("$", 1) - .set("$[0].selfRecursiveListObjects", expected) - .sample() - .get(0) - .getSelfRecursiveListObjects(); - - then(actual).isEqualTo(expected); - } - - @RepeatedTest(TEST_COUNT) - void setNestedSelfRecursiveObjectList() { - List expected = SUT.giveMeBuilder( - new TypeReference>() { - } - ) - .size("$", 1) - .set("$[0].selfRecursiveListObjects", SUT.giveMeOne(new TypeReference>() { - })) - .sample(); - - List actual = SUT.giveMeBuilder(new TypeReference>() { - }) - .size("$", 1) - .set("$[0].selfRecursiveListObjects", expected) - .sample() - .get(0) - .getSelfRecursiveListObjects(); - - then(actual).isEqualTo(expected); - } - - @RepeatedTest(TEST_COUNT) - void setSelfRecursiveObject() { - SelfRecursiveObject actual = SUT.giveMeOne(SelfRecursiveObject.class); - - SelfRecursiveObject expected = SUT.giveMeBuilder(SelfRecursiveObject.class) - .set("selfRecursiveObject", actual) - .sample() - .getSelfRecursiveObject(); - - then(actual).isEqualTo(expected); - } -} diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/SeedInitializationAdapterTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/SeedInitializationAdapterTest.java deleted file mode 100644 index 32d9557c58..0000000000 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/SeedInitializationAdapterTest.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.java.adapter; - -import static org.assertj.core.api.BDDAssertions.then; - -import org.junit.jupiter.api.Test; - -import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; -import com.navercorp.fixturemonkey.api.random.Randoms; - -class SeedInitializationAdapterTest { - - @Test - void readsSeedFromFile() { - // given - long fileSeed = 123456789L; - - // when - FixtureMonkey.builder() - .useExperimental(options -> options.fileSeed()) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - // then - then(Randoms.currentSeed()).isEqualTo(fileSeed); - } - - @Test - void builderSeedOverridesFileSeed() { - // given - long builderSeed = 987654321L; - - // when - FixtureMonkey.builder() - .seed(builderSeed) - .plugin(new JavaNodeTreeAdapterPlugin()) - .build(); - - // then - then(Randoms.currentSeed()).isEqualTo(builderSeed); - } - -} diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/SizeAnnotationAdapterTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/SizeAnnotationAdapterTest.java deleted file mode 100644 index 2456bb30f3..0000000000 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/adapter/SizeAnnotationAdapterTest.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.navercorp.fixturemonkey.tests.java.adapter; - -import java.util.Map; - -import javax.validation.constraints.Size; - -import org.junit.jupiter.api.Test; - -import lombok.Value; - -import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.JavaNodeTreeAdapterPlugin; -import com.navercorp.fixturemonkey.adapter.tracing.AdapterTracer; -import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; -import com.navercorp.fixturemonkey.javax.validation.plugin.JavaxValidationPlugin; - -class SizeAnnotationAdapterTest { - - private static final FixtureMonkey SUT = FixtureMonkey.builder() - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .plugin(new JavaxValidationPlugin()) - .plugin(new JavaNodeTreeAdapterPlugin().tracer(AdapterTracer.console())) - .build(); - - @Value - public static class SizeAnnotatedMapObject { - - String id; - - @Size(min = 1, max = 1) - Map values; - } - - @Test - void sampleSizeAnnotatedMapWithThenApply() { - try { - SizeAnnotatedMapObject actual = SUT.giveMeBuilder(SizeAnnotatedMapObject.class) - .set("id", "base") - .thenApply((obj, builder) -> builder.set("id", obj.getId() + "-applied")) - .sample(); - - System.out.println("SUCCESS: " + actual); - } catch (Exception e) { - System.out.println("FAILED: " + e.getMessage()); - if (e.getCause() != null) { - System.out.println("CAUSE: " + e.getCause().getMessage()); - if (e.getCause().getCause() != null) { - System.out.println("ROOT CAUSE: " + e.getCause().getCause().getMessage()); - } - } - throw e; - } - } -} diff --git a/fixture-monkey-tests/kotlin-concurrent-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/concurrent/kotlin/ConcurrentTest.kt b/fixture-monkey-tests/kotlin-concurrent-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/concurrent/kotlin/ConcurrentTest.kt index c0e52a8273..bb6b4022a5 100644 --- a/fixture-monkey-tests/kotlin-concurrent-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/concurrent/kotlin/ConcurrentTest.kt +++ b/fixture-monkey-tests/kotlin-concurrent-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/concurrent/kotlin/ConcurrentTest.kt @@ -5,22 +5,22 @@ import com.navercorp.fixturemonkey.kotlin.KotlinPlugin import com.navercorp.fixturemonkey.kotlin.giveMeOne import com.navercorp.fixturemonkey.tests.TestEnvironment import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.RepeatedTest +import org.junit.jupiter.api.Test class ConcurrentTest { - @RepeatedTest(TestEnvironment.TEST_COUNT) + @Test fun test1() { val actual: KotlinObject = SUT.giveMeOne() then(actual).isNotNull() } - @RepeatedTest(TestEnvironment.TEST_COUNT) + @Test fun test2() { val actual: KotlinObject = SUT.giveMeOne() then(actual).isNotNull() } - @RepeatedTest(TestEnvironment.TEST_COUNT) + @Test fun test3() { val actual: KotlinObject = SUT.giveMeOne() then(actual).isNotNull() diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/AnonymousInstanceTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/AnonymousInstanceTest.kt index 40957a301e..884fbe485c 100644 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/AnonymousInstanceTest.kt +++ b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/AnonymousInstanceTest.kt @@ -37,11 +37,11 @@ import com.navercorp.fixturemonkey.tests.kotlin.JavaAnonymousInstanceTestSpecs.J import com.navercorp.fixturemonkey.tests.kotlin.JavaAnonymousInstanceTestSpecs.JavaInterfaceWithParams import com.navercorp.fixturemonkey.tests.kotlin.JavaAnonymousInstanceTestSpecs.NestedInheritedJavaInterface import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.RepeatedTest +import org.junit.jupiter.api.Test import javax.validation.constraints.NotEmpty class AnonymousInstanceTest { - @RepeatedTest(TEST_COUNT) + @Test fun sampleInterface() { val actual = SUT.giveMeOne() @@ -49,7 +49,7 @@ class AnonymousInstanceTest { then(actual.integer()).isNotNull } - @RepeatedTest(TEST_COUNT) + @Test fun objectBaseMethods() { val actual = SUT.giveMeOne() @@ -58,7 +58,7 @@ class AnonymousInstanceTest { then(actual.toString()).isNotNull() } - @RepeatedTest(TEST_COUNT) + @Test fun equalsOnSimilarInterface() { val one = SUT.giveMeBuilder() .setExpGetter(Interface::string, "test") @@ -72,7 +72,7 @@ class AnonymousInstanceTest { then(one).isNotEqualTo(another) } - @RepeatedTest(TEST_COUNT) + @Test fun setInterface() { val expected = "test" @@ -84,14 +84,14 @@ class AnonymousInstanceTest { then(actual).isEqualTo(expected) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleInterfaceWithParam() { val actual = SUT.giveMeOne() then(actual).isNull() } - @RepeatedTest(TEST_COUNT) + @Test fun sampleContainerInterface() { val actual = SUT.giveMeOne() @@ -99,7 +99,7 @@ class AnonymousInstanceTest { then(actual.map()).isNotNull } - @RepeatedTest(TEST_COUNT) + @Test fun setContainerInterfaceList() { val actual: List = SUT.giveMeBuilder() .size("list", 3) @@ -111,21 +111,21 @@ class AnonymousInstanceTest { then(actual[0]).isEqualTo("test") } - @RepeatedTest(TEST_COUNT) + @Test fun sampleAnnotatedInterface() { val actual = SUT.giveMeOne().string() then(actual).isNotEmpty } - @RepeatedTest(TEST_COUNT) + @Test fun sampleGetterInterface() { val actual = SUT.giveMeOne().getString() then(actual).isNotNull } - @RepeatedTest(TEST_COUNT) + @Test fun setGetterInterface() { val expected = "test" @@ -137,7 +137,7 @@ class AnonymousInstanceTest { then(actual).isEqualTo(expected) } - @RepeatedTest(TEST_COUNT) + @Test fun samplePropertyInterface() { val actual = SUT.giveMeOne() @@ -145,7 +145,7 @@ class AnonymousInstanceTest { then(actual.int).isNotNull } - @RepeatedTest(TEST_COUNT) + @Test fun setPropertyInterface() { val expected = "expected" @@ -157,7 +157,7 @@ class AnonymousInstanceTest { then(actual).isEqualTo(expected) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleInheritedInterface() { val actual = SUT.giveMeOne() @@ -166,7 +166,7 @@ class AnonymousInstanceTest { then(actual.integer()).isNotNull } - @RepeatedTest(TEST_COUNT) + @Test fun setInheritedInterface() { val expected = "test" @@ -178,14 +178,14 @@ class AnonymousInstanceTest { then(actual).isEqualTo(expected) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleInheritedInterfaceWithOverrideMethod() { val actual = SUT.giveMeOne().string() then(actual).isNotNull } - @RepeatedTest(TEST_COUNT) + @Test fun setInheritedInterfaceWithOverrideMethod() { val expected = "test" @@ -197,21 +197,21 @@ class AnonymousInstanceTest { then(actual).isEqualTo(expected) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleExtendsTwoInterface() { val actual = SUT.giveMeOne().string() then(actual).isNotNull } - @RepeatedTest(TEST_COUNT) + @Test fun sampleNestedInheritedInterface() { val actual = SUT.giveMeOne().string() then(actual).isNotNull } - @RepeatedTest(TEST_COUNT) + @Test fun setNestedInheritedInterface() { val expected = "test" @@ -223,14 +223,14 @@ class AnonymousInstanceTest { then(actual).isEqualTo(expected) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleInheritedPropertyInterface() { val actual = SUT.giveMeOne().string then(actual).isNotNull } - @RepeatedTest(TEST_COUNT) + @Test fun setInheritedPropertyInterface() { val expected = "test" @@ -242,14 +242,14 @@ class AnonymousInstanceTest { then(actual).isEqualTo(expected) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleNestedInheritedPropertyInterface() { val actual = SUT.giveMeOne().string then(actual).isNotNull } - @RepeatedTest(TEST_COUNT) + @Test fun setNestedInheritedPropertyInterface() { val expected = "test" @@ -261,7 +261,7 @@ class AnonymousInstanceTest { then(actual).isEqualTo(expected) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleJavaInterface() { val actual = SUT.giveMeOne() @@ -270,7 +270,7 @@ class AnonymousInstanceTest { then(actual.integer()).isNotNull } - @RepeatedTest(TEST_COUNT) + @Test fun setJavaInterface() { val expected = "test" @@ -282,21 +282,21 @@ class AnonymousInstanceTest { then(actual).isEqualTo(expected) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleJavaInterfaceWithParamReturnsNullProperties() { val actual = SUT.giveMeOne() then(actual).isNull() } - @RepeatedTest(TEST_COUNT) + @Test fun sampleJavaInterfaceWithConstantIsNull() { val actual = SUT.giveMeOne() then(actual).isNull() } - @RepeatedTest(TEST_COUNT) + @Test fun sampleJavaContainerInterface() { val actual = SUT.giveMeOne() @@ -304,7 +304,7 @@ class AnonymousInstanceTest { then(actual.map()).isNotNull } - @RepeatedTest(TEST_COUNT) + @Test fun setJavaContainerInterfaceList() { val actual = SUT.giveMeBuilder() .size("list", 3) @@ -316,14 +316,14 @@ class AnonymousInstanceTest { then(actual[0]).isEqualTo("test") } - @RepeatedTest(TEST_COUNT) + @Test fun sampleJavaAnnotatedInterface() { val actual = SUT.giveMeOne().string() then(actual).isNotEmpty } - @RepeatedTest(TEST_COUNT) + @Test fun setJavaGetterInterfacePropertyName() { val expected = "test" @@ -335,7 +335,7 @@ class AnonymousInstanceTest { then(actual).isEqualTo(expected) } - @RepeatedTest(TEST_COUNT) + @Test fun setJavaGetterInterfaceMethodNameNotWorks() { val notExpected = "test" @@ -347,7 +347,7 @@ class AnonymousInstanceTest { then(actual).isNotEqualTo(notExpected) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleInheritedJavaInterface() { val actual = SUT.giveMeOne() @@ -356,7 +356,7 @@ class AnonymousInstanceTest { then(actual.integer()).isNotNull } - @RepeatedTest(TEST_COUNT) + @Test fun setInheritedJavaInterface() { val expected = "test" @@ -368,14 +368,14 @@ class AnonymousInstanceTest { then(actual).isEqualTo(expected) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleInheritedJavaInterfaceWithSameMethodName() { val actual = SUT.giveMeOne().string() then(actual).isNotNull } - @RepeatedTest(TEST_COUNT) + @Test fun setInheritedJavaInterfaceWithSameMethodName() { val expected = "test" @@ -387,7 +387,7 @@ class AnonymousInstanceTest { then(actual).isEqualTo(expected) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleInheritedTwoJavaInterface() { val actual = SUT.giveMeOne() @@ -397,14 +397,14 @@ class AnonymousInstanceTest { then(actual.map()).isNotNull } - @RepeatedTest(TEST_COUNT) + @Test fun sampleNestedInheritedJavaInterface() { val actual = SUT.giveMeOne().string() then(actual).isNotNull } - @RepeatedTest(TEST_COUNT) + @Test fun setNestedInheritedJavaInterface() { val expected = "test" diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/BasicKotlinAdapterTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/BasicKotlinTest.kt similarity index 87% rename from fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/BasicKotlinAdapterTest.kt rename to fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/BasicKotlinTest.kt index ecaa84bfd2..bea40ed1a9 100644 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/BasicKotlinAdapterTest.kt +++ b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/BasicKotlinTest.kt @@ -16,22 +16,20 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.tests.kotlin.adapter +package com.navercorp.fixturemonkey.tests.kotlin import com.navercorp.fixturemonkey.FixtureMonkey import com.navercorp.fixturemonkey.kotlin.KotlinPlugin -import com.navercorp.fixturemonkey.kotlin.KotlinNodeTreeAdapterPlugin import com.navercorp.fixturemonkey.kotlin.giveMeKotlinBuilder import com.navercorp.fixturemonkey.kotlin.giveMeOne import com.navercorp.fixturemonkey.tests.TestEnvironment.ADAPTER_TEST_COUNT import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.RepeatedTest import org.junit.jupiter.api.Test /** * Basic Kotlin adapter tests - starting with the simplest cases. */ -class BasicKotlinAdapterTest { +class BasicKotlinTest { data class SimpleObject(val name: String, val value: Int) data class NestedObject(val id: String, val inner: SimpleObject) @@ -41,13 +39,12 @@ class BasicKotlinAdapterTest { companion object { private val SUT = FixtureMonkey.builder() .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) .build() } // ==================== Simple Object Tests ==================== - @RepeatedTest(ADAPTER_TEST_COUNT) + @Test fun sampleSimpleObject() { // when val actual = SUT.giveMeOne() @@ -57,7 +54,7 @@ class BasicKotlinAdapterTest { then(actual.name).isNotNull } - @RepeatedTest(ADAPTER_TEST_COUNT) + @Test fun setSimpleObjectProperty() { // given val expected = "expectedName" @@ -71,7 +68,7 @@ class BasicKotlinAdapterTest { then(actual.name).isEqualTo(expected) } - @RepeatedTest(ADAPTER_TEST_COUNT) + @Test fun setSimpleObjectPropertyWithPropertySelector() { // given val expected = "expectedName" @@ -101,7 +98,7 @@ class BasicKotlinAdapterTest { // ==================== Nested Object Tests ==================== - @RepeatedTest(ADAPTER_TEST_COUNT) + @Test fun sampleNestedObject() { // when val actual = SUT.giveMeOne() @@ -112,7 +109,7 @@ class BasicKotlinAdapterTest { then(actual.inner.name).isNotNull } - @RepeatedTest(ADAPTER_TEST_COUNT) + @Test fun setNestedProperty() { // given val expected = "nestedName" @@ -128,7 +125,7 @@ class BasicKotlinAdapterTest { // ==================== List Container Tests ==================== - @RepeatedTest(ADAPTER_TEST_COUNT) + @Test fun sampleListContainer() { // when val actual = SUT.giveMeOne() @@ -138,7 +135,7 @@ class BasicKotlinAdapterTest { then(actual.items).isNotNull } - @RepeatedTest(ADAPTER_TEST_COUNT) + @Test fun setListSize() { // given val expectedSize = 3 @@ -152,7 +149,7 @@ class BasicKotlinAdapterTest { then(actual.items).hasSize(expectedSize) } - @RepeatedTest(ADAPTER_TEST_COUNT) + @Test fun setListElement() { // given val expected = "expectedElement" diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/CircularReferenceTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/CircularReferenceTest.kt index db0110b403..332c4a9d91 100644 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/CircularReferenceTest.kt +++ b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/CircularReferenceTest.kt @@ -25,17 +25,17 @@ import com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT import com.navercorp.fixturemonkey.tests.kotlin.specs.CircularReferenceDefaultArgument import com.navercorp.fixturemonkey.tests.kotlin.specs.CircularReferenceValueNullable import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.RepeatedTest +import org.junit.jupiter.api.Test class CircularReferenceTest { - @RepeatedTest(TEST_COUNT) + @Test fun circularReferenceDefaultArgument() { val actual = SUT.giveMeOne().value then(actual).isNotNull() } - @RepeatedTest(TEST_COUNT) + @Test fun circularReferenceNullable() { val actual: CircularReferenceValueNullable = SUT.giveMeOne() diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/CustomizationTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/CustomizationTest.kt index 662e5520c8..c12482ec8f 100644 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/CustomizationTest.kt +++ b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/CustomizationTest.kt @@ -40,7 +40,6 @@ import com.navercorp.fixturemonkey.kotlin.sizeExp import com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT import com.navercorp.fixturemonkey.tests.kotlin.specs.KotlinObject import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.RepeatedTest import org.junit.jupiter.api.Test import java.time.Instant import java.time.temporal.ChronoUnit @@ -59,7 +58,7 @@ class CustomizationTest { then(actual).isEqualTo("parent") } - @RepeatedTest(TEST_COUNT) + @Test fun customizePropertySet() { val actual = SUT.giveMeExperimentalBuilder() .customizeProperty(typedRoot()) { @@ -71,7 +70,7 @@ class CustomizationTest { then(actual).hasSizeLessThanOrEqualTo(4) } - @RepeatedTest(TEST_COUNT) + @Test fun customizePropertyFilter() { val now = Instant.now() val min = now.minus(365, ChronoUnit.DAYS) @@ -86,7 +85,7 @@ class CustomizationTest { then(actual).isBetween(min, max) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleCustomizedWildcardType() { // given class MapObject(val map: Map) @@ -114,7 +113,7 @@ class CustomizationTest { then(actual).isEqualTo(expected) } - @RepeatedTest(TEST_COUNT) + @Test fun overwriteExistingType() { val expected = "string" val sut = FixtureMonkey.builder() @@ -147,7 +146,7 @@ class CustomizationTest { then(actual).isEqualTo(expected) } - @RepeatedTest(TEST_COUNT) + @Test fun setLazyJustNotChanged() { // given class StringObject(val string: String) @@ -164,7 +163,7 @@ class CustomizationTest { then(actual).isEqualTo(expected) } - @RepeatedTest(TEST_COUNT) + @Test fun setPostCondition() { class StringObject(val string: String) @@ -176,7 +175,7 @@ class CustomizationTest { then(actual).hasSizeLessThan(5) } - @RepeatedTest(TEST_COUNT) + @Test fun setPostConditionWithProperty() { class StringObject(val string: String) @@ -188,7 +187,7 @@ class CustomizationTest { then(actual).hasSizeLessThan(5) } - @RepeatedTest(TEST_COUNT) + @Test fun customizePropertyAfterSet() { // given class StringValue(val value: String) @@ -208,7 +207,7 @@ class CustomizationTest { then(actual).isEqualTo(expected) } - @RepeatedTest(TEST_COUNT) + @Test fun customizePropertyIgnoredIfSet() { // given class StringValue(val value: String) @@ -292,7 +291,7 @@ class CustomizationTest { then(actual).isEqualTo(expected) } - @RepeatedTest(TEST_COUNT) + @Test fun register() { class NestedInnerObject(val list: List) @@ -319,7 +318,7 @@ class CustomizationTest { then(actual).isNotNull } - @RepeatedTest(TEST_COUNT) + @Test fun innerSpecInner() { // given data class ChildObject(val values: List) @@ -364,7 +363,7 @@ class CustomizationTest { then(actual).allMatch { it.value == "1" } } - @RepeatedTest(TEST_COUNT) + @Test fun generateObjectInstanceThrows() { // when val actual: KotlinObject = SUT.giveMeOne() diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/InnerSpecTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/InnerSpecTest.kt index 9bf404e703..0ebba09dea 100644 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/InnerSpecTest.kt +++ b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/InnerSpecTest.kt @@ -23,11 +23,11 @@ import com.navercorp.fixturemonkey.kotlin.KotlinPlugin import com.navercorp.fixturemonkey.kotlin.giveMeKotlinBuilder import com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.RepeatedTest +import org.junit.jupiter.api.Test class InnerSpecTest { - @RepeatedTest(TEST_COUNT) + @Test fun setInnerSpecByTrailingLambda() { val actual = SUT.giveMeKotlinBuilder>() .setInner { @@ -39,7 +39,7 @@ class InnerSpecTest { then(actual).containsKeys("key1", "key2") } - @RepeatedTest(TEST_COUNT) + @Test fun setKotlinInnerByTrailingLambda() { val actual = SUT.giveMeKotlinBuilder>() .setKotlinInner { diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/InstantiatorTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/InstantiatorTest.kt index 54e934a3e6..474c5be51b 100644 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/InstantiatorTest.kt +++ b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/InstantiatorTest.kt @@ -101,6 +101,32 @@ class InstantiatorTest { then(actual).isEqualTo("bar") } + /** + * Reproduces the doc-examples scenario `InstantiateMethodsKotlinTest.specifyingParameterValues`: + * an aliased constructor parameter (`parameter("productName")` against a parameter + * actually named `name`) plus a `set("productName", ...)` should land on the aliased + * parameter. The introspector ends up walking the value map by position because the alias + * hides the original parameter name from name-based matching, so it relies on the iteration + * order of the map ObjectCombinableArbitrary feeds to its combinator. Before the fix that + * map was a HashMap, and on JVMs / hashCode distributions where the bucket order disagrees + * with insertion order, the value lands on the wrong constructor parameter and Kotlin throws + * "argument type mismatch". + */ + @RepeatedTest(TEST_COUNT) + fun instantiateByAliasedParameterPreservesValueAssignment() { + val actual = SUT.giveMeKotlinBuilder() + .instantiateBy { + constructor { + parameter("productName") + parameter() + } + } + .set("productName", "specialProduct") + .sample() + + then(actual.name).isEqualTo("specialProduct") + } + @RepeatedTest(TEST_COUNT) fun instantiateRootType() { val actual = SUT.giveMeKotlinBuilder() @@ -619,6 +645,34 @@ class InstantiatorTest { class Baz(val foo: Foo, val bar: Bar) + class MultiConstructorProduct { + val id: Long + val name: String + val price: Long + val options: List + + constructor() { + this.id = 0L + this.name = "defaultProduct" + this.price = 0L + this.options = emptyList() + } + + constructor(name: String, price: Long) { + this.id = 0L + this.name = name + this.price = price + this.options = emptyList() + } + + constructor(name: String, price: Long, options: List) { + this.id = 0L + this.name = name + this.price = price + this.options = options + } + } + companion object { private val SUT = FixtureMonkey.builder() .plugin(KotlinPlugin()) diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/InterfaceTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/InterfaceTest.kt index 631787238b..c1855519af 100644 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/InterfaceTest.kt +++ b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/InterfaceTest.kt @@ -27,12 +27,11 @@ import com.navercorp.fixturemonkey.kotlin.giveMeOne import com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT import com.navercorp.fixturemonkey.tests.kotlin.InterfaceTest.SealedObjectClass.ConcreteSealedObjectClass import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.RepeatedTest import org.junit.jupiter.api.Test import java.util.LinkedList class InterfaceTest { - @RepeatedTest(TEST_COUNT) + @Test fun anonymousArbitraryIntrospector() { // given val sut = FixtureMonkey.builder() @@ -47,7 +46,7 @@ class InterfaceTest { then(actual).isNotNull() } - @RepeatedTest(TEST_COUNT) + @Test fun notUseAnonymousArbitraryIntrospector() { // given val sut = FixtureMonkey.builder() @@ -61,7 +60,7 @@ class InterfaceTest { then(actual).isNull() } - @RepeatedTest(TEST_COUNT) + @Test fun sealedInterfaceApplySet() { val actual = SUT.giveMeBuilder() .thenApply { _, builder -> builder.set("stringObject.string", "expected") } @@ -70,7 +69,7 @@ class InterfaceTest { then((actual as SealedInterfaceImplementation).stringObject.string).isEqualTo("expected") } - @RepeatedTest(TEST_COUNT) + @Test fun interfaceImplementsExtendsInterface() { val sut = FixtureMonkey.builder() .plugin(KotlinPlugin()) @@ -104,14 +103,14 @@ class InterfaceTest { then(actual).isInstanceOf(ArrayList::class.java) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleSealedClass() { val actual = SUT.giveMeOne() then(actual).isNotNull } - @RepeatedTest(TEST_COUNT) + @Test fun fixedSealedClass() { val actual = SUT.giveMeBuilder() .fixed() @@ -120,14 +119,14 @@ class InterfaceTest { then(actual).isNotNull } - @RepeatedTest(TEST_COUNT) + @Test fun sampleImplementedSealedClass() { val actual = SUT.giveMeOne() then(actual).isNotNull } - @RepeatedTest(TEST_COUNT) + @Test fun fixedImplementedSealedClass() { val actual = SUT.giveMeBuilder() .fixed() @@ -136,14 +135,14 @@ class InterfaceTest { then(actual).isNotNull } - @RepeatedTest(TEST_COUNT) + @Test fun sealedObject() { val actual: SealedObjectClass = SUT.giveMeOne() then(actual).isInstanceOf(ConcreteSealedObjectClass::class.java) } - @RepeatedTest(TEST_COUNT) + @Test fun sealedObjectThenApply() { val actual = SUT.giveMeBuilder() .thenApply { obj, builder -> } diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/IntrospectorTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/IntrospectorTest.kt index 9dd2aa61d6..fa01584941 100644 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/IntrospectorTest.kt +++ b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/IntrospectorTest.kt @@ -32,7 +32,6 @@ import com.navercorp.fixturemonkey.kotlin.pushExactTypeArbitraryIntrospector import com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT import com.navercorp.fixturemonkey.tests.kotlin.BuilderJavaTestSpecs.BuilderObjectCustomBuildName import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.RepeatedTest import org.junit.jupiter.api.Test import java.sql.Timestamp import java.util.UUID @@ -151,7 +150,7 @@ class IntrospectorTest { then(actual).isNull() } - @RepeatedTest(TEST_COUNT) + @Test fun pushPrimaryConstructorIntrospector() { // given class StringObject(val string: String) diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/JakartaValidationTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/JakartaValidationTest.kt similarity index 93% rename from fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/JakartaValidationTest.kt rename to fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/JakartaValidationTest.kt index 7335bedcf4..1ebf85fefe 100644 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/JakartaValidationTest.kt +++ b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/JakartaValidationTest.kt @@ -1,4 +1,4 @@ -package com.navercorp.fixturemonkey.tests.kotlin.adapter +package com.navercorp.fixturemonkey.tests.kotlin import com.navercorp.fixturemonkey.FixtureMonkey import com.navercorp.fixturemonkey.jakarta.validation.plugin.JakartaValidationPlugin @@ -12,10 +12,10 @@ import jakarta.validation.constraints.Min import jakarta.validation.constraints.NotBlank import jakarta.validation.constraints.Size import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.RepeatedTest +import org.junit.jupiter.api.Test class JakartaValidationTest { - @RepeatedTest(TEST_COUNT) + @Test fun instantiateByConstructorWithJakartaValidationConstraint() { // given data class ValidatedObject( @@ -37,7 +37,7 @@ class JakartaValidationTest { then(actual.length).isBetween(1, 10) } - @RepeatedTest(TEST_COUNT) + @Test fun instantiateByConstructorWithNotBlankConstraint() { // given data class ValidatedObject( @@ -59,7 +59,7 @@ class JakartaValidationTest { then(actual).isNotBlank } - @RepeatedTest(TEST_COUNT) + @Test fun instantiateByConstructorWithNumericRangeConstraint() { // given data class ValidatedObject( @@ -82,7 +82,7 @@ class JakartaValidationTest { then(actual).isBetween(1, 100) } - @RepeatedTest(TEST_COUNT) + @Test fun instantiateByConstructorWithMultipleConstraints() { // given data class ValidatedObject( @@ -108,7 +108,7 @@ class JakartaValidationTest { then(actual.age).isBetween(0, 100) } - @RepeatedTest(TEST_COUNT) + @Test fun instantiateByConstructorWithoutInstantiateRespectsConstraint() { // given data class ValidatedObject( @@ -123,7 +123,7 @@ class JakartaValidationTest { then(actual.length).isBetween(1, 10) } - @RepeatedTest(TEST_COUNT) + @Test fun instantiateBySecondaryConstructorWithJakartaValidationConstraint() { // given class ValidatedObject( @@ -148,7 +148,7 @@ class JakartaValidationTest { then(actual.length).isBetween(1, 10) } - @RepeatedTest(TEST_COUNT) + @Test fun privateBackingFieldWithPublicComputedProperty() { // given class ObjectWithPrivateBacking( @@ -170,7 +170,7 @@ class JakartaValidationTest { then(actual.value).isNotNull } - @RepeatedTest(TEST_COUNT) + @Test fun privateBackingFieldWithValidationConstraint() { // given class ObjectWithPrivateBacking( @@ -193,7 +193,7 @@ class JakartaValidationTest { then(actual.value.length).isBetween(1, 10) } - @RepeatedTest(TEST_COUNT) + @Test fun privateBackingFieldSetValueByParameterName() { // given class ObjectWithPrivateBacking( @@ -216,7 +216,7 @@ class JakartaValidationTest { then(actual.value).isEqualTo("hello") } - @RepeatedTest(TEST_COUNT) + @Test fun privateBackingFieldWithoutInstantiateBy() { // given class ObjectWithPrivateBacking( @@ -232,7 +232,7 @@ class JakartaValidationTest { then(actual.value).isNotNull } - @RepeatedTest(TEST_COUNT) + @Test fun privateBackingFieldWithValidationConstraintWithoutInstantiateBy() { // given class ObjectWithPrivateBacking( @@ -249,7 +249,7 @@ class JakartaValidationTest { then(actual.value.length).isBetween(1, 10) } - @RepeatedTest(TEST_COUNT) + @Test fun privateValInstantiateByFieldTargetSize() { // given class Obj( @@ -269,7 +269,7 @@ class JakartaValidationTest { then(actual.length).isBetween(2, 5) } - @RepeatedTest(TEST_COUNT) + @Test fun privateValInstantiateByMultiplePrivateFields() { // given class Obj( @@ -298,7 +298,7 @@ class JakartaValidationTest { then(actual.age).isBetween(10, 99) } - @RepeatedTest(TEST_COUNT) + @Test fun privateValInstantiateBySetOverridesConstraint() { // given class Obj( @@ -319,7 +319,7 @@ class JakartaValidationTest { then(actual).isEqualTo("hi") } - @RepeatedTest(TEST_COUNT) + @Test fun privateValInstantiateByMixedPrivateAndPublic() { // given class Obj( diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/KotestInJunitTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/KotestInJunitTest.kt index 3f46dacfcc..b8c24acf29 100644 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/KotestInJunitTest.kt +++ b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/KotestInJunitTest.kt @@ -41,7 +41,6 @@ import io.kotest.property.Arb import io.kotest.property.arbitrary.single import io.kotest.property.arbs.geo.zipcodes import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.RepeatedTest import org.junit.jupiter.api.Test import java.math.BigDecimal import java.math.BigInteger @@ -58,7 +57,7 @@ import javax.validation.constraints.PositiveOrZero import javax.validation.constraints.Size class KotestInJunitTest { - @RepeatedTest(TEST_COUNT) + @Test fun sampleStringWithSize() { class StringObject(@field:Size(min = 10, max = 20) val value: String) @@ -67,7 +66,7 @@ class KotestInJunitTest { then(actual).hasSizeBetween(10, 20) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleStringWithNotEmpty() { class StringObject(@field:NotEmpty val value: String) @@ -76,7 +75,7 @@ class KotestInJunitTest { then(actual).isNotEmpty() } - @RepeatedTest(TEST_COUNT) + @Test fun sampleShortWithNegative() { class ShortObject(@field:Negative val value: Short) @@ -85,7 +84,7 @@ class KotestInJunitTest { then(actual).isNegative() } - @RepeatedTest(TEST_COUNT) + @Test fun sampleShortWithNegativeOrZero() { class ShortObject(@field:NegativeOrZero val value: Short) @@ -94,7 +93,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(0) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleShortWithPositive() { class ShortObject(@field:Positive val value: Short) @@ -103,7 +102,7 @@ class KotestInJunitTest { then(actual).isPositive() } - @RepeatedTest(TEST_COUNT) + @Test fun sampleShortWithPositiveOrZero() { class ShortObject(@field:PositiveOrZero val value: Short) @@ -112,7 +111,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(0) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleShortWithMin() { class ShortObject(@field:Min(10) val value: Short) @@ -121,7 +120,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(10) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleShortWithDecimalMin() { class ShortObject(@field:DecimalMin("10") val value: Short) @@ -130,7 +129,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(10) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleShortWithMax() { class ShortObject(@field:Max(50) val value: Short) @@ -139,7 +138,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(50) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleShortWithDecimalMax() { class ShortObject(@field:DecimalMax("50") val value: Short) @@ -148,7 +147,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(50) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleShortWithDigits() { class ShortObject(@field:Digits(integer = 2, fraction = 0) val value: Short) @@ -157,7 +156,7 @@ class KotestInJunitTest { then(actual).matches { it in -99..99 } } - @RepeatedTest(TEST_COUNT) + @Test fun sampleByteWithNegative() { class ByteObject(@field:Negative val value: Byte) @@ -166,7 +165,7 @@ class KotestInJunitTest { then(actual).isNegative() } - @RepeatedTest(TEST_COUNT) + @Test fun sampleByteWithNegativeOrZero() { class ByteObject(@field:NegativeOrZero val value: Byte) @@ -175,7 +174,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(0) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleByteWithPositive() { class ByteObject(@field:Positive val value: Byte) @@ -184,7 +183,7 @@ class KotestInJunitTest { then(actual).isPositive() } - @RepeatedTest(TEST_COUNT) + @Test fun sampleByteWithPositiveOrZero() { class ByteObject(@field:PositiveOrZero val value: Byte) @@ -193,7 +192,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(0) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleByteWithMin() { class ByteObject(@field:Min(10) val value: Byte) @@ -202,7 +201,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(10) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleByteWithDecimalMin() { class ByteObject(@field:DecimalMin("10") val value: Byte) @@ -211,7 +210,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(10) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleByteWithMax() { class ByteObject(@field:Max(50) val value: Byte) @@ -220,7 +219,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(50) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleByteWithDecimalMax() { class ByteObject(@field:DecimalMax("50") val value: Byte) @@ -229,7 +228,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(50) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleByteWithDigits() { class ByteObject(@field:Digits(integer = 2, fraction = 0) val value: Byte) @@ -238,7 +237,7 @@ class KotestInJunitTest { then(actual).matches { it in -99..99 } } - @RepeatedTest(TEST_COUNT) + @Test fun sampleDoubleWithNegative() { class DoubleObject(@field:Negative val value: Double) @@ -247,7 +246,7 @@ class KotestInJunitTest { then(actual).isNegative() } - @RepeatedTest(TEST_COUNT) + @Test fun sampleDoubleWithNegativeOrZero() { class DoubleObject(@field:NegativeOrZero val value: Double) @@ -256,7 +255,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(0.0) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleDoubleWithPositive() { class DoubleObject(@field:Positive val value: Double) @@ -265,7 +264,7 @@ class KotestInJunitTest { then(actual).isPositive() } - @RepeatedTest(TEST_COUNT) + @Test fun sampleDoubleWithPositiveOrZero() { class DoubleObject(@field:PositiveOrZero val value: Double) @@ -274,7 +273,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(0.0) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleDoubleWithMin() { class DoubleObject(@field:Min(10) val value: Double) @@ -283,7 +282,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(10.0) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleDoubleWithDecimalMin() { class DoubleObject(@field:DecimalMin("10") val value: Double) @@ -292,7 +291,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(10.0) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleDoubleWithMax() { class DoubleObject(@field:Max(50) val value: Double) @@ -301,7 +300,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(50.0) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleDoubleWithDecimalMax() { class DoubleObject(@field:DecimalMax("50") val value: Double) @@ -310,7 +309,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(50.0) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleDoubleWithDigits() { class DoubleObject(@field:Digits(integer = 2, fraction = 0) val value: Double) @@ -319,7 +318,7 @@ class KotestInJunitTest { then(actual).matches { it in -99.0..99.0 } } - @RepeatedTest(TEST_COUNT) + @Test fun sampleDoubleWithEqualMinMax() { class DoubleObject( @field:DecimalMin("10.0") @field:DecimalMax("10.0") @@ -330,7 +329,7 @@ class KotestInJunitTest { then(actual).isEqualTo(10.0) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleDoubleWithMultipleConstraints() { class DoubleObject( @field:DecimalMax("11.5") @field:Max(10) @@ -341,7 +340,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(10.0) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleDoubleWithPreciseExclusiveBounds() { class DoubleObject( @field:DecimalMin(value = "10.0", inclusive = false) @@ -356,7 +355,7 @@ class KotestInJunitTest { .isLessThan(10.1) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleFloatWithNegative() { class FloatObject(@field:Negative val value: Float) @@ -365,7 +364,7 @@ class KotestInJunitTest { then(actual).isNegative() } - @RepeatedTest(TEST_COUNT) + @Test fun sampleFloatWithNegativeOrZero() { class FloatObject(@field:NegativeOrZero val value: Float) @@ -374,7 +373,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(0.0f) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleFloatWithPositive() { class FloatObject(@field:Positive val value: Float) @@ -383,7 +382,7 @@ class KotestInJunitTest { then(actual).isPositive() } - @RepeatedTest(TEST_COUNT) + @Test fun sampleFloatWithPositiveOrZero() { class FloatObject(@field:PositiveOrZero val value: Float) @@ -392,7 +391,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(0.0f) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleFloatWithMin() { class FloatObject(@field:Min(10) val value: Float) @@ -401,7 +400,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(10.0f) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleFloatWithDecimalMin() { class FloatObject(@field:DecimalMin("10") val value: Float) @@ -410,7 +409,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(10.0f) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleFloatWithMax() { class FloatObject(@field:Max(50) val value: Float) @@ -419,7 +418,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(50.0f) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleFloatWithDecimalMax() { class FloatObject(@field:DecimalMax("50") val value: Float) @@ -428,7 +427,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(50.0f) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleFloatWithDigits() { class FloatObject(@field:Digits(integer = 2, fraction = 0) val value: Float) @@ -437,7 +436,7 @@ class KotestInJunitTest { then(actual).matches { it in -99.0..99.0 } } - @RepeatedTest(TEST_COUNT) + @Test fun sampleFloatWithEqualMinMax() { class DoubleObject( @field:DecimalMin("10.0") @field:DecimalMax("10.0") @@ -448,7 +447,7 @@ class KotestInJunitTest { then(actual).isEqualTo(10.0) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleFloatWithMultipleConstraints() { class DoubleObject( @field:DecimalMax("11.5") @field:Max(10) @@ -459,7 +458,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(10.0) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleFloatWithPreciseExclusiveBounds() { class FloatObject( @field:DecimalMin(value = "10.0", inclusive = false) @@ -474,7 +473,7 @@ class KotestInJunitTest { .isLessThan(10.1f) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleIntWithNegative() { class IntObject(@field:Negative val value: Int) @@ -483,7 +482,7 @@ class KotestInJunitTest { then(actual).isNegative() } - @RepeatedTest(TEST_COUNT) + @Test fun sampleIntWithNegativeOrZero() { class IntObject(@field:NegativeOrZero val value: Int) @@ -492,7 +491,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(0) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleIntWithPositive() { class IntObject(@field:Positive val value: Int) @@ -501,7 +500,7 @@ class KotestInJunitTest { then(actual).isPositive() } - @RepeatedTest(TEST_COUNT) + @Test fun sampleIntWithPositiveOrZero() { class IntObject(@field:PositiveOrZero val value: Int) @@ -510,7 +509,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(0) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleIntWithMin() { class IntObject(@field:Min(10) val value: Int) @@ -519,7 +518,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(10) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleIntWithDecimalMin() { class IntObject(@field:DecimalMin("10") val value: Int) @@ -528,7 +527,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(10) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleIntWithMax() { class IntObject(@field:Max(50) val value: Int) @@ -537,7 +536,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(50) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleIntWithDecimalMax() { class IntObject(@field:DecimalMax("50") val value: Int) @@ -546,7 +545,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(50) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleIntWithDigits() { class IntObject(@field:Digits(integer = 2, fraction = 0) val value: Int) @@ -555,7 +554,7 @@ class KotestInJunitTest { then(actual).matches { it in -99..99 } } - @RepeatedTest(TEST_COUNT) + @Test fun sampleLongWithNegative() { class LongObject(@field:Negative val value: Long) @@ -564,7 +563,7 @@ class KotestInJunitTest { then(actual).isNegative() } - @RepeatedTest(TEST_COUNT) + @Test fun sampleLongWithNegativeOrZero() { class LongObject(@field:NegativeOrZero val value: Long) @@ -573,7 +572,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(0) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleLongWithPositive() { class LongObject(@field:Positive val value: Long) @@ -582,7 +581,7 @@ class KotestInJunitTest { then(actual).isPositive() } - @RepeatedTest(TEST_COUNT) + @Test fun sampleLongWithPositiveOrZero() { class LongObject(@field:PositiveOrZero val value: Long) @@ -591,7 +590,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(0) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleLongWithMin() { class LongObject(@field:Min(10) val value: Long) @@ -600,7 +599,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(10) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleLongWithDecimalMin() { class LongObject(@field:DecimalMin("10") val value: Long) @@ -609,7 +608,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(10) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleLongWithMax() { class LongObject(@field:Max(50) val value: Long) @@ -618,7 +617,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(50) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleLongWithDecimalMax() { class LongObject(@field:DecimalMax("50") val value: Long) @@ -627,7 +626,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(50) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleLongWithDigits() { class LongObject(@field:Digits(integer = 2, fraction = 0) val value: Long) @@ -636,7 +635,7 @@ class KotestInJunitTest { then(actual).matches { it in -99L..99L } } - @RepeatedTest(TEST_COUNT) + @Test fun sampleBigIntegerWithNegative() { class BigIntegerObject(@field:Negative val value: BigInteger) @@ -645,7 +644,7 @@ class KotestInJunitTest { then(actual).isNegative() } - @RepeatedTest(TEST_COUNT) + @Test fun sampleBigIntegerWithNegativeOrZero() { class BigIntegerObject(@field:NegativeOrZero val value: BigInteger) @@ -654,7 +653,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(BigInteger.ZERO) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleBigIntegerWithPositive() { class BigIntegerObject(@field:Positive val value: BigInteger) @@ -663,7 +662,7 @@ class KotestInJunitTest { then(actual).isPositive() } - @RepeatedTest(TEST_COUNT) + @Test fun sampleBigIntegerWithPositiveOrZero() { class BigIntegerObject(@field:PositiveOrZero val value: BigInteger) @@ -672,7 +671,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(BigInteger.ZERO) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleBigIntegerWithMin() { class BigIntegerObject(@field:Min(10) val value: BigInteger) @@ -681,7 +680,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(BigInteger.valueOf(10)) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleBigIntegerWithDecimalMin() { class BigIntegerObject(@field:DecimalMin("10") val value: BigInteger) @@ -690,7 +689,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(BigInteger.valueOf(10)) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleBigIntegerWithMax() { class BigIntegerObject(@field:Max(50) val value: BigInteger) @@ -699,7 +698,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(BigInteger.valueOf(50)) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleBigIntegerWithDecimalMax() { class BigIntegerObject(@field:DecimalMax("50") val value: BigInteger) @@ -708,7 +707,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(BigInteger.valueOf(50)) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleBigIntegerWithDigits() { class BigIntegerObject(@field:Digits(integer = 2, fraction = 0) val value: BigInteger) @@ -719,7 +718,7 @@ class KotestInJunitTest { } } - @RepeatedTest(TEST_COUNT) + @Test fun sampleBigDecimalWithNegative() { class BigDecimalObject(@field:Negative val value: BigDecimal) @@ -728,7 +727,7 @@ class KotestInJunitTest { then(actual).isNegative() } - @RepeatedTest(TEST_COUNT) + @Test fun sampleBigDecimalWithNegativeOrZero() { class BigDecimalObject(@field:NegativeOrZero val value: BigDecimal) @@ -737,7 +736,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(BigDecimal.ZERO) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleBigDecimalWithPositive() { class BigDecimalObject(@field:Positive val value: BigDecimal) @@ -746,7 +745,7 @@ class KotestInJunitTest { then(actual).isPositive() } - @RepeatedTest(TEST_COUNT) + @Test fun sampleBigDecimalWithPositiveOrZero() { class BigDecimalObject(@field:PositiveOrZero val value: BigDecimal) @@ -755,7 +754,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(BigDecimal.ZERO) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleBigDecimalWithMin() { class BigDecimalObject(@field:Min(10) val value: BigDecimal) @@ -764,7 +763,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(BigDecimal.valueOf(10L)) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleBigDecimalWithDecimalMin() { class BigDecimalObject(@field:DecimalMin("10") val value: BigDecimal) @@ -773,7 +772,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(BigDecimal.valueOf(10L)) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleBigDecimalWithMax() { class BigDecimalObject(@field:Max(50) val value: BigDecimal) @@ -782,7 +781,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(BigDecimal.valueOf(50L)) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleBigDecimalWithDecimalMax() { class BigDecimalObject(@field:DecimalMax("50") val value: BigDecimal) @@ -791,7 +790,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(BigDecimal.valueOf(50L)) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleBigDecimalWithDigits() { class BigDecimalObject(@field:Digits(integer = 2, fraction = 0) val value: BigDecimal) @@ -802,7 +801,7 @@ class KotestInJunitTest { } } - @RepeatedTest(TEST_COUNT) + @Test fun sampleBigDecimalWithEqualMinMax() { class BigDecimalObject( @field:DecimalMin("10.00") @field:DecimalMax("10.00") @@ -813,7 +812,7 @@ class KotestInJunitTest { then(actual).isEqualByComparingTo(BigDecimal("10.00")) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleBigDecimalWithMultipleConstraints() { class BigDecimalObject( @field:DecimalMax("11.5") @field:Max(10) @@ -824,7 +823,7 @@ class KotestInJunitTest { then(actual).isLessThanOrEqualTo(BigDecimal.valueOf(10)) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleBigDecimalWithPreciseExclusiveBounds() { class BigDecimalObject( @field:DecimalMin(value = "10.0", inclusive = false) @@ -839,7 +838,7 @@ class KotestInJunitTest { .isLessThan(BigDecimal("10.1")) } - @RepeatedTest(TEST_COUNT) + @Test fun setPostConditionExtension() { class StringObject(val string: String) @@ -853,7 +852,7 @@ class KotestInJunitTest { then(actual).hasSizeLessThan(5) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleMinZeroInteger() { class IntegerObject(@field:Min(0L) val value: Int) @@ -862,7 +861,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(0) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleMinZeroDecimal() { class DecimalObject(@field:Min(0L) val value: Double) @@ -871,7 +870,7 @@ class KotestInJunitTest { then(actual).isGreaterThanOrEqualTo(0.0) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleSetArb() { class StringObject(val string: String) @@ -889,35 +888,35 @@ class KotestInJunitTest { then(actual).isInstanceOf(KotestIntegerCombinableArbitrary::class.java) } - @RepeatedTest(TEST_COUNT) + @Test fun integerCombinableArbitraryPositive() { val actual = CombinableArbitrary.integers().positive().combined() then(actual).isPositive() } - @RepeatedTest(TEST_COUNT) + @Test fun integerCombinableArbitraryNegative() { val actual = CombinableArbitrary.integers().negative().combined() then(actual).isNegative() } - @RepeatedTest(TEST_COUNT) + @Test fun integerCombinableArbitraryEven() { val actual = CombinableArbitrary.integers().even().combined() then(actual).isEven() } - @RepeatedTest(TEST_COUNT) + @Test fun integerCombinableArbitraryOdd() { val actual = CombinableArbitrary.integers().odd().combined() then(actual).isOdd() } - @RepeatedTest(TEST_COUNT) + @Test fun integerCombinableArbitraryWithRange() { val actual = CombinableArbitrary.integers().withRange(10, 20).combined() @@ -931,42 +930,42 @@ class KotestInJunitTest { then(actual).isInstanceOf(KotestByteCombinableArbitrary::class.java) } - @RepeatedTest(TEST_COUNT) + @Test fun byteCombinableArbitraryPositive() { val actual = CombinableArbitrary.bytes().positive().combined() then(actual).isPositive() } - @RepeatedTest(TEST_COUNT) + @Test fun byteCombinableArbitraryNegative() { val actual = CombinableArbitrary.bytes().negative().combined() then(actual).isNegative() } - @RepeatedTest(TEST_COUNT) + @Test fun byteCombinableArbitraryEven() { val actual = CombinableArbitrary.bytes().even().combined() then(actual % 2).isEqualTo(0) } - @RepeatedTest(TEST_COUNT) + @Test fun byteCombinableArbitraryOdd() { val actual = CombinableArbitrary.bytes().odd().combined() then(actual % 2 != 0).isTrue() } - @RepeatedTest(TEST_COUNT) + @Test fun byteCombinableArbitraryAscii() { val actual = CombinableArbitrary.bytes().ascii().combined() then(actual).isBetween(0.toByte(), 127.toByte()) } - @RepeatedTest(TEST_COUNT) + @Test fun byteCombinableArbitraryWithRange() { val actual = CombinableArbitrary.bytes().withRange(10.toByte(), 20.toByte()).combined() @@ -980,56 +979,56 @@ class KotestInJunitTest { then(actual).isInstanceOf(KotestLongCombinableArbitrary::class.java) } - @RepeatedTest(TEST_COUNT) + @Test fun longCombinableArbitraryPositive() { val actual = CombinableArbitrary.longs().positive().combined() then(actual).isPositive() } - @RepeatedTest(TEST_COUNT) + @Test fun longCombinableArbitraryNegative() { val actual = CombinableArbitrary.longs().negative().combined() then(actual).isNegative() } - @RepeatedTest(TEST_COUNT) + @Test fun longCombinableArbitraryEven() { val actual = CombinableArbitrary.longs().even().combined() then(actual % 2).isEqualTo(0) } - @RepeatedTest(TEST_COUNT) + @Test fun longCombinableArbitraryOdd() { val actual = CombinableArbitrary.longs().odd().combined() then(actual % 2 != 0.toLong()).isTrue() } - @RepeatedTest(TEST_COUNT) + @Test fun longCombinableArbitraryWithRange() { val actual = CombinableArbitrary.longs().withRange(10L, 20L).combined() then(actual).isBetween(10L, 20L) } - @RepeatedTest(TEST_COUNT) + @Test fun longCombinableArbitraryNonZero() { val actual = CombinableArbitrary.longs().nonZero().combined() then(actual).isNotEqualTo(0L) } - @RepeatedTest(TEST_COUNT) + @Test fun longCombinableArbitraryMultipleOf() { val actual = CombinableArbitrary.longs().multipleOf(7L).combined() then(actual % 7L).isEqualTo(0L) } - @RepeatedTest(TEST_COUNT) + @Test fun longCombinableArbitraryNonZeroWithRange() { // withRange(-5L, 5L).nonZero() => nonZero() val actual = CombinableArbitrary.longs().withRange(-5L, 5L).nonZero().combined() @@ -1037,7 +1036,7 @@ class KotestInJunitTest { then(actual).isNotEqualTo(0L) } - @RepeatedTest(TEST_COUNT) + @Test fun longCombinableArbitraryMultipleOfWithPositiveAndRange() { // positive().withRange(1L, 50L).multipleOf(3L) => multipleOf(3L) val actual = CombinableArbitrary.longs() @@ -1049,7 +1048,7 @@ class KotestInJunitTest { then(actual % 3L).isEqualTo(0L) } - @RepeatedTest(TEST_COUNT) + @Test fun longCombinableArbitraryLastMethodWinsWithPositiveAndNegative() { // positive().negative() => negative() val actual = CombinableArbitrary.longs().positive().negative().combined() @@ -1057,7 +1056,7 @@ class KotestInJunitTest { then(actual).isNegative() } - @RepeatedTest(TEST_COUNT) + @Test fun longCombinableArbitraryLastMethodWinsWithEvenAndOdd() { // even().odd() => odd() val actual = CombinableArbitrary.longs().even().odd().combined() @@ -1065,7 +1064,7 @@ class KotestInJunitTest { then(actual.toInt() % 2 != 0).isTrue() } - @RepeatedTest(TEST_COUNT) + @Test fun longCombinableArbitraryLastMethodWinsWithNegativeAndRange() { // negative().withRange() => withRange() val actual = CombinableArbitrary.longs().negative().withRange(100L, 1000L).combined() @@ -1081,34 +1080,34 @@ class KotestInJunitTest { then(actual).isInstanceOf(KotestShortCombinableArbitrary::class.java) } - @RepeatedTest(TEST_COUNT) + @Test fun shortCombinableArbitraryPositive() { val actual = CombinableArbitrary.shorts().positive().combined() then(actual).isPositive() } - @RepeatedTest(TEST_COUNT) + @Test fun shortCombinableArbitraryNegative() { val actual = CombinableArbitrary.shorts().negative().combined() then(actual).isNegative() } - @RepeatedTest(TEST_COUNT) + @Test fun shortCombinableArbitraryEven() { val actual = CombinableArbitrary.shorts().even().combined() then(actual % 2).isEqualTo(0) } - @RepeatedTest(TEST_COUNT) + @Test fun shortCombinableArbitraryOdd() { val actual = CombinableArbitrary.shorts().odd().combined() then(actual % 2 != 0).isTrue() } - @RepeatedTest(TEST_COUNT) + @Test fun shortCombinableArbitraryWithRange() { val actual = CombinableArbitrary.shorts().withRange(10.toShort(), 20.toShort()).combined() @@ -1122,63 +1121,63 @@ class KotestInJunitTest { then(actual).isInstanceOf(KotestCharacterCombinableArbitrary::class.java) } - @RepeatedTest(TEST_COUNT) + @Test fun characterCombinableArbitraryWithRange() { val actual = CombinableArbitrary.chars().withRange('A', 'Z').combined() then(actual).isBetween('A', 'Z') } - @RepeatedTest(TEST_COUNT) + @Test fun characterCombinableArbitraryAlpha() { val actual = CombinableArbitrary.chars().alphabetic().combined() then(actual.isLetter()).isTrue() } - @RepeatedTest(TEST_COUNT) + @Test fun characterCombinableArbitraryNumeric() { val actual = CombinableArbitrary.chars().numeric().combined() then(actual.isDigit()).isTrue() } - @RepeatedTest(TEST_COUNT) + @Test fun characterCombinableArbitraryAlphaNumeric() { val actual = CombinableArbitrary.chars().alphaNumeric().combined() then(actual.isLetterOrDigit()).isTrue() } - @RepeatedTest(TEST_COUNT) + @Test fun characterCombinableArbitraryAscii() { val actual = CombinableArbitrary.chars().ascii().combined() then(actual.code).isLessThanOrEqualTo(127) } - @RepeatedTest(TEST_COUNT) + @Test fun characterCombinableArbitraryUppercase() { val actual = CombinableArbitrary.chars().uppercase().combined() then(actual.isUpperCase()).isTrue() } - @RepeatedTest(TEST_COUNT) + @Test fun characterCombinableArbitraryLowercase() { val actual = CombinableArbitrary.chars().lowercase().combined() then(actual.isLowerCase()).isTrue() } - @RepeatedTest(TEST_COUNT) + @Test fun characterCombinableArbitraryKorean() { val actual = CombinableArbitrary.chars().korean().combined() then(actual).isBetween('가', '힣') } - @RepeatedTest(TEST_COUNT) + @Test fun characterCombinableArbitraryWhitespace() { val actual = CombinableArbitrary.chars().whitespace().combined() @@ -1202,7 +1201,7 @@ class KotestInJunitTest { ) } - @RepeatedTest(TEST_COUNT) + @Test fun byteCombinableArbitraryLastMethodWinsWithPositiveAndNegative() { // positive().negative() => negative() val actual = CombinableArbitrary.bytes().positive().negative().combined() @@ -1210,7 +1209,7 @@ class KotestInJunitTest { then(actual).isNegative() } - @RepeatedTest(TEST_COUNT) + @Test fun byteCombinableArbitraryLastMethodWinsWithEvenAndOdd() { // even().odd() => odd() val actual = CombinableArbitrary.bytes().even().odd().combined() @@ -1218,7 +1217,7 @@ class KotestInJunitTest { then(actual % 2 != 0).isTrue() } - @RepeatedTest(TEST_COUNT) + @Test fun byteCombinableArbitraryLastMethodWinsWithNegativeAndRange() { // negative().withRange() => withRange() val actual = CombinableArbitrary.bytes().negative().withRange(100.toByte(), 127.toByte()).combined() @@ -1226,7 +1225,7 @@ class KotestInJunitTest { then(actual).isBetween(100.toByte(), 127.toByte()) } - @RepeatedTest(TEST_COUNT) + @Test fun byteCombinableArbitraryLastMethodWinsWithAsciiAndPositive() { // ascii().positive() => positive() val actual = CombinableArbitrary.bytes().ascii().positive().combined() @@ -1234,7 +1233,7 @@ class KotestInJunitTest { then(actual).isPositive() } - @RepeatedTest(TEST_COUNT) + @Test fun byteCombinableArbitraryLastMethodWinsWithPositiveAndAscii() { // positive().ascii() => ascii() val actual = CombinableArbitrary.bytes().positive().ascii().combined() @@ -1242,7 +1241,7 @@ class KotestInJunitTest { then(actual).isBetween(0.toByte(), 127.toByte()) } - @RepeatedTest(TEST_COUNT) + @Test fun byteCombinableArbitraryLastMethodWinsWithAsciiAndEven() { // ascii().even() => even() val actual = CombinableArbitrary.bytes().ascii().even().combined() @@ -1250,7 +1249,7 @@ class KotestInJunitTest { then(actual % 2).isEqualTo(0) } - @RepeatedTest(TEST_COUNT) + @Test fun byteCombinableArbitraryLastMethodWinsWithEvenAndAscii() { // even().ascii() => ascii() val actual = CombinableArbitrary.bytes().even().ascii().combined() @@ -1258,7 +1257,7 @@ class KotestInJunitTest { then(actual).isBetween(0.toByte(), 127.toByte()) } - @RepeatedTest(TEST_COUNT) + @Test fun byteCombinableArbitraryLastMethodWinsWithAsciiAndNegative() { // ascii().negative() => negative() val actual = CombinableArbitrary.bytes().ascii().negative().combined() @@ -1266,7 +1265,7 @@ class KotestInJunitTest { then(actual).isNegative() } - @RepeatedTest(TEST_COUNT) + @Test fun integerCombinableArbitraryLastMethodWinsWithPositiveAndNegative() { // positive().negative() => negative() val actual = CombinableArbitrary.integers().positive().negative().combined() @@ -1274,7 +1273,7 @@ class KotestInJunitTest { then(actual).isNegative() } - @RepeatedTest(TEST_COUNT) + @Test fun integerCombinableArbitraryLastMethodWinsWithEvenAndOdd() { // even().odd() => odd() val actual = CombinableArbitrary.integers().even().odd().combined() @@ -1282,7 +1281,7 @@ class KotestInJunitTest { then(actual).isOdd() } - @RepeatedTest(TEST_COUNT) + @Test fun integerCombinableArbitraryLastMethodWinsWithNegativeAndRange() { // negative().withRange() => withRange() val actual = CombinableArbitrary.integers().negative().withRange(100, 1000).combined() @@ -1297,21 +1296,21 @@ class KotestInJunitTest { then(actual).isInstanceOf(KotestBigIntegerCombinableArbitrary::class.java) } - @RepeatedTest(TEST_COUNT) + @Test fun bigIntegerCombinableArbitraryPositive() { val actual = CombinableArbitrary.bigIntegers().positive().combined() then(actual).isPositive() } - @RepeatedTest(TEST_COUNT) + @Test fun bigIntegerCombinableArbitraryNegative() { val actual = CombinableArbitrary.bigIntegers().negative().combined() then(actual).isNegative() } - @RepeatedTest(TEST_COUNT) + @Test fun bigIntegerCombinableArbitraryWithRange() { val actual = CombinableArbitrary.bigIntegers().withRange( BigInteger.valueOf(100), BigInteger.valueOf(1000) @@ -1327,21 +1326,21 @@ class KotestInJunitTest { then(actual).isInstanceOf(KotestBigDecimalCombinableArbitrary::class.java) } - @RepeatedTest(TEST_COUNT) + @Test fun bigDecimalCombinableArbitraryPositive() { val actual = CombinableArbitrary.bigDecimals().positive().combined() then(actual).isPositive() } - @RepeatedTest(TEST_COUNT) + @Test fun bigDecimalCombinableArbitraryNegative() { val actual = CombinableArbitrary.bigDecimals().negative().combined() then(actual).isNegative() } - @RepeatedTest(TEST_COUNT) + @Test fun bigDecimalCombinableArbitraryWithRange() { val actual = CombinableArbitrary.bigDecimals().withRange( BigDecimal("100.0"), BigDecimal("1000.0") @@ -1350,14 +1349,14 @@ class KotestInJunitTest { then(actual).isBetween(BigDecimal("100.0"), BigDecimal("1000.0")) } - @RepeatedTest(TEST_COUNT) + @Test fun bigDecimalCombinableArbitraryWithPrecision() { val actual = CombinableArbitrary.bigDecimals().withPrecision(2).combined() then(actual.precision()).isLessThanOrEqualTo(2) } - @RepeatedTest(TEST_COUNT) + @Test fun bigDecimalCombinableArbitraryLastMethodWins() { val actual = CombinableArbitrary.bigDecimals() .withRange(BigDecimal("10.0"), BigDecimal("20.0")) diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/KotlinInnerSpecTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/KotlinInnerSpecTest.kt index 6dbcc0f0b5..3dee292dc7 100644 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/KotlinInnerSpecTest.kt +++ b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/KotlinInnerSpecTest.kt @@ -18,6 +18,7 @@ package com.navercorp.fixturemonkey.tests.kotlin * limitations under the License. */ +import org.junit.jupiter.api.Test import com.navercorp.fixturemonkey.FixtureMonkey import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfo import com.navercorp.fixturemonkey.customizer.Values @@ -37,7 +38,6 @@ import com.navercorp.fixturemonkey.tests.kotlin.InnerSpecTestSpecs.SimpleObject import com.navercorp.fixturemonkey.tests.kotlin.InnerSpecTestSpecs.SupplierStringObject import net.jqwik.api.Arbitraries -import net.jqwik.api.Example import org.assertj.core.api.BDDAssertions.then import org.assertj.core.api.BDDAssertions.thenThrownBy import java.util.function.Supplier @@ -46,7 +46,7 @@ import kotlin.jvm.java class KotlinInnerSpecTest { - @Example + @Test fun key() { // when val actual = SUT.giveMeBuilder() @@ -62,7 +62,7 @@ class KotlinInnerSpecTest { then(actual.keys).contains("key") } - @Example + @Test fun value() { // when val actual = SUT.giveMeBuilder() @@ -78,7 +78,7 @@ class KotlinInnerSpecTest { then(actual.values).contains("value") } - @Example + @Test fun entry() { // when val actual = SUT.giveMeBuilder() @@ -94,7 +94,7 @@ class KotlinInnerSpecTest { then(actual["key"]).isEqualTo("value") } - @Example + @Test fun keys() { // when val actual = SUT.giveMeBuilder() @@ -110,7 +110,7 @@ class KotlinInnerSpecTest { then(actual.keys).containsAll(setOf("key1", "key2", "key3")) } - @Example + @Test fun values() { // when val actual = SUT.giveMeBuilder() @@ -126,7 +126,7 @@ class KotlinInnerSpecTest { then(actual.values).containsAll(setOf("value1", "value2", "value3")) } - @Example + @Test fun entries() { // when val actual = SUT.giveMeBuilder() @@ -143,7 +143,7 @@ class KotlinInnerSpecTest { then(actual["key2"]).isEqualTo("value2") } - @Example + @Test fun entryTwice() { // when val actual = SUT.giveMeBuilder() @@ -160,7 +160,7 @@ class KotlinInnerSpecTest { then(actual.strMap["key2"]).isEqualTo("value2") } - @Example + @Test fun valueNull() { // when val actual = SUT.giveMeBuilder() @@ -175,7 +175,7 @@ class KotlinInnerSpecTest { then(actual.strMap.containsValue(null as String?)).isTrue() } - @Example + @Test fun keyNullThrows() { thenThrownBy { SUT.giveMeBuilder() @@ -190,7 +190,7 @@ class KotlinInnerSpecTest { .hasMessageContaining("Map key cannot be null.") } - @Example + @Test fun keyInKey() { val sut = FixtureMonkey.builder() .plugin(KotlinPlugin()) @@ -212,7 +212,7 @@ class KotlinInnerSpecTest { then(keyList).contains("key") } - @Example + @Test fun valueInKey() { val sut = FixtureMonkey.builder() .plugin(KotlinPlugin()) @@ -234,7 +234,7 @@ class KotlinInnerSpecTest { then(keyList).contains("value") } - @Example + @Test fun keyInValue() { // when val actual = SUT.giveMeBuilder() @@ -255,7 +255,7 @@ class KotlinInnerSpecTest { then(valueList).contains("key") } - @Example + @Test fun valueInValue() { // when val actual = SUT.giveMeBuilder() @@ -276,7 +276,7 @@ class KotlinInnerSpecTest { then(valueList).contains("value") } - @Example + @Test fun sizeInValue() { // when val actual = SUT.giveMeBuilder() @@ -294,7 +294,7 @@ class KotlinInnerSpecTest { then(sizeList).contains(10) } - @Example + @Test fun listElementInValue() { // when val actual = SUT.giveMeBuilder() @@ -315,7 +315,7 @@ class KotlinInnerSpecTest { then(elementList).contains("test") } - @Example + @Test fun propertyInValue() { // when val actual = SUT.giveMeBuilder() @@ -334,7 +334,7 @@ class KotlinInnerSpecTest { then(fieldList).contains("test") } - @Example + @Test fun entryInEntryValue() { // when val actual = SUT.giveMeBuilder() @@ -353,7 +353,7 @@ class KotlinInnerSpecTest { then(value?.get("key2")).isEqualTo("value") } - @Example + @Test fun entryInEntryKey() { // given val sut = FixtureMonkey.builder() @@ -381,7 +381,7 @@ class KotlinInnerSpecTest { then(expected["key"]).isEqualTo("value2") } - @Example + @Test fun entryValueSetNull() { // when val actual = SUT.giveMeBuilder() @@ -396,7 +396,7 @@ class KotlinInnerSpecTest { then(actual.strMap["key"]).isNull() } - @Example + @Test fun listElementInListElement() { // when val actual = SUT.giveMeBuilder() @@ -414,7 +414,7 @@ class KotlinInnerSpecTest { then(actual.values[0][0]).isEqualTo("test") } - @Example + @Test fun propertyInProperty() { // when val actual = SUT.giveMeBuilder() @@ -430,7 +430,7 @@ class KotlinInnerSpecTest { then(actual.value.value.str).isEqualTo("test") } - @Example + @Test fun sizeAndEntry() { // when val actual = SUT.giveMeBuilder() @@ -447,7 +447,7 @@ class KotlinInnerSpecTest { then(actual["key"]).isEqualTo("test") } - @Example + @Test fun entryAndSize() { // when val actual = SUT.giveMeBuilder() @@ -464,7 +464,7 @@ class KotlinInnerSpecTest { then(actual["key"]).isEqualTo("test") } - @Example + @Test fun sizeTwiceReturnsLatterSize() { // when val actual = SUT.giveMeBuilder() @@ -481,7 +481,7 @@ class KotlinInnerSpecTest { then(actual).hasSize(0) } - @Example + @Test fun keyLazy() { val variable = SUT.giveMeBuilder() val builder = SUT.giveMeBuilder() @@ -498,7 +498,7 @@ class KotlinInnerSpecTest { then(actual.strMap.containsKey("key")).isTrue() } - @Example + @Test fun valueLazy() { val variable = SUT.giveMeBuilder() val builder = SUT.giveMeBuilder() @@ -515,7 +515,7 @@ class KotlinInnerSpecTest { then(actual.strMap.containsValue("value")).isTrue() } - @Example + @Test fun entryLazy() { val keyVariable = SUT.giveMeBuilder() val valueVariable = SUT.giveMeBuilder() @@ -534,7 +534,7 @@ class KotlinInnerSpecTest { then(actual.strMap["key"]).isEqualTo("value") } - @Example + @Test fun keyLazyNullThrows() { thenThrownBy { SUT.giveMeBuilder() @@ -549,7 +549,7 @@ class KotlinInnerSpecTest { .hasMessageContaining("Map key cannot be null.") } - @Example + @Test fun allKeyLazy() { val actual = SUT.giveMeBuilder() .setKotlinInner { @@ -562,7 +562,7 @@ class KotlinInnerSpecTest { then(actual.integerMap.keys).allMatch { it in 0..100 } } - @Example + @Test fun allValueLazy() { val actual = SUT.giveMeBuilder() .setKotlinInner { @@ -575,7 +575,7 @@ class KotlinInnerSpecTest { then(actual.integerMap.values).allMatch { it in 0..100 } } - @Example + @Test fun allEntry() { val actual = SUT.giveMeBuilder() .setKotlinInner { @@ -592,7 +592,7 @@ class KotlinInnerSpecTest { then(actual.integerMap.values).allMatch { it == 100 } } - @Example + @Test fun allEntryLazy() { val actual = SUT.giveMeBuilder() .setKotlinInner { @@ -609,7 +609,7 @@ class KotlinInnerSpecTest { then(actual.integerMap.values).allMatch { it in 0..100 } } - @Example + @Test fun allKey() { val expected = "test" @@ -627,7 +627,7 @@ class KotlinInnerSpecTest { then(actual).allMatch { it == expected } } - @Example + @Test fun allValue() { val expected = "test" @@ -644,7 +644,7 @@ class KotlinInnerSpecTest { then(actual).allMatch { it == expected } } - @Example + @Test fun allValueInner() { val expected = "test" @@ -662,7 +662,7 @@ class KotlinInnerSpecTest { then(actual).allMatch { it == expected } } - @Example + @Test fun allListElement() { val expected = "test" @@ -676,7 +676,7 @@ class KotlinInnerSpecTest { then(actual).allMatch { it == expected } } - @Example + @Test fun allListElementInnerSpec() { val expected = "test" @@ -691,7 +691,7 @@ class KotlinInnerSpecTest { then(actual).allMatch { it == expected } } - @Example + @Test fun setPostCondition() { val actual = SUT.giveMeBuilder() .setKotlinInner { @@ -704,7 +704,7 @@ class KotlinInnerSpecTest { then(actual.str).hasSizeGreaterThan(5) } - @Example + @Test fun inner() { val innerSpec = kotlinInnerSpec { property("str", "test") } @@ -717,7 +717,7 @@ class KotlinInnerSpecTest { then(actual.str).isEqualTo("test") } - @Example + @Test fun propertyInner() { val innerSpec = kotlinInnerSpec { property("str", "test") } @@ -730,7 +730,7 @@ class KotlinInnerSpecTest { then(actual.value.str).isEqualTo("test") } - @Example + @Test fun listElementInMaxSize() { val expected = "expected" @@ -745,7 +745,7 @@ class KotlinInnerSpecTest { then(actual).allMatch { it == expected } } - @Example + @Test fun setAfterSizeReturnsSet() { val actual = SUT.giveMeBuilder() .setKotlinInner { @@ -758,7 +758,7 @@ class KotlinInnerSpecTest { then(actual).isEmpty() } - @Example + @Test fun sizeAfterSetReturnsSize() { val actual = SUT.giveMeBuilder() .setKotlinInner { @@ -771,7 +771,7 @@ class KotlinInnerSpecTest { then(actual).hasSize(2) } - @Example + @Test fun sizeAfterSetWithSeparateInnerSpecReturnsSize() { val actual = SUT.giveMeBuilder() .setKotlinInner { @@ -786,7 +786,7 @@ class KotlinInnerSpecTest { then(actual).hasSize(2) } - @Example + @Test fun setAfterSetWithSeparateInnerSpecReturnsSet() { val actual = SUT.giveMeBuilder() .setKotlinInner { @@ -801,7 +801,7 @@ class KotlinInnerSpecTest { then(actual).isEmpty() } - @Example + @Test fun innerSpecIncrementsSequence() { val actual = SUT.giveMeBuilder() .setKotlinInner { @@ -815,7 +815,7 @@ class KotlinInnerSpecTest { then(actual.values).hasSize(5) } - @Example + @Test fun setNotNull() { val actual = SUT.giveMeBuilder() .setKotlinInner { @@ -827,7 +827,7 @@ class KotlinInnerSpecTest { then(actual).isNotNull() } - @Example + @Test fun keysForCollection() { val keyList = listOf("key1", "key2", "key3") @@ -844,7 +844,7 @@ class KotlinInnerSpecTest { then(actual.keys).containsAll(keyList) } - @Example + @Test fun valuesForCollection() { val valueList = listOf("value1", "value2", "value3") @@ -861,7 +861,7 @@ class KotlinInnerSpecTest { then(actual.values).containsAll(valueList) } - @Example + @Test fun entriesForCollection() { val entries = listOf("key1", "value1", "key2", "value2") @@ -879,7 +879,7 @@ class KotlinInnerSpecTest { then(actual["key2"]).isEqualTo("value2") } - @Example + @Test fun supportSupplierWrapping() { val expected = "test" @@ -895,7 +895,7 @@ class KotlinInnerSpecTest { then(actual).isEqualTo(expected) } - @Example + @Test fun supportSupplierObjectField() { val expected = Supplier { "test" } diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/OptionTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/OptionTest.kt index 4bac65e618..e69a4493d2 100644 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/OptionTest.kt +++ b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/OptionTest.kt @@ -30,7 +30,7 @@ import com.navercorp.fixturemonkey.kotlin.KotlinPlugin import com.navercorp.fixturemonkey.kotlin.giveMeOne import com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.RepeatedTest +import org.junit.jupiter.api.Test import java.io.File import java.lang.reflect.Modifier import java.time.Instant @@ -39,7 +39,7 @@ import java.time.OffsetTime import javax.validation.constraints.FutureOrPresent class OptionTest { - @RepeatedTest(TEST_COUNT) + @Test fun customizeJavaConstraintGenerators() { // given class InstantObject(@field:FutureOrPresent val value: Instant) @@ -73,7 +73,7 @@ class OptionTest { then(actual).isBetween(thisYearInstant, nextYearInstant) } - @RepeatedTest(TEST_COUNT) + @Test fun customizeJavaConstraintGeneratorsTwice() { // given class InstantObject(@field:FutureOrPresent val value: Instant) @@ -117,7 +117,7 @@ class OptionTest { - @RepeatedTest(TEST_COUNT) + @Test fun requiredPropertyGenerator() { val sut = FixtureMonkey.builder() .objectIntrospector( diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/PluginTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/PluginTest.kt index 2665b7b50c..0f41a29f58 100644 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/PluginTest.kt +++ b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/PluginTest.kt @@ -29,14 +29,13 @@ import com.navercorp.fixturemonkey.kotlin.giveMeBuilder import com.navercorp.fixturemonkey.kotlin.giveMeOne import com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.RepeatedTest import org.junit.jupiter.api.Test import java.time.Instant import java.util.LinkedList import java.util.TreeSet class PluginTest { - @RepeatedTest(TEST_COUNT) + @Test fun propertyCandidateResolverReturnsConcreteListType() { val sut = FixtureMonkey.builder() .plugin(KotlinPlugin()) @@ -57,7 +56,7 @@ class PluginTest { then(actual).isInstanceOf(LinkedList::class.java) } - @RepeatedTest(TEST_COUNT) + @Test fun nestedPropertyCandidateResolverReturnsConcreteListType() { val sut = FixtureMonkey.builder() .plugin(KotlinPlugin()) @@ -82,7 +81,7 @@ class PluginTest { then(actual).isInstanceOf(LinkedList::class.java) } - @RepeatedTest(TEST_COUNT) + @Test fun propertyCandidateResolverReturnsConcreteSetType() { val sut = FixtureMonkey.builder() .plugin(KotlinPlugin()) @@ -103,7 +102,7 @@ class PluginTest { then(actual).isInstanceOf(TreeSet::class.java) } - @RepeatedTest(TEST_COUNT) + @Test fun nestedPropertyCandidateResolverReturnsConcreteSetType() { val sut = FixtureMonkey.builder() .plugin(KotlinPlugin()) @@ -146,7 +145,7 @@ class PluginTest { .abstractClassExtends( AssignableTypeMatcher(ParentAbstractClass::class.java) ) { property -> - when (property.type) { + when (property.jvmType.rawType) { FirstAbstractClass::class.java -> listOf(PropertyUtils.toProperty(FirstConcreteClass::class.java)) SecondAbstractClass::class.java -> listOf(PropertyUtils.toProperty(SecondConcreteClass::class.java)) else -> throw NotImplementedError() @@ -178,7 +177,7 @@ class PluginTest { .abstractClassExtends( AssignableTypeMatcher(ParentAbstractClass::class.java) ) { property -> - when (property.type) { + when (property.jvmType.rawType) { FirstAbstractClass::class.java -> listOf(PropertyUtils.toProperty(FirstConcreteClass::class.java)) SecondAbstractClass::class.java -> listOf(PropertyUtils.toProperty(SecondConcreteClass::class.java)) else -> throw NotImplementedError() @@ -193,7 +192,7 @@ class PluginTest { then(actual).isInstanceOf(SecondConcreteClass::class.java) } - @RepeatedTest(TEST_COUNT) + @Test fun setConcreteTypeChildReturnsExactlyConcreteTypeChildType() { // given abstract class AbstractClass @@ -281,7 +280,7 @@ class PluginTest { then(actual).isEqualTo(expected) } - @RepeatedTest(TEST_COUNT) + @Test fun setComplexReturnsSimple() { // given abstract class ParentAbstractClass diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/PropertySelectorTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/PropertySelectorTest.kt index 0d920cd7a5..e75986b72c 100644 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/PropertySelectorTest.kt +++ b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/PropertySelectorTest.kt @@ -24,8 +24,8 @@ import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitra import com.navercorp.fixturemonkey.kotlin.KotlinPlugin import com.navercorp.fixturemonkey.kotlin.expression.root import com.navercorp.fixturemonkey.kotlin.get -import com.navercorp.fixturemonkey.kotlin.giveMeKotlinBuilder import com.navercorp.fixturemonkey.kotlin.giveMeExperimentalBuilder +import com.navercorp.fixturemonkey.kotlin.giveMeKotlinBuilder import com.navercorp.fixturemonkey.kotlin.instantiator.instantiateBy import com.navercorp.fixturemonkey.kotlin.into import com.navercorp.fixturemonkey.kotlin.intoGetter @@ -36,16 +36,18 @@ import com.navercorp.fixturemonkey.kotlin.setNotNull import com.navercorp.fixturemonkey.kotlin.setNull import com.navercorp.fixturemonkey.kotlin.sizeExp import com.navercorp.fixturemonkey.kotlin.sizeExpGetter -import com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT +import com.navercorp.fixturemonkey.tests.TestEnvironment.ADAPTER_TEST_COUNT import com.navercorp.fixturemonkey.tests.kotlin.ImmutableJavaTestSpecs.ArrayObject import com.navercorp.fixturemonkey.tests.kotlin.ImmutableJavaTestSpecs.JavaStringObject import com.navercorp.fixturemonkey.tests.kotlin.ImmutableJavaTestSpecs.NestedArrayObject import com.navercorp.fixturemonkey.tests.kotlin.ImmutableJavaTestSpecs.RootJavaStringObject +import com.navercorp.fixturemonkey.tests.kotlin.InnerSpecTestSpecs.ComplexObject +import com.navercorp.fixturemonkey.tests.kotlin.InnerSpecTestSpecs.ComplexObjectObject +import com.navercorp.fixturemonkey.tests.kotlin.InnerSpecTestSpecs.ListStringObject +import com.navercorp.fixturemonkey.tests.kotlin.InnerSpecTestSpecs.SimpleObject import com.navercorp.fixturemonkey.tests.kotlin.JavaConstructorTestSpecs.JavaTypeObject -import java.math.BigDecimal import org.assertj.core.api.BDDAssertions.then import org.assertj.core.api.BDDAssertions.thenThrownBy -import org.junit.jupiter.api.RepeatedTest import org.junit.jupiter.api.Test class PropertySelectorTest { @@ -196,7 +198,7 @@ class PropertySelectorTest { then(actual).isNull() } - @RepeatedTest(TEST_COUNT) + @Test fun setNotNullRootExp() { val actual = SUT.giveMeKotlinBuilder() .setNotNull(String::root) @@ -205,7 +207,7 @@ class PropertySelectorTest { then(actual).isNotNull() } - @RepeatedTest(TEST_COUNT) + @Test fun sizeRootExp() { val actual = SUT.giveMeKotlinBuilder>() .size(List::root, 1) @@ -214,7 +216,7 @@ class PropertySelectorTest { then(actual).hasSize(1) } - @RepeatedTest(TEST_COUNT) + @Test fun sizeRangeRootExp() { val actual = SUT.giveMeKotlinBuilder>() .size(List::root, 1, 3) @@ -223,7 +225,7 @@ class PropertySelectorTest { then(actual).hasSizeBetween(1, 3) } - @RepeatedTest(TEST_COUNT) + @Test fun minSizeRootExp() { val actual = SUT.giveMeKotlinBuilder>() .minSize(List::root, 1) @@ -232,7 +234,7 @@ class PropertySelectorTest { then(actual).hasSizeGreaterThanOrEqualTo(1) } - @RepeatedTest(TEST_COUNT) + @Test fun maxSizeRootExp() { val actual = SUT.giveMeKotlinBuilder>() .maxSize(List::root, 1) @@ -250,7 +252,7 @@ class PropertySelectorTest { then(actual).hasSizeLessThan(5) } - @RepeatedTest(TEST_COUNT) + @Test fun setRootElementExp() { val expected = "test" @@ -262,7 +264,7 @@ class PropertySelectorTest { then(actual[0]).isEqualTo(expected) } - @RepeatedTest(TEST_COUNT) + @Test fun setRootArrayElementExp() { val expected = "test" @@ -274,7 +276,7 @@ class PropertySelectorTest { then(actual[0]).isEqualTo(expected) } - @RepeatedTest(TEST_COUNT) + @Test fun setRootAllElementExp() { val expected = "test" @@ -286,7 +288,7 @@ class PropertySelectorTest { then(actual).allMatch { it == expected } } - @RepeatedTest(TEST_COUNT) + @Test fun setRootArrayAllElementExp() { val expected = "test" @@ -298,7 +300,7 @@ class PropertySelectorTest { then(actual).allMatch { it == expected } } - @RepeatedTest(TEST_COUNT) + @Test fun setRootNestedListElementExp() { val expected = "test" @@ -311,7 +313,7 @@ class PropertySelectorTest { then(actual).isEqualTo(expected) } - @RepeatedTest(TEST_COUNT) + @Test fun setRootNestedListAllElementExp() { val expected = "test" @@ -324,7 +326,7 @@ class PropertySelectorTest { then(actual).allMatch { list -> list.all { it == expected } } } - @RepeatedTest(TEST_COUNT) + @Test fun setRootNestedArrayElementExp() { val expected = "test" @@ -337,7 +339,7 @@ class PropertySelectorTest { then(actual).isEqualTo(expected) } - @RepeatedTest(TEST_COUNT) + @Test fun setRootNestedArrayAllElementExp() { val expected = "test" @@ -517,6 +519,159 @@ class PropertySelectorTest { then(actual).isEqualTo(expected) } + @Test + fun threeLevelDeepSetShouldPreventAllAncestorNull() { + // given + val expected = "test" + + val sut = FixtureMonkey.builder() + .plugin(KotlinPlugin()) + .defaultNullInjectGenerator { 1.0 } + .build() + + // when + val result = sut.giveMeKotlinBuilder() + .setExp(ComplexObjectObject::value into ComplexObject::value into SimpleObject::str, expected) + .sample() + + // then + then(result).isNotNull + then(result.value).isNotNull + then(result.value.value).isNotNull + then(result.value.value.str).isEqualTo(expected) + } + + @Test + fun setContainerElementShouldPreventParentNull() { + // given + val expected = "test" + + val sut = FixtureMonkey.builder() + .plugin(KotlinPlugin()) + .defaultNullInjectGenerator { 1.0 } + .build() + + // when + val result = sut.giveMeKotlinBuilder() + .sizeExp(ListStringObject::values, 1) + .setExp(ListStringObject::values[0], expected) + .sample() + + // then + then(result).isNotNull + then(result.values).isNotNull + then(result.values[0]).isEqualTo(expected) + } + + @Test + fun setMultipleSiblingPathsShouldPreventParentNull() { + // given + val expectedStr = "test" + val expectedInt = 42 + + val sut = FixtureMonkey.builder() + .plugin(KotlinPlugin()) + .defaultNullInjectGenerator { 1.0 } + .build() + + // when + val result = sut.giveMeKotlinBuilder() + .setExp(ComplexObjectObject::value into ComplexObject::value into SimpleObject::str, expectedStr) + .setExp(ComplexObjectObject::value into ComplexObject::value into SimpleObject::integer, expectedInt) + .sample() + + // then + then(result).isNotNull + then(result.value).isNotNull + then(result.value.value).isNotNull + then(result.value.value.str).isEqualTo(expectedStr) + then(result.value.value.integer).isEqualTo(expectedInt) + } + + @Test + fun sizeOnlyContainerShouldPreventParentNull() { + // given + val sut = FixtureMonkey.builder() + .plugin(KotlinPlugin()) + .defaultNullInjectGenerator { 1.0 } + .build() + + // when + val result = sut.giveMeKotlinBuilder() + .sizeExp(ListStringObject::values, 2) + .sample() + + // then + then(result).isNotNull + then(result.values).isNotNull + then(result.values).hasSize(2) + } + + @Test + fun setNotNullNestedPathShouldPreventAncestorNull() { + // given + val sut = FixtureMonkey.builder() + .plugin(KotlinPlugin()) + .defaultNullInjectGenerator { 1.0 } + .build() + + // when + val result = sut.giveMeKotlinBuilder() + .setNotNullExp(ComplexObjectObject::value into ComplexObject::value) + .sample() + + // then + then(result).isNotNull + then(result.value).isNotNull + then(result.value.value).isNotNull + } + + @Test + fun customizePropertyNestedPathShouldPreventParentNull() { + // given + val expected = "test" + + val sut = FixtureMonkey.builder() + .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) + .plugin(KotlinPlugin()) + .defaultNullInjectGenerator { 1.0 } + .build() + + // when + val result = sut.giveMeKotlinBuilder() + .customizeProperty(RootJavaStringObject::getObj intoGetter JavaStringObject::getString) { + it.map { _ -> expected } + } + .sample() + + // then + then(result).isNotNull + then(result.obj).isNotNull + then(result.obj.string).isEqualTo(expected) + } + + @Test + fun setExpChildPathShouldPreventParentNull() { + // given + val expected = "test" + + val sut = FixtureMonkey.builder() + .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) + .plugin(KotlinPlugin()) + .defaultNullInjectGenerator { 1.0 } + .build() + + // when + val result = sut.giveMeKotlinBuilder() + .setExp(RootJavaStringObject::getObj intoGetter JavaStringObject::getString, expected) + .sample() + + // then + then(result).isNotNull + then(result.obj).isNotNull + then(result.obj.string).isEqualTo(expected) + } + companion object { private val SUT: FixtureMonkey = FixtureMonkey.builder() .plugin(KotlinPlugin()) diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/SimpleValueJqwikPluginTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/SimpleValueJqwikPluginTest.kt index c80d2dcecf..92d6f95534 100644 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/SimpleValueJqwikPluginTest.kt +++ b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/SimpleValueJqwikPluginTest.kt @@ -26,7 +26,6 @@ import com.navercorp.fixturemonkey.kotlin.giveMeKotlinBuilder import com.navercorp.fixturemonkey.kotlin.giveMeOne import com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.RepeatedTest import org.junit.jupiter.api.Test import java.time.Instant import java.time.LocalDateTime @@ -35,7 +34,7 @@ import javax.validation.constraints.Max import javax.validation.constraints.Min class SimpleValueJqwikPluginTest { - @RepeatedTest(TEST_COUNT) + @Test fun sampleInt() { val sut = FixtureMonkey.builder() .plugin(SimpleValueJqwikPlugin()) @@ -46,7 +45,7 @@ class SimpleValueJqwikPluginTest { then(actual).isBetween(-10000, 10000) } - @RepeatedTest(TEST_COUNT) + @Test fun modifyNumberValue() { val sut = FixtureMonkey.builder() .plugin( @@ -61,7 +60,7 @@ class SimpleValueJqwikPluginTest { then(actual).isBetween(-1, 1) } - @RepeatedTest(TEST_COUNT) + @Test fun modifyStringLength() { val sut = FixtureMonkey.builder() .plugin( @@ -76,7 +75,7 @@ class SimpleValueJqwikPluginTest { then(actual).hasSizeBetween(2, 3) } - @RepeatedTest(TEST_COUNT) + @Test fun modifyCharacterPredicate() { val sut = FixtureMonkey.builder() .plugin( @@ -90,7 +89,7 @@ class SimpleValueJqwikPluginTest { then(actual.chars()).allMatch { it in 50..100 } } - @RepeatedTest(TEST_COUNT) + @Test fun modifyContainerSize() { val sut = FixtureMonkey.builder() .plugin( @@ -105,7 +104,7 @@ class SimpleValueJqwikPluginTest { then(actual).hasSizeBetween(2, 3) } - @RepeatedTest(TEST_COUNT) + @Test fun modifyDate() { val sut = FixtureMonkey.builder() .plugin( @@ -122,7 +121,7 @@ class SimpleValueJqwikPluginTest { then(actual).isBetween(yesterday, tomorrow) } - @RepeatedTest(TEST_COUNT) + @Test fun withValidationPlugin() { // given class JavaxValidationAnnotationValue( @@ -143,7 +142,7 @@ class SimpleValueJqwikPluginTest { then(actual.notAnnotatedInt).isBetween(-10000, 10000) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleSetObject() { class SetObject(val integers: Set) @@ -161,7 +160,7 @@ class SimpleValueJqwikPluginTest { then(setObject.integers).hasSize(3) } - @RepeatedTest(TEST_COUNT) + @Test fun sampleByte() { val sut = FixtureMonkey.builder() .plugin(KotlinPlugin()) @@ -173,7 +172,7 @@ class SimpleValueJqwikPluginTest { then(actual).isBetween(Byte.MIN_VALUE, Byte.MAX_VALUE) } - @RepeatedTest(TEST_COUNT) + @Test fun modifyNumberValueByte() { val sut = FixtureMonkey.builder() .plugin(KotlinPlugin()) @@ -189,7 +188,7 @@ class SimpleValueJqwikPluginTest { then(actual).isBetween(-1, 1) } - @RepeatedTest(TEST_COUNT) + @Test fun modifyOutOfRangeNumberValueByte() { val sut = FixtureMonkey.builder() .plugin(KotlinPlugin()) @@ -205,7 +204,7 @@ class SimpleValueJqwikPluginTest { then(actual).isBetween(Byte.MIN_VALUE, Byte.MAX_VALUE) } - @RepeatedTest(TEST_COUNT) + @Test fun setPositiveMinNumberReturnsPositive() { val sut = FixtureMonkey.builder() .plugin(SimpleValueJqwikPlugin().minNumberValue(0)) @@ -216,7 +215,7 @@ class SimpleValueJqwikPluginTest { then(actual).isGreaterThanOrEqualTo(0); } - @RepeatedTest(TEST_COUNT) + @Test fun setNegativeMaxNumberReturnsNegative() { val sut = FixtureMonkey.builder() .plugin(SimpleValueJqwikPlugin().maxNumberValue(-0)) @@ -227,7 +226,7 @@ class SimpleValueJqwikPluginTest { then(actual).isLessThanOrEqualTo(0); } - @RepeatedTest(TEST_COUNT) + @Test fun modifyPositiveDecimalNumberRange() { val sut = FixtureMonkey.builder() .plugin( @@ -242,7 +241,7 @@ class SimpleValueJqwikPluginTest { then(actual).isBetween(1.0, 10.0) } - @RepeatedTest(TEST_COUNT) + @Test fun modifyNegativeDecimalNumberRange() { val sut = FixtureMonkey.builder() .plugin( @@ -257,7 +256,7 @@ class SimpleValueJqwikPluginTest { then(actual).isBetween(-10.0, -1.0) } - @RepeatedTest(TEST_COUNT) + @Test fun modifyMixedDecimalNumberRange() { val sut = FixtureMonkey.builder() .plugin( diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/AnonymousInstanceAdapterTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/AnonymousInstanceAdapterTest.kt deleted file mode 100644 index 4b13a94cc9..0000000000 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/AnonymousInstanceAdapterTest.kt +++ /dev/null @@ -1,482 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.kotlin.adapter - -import com.navercorp.fixturemonkey.FixtureMonkey -import com.navercorp.fixturemonkey.kotlin.KotlinNodeTreeAdapterPlugin -import com.navercorp.fixturemonkey.api.plugin.InterfacePlugin -import com.navercorp.fixturemonkey.javax.validation.plugin.JavaxValidationPlugin -import com.navercorp.fixturemonkey.kotlin.KotlinPlugin -import com.navercorp.fixturemonkey.kotlin.giveMeBuilder -import com.navercorp.fixturemonkey.kotlin.giveMeOne -import com.navercorp.fixturemonkey.kotlin.setExpGetter -import com.navercorp.fixturemonkey.tests.TestEnvironment.ADAPTER_TEST_COUNT -import com.navercorp.fixturemonkey.tests.kotlin.JavaAnonymousInstanceTestSpecs.InheritedJavaInterface -import com.navercorp.fixturemonkey.tests.kotlin.JavaAnonymousInstanceTestSpecs.InheritedJavaInterfaceWithSameNameMethod -import com.navercorp.fixturemonkey.tests.kotlin.JavaAnonymousInstanceTestSpecs.InheritedTwoJavaInterface -import com.navercorp.fixturemonkey.tests.kotlin.JavaAnonymousInstanceTestSpecs.JavaAnnotatedInterface -import com.navercorp.fixturemonkey.tests.kotlin.JavaAnonymousInstanceTestSpecs.JavaContainerInterface -import com.navercorp.fixturemonkey.tests.kotlin.JavaAnonymousInstanceTestSpecs.JavaGetterInterface -import com.navercorp.fixturemonkey.tests.kotlin.JavaAnonymousInstanceTestSpecs.JavaInterface -import com.navercorp.fixturemonkey.tests.kotlin.JavaAnonymousInstanceTestSpecs.JavaInterfaceWithConstant -import com.navercorp.fixturemonkey.tests.kotlin.JavaAnonymousInstanceTestSpecs.JavaInterfaceWithParams -import com.navercorp.fixturemonkey.tests.kotlin.JavaAnonymousInstanceTestSpecs.NestedInheritedJavaInterface -import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.RepeatedTest -import javax.validation.constraints.NotEmpty - -class AnonymousInstanceAdapterTest { - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleInterface() { - val actual = SUT.giveMeOne() - - then(actual.string()).isNotNull - then(actual.integer()).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun objectBaseMethods() { - val actual = SUT.giveMeOne() - - then(actual.hashCode()).isNotNull - then(actual).isEqualTo(actual) - then(actual.toString()).isNotNull() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun equalsOnSimilarInterface() { - val one = SUT.giveMeBuilder() - .setExpGetter(Interface::string, "test") - .setExpGetter(Interface::integer, 123) - .sample() - val another = SUT.giveMeBuilder() - .setExpGetter(SimilarInterface::string, "test") - .setExpGetter(SimilarInterface::integer, 123) - .sample() - - then(one).isNotEqualTo(another) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setInterface() { - val expected = "test" - - val actual = SUT.giveMeBuilder() - .setExpGetter(Interface::string, expected) - .sample() - .string() - - then(actual).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleInterfaceWithParam() { - val actual = SUT.giveMeOne() - - then(actual).isNull() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleContainerInterface() { - val actual = SUT.giveMeOne() - - then(actual.list()).isNotNull - then(actual.map()).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setContainerInterfaceList() { - val actual: List = SUT.giveMeBuilder() - .size("list", 3) - .set("list[0]", "test") - .sample() - .list() - - then(actual).hasSize(3) - then(actual[0]).isEqualTo("test") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleAnnotatedInterface() { - val actual = SUT.giveMeOne().string() - - then(actual).isNotEmpty - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleGetterInterface() { - val actual = SUT.giveMeOne().getString() - - then(actual).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setGetterInterface() { - val expected = "test" - - val actual = SUT.giveMeBuilder() - .set("string", expected) - .sample() - .getString() - - then(actual).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun samplePropertyInterface() { - val actual = SUT.giveMeOne() - - then(actual.string).isNotNull - then(actual.int).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setPropertyInterface() { - val expected = "expected" - - val actual = SUT.giveMeBuilder() - .set("string", expected) - .sample() - .string - - then(actual).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleInheritedInterface() { - val actual = SUT.giveMeOne() - - then(actual.value()).isNotNull - then(actual.string()).isNotNull - then(actual.integer()).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setInheritedInterface() { - val expected = "test" - - val actual = SUT.giveMeBuilder() - .set("value", expected) - .sample() - .value() - - then(actual).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleInheritedInterfaceWithOverrideMethod() { - val actual = SUT.giveMeOne().string() - - then(actual).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setInheritedInterfaceWithOverrideMethod() { - val expected = "test" - - val actual = SUT.giveMeBuilder() - .set("string", expected) - .sample() - .string() - - then(actual).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleExtendsTwoInterface() { - val actual = SUT.giveMeOne().string() - - then(actual).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleNestedInheritedInterface() { - val actual = SUT.giveMeOne().string() - - then(actual).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setNestedInheritedInterface() { - val expected = "test" - - val actual = SUT.giveMeBuilder() - .set("string", expected) - .sample() - .string() - - then(actual).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleInheritedPropertyInterface() { - val actual = SUT.giveMeOne().string - - then(actual).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setInheritedPropertyInterface() { - val expected = "test" - - val actual = SUT.giveMeBuilder() - .set("string", expected) - .sample() - .string - - then(actual).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleNestedInheritedPropertyInterface() { - val actual = SUT.giveMeOne().string - - then(actual).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setNestedInheritedPropertyInterface() { - val expected = "test" - - val actual = SUT.giveMeBuilder() - .set("string", expected) - .sample() - .string - - then(actual).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleJavaInterface() { - val actual = SUT.giveMeOne() - - then(actual).isNotNull - then(actual.string()).isNotNull - then(actual.integer()).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setJavaInterface() { - val expected = "test" - - val actual = SUT.giveMeBuilder() - .set("string", expected) - .sample() - .string() - - then(actual).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleJavaInterfaceWithParamReturnsNullProperties() { - val actual = SUT.giveMeOne() - - then(actual).isNull() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleJavaInterfaceWithConstantIsNull() { - val actual = SUT.giveMeOne() - - then(actual).isNull() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleJavaContainerInterface() { - val actual = SUT.giveMeOne() - - then(actual.list()).isNotNull - then(actual.map()).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setJavaContainerInterfaceList() { - val actual = SUT.giveMeBuilder() - .size("list", 3) - .set("list[0]", "test") - .sample() - .list() - - then(actual).hasSize(3) - then(actual[0]).isEqualTo("test") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleJavaAnnotatedInterface() { - val actual = SUT.giveMeOne().string() - - then(actual).isNotEmpty - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setJavaGetterInterfacePropertyName() { - val expected = "test" - - val actual = SUT.giveMeBuilder() - .set("value", expected) - .sample() - .value - - then(actual).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setJavaGetterInterfaceMethodNameNotWorks() { - val notExpected = "test" - - val actual = SUT.giveMeBuilder() - .set("getValue", notExpected) - .sample() - .value - - then(actual).isNotEqualTo(notExpected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleInheritedJavaInterface() { - val actual = SUT.giveMeOne() - - then(actual.value()).isNotNull - then(actual.string()).isNotNull - then(actual.integer()).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setInheritedJavaInterface() { - val expected = "test" - - val actual = SUT.giveMeBuilder() - .set("value", expected) - .sample() - .value() - - then(actual).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleInheritedJavaInterfaceWithSameMethodName() { - val actual = SUT.giveMeOne().string() - - then(actual).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setInheritedJavaInterfaceWithSameMethodName() { - val expected = "test" - - val actual = SUT.giveMeBuilder() - .set("string", expected) - .sample() - .string() - - then(actual).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleInheritedTwoJavaInterface() { - val actual = SUT.giveMeOne() - - then(actual.integer()).isNotNull - then(actual.string()).isNotNull - then(actual.list()).isNotNull - then(actual.map()).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleNestedInheritedJavaInterface() { - val actual = SUT.giveMeOne().string() - - then(actual).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setNestedInheritedJavaInterface() { - val expected = "test" - - val actual = SUT.giveMeBuilder() - .set("string", expected) - .sample() - .string() - - then(actual).isEqualTo(expected) - } - - interface Interface { - fun string(): String - fun integer(): Int - } - - interface SimilarInterface { - fun string(): String - fun integer(): Int - } - - interface InterfaceWithParams { - fun string(str: String): String? - fun integer(int: Int): Int? - } - - interface ContainerInterface { - fun list(): List - fun map(): Map - } - - interface AnnotatedInterface { - @NotEmpty - fun string(): String - } - - interface GetterInterface { - fun getString(): String - } - - interface PropertyInterface { - val string: String - - val int: Int - } - - interface InheritedInterface : Interface { - fun value(): String - } - - interface InheritedInterfaceWithOverrideMethod : Interface { - override fun string(): String - } - - interface InheritedTwoInterface : Interface, ContainerInterface - - interface NestedInheritedInterface : InheritedInterfaceWithOverrideMethod, Interface - - interface InheritedPropertyInterface : PropertyInterface { - override val string: String - } - - interface NestedInheritedPropertyInterface : InheritedPropertyInterface, PropertyInterface - - companion object { - val SUT: FixtureMonkey = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(JavaxValidationPlugin()) - .plugin(InterfacePlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .defaultNotNull(true) - .build() - } -} diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/CircularReferenceAdapterTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/CircularReferenceAdapterTest.kt deleted file mode 100644 index d0d9b9fe7e..0000000000 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/CircularReferenceAdapterTest.kt +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.kotlin.adapter - -import com.navercorp.fixturemonkey.FixtureMonkey -import com.navercorp.fixturemonkey.kotlin.KotlinNodeTreeAdapterPlugin -import com.navercorp.fixturemonkey.kotlin.KotlinPlugin -import com.navercorp.fixturemonkey.kotlin.giveMeOne -import com.navercorp.fixturemonkey.tests.TestEnvironment.ADAPTER_TEST_COUNT -import com.navercorp.fixturemonkey.tests.kotlin.specs.CircularReferenceDefaultArgument -import com.navercorp.fixturemonkey.tests.kotlin.specs.CircularReferenceValueNullable -import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.RepeatedTest - -class CircularReferenceAdapterTest { - @RepeatedTest(ADAPTER_TEST_COUNT) - fun circularReferenceDefaultArgument() { - val actual = SUT.giveMeOne().value - - then(actual).isNotNull() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun circularReferenceNullable() { - val actual: CircularReferenceValueNullable = SUT.giveMeOne() - - then(actual).isNotNull() - } - - companion object { - private val SUT: FixtureMonkey = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - } -} diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/ContainerAdapterTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/ContainerAdapterTest.kt deleted file mode 100644 index 1c71d089ad..0000000000 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/ContainerAdapterTest.kt +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.kotlin.adapter - -import com.navercorp.fixturemonkey.FixtureMonkey -import com.navercorp.fixturemonkey.kotlin.KotlinNodeTreeAdapterPlugin -import com.navercorp.fixturemonkey.kotlin.KotlinPlugin -import com.navercorp.fixturemonkey.kotlin.giveMeKotlinBuilder -import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.Test - -class ContainerAdapterTest { - @Test - fun setShrinkContainerNode() { - val expected = listOf("a") - - val actual = SUT.giveMeKotlinBuilder>() - .size("$", 3) - .set("$[0]", "a1") - .set("$[1]", "b") - .set("$[2]", "c") - .set(expected) - .sample() - - then(actual).isEqualTo(expected) - } - - @Test - fun setExpandContainerNode() { - val expected = listOf("a", "b", "c") - - val actual = SUT.giveMeKotlinBuilder>() - .size("$", 1) - .set(expected) - .sample() - - then(actual).isEqualTo(expected) - } - - companion object { - private val SUT: FixtureMonkey = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - } -} diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/CustomizationAdapterTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/CustomizationAdapterTest.kt deleted file mode 100644 index 7f7a602cee..0000000000 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/CustomizationAdapterTest.kt +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.kotlin.adapter - -import com.navercorp.fixturemonkey.FixtureMonkey -import com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary -import com.navercorp.fixturemonkey.api.experimental.TypedExpressionGenerator.typedRoot -import com.navercorp.fixturemonkey.api.experimental.TypedExpressionGenerator.typedString -import com.navercorp.fixturemonkey.api.introspector.ArbitraryIntrospectorResult -import com.navercorp.fixturemonkey.api.type.Types.GeneratingWildcardType -import com.navercorp.fixturemonkey.customizer.InnerSpec -import com.navercorp.fixturemonkey.customizer.Values -import com.navercorp.fixturemonkey.kotlin.KotlinNodeTreeAdapterPlugin -import com.navercorp.fixturemonkey.kotlin.KotlinPlugin -import com.navercorp.fixturemonkey.kotlin.get -import com.navercorp.fixturemonkey.kotlin.giveMeBuilder -import com.navercorp.fixturemonkey.kotlin.giveMeExperimentalBuilder -import com.navercorp.fixturemonkey.kotlin.giveMeKotlinBuilder -import com.navercorp.fixturemonkey.kotlin.giveMeOne -import com.navercorp.fixturemonkey.kotlin.into -import com.navercorp.fixturemonkey.kotlin.pushExactTypeArbitraryIntrospector -import com.navercorp.fixturemonkey.kotlin.register -import com.navercorp.fixturemonkey.kotlin.setExp -import com.navercorp.fixturemonkey.kotlin.sizeExp -import com.navercorp.fixturemonkey.tests.TestEnvironment.ADAPTER_TEST_COUNT -import com.navercorp.fixturemonkey.tests.kotlin.specs.KotlinObject -import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.RepeatedTest -import org.junit.jupiter.api.Test -import java.time.Instant -import java.time.temporal.ChronoUnit - -class CustomizationAdapterTest { - @Test - fun setChild() { - open class Parent(val parent: String) - class Child : Parent("parent") - - val actual = SUT.giveMeBuilder() - .set(Child()) - .sample() - .parent - - then(actual).isEqualTo("parent") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun customizePropertySet() { - val actual = SUT.giveMeExperimentalBuilder() - .customizeProperty(typedRoot()) { - it.filter { str -> str.length > 5 } - .map { str -> str.substring(0..3) } - } - .sample() - - then(actual).hasSizeLessThanOrEqualTo(4) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun customizePropertyFilter() { - val now = Instant.now() - val min = now.minus(365, ChronoUnit.DAYS) - val max = now.plus(365, ChronoUnit.DAYS) - - val actual = SUT.giveMeExperimentalBuilder() - .customizeProperty(typedRoot()) { - it.filter { instant -> instant.isAfter(min) && instant.isBefore(max) } - } - .sample() - - then(actual).isBetween(min, max) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleCustomizedWildcardType() { - // given - class MapObject(val map: Map) - - val expected = "test" - - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .pushExactTypeArbitraryIntrospector { - ArbitraryIntrospectorResult( - CombinableArbitrary.from(expected) - ) - } - .build() - - // when - val actual = sut.giveMeBuilder() - .sizeExp(MapObject::map, 1) - .sample() - .map - .values - .first() - - // then - then(actual).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun overwriteExistingType() { - val expected = "string" - val sut = FixtureMonkey.builder() - .pushExactTypeArbitraryIntrospector { - ArbitraryIntrospectorResult( - CombinableArbitrary.from(expected) - ) - } - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val actual: String = sut.giveMeOne() - - then(actual).isEqualTo(expected) - } - - @Test - fun setToObject() { - // given - class Object(val obj: Any?) - - val expected = "test" - - // when - val actual = SUT.giveMeBuilder() - .setExp(Object::obj, expected) - .sample() - .obj - - // then - then(actual).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setLazyJustNotChanged() { - // given - class StringObject(val string: String) - - val expected = StringObject("test") - - // when - val actual = SUT.giveMeBuilder() - .setLazy("$") { Values.just(expected) } - .setExp(StringObject::string, "notTest") - .sample() - - // then - then(actual).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setPostCondition() { - class StringObject(val string: String) - - val actual = SUT.giveMeKotlinBuilder() - .setPostCondition("string") { it.length < 5 } - .sample() - .string - - then(actual).hasSizeLessThan(5) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setPostConditionWithProperty() { - class StringObject(val string: String) - - val actual = SUT.giveMeKotlinBuilder() - .setPostCondition(StringObject::string) { it.length < 5 } - .sample() - .string - - then(actual).hasSizeLessThan(5) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun customizePropertyAfterSet() { - // given - class StringValue(val value: String) - - val expected = "abc" - - // when - val actual = SUT.giveMeKotlinBuilder() - .setExp(StringValue::value, "abcdef") - .customizeProperty(typedString("value")) { - it.map { str -> str.substring(0..2) } - } - .sample() - .value - - //then - then(actual).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun customizePropertyIgnoredIfSet() { - // given - class StringValue(val value: String) - - val expected = "fixed" - - // when - val actual = SUT.giveMeKotlinBuilder() - .customizeProperty(typedString("value")) { - it.filter { value -> value.length > 5 } - } - .setExp(StringValue::value, expected) - .sample() - .value - - //then - then(actual).isEqualTo(expected) - } - - @Test - fun registerAssignableType() { - // given - open class Parent(val parent: String) - - class Child(parent: String) : Parent(parent) - - val expected = "registered" - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .register { - it.giveMeBuilder() - .setExp(Parent::parent, expected) - } - .build() - - // when - val actual = sut.giveMeOne().parent - - // then - then(actual).isEqualTo(expected) - } - - @Test - fun registerKotlinTypeBuilder() { - val expected = "test" - val sut = FixtureMonkey.builder() - .plugin(KotlinNodeTreeAdapterPlugin()) - .register(String::class.java) { - it.giveMeKotlinBuilder(expected) - } - .build() - val actual: String = sut.giveMeOne() - - then(actual).isEqualTo(expected) - } - - @Test - fun setAndRegister() { - // given - class ListStringObject(val list: List) - class ListStringObjectObject(val value: ListStringObject) - - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .register(ListStringObjectObject::class.java) { - it.giveMeBuilder() - .size("value.list", 3) - } - .build() - - val set = ListStringObject(listOf("a", "b")) - - // when - val actual = sut.giveMeBuilder() - .set("value", set) - .sample() - .value - .list - - // then - val expected = set.list - then(actual).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun register() { - class NestedInnerObject(val list: List) - - class InnerObject(val list: List) - - class WrapperObject(val obj: InnerObject) - - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .register(WrapperObject::class.java) { - it.giveMeKotlinBuilder() - .sizeExp(WrapperObject::obj into InnerObject::list, 1) - .thenApply { _, _ -> } - } - .build() - - val actual = sut.giveMeKotlinBuilder() - .sizeExp(WrapperObject::obj into InnerObject::list[0] into NestedInnerObject::list, 1) - .sample() - .obj - .list[0] - .list[0] - - then(actual).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun innerSpecInner() { - // given - data class ChildObject(val values: List) - - data class ParentObject(val list: List) - - // when - val actual = SUT.giveMeKotlinBuilder() - .setInner { - property("list") { l -> - l.size(1) - .listElement(0) { e -> - e.inner( - InnerSpec() - .property("values") { v -> v.size(5) } - ) - } - } - }.sample().list[0].values - - // then - then(actual).hasSize(5) - } - - @Test - fun parentRegisterThenApplyAndSizeReturnsChildRegister() { - data class ChildObject(val value: String) - - data class ParentObject(val values: List) - - val sut = FixtureMonkey.builder() - .register { it.giveMeKotlinBuilder().thenApply { _, _ -> } } - .register { it.giveMeKotlinBuilder().set(ChildObject::value, "1") } - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val actual = sut.giveMeKotlinBuilder() - .size(ParentObject::values, 10) - .sample() - .values - - then(actual).allMatch { it.value == "1" } - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun generateObjectInstanceThrows() { - // when - val actual: KotlinObject = SUT.giveMeOne() - - then(actual).isInstanceOf(KotlinObject::class.java) - } - - companion object { - private val SUT: FixtureMonkey = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - } -} diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/GenericAdapterTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/GenericAdapterTest.kt deleted file mode 100644 index 868131f4f9..0000000000 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/GenericAdapterTest.kt +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.kotlin.adapter - -import com.navercorp.fixturemonkey.FixtureMonkey -import com.navercorp.fixturemonkey.kotlin.KotlinNodeTreeAdapterPlugin -import com.navercorp.fixturemonkey.kotlin.KotlinPlugin -import com.navercorp.fixturemonkey.kotlin.giveMeOne -import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.Test - -class GenericAdapterTest { - - @Test - fun bar() { - val bar: Bar = SUT.giveMeOne() - - then(bar).isNotNull() - then(bar.bar).isNotNull() - then(bar.bar.foo).isNotNull() - } - - class Foo(val foo: T) - - class Bar(val bar: Foo) - - companion object { - private val SUT = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .defaultNotNull(true) - .build() - } -} diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/InnerSpecAdapterTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/InnerSpecAdapterTest.kt deleted file mode 100644 index dbbcfc7df4..0000000000 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/InnerSpecAdapterTest.kt +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.kotlin.adapter - -import com.navercorp.fixturemonkey.FixtureMonkey -import com.navercorp.fixturemonkey.kotlin.KotlinNodeTreeAdapterPlugin -import com.navercorp.fixturemonkey.kotlin.KotlinPlugin -import com.navercorp.fixturemonkey.kotlin.giveMeKotlinBuilder -import com.navercorp.fixturemonkey.tests.TestEnvironment.ADAPTER_TEST_COUNT -import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.RepeatedTest - -class InnerSpecAdapterTest { - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setInnerSpecByTrailingLambda() { - val actual = SUT.giveMeKotlinBuilder>() - .setInner { - keys("key1", "key2") - .minSize(3) - } - .sample() - - then(actual).containsKeys("key1", "key2") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setKotlinInnerByTrailingLambda() { - val actual = SUT.giveMeKotlinBuilder>() - .setKotlinInner { - keys("key1", "key2") - minSize(3) - } - .sample() - - then(actual).containsKeys("key1", "key2") - } - - companion object { - private val SUT: FixtureMonkey = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - } -} diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/InstantiatorAdapterTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/InstantiatorAdapterTest.kt deleted file mode 100644 index 53a6563aaf..0000000000 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/InstantiatorAdapterTest.kt +++ /dev/null @@ -1,634 +0,0 @@ -package com.navercorp.fixturemonkey.tests.kotlin.adapter - -import com.navercorp.fixturemonkey.FixtureMonkey -import com.navercorp.fixturemonkey.kotlin.KotlinNodeTreeAdapterPlugin -import com.navercorp.fixturemonkey.api.instantiator.Instantiator -import com.navercorp.fixturemonkey.kotlin.KotlinPlugin -import com.navercorp.fixturemonkey.kotlin.giveMeBuilder -import com.navercorp.fixturemonkey.kotlin.giveMeKotlinBuilder -import com.navercorp.fixturemonkey.kotlin.giveMeOne -import com.navercorp.fixturemonkey.kotlin.instantiator.instantiateBy -import com.navercorp.fixturemonkey.tests.TestEnvironment.ADAPTER_TEST_COUNT -import com.navercorp.fixturemonkey.tests.kotlin.JavaConstructorTestSpecs -import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.RepeatedTest -import java.lang.reflect.Modifier - -class InstantiatorAdapterTest { - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateJavaPrimaryConstructor() { - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - Instantiator.constructor() - .parameter(String::class.java, "foo") - .parameter(Int::class.java, "bar") - } - .sample() - .bar - - then(actual).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiatePrimaryConstructor() { - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - constructor { - parameter("foo") - parameter("bar") - } - } - .sample() - .bar - - then(actual).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateSecondaryConstructor() { - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - constructor { - parameter("foo") - } - } - .sample() - .bar - - then(actual).isEqualTo(1) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiatePrimaryConstructorWithoutParameterName() { - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - constructor { - parameter() - parameter() - } - } - .sample() - .bar - - then(actual).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateSecondaryConstructorWithoutParameterName() { - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - constructor { - parameter() - } - } - .sample() - .bar - - then(actual).isEqualTo(1) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setWithInstantiate() { - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - constructor { - parameter() - } - } - .set("foo", "bar") - .sample() - .foo - - then(actual).isEqualTo("bar") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateRootType() { - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - constructor { - parameter() - } - } - .sample() - .bar - - then(actual).isEqualTo(1) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateGenericType() { - val actual = SUT.giveMeKotlinBuilder>() - .instantiateBy { - constructor> { - parameter() - } - } - .sample() - .bar - - then(actual).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateByConstructorTwoTypes() { - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - constructor { - parameter() - } - constructor> { - parameter() - } - } - .sample() - - then(actual).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateByMixedTwoTypes() { - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - constructor> { - parameter() - } - factory("build") { - parameter() - } - } - .sample() - - then(actual).isNotNull - then(actual.foo.foo).isEqualTo("factory") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateByCompanionObjectFactoryMethodWithoutType() { - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - factory("build") - } - .sample() - .foo - - then(actual).isEqualTo("factory") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateByCompanionObjectFactoryMethod() { - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - factory("build") - } - .sample() - .foo - - then(actual).isEqualTo("factory") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateByCompanionObjectFactoryMethodWithoutTypeWithParameter() { - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - factory("build") { - parameter() - } - } - .sample() - .foo - - then(actual).isEqualTo("factory") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateByCompanionObjectFactoryMethodWithParameter() { - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - factory("build") { - parameter() - } - } - .sample() - .foo - - then(actual).isEqualTo("factory") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setInstantiateByCompanionObjectFactoryMethodWithParameter() { - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - factory("build") { - parameter() - } - } - .set("factoryBar", 1) - .sample() - .bar - - then(actual).isEqualTo(1) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateJavaObjectByRootProperty() { - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - constructor { - property() - } - } - .sample() - .string - - then(actual).isNotEqualTo("string") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateJavaObjectByRootPropertyFilter() { - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - constructor { - property { - filter { !it.isFinal } - } - } - } - .sample() - .string - - then(actual).isEqualTo("third") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateJavaObjectByRootField() { - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - constructor { - javaField() - } - } - .sample() - .string - - then(actual).isNotEqualTo("string") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateJavaObjectByRootFieldFilter() { - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - constructor { - javaField { - filter { !Modifier.isFinal(it.modifiers) } - } - } - } - .sample() - .string - - then(actual).isEqualTo("third") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateJavaObjectByRootJavaBeans() { - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - constructor { - javaBeansProperty() - } - } - .sample() - .string - - then(actual).isNotEqualTo("string") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateJavaObjectByRootFieldJavaBeans() { - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - constructor { - javaBeansProperty { - filter { "string" != it.name } - } - } - } - .sample() - .string - - then(actual).isEqualTo("third") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiatePropertyByKotlinProperty() { - class PropertyObject { - var string: String = "test" - } - - class ConstructorObject(val propertyObject: PropertyObject) - - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { constructor { property() } } - .sample() - .propertyObject - .string - - then(actual).isNotEqualTo("test") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiatePropertyByKotlinPropertyFilter() { - class PropertyObject { - var string: String = "test" - } - - class ConstructorObject(val propertyObject: PropertyObject) - - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - constructor { - property { - filter { - it.name != "string" - } - } - } - } - .sample() - .propertyObject - .string - - then(actual).isEqualTo("test") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiatePropertyByKotlinPropertyPrivateSetter() { - class PropertyObject { - var string: String = "test" - private set - } - - class ConstructorObject(val propertyObject: PropertyObject) - - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { constructor { property() } } - .sample() - .propertyObject - .string - - then(actual).isEqualTo("test") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateNoArgsConstructor() { - class NoArgsConstructorObject() { - var string: String = "noArgs" - - constructor(string: String) : this() { - this.string = string - } - } - - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { constructor() } - .sample() - .string - - then(actual).isEqualTo("noArgs") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiatePropertyNoArgsConstructor() { - class NoArgsConstructorObject { - var string: String = "noArgs" - } - - class AllArgsConstructorObject(val value: NoArgsConstructorObject) - - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { constructor() } - .sample() - .value - .string - - then(actual).isEqualTo("noArgs") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateCompositeJavaObjectByProperty() { - class ConstructorAndProperty(val value: String) { - var propertyNotInConstructor: String? = null - } - - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - constructor { - parameter() - property() - } - } - .setNotNull("propertyNotInConstructor") - .sample() - - then(actual.value).isNotNull() - then(actual.propertyNotInConstructor).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiatePrivateConstructor() { - class PrivateConstructorObject private constructor(val value: String) - - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - constructor() - } - .sample() - .value - - then(actual).isNotNull() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiatePrivateConstructorWithoutInstantiate() { - class PrivateConstructorObject private constructor(val value: String) - - val actual = SUT.giveMeOne() - .value - - then(actual).isNotNull() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateDefaultArgumentConstructor() { - class ConstructorObject(val value: String = "default") - - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { constructor() } - .sample() - .value - - then(actual).isNotEqualTo("default") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateJavaConstructorWithDefaultArgument() { - class ConstructorObject(val value: String = "default") - - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - Instantiator.constructor() - } - .sample() - .value - - then(actual).isNotEqualTo("default") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateConstructorWithDefaultArgument() { - class ConstructorObject(val value: String = "default") - - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - constructor { - parameter(useDefaultArgument = true) - } - } - .sample() - .value - - then(actual).isEqualTo("default") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateByCompanionObjectFactoryMethodInRegister() { - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .register(Foo::class.java) { - it.giveMeKotlinBuilder() - .instantiateBy { - factory("build") { - parameter() - } - } - } - .build() - - val actual = sut.giveMeOne().foo - - then(actual).isEqualTo("factory") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateByConstructorMethodInRegister() { - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .register(Foo::class.java) { - it.giveMeKotlinBuilder() - .instantiateBy { - constructor { - parameter() - } - } - } - .build() - - val actual = sut.giveMeOne().bar - - then(actual).isEqualTo(1) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateByInRegisterLatterWins() { - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .register(Foo::class.java) { - it.giveMeKotlinBuilder() - .instantiateBy { - factory("build") { - parameter() - } - } - .instantiateBy { - constructor { - parameter() - } - } - } - .build() - - val actual = sut.giveMeOne().bar - - then(actual).isEqualTo(1) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateByPropertyInRegister() { - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .register(Foo::class.java) { - it.giveMeKotlinBuilder() - .instantiateBy { - factory("build") { - parameter() - } - } - } - .build() - - val actual = sut.giveMeOne().foo.foo - - then(actual).isEqualTo("factory") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun instantiateByPropertySetFactoryPropertyInRegister() { - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .register(Foo::class.java) { - it.giveMeKotlinBuilder() - .instantiateBy { - factory("build") { - parameter() - } - } - } - .build() - val expected = 2 - - val actual = sut.giveMeBuilder() - .set("foo.factoryBar", expected) - .sample() - .foo - .bar - - then(actual).isEqualTo(expected) - } - - class FooWrapper(val foo: Foo) - - class Foo(val foo: String, val bar: Int) { - constructor(foo: String) : this(foo, 1) - - companion object { - fun build(factoryBar: Int): Foo = Foo("factory", factoryBar) - } - } - - class Bar(val bar: T) - - class Baz(val foo: Foo, val bar: Bar) - - companion object { - private val SUT = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - } -} diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/InterfaceAdapterTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/InterfaceAdapterTest.kt deleted file mode 100644 index 16059353b0..0000000000 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/InterfaceAdapterTest.kt +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.kotlin.adapter - -import com.navercorp.fixturemonkey.FixtureMonkey -import com.navercorp.fixturemonkey.kotlin.KotlinNodeTreeAdapterPlugin -import com.navercorp.fixturemonkey.api.matcher.AssignableTypeMatcher -import com.navercorp.fixturemonkey.api.plugin.InterfacePlugin -import com.navercorp.fixturemonkey.kotlin.KotlinPlugin -import com.navercorp.fixturemonkey.kotlin.giveMeBuilder -import com.navercorp.fixturemonkey.kotlin.giveMeOne -import com.navercorp.fixturemonkey.tests.TestEnvironment.ADAPTER_TEST_COUNT -import com.navercorp.fixturemonkey.tests.kotlin.adapter.InterfaceAdapterTest.SealedObjectClass.ConcreteSealedObjectClass -import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.RepeatedTest -import org.junit.jupiter.api.Test -import java.util.LinkedList - -class InterfaceAdapterTest { - @RepeatedTest(ADAPTER_TEST_COUNT) - fun anonymousArbitraryIntrospector() { - // given - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(InterfacePlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - // when - val actual = sut.giveMeOne().string() - - // then - then(actual).isNotNull() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun notUseAnonymousArbitraryIntrospector() { - // given - val sut = FixtureMonkey.builder() - .plugin(InterfacePlugin().useAnonymousArbitraryIntrospector(false)) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - // when - val actual: Interface = sut.giveMeOne() - - // then - then(actual).isNull() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sealedInterfaceApplySet() { - val actual = SUT.giveMeBuilder() - .thenApply { _, builder -> builder.set("stringObject.string", "expected") } - .sample() - - then((actual as SealedInterfaceImplementation).stringObject.string).isEqualTo("expected") - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun interfaceImplementsExtendsInterface() { - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin( - InterfacePlugin() - .interfaceImplements(Collection::class.java, listOf(Set::class.java)) - ) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val actual: Collection = sut.giveMeOne() - - then(actual).isInstanceOf(HashSet::class.java) - } - - @Test - fun interfaceImplementsAssignableTypeGeneratesConcreteTypeNotThrows() { - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin( - InterfacePlugin() - .interfaceImplements( - AssignableTypeMatcher(Collection::class.java), - listOf(LinkedList::class.java) - ) - - ) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val actual: ArrayList = sut.giveMeOne() - - then(actual).isInstanceOf(ArrayList::class.java) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleSealedClass() { - val actual = SUT.giveMeOne() - - then(actual).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun fixedSealedClass() { - val actual = SUT.giveMeBuilder() - .fixed() - .sample() - - then(actual).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleImplementedSealedClass() { - val actual = SUT.giveMeOne() - - then(actual).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun fixedImplementedSealedClass() { - val actual = SUT.giveMeBuilder() - .fixed() - .sample() - - then(actual).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sealedObject() { - val actual: SealedObjectClass = SUT.giveMeOne() - - then(actual).isInstanceOf(ConcreteSealedObjectClass::class.java) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sealedObjectThenApply() { - val actual = SUT.giveMeBuilder() - .thenApply { obj, builder -> } - .sample() - - then(actual).isInstanceOf(ConcreteSealedObjectClass::class.java) - } - - interface Interface { - fun string(): String - } - - sealed interface SealedInterface - - class SealedInterfaceImplementation(val stringObject: StringObject) : SealedInterface - - class StringObject(val string: String) - - sealed class SealedClass - - class ImplementedSealedClass( - val string: String, - val integer: Int, - val float: Float, - val long: Long, - val double: Double, - val byte: Byte, - val char: Char, - val short: Short, - val boolean: Boolean, - val enum: Enum, - ) : SealedClass() - - enum class Enum { ONE, TWO, THREE } - - sealed class SealedObjectClass { - object ConcreteSealedObjectClass : SealedObjectClass() - } - - companion object { - private val SUT: FixtureMonkey = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - } -} diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/IntrospectorAdapterTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/IntrospectorAdapterTest.kt deleted file mode 100644 index a206131ad1..0000000000 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/IntrospectorAdapterTest.kt +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.kotlin.adapter - -import com.navercorp.fixturemonkey.FixtureMonkey -import com.navercorp.fixturemonkey.kotlin.KotlinNodeTreeAdapterPlugin -import com.navercorp.fixturemonkey.api.introspector.AnonymousArbitraryIntrospector -import com.navercorp.fixturemonkey.api.introspector.BeanArbitraryIntrospector -import com.navercorp.fixturemonkey.api.introspector.BuilderArbitraryIntrospector -import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector -import com.navercorp.fixturemonkey.api.introspector.FactoryMethodArbitraryIntrospector -import com.navercorp.fixturemonkey.api.introspector.FailoverIntrospector -import com.navercorp.fixturemonkey.api.introspector.FieldReflectionArbitraryIntrospector -import com.navercorp.fixturemonkey.kotlin.giveMeOne -import com.navercorp.fixturemonkey.kotlin.introspector.PrimaryConstructorArbitraryIntrospector -import com.navercorp.fixturemonkey.kotlin.pushExactTypeArbitraryIntrospector -import com.navercorp.fixturemonkey.tests.TestEnvironment.ADAPTER_TEST_COUNT -import com.navercorp.fixturemonkey.tests.kotlin.BuilderJavaTestSpecs.BuilderObjectCustomBuildName -import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.RepeatedTest -import org.junit.jupiter.api.Test -import java.sql.Timestamp -import java.util.UUID -import kotlin.reflect.jvm.javaMethod - -class IntrospectorAdapterTest { - @Test - fun constructorArbitraryIntrospectorWithoutPrimaryConstructor() { - // given - class ConstructorWithoutAnyAnnotations(val string: String) - - val sut = FixtureMonkey.builder() - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - // when - val actual: ConstructorWithoutAnyAnnotations = sut.giveMeOne() - - // then - then(actual).isNull() - } - - @Test - fun failoverIntrospectorHandlingExceptionWhenDeclaring() { - val sut = FixtureMonkey.builder() - .pushExactTypeArbitraryIntrospector( - FailoverIntrospector( - listOf( - ConstructorPropertiesArbitraryIntrospector.INSTANCE, - FactoryMethodArbitraryIntrospector( - FactoryMethodArbitraryIntrospector.FactoryMethodWithParameterNames( - UUID::randomUUID.javaMethod, - listOf(), - ), - ), - ), - ), - ) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val actual = sut.giveMeOne() - - then(actual).isNotNull - } - - @Test - fun primaryConstructorArbitraryIntrospectorNotThrows() { - val actual: Timestamp = SUT.giveMeOne() - - then(actual).isNull() - } - - @Test - fun beanArbitraryIntrospectorNotThrows() { - val sut = FixtureMonkey.builder() - .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val actual: Timestamp = sut.giveMeOne() - - then(actual).isNull() - } - - @Test - fun fieldReflectionArbitraryIntrospectorNotThrows() { - val sut = FixtureMonkey.builder() - .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val actual: Timestamp = sut.giveMeOne() - - then(actual).isNull() - } - - @Test - fun constructorPropertiesArbitraryIntrospectorNotThrows() { - val sut = FixtureMonkey.builder() - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val actual: Timestamp = sut.giveMeOne() - - then(actual).isNull() - } - - @Test - fun anonymousArbitraryIntrospectorNotThrows() { - val sut = FixtureMonkey.builder() - .objectIntrospector(AnonymousArbitraryIntrospector.INSTANCE) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val actual: Timestamp = sut.giveMeOne() - - then(actual).isNull() - } - - @Test - fun builderArbitraryIntrospectorNotThrows() { - val sut = FixtureMonkey.builder() - .objectIntrospector(BuilderArbitraryIntrospector.INSTANCE) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val actual: Timestamp = sut.giveMeOne() - - then(actual).isNull() - } - - @Test - fun builderArbitraryIntrospectorMissBuildMethodNotThrows() { - val sut = FixtureMonkey.builder() - .objectIntrospector(BuilderArbitraryIntrospector.INSTANCE) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val actual: BuilderObjectCustomBuildName = sut.giveMeOne() - - then(actual).isNull() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun pushPrimaryConstructorIntrospector() { - // given - class StringObject(val string: String) - - val sut = FixtureMonkey.builder() - .pushExactTypeArbitraryIntrospector(PrimaryConstructorArbitraryIntrospector.INSTANCE) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - // when - val actual = sut.giveMeOne().string - - // then - then(actual).isNotNull - } - - companion object { - private val SUT: FixtureMonkey = FixtureMonkey.builder() - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - } -} diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/KotestInJunitAdapterTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/KotestInJunitAdapterTest.kt deleted file mode 100644 index 9f7a09bbe8..0000000000 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/KotestInJunitAdapterTest.kt +++ /dev/null @@ -1,643 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.kotlin.adapter - -import com.navercorp.fixturemonkey.FixtureMonkey -import com.navercorp.fixturemonkey.kotlin.KotlinNodeTreeAdapterPlugin -import com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary -import com.navercorp.fixturemonkey.javax.validation.plugin.JavaxValidationPlugin -import com.navercorp.fixturemonkey.kotest.KotestIntegerCombinableArbitrary -import com.navercorp.fixturemonkey.kotest.KotestByteCombinableArbitrary -import com.navercorp.fixturemonkey.kotest.KotestPlugin -import com.navercorp.fixturemonkey.kotest.KotestStringCombinableArbitrary -import com.navercorp.fixturemonkey.kotest.giveMeArb -import com.navercorp.fixturemonkey.kotest.setArb -import com.navercorp.fixturemonkey.kotlin.KotlinPlugin -import com.navercorp.fixturemonkey.kotlin.giveMeKotlinBuilder -import com.navercorp.fixturemonkey.kotlin.giveMeOne -import com.navercorp.fixturemonkey.kotlin.setPostCondition -import com.navercorp.fixturemonkey.tests.TestEnvironment.ADAPTER_TEST_COUNT -import io.kotest.property.Arb -import io.kotest.property.arbitrary.single -import io.kotest.property.arbs.geo.zipcodes -import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.RepeatedTest -import org.junit.jupiter.api.Test -import java.math.BigDecimal -import java.math.BigInteger -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Digits -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.Negative -import javax.validation.constraints.NegativeOrZero -import javax.validation.constraints.NotEmpty -import javax.validation.constraints.Positive -import javax.validation.constraints.PositiveOrZero -import javax.validation.constraints.Size - -class KotestInJunitAdapterTest { - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleStringWithSize() { - class StringObject(@field:Size(min = 10, max = 20) val value: String) - - val actual = SUT.giveMeOne().value - - then(actual).hasSizeBetween(10, 20) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleStringWithNotEmpty() { - class StringObject(@field:NotEmpty val value: String) - - val actual = SUT.giveMeOne().value - - then(actual).isNotEmpty() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleShortWithNegative() { - class ShortObject(@field:Negative val value: Short) - - val actual = SUT.giveMeOne().value - - then(actual).isNegative() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleShortWithNegativeOrZero() { - class ShortObject(@field:NegativeOrZero val value: Short) - - val actual = SUT.giveMeOne().value - - then(actual).isLessThanOrEqualTo(0) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleShortWithPositive() { - class ShortObject(@field:Positive val value: Short) - - val actual = SUT.giveMeOne().value - - then(actual).isPositive() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleShortWithPositiveOrZero() { - class ShortObject(@field:PositiveOrZero val value: Short) - - val actual = SUT.giveMeOne().value - - then(actual).isGreaterThanOrEqualTo(0) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleShortWithMin() { - class ShortObject(@field:Min(10) val value: Short) - - val actual = SUT.giveMeOne().value - - then(actual).isGreaterThanOrEqualTo(10) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleShortWithDecimalMin() { - class ShortObject(@field:DecimalMin("10") val value: Short) - - val actual = SUT.giveMeOne().value - - then(actual).isGreaterThanOrEqualTo(10) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleShortWithMax() { - class ShortObject(@field:Max(50) val value: Short) - - val actual = SUT.giveMeOne().value - - then(actual).isLessThanOrEqualTo(50) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleShortWithDecimalMax() { - class ShortObject(@field:DecimalMax("50") val value: Short) - - val actual = SUT.giveMeOne().value - - then(actual).isLessThanOrEqualTo(50) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleShortWithDigits() { - class ShortObject(@field:Digits(integer = 2, fraction = 0) val value: Short) - - val actual = SUT.giveMeOne().value - - then(actual).matches { it in -99..99 } - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleIntWithNegative() { - class IntObject(@field:Negative val value: Int) - - val actual = SUT.giveMeOne().value - - then(actual).isNegative() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleIntWithNegativeOrZero() { - class IntObject(@field:NegativeOrZero val value: Int) - - val actual = SUT.giveMeOne().value - - then(actual).isLessThanOrEqualTo(0) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleIntWithPositive() { - class IntObject(@field:Positive val value: Int) - - val actual = SUT.giveMeOne().value - - then(actual).isPositive() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleIntWithPositiveOrZero() { - class IntObject(@field:PositiveOrZero val value: Int) - - val actual = SUT.giveMeOne().value - - then(actual).isGreaterThanOrEqualTo(0) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleIntWithMin() { - class IntObject(@field:Min(10) val value: Int) - - val actual = SUT.giveMeOne().value - - then(actual).isGreaterThanOrEqualTo(10) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleIntWithDecimalMin() { - class IntObject(@field:DecimalMin("10") val value: Int) - - val actual = SUT.giveMeOne().value - - then(actual).isGreaterThanOrEqualTo(10) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleIntWithMax() { - class IntObject(@field:Max(50) val value: Int) - - val actual = SUT.giveMeOne().value - - then(actual).isLessThanOrEqualTo(50) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleIntWithDecimalMax() { - class IntObject(@field:DecimalMax("50") val value: Int) - - val actual = SUT.giveMeOne().value - - then(actual).isLessThanOrEqualTo(50) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleIntWithDigits() { - class IntObject(@field:Digits(integer = 2, fraction = 0) val value: Int) - - val actual = SUT.giveMeOne().value - - then(actual).matches { it in -99..99 } - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleLongWithNegative() { - class LongObject(@field:Negative val value: Long) - - val actual = SUT.giveMeOne().value - - then(actual).isNegative() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleLongWithNegativeOrZero() { - class LongObject(@field:NegativeOrZero val value: Long) - - val actual = SUT.giveMeOne().value - - then(actual).isLessThanOrEqualTo(0) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleLongWithPositive() { - class LongObject(@field:Positive val value: Long) - - val actual = SUT.giveMeOne().value - - then(actual).isPositive() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleLongWithPositiveOrZero() { - class LongObject(@field:PositiveOrZero val value: Long) - - val actual = SUT.giveMeOne().value - - then(actual).isGreaterThanOrEqualTo(0) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleLongWithMin() { - class LongObject(@field:Min(10) val value: Long) - - val actual = SUT.giveMeOne().value - - then(actual).isGreaterThanOrEqualTo(10) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleLongWithDecimalMin() { - class LongObject(@field:DecimalMin("10") val value: Long) - - val actual = SUT.giveMeOne().value - - then(actual).isGreaterThanOrEqualTo(10) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleLongWithMax() { - class LongObject(@field:Max(50) val value: Long) - - val actual = SUT.giveMeOne().value - - then(actual).isLessThanOrEqualTo(50) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleLongWithDecimalMax() { - class LongObject(@field:DecimalMax("50") val value: Long) - - val actual = SUT.giveMeOne().value - - then(actual).isLessThanOrEqualTo(50) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleLongWithDigits() { - class LongObject(@field:Digits(integer = 2, fraction = 0) val value: Long) - - val actual = SUT.giveMeOne().value - - then(actual).matches { it in -99L..99L } - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleBigIntegerWithNegative() { - class BigIntegerObject(@field:Negative val value: BigInteger) - - val actual = SUT.giveMeOne().value - - then(actual).isNegative() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleBigIntegerWithNegativeOrZero() { - class BigIntegerObject(@field:NegativeOrZero val value: BigInteger) - - val actual = SUT.giveMeOne().value - - then(actual).isLessThanOrEqualTo(BigInteger.ZERO) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleBigIntegerWithPositive() { - class BigIntegerObject(@field:Positive val value: BigInteger) - - val actual = SUT.giveMeOne().value - - then(actual).isPositive() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleBigIntegerWithPositiveOrZero() { - class BigIntegerObject(@field:PositiveOrZero val value: BigInteger) - - val actual = SUT.giveMeOne().value - - then(actual).isGreaterThanOrEqualTo(BigInteger.ZERO) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleBigIntegerWithMin() { - class BigIntegerObject(@field:Min(10) val value: BigInteger) - - val actual = SUT.giveMeOne().value - - then(actual).isGreaterThanOrEqualTo(BigInteger.valueOf(10)) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleBigIntegerWithDecimalMin() { - class BigIntegerObject(@field:DecimalMin("10") val value: BigInteger) - - val actual = SUT.giveMeOne().value - - then(actual).isGreaterThanOrEqualTo(BigInteger.valueOf(10)) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleBigIntegerWithMax() { - class BigIntegerObject(@field:Max(50) val value: BigInteger) - - val actual = SUT.giveMeOne().value - - then(actual).isLessThanOrEqualTo(BigInteger.valueOf(50)) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleBigIntegerWithDecimalMax() { - class BigIntegerObject(@field:DecimalMax("50") val value: BigInteger) - - val actual = SUT.giveMeOne().value - - then(actual).isLessThanOrEqualTo(BigInteger.valueOf(50)) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleBigIntegerWithDigits() { - class BigIntegerObject(@field:Digits(integer = 2, fraction = 0) val value: BigInteger) - - val actual = SUT.giveMeOne().value - - then(actual).matches { - it in BigInteger.valueOf(-99L)..BigInteger.valueOf(99L) - } - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleBigDecimalWithNegative() { - class BigDecimalObject(@field:Negative val value: BigDecimal) - - val actual = SUT.giveMeOne().value - - then(actual).isNegative() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleBigDecimalWithNegativeOrZero() { - class BigDecimalObject(@field:NegativeOrZero val value: BigDecimal) - - val actual = SUT.giveMeOne().value - - then(actual).isLessThanOrEqualTo(BigDecimal.ZERO) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleBigDecimalWithPositive() { - class BigDecimalObject(@field:Positive val value: BigDecimal) - - val actual = SUT.giveMeOne().value - - then(actual).isPositive() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleBigDecimalWithPositiveOrZero() { - class BigDecimalObject(@field:PositiveOrZero val value: BigDecimal) - - val actual = SUT.giveMeOne().value - - then(actual).isGreaterThanOrEqualTo(BigDecimal.ZERO) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleBigDecimalWithMin() { - class BigDecimalObject(@field:Min(10) val value: BigDecimal) - - val actual = SUT.giveMeOne().value - - then(actual).isGreaterThanOrEqualTo(BigDecimal.valueOf(10L)) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleBigDecimalWithDecimalMin() { - class BigDecimalObject(@field:DecimalMin("10") val value: BigDecimal) - - val actual = SUT.giveMeOne().value - - then(actual).isGreaterThanOrEqualTo(BigDecimal.valueOf(10L)) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleBigDecimalWithMax() { - class BigDecimalObject(@field:Max(50) val value: BigDecimal) - - val actual = SUT.giveMeOne().value - - then(actual).isLessThanOrEqualTo(BigDecimal.valueOf(50L)) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleBigDecimalWithDecimalMax() { - class BigDecimalObject(@field:DecimalMax("50") val value: BigDecimal) - - val actual = SUT.giveMeOne().value - - then(actual).isLessThanOrEqualTo(BigDecimal.valueOf(50L)) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleBigDecimalWithDigits() { - class BigDecimalObject(@field:Digits(integer = 2, fraction = 0) val value: BigDecimal) - - val actual = SUT.giveMeOne().value - - then(actual).matches { - it in BigDecimal.valueOf(-99)..BigDecimal.valueOf(99) - } - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setPostConditionExtension() { - class StringObject(val string: String) - - val actual = SUT.giveMeKotlinBuilder() - .setPostCondition("string") { - it.length < 5 - } - .sample() - .string - - then(actual).hasSizeLessThan(5) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleMinZeroInteger() { - class IntegerObject(@field:Min(0L) val value: Int) - - val actual = SUT.giveMeOne().value - - then(actual).isGreaterThanOrEqualTo(0) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleMinZeroDecimal() { - class DecimalObject(@field:Min(0L) val value: Double) - - val actual = SUT.giveMeOne().value - - then(actual).isGreaterThanOrEqualTo(0.0) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleSetArb() { - class StringObject(val string: String) - - val actual = SUT.giveMeArb { setArb(StringObject::string, Arb.zipcodes()) } - .single() - .string - - then(actual).hasSize(5) - } - - @Test - fun integerCombinableArbitrary() { - val actual = CombinableArbitrary.integers() - - then(actual).isInstanceOf(KotestIntegerCombinableArbitrary::class.java) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun integerCombinableArbitraryPositive() { - val actual = CombinableArbitrary.integers().positive().combined() - - then(actual).isPositive() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun integerCombinableArbitraryNegative() { - val actual = CombinableArbitrary.integers().negative().combined() - - then(actual).isNegative() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun integerCombinableArbitraryEven() { - val actual = CombinableArbitrary.integers().even().combined() - - then(actual).isEven() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun integerCombinableArbitraryOdd() { - val actual = CombinableArbitrary.integers().odd().combined() - - then(actual).isOdd() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun integerCombinableArbitraryWithRange() { - val actual = CombinableArbitrary.integers().withRange(10, 20).combined() - - then(actual).isBetween(10, 20) - } - - @Test - fun byteCombinableArbitrary() { - val actual = CombinableArbitrary.bytes() - - then(actual).isInstanceOf(KotestByteCombinableArbitrary::class.java) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun byteCombinableArbitraryPositive() { - val actual = CombinableArbitrary.bytes().positive().combined() - - then(actual).isPositive() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun byteCombinableArbitraryNegative() { - val actual = CombinableArbitrary.bytes().negative().combined() - - then(actual).isNegative() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun byteCombinableArbitraryEven() { - val actual = CombinableArbitrary.bytes().even().combined() - - then(actual % 2).isEqualTo(0) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun byteCombinableArbitraryOdd() { - val actual = CombinableArbitrary.bytes().odd().combined() - - then(actual % 2 != 0).isTrue() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun byteCombinableArbitraryAscii() { - val actual = CombinableArbitrary.bytes().ascii().combined() - - then(actual).isBetween(0.toByte(), 127.toByte()) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun byteCombinableArbitraryWithRange() { - val actual = CombinableArbitrary.bytes().withRange(10.toByte(), 20.toByte()).combined() - - then(actual).isBetween(10.toByte(), 20.toByte()) - } - - @Test - fun stringCombinableArbitrary() { - val actual = CombinableArbitrary.strings() - - then(actual).isInstanceOf(KotestStringCombinableArbitrary::class.java) - } - - @Test - fun stringCombinableArbitraryAscii() { - val actual = CombinableArbitrary.strings().ascii().combined() - - then(actual).satisfiesAnyOf( - { then(it).isASCII() }, - { then(it).isNullOrEmpty() } - ) - } - - companion object { - private val SUT: FixtureMonkey = FixtureMonkey.builder() - .plugin(JavaxValidationPlugin()) - .plugin(KotestPlugin()) - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - } -} diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/KotestInKotestAdapterTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/KotestInKotestAdapterTest.kt deleted file mode 100644 index fcb6c43464..0000000000 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/KotestInKotestAdapterTest.kt +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.kotlin.adapter - -import com.navercorp.fixturemonkey.ArbitraryBuilder -import com.navercorp.fixturemonkey.FixtureMonkey -import com.navercorp.fixturemonkey.kotlin.KotlinNodeTreeAdapterPlugin -import com.navercorp.fixturemonkey.kotest.KotestPlugin -import com.navercorp.fixturemonkey.kotest.checkAll -import com.navercorp.fixturemonkey.kotest.giveMeArb -import com.navercorp.fixturemonkey.kotlin.KotlinPlugin -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.collections.shouldHaveSize -import io.kotest.matchers.shouldBe -import io.kotest.matchers.shouldNotBe -import io.kotest.matchers.types.shouldNotBeSameInstanceAs -import io.kotest.property.forAll - -class KotestInKotestAdapterTest : StringSpec({ - "checkAll" { - SUT.checkAll { string: String, int: Int -> - string shouldNotBeSameInstanceAs int - string shouldBe string - } - } - "checkAllObject" { - SUT.checkAll { stringObject: StringObject -> - stringObject.value shouldNotBe null - } - } - "checkAllArbitraryBuilder" { - SUT.checkAll { string: ArbitraryBuilder> -> - string - .size("$", 3) - .sample() shouldHaveSize 3 - } - } - "forAll" { - forAll(SUT.giveMeArb { set("test") }) { a -> - a == "test" - } - } -}) { - companion object { - val SUT: FixtureMonkey = FixtureMonkey.builder() - .plugin(KotestPlugin()) - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - } - - data class StringObject(val value: String) -} diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/KotlinInnerSpecAdapterTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/KotlinInnerSpecAdapterTest.kt deleted file mode 100644 index aecddfcc23..0000000000 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/KotlinInnerSpecAdapterTest.kt +++ /dev/null @@ -1,923 +0,0 @@ -package com.navercorp.fixturemonkey.tests.kotlin.adapter - -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -import com.navercorp.fixturemonkey.FixtureMonkey -import com.navercorp.fixturemonkey.kotlin.KotlinNodeTreeAdapterPlugin -import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfo -import com.navercorp.fixturemonkey.customizer.Values -import com.navercorp.fixturemonkey.customizer.Values.NOT_NULL -import com.navercorp.fixturemonkey.kotlin.KotlinPlugin -import com.navercorp.fixturemonkey.kotlin.giveMeBuilder -import com.navercorp.fixturemonkey.kotlin.kotlinInnerSpec -import com.navercorp.fixturemonkey.kotlin.setKotlinInner -import com.navercorp.fixturemonkey.tests.kotlin.InnerSpecTestSpecs.ComplexObject -import com.navercorp.fixturemonkey.tests.kotlin.InnerSpecTestSpecs.ComplexObjectObject -import com.navercorp.fixturemonkey.tests.kotlin.InnerSpecTestSpecs.IntegerMapObject -import com.navercorp.fixturemonkey.tests.kotlin.InnerSpecTestSpecs.ListStringObject -import com.navercorp.fixturemonkey.tests.kotlin.InnerSpecTestSpecs.MapObject -import com.navercorp.fixturemonkey.tests.kotlin.InnerSpecTestSpecs.NestedKeyMapObject -import com.navercorp.fixturemonkey.tests.kotlin.InnerSpecTestSpecs.NestedListStringObject -import com.navercorp.fixturemonkey.tests.kotlin.InnerSpecTestSpecs.SimpleObject -import com.navercorp.fixturemonkey.tests.kotlin.InnerSpecTestSpecs.SupplierStringObject - -import net.jqwik.api.Arbitraries -import net.jqwik.api.Property -import org.assertj.core.api.BDDAssertions.then -import org.assertj.core.api.BDDAssertions.thenThrownBy -import java.util.function.Supplier -import java.util.stream.Collectors - -class KotlinInnerSpecAdapterTest { - - @Property - fun key() { - // when - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("strMap") { - minSize(1) - key("key") - } - } - .sample() - .strMap - - then(actual.keys).contains("key") - } - - @Property - fun value() { - // when - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("strMap") { - minSize(1) - value("value") - } - } - .sample() - .strMap - - then(actual.values).contains("value") - } - - @Property - fun entry() { - // when - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("strMap") { - minSize(1) - entry("key", "value") - } - } - .sample() - .strMap - - then(actual["key"]).isEqualTo("value") - } - - @Property - fun keys() { - // when - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("strMap") { - minSize(3) - keys("key1", "key2", "key3") - } - } - .sample() - .strMap - - then(actual.keys).containsAll(setOf("key1", "key2", "key3")) - } - - @Property - fun values() { - // when - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("strMap") { - minSize(3) - values("value1", "value2", "value3") - } - } - .sample() - .strMap - - then(actual.values).containsAll(setOf("value1", "value2", "value3")) - } - - @Property - fun entries() { - // when - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("strMap") { - minSize(2) - entries("key1", "value1", "key2", "value2") - } - } - .sample() - .strMap - - then(actual["key1"]).isEqualTo("value1") - then(actual["key2"]).isEqualTo("value2") - } - - @Property - fun entryTwice() { - // when - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("strMap") { - minSize(2) - entry("key1", "value1") - entry("key2", "value2") - } - } - .sample() - - then(actual.strMap["key1"]).isEqualTo("value1") - then(actual.strMap["key2"]).isEqualTo("value2") - } - - @Property - fun valueNull() { - // when - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("strMap") { - minSize(1) - value(null) - } - } - .sample() - - then(actual.strMap.containsValue(null as String?)).isTrue() - } - - @Property - fun keyNullThrows() { - thenThrownBy { - SUT.giveMeBuilder() - .setKotlinInner { - property("strMap") { - minSize(1) - key(null) - } - } - .sample() - }.isExactlyInstanceOf(IllegalArgumentException::class.java) - .hasMessageContaining("Map key cannot be null.") - } - - @Property - fun keyInKey() { - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .defaultNotNull(true) - .defaultArbitraryContainerInfoGenerator { _ -> ArbitraryContainerInfo(1, 3) } - .build() - - val actual = sut.giveMeBuilder() - .setKotlinInner { - property("mapKeyMap") { - key { key("key") } - } - } - .sample() - - val keyList = actual.mapKeyMap.keys.stream() - .flatMap { it.keys.stream() } - .collect(Collectors.toList()) - then(keyList).contains("key") - } - - @Property - fun valueInKey() { - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .defaultNotNull(true) - .defaultArbitraryContainerInfoGenerator { _ -> ArbitraryContainerInfo(1, 3) } - .build() - - val actual = sut.giveMeBuilder() - .setKotlinInner { - property("mapKeyMap") { - key { value("value") } - } - } - .sample() - - val keyList = actual.mapKeyMap.keys.stream() - .flatMap { it.values.stream() } - .collect(Collectors.toList()) - then(keyList).contains("value") - } - - @Property - fun keyInValue() { - // when - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("mapValueMap") { - minSize(1) - value { - minSize(1) - key("key") - } - } - } - .sample() - - val valueList = actual.mapValueMap.values.stream() - .flatMap { it.keys.stream() } - .collect(Collectors.toList()) - then(valueList).contains("key") - } - - @Property - fun valueInValue() { - // when - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("mapValueMap") { - minSize(1) - value { - minSize(1) - value("value") - } - } - } - .sample() - - val valueList = actual.mapValueMap.values.stream() - .flatMap { it.values.stream() } - .collect(Collectors.toList()) - then(valueList).contains("value") - } - - @Property - fun sizeInValue() { - // when - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("listValueMap") { - size(1) - value { size(10) } - } - } - .sample() - - val sizeList = actual.listValueMap.values.stream() - .map { it.size } - .collect(Collectors.toList()) - then(sizeList).contains(10) - } - - @Property - fun listElementInValue() { - // when - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("listValueMap") { - size(1) - value { - size(1) - listElement(0, "test") - } - } - } - .sample() - - val elementList = actual.listValueMap.values.stream() - .flatMap { it.stream() } - .collect(Collectors.toList()) - then(elementList).contains("test") - } - - @Property - fun propertyInValue() { - // when - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("objectValueMap") { - size(1) - value { property("str", "test") } - } - } - .sample() - - val fieldList = actual.objectValueMap.values.stream() - .filter { it != null } - .map { it.str } - .collect(Collectors.toList()) - then(fieldList).contains("test") - } - - @Property - fun entryInEntryValue() { - // when - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("mapValueMap") { - minSize(1) - entry("key1") { - minSize(1) - entry("key2", "value") - } - } - } - .sample() - - val value = actual.mapValueMap["key1"] - then(value?.get("key2")).isEqualTo("value") - } - - @Property - fun entryInEntryKey() { - // given - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .defaultNotNull(true) - .defaultArbitraryContainerInfoGenerator { _ -> ArbitraryContainerInfo(1, 3) } - .build() - - // when - val actual = sut.giveMeBuilder() - .setKotlinInner { - property("mapKeyMap") { - entry({ entry("key", "value2") }, "value1") - } - } - .sample() - - // then - val expected = actual.mapKeyMap.entries - .stream() - .filter { "value1" == it.value } - .findAny() - .get() - .key - then(expected["key"]).isEqualTo("value2") - } - - @Property - fun entryValueSetNull() { - // when - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("strMap") { - size(1) - entry("key", null) - } - } - .sample() - - then(actual.strMap["key"]).isNull() - } - - @Property - fun listElementInListElement() { - // when - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("values") { - size(1) - listElement(0) { - size(1) - listElement(0, "test") - } - } - } - .sample() - - then(actual.values[0][0]).isEqualTo("test") - } - - @Property - fun propertyInProperty() { - // when - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("value") { - property("value") { - property("str", "test") - } - } - } - .sample() - - then(actual.value.value.str).isEqualTo("test") - } - - @Property - fun sizeAndEntry() { - // when - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("strMap") { - size(4) - entry("key", "test") - } - } - .sample() - .strMap - - then(actual).hasSize(4) - then(actual["key"]).isEqualTo("test") - } - - @Property - fun entryAndSize() { - // when - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("strMap") { - entry("key", "test") - size(4) - } - } - .sample() - .strMap - - then(actual).hasSize(4) - then(actual["key"]).isEqualTo("test") - } - - @Property - fun sizeTwiceReturnsLatterSize() { - // when - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("strMap") { - size(1) - entry("key", "test") - size(0) - } - } - .sample() - .strMap - - then(actual).hasSize(0) - } - - @Property - fun keyLazy() { - val variable = SUT.giveMeBuilder() - val builder = SUT.giveMeBuilder() - .setKotlinInner { - property("strMap") { - size(1) - keyLazy { variable.sample() } - } - } - variable.set("key") - - val actual = builder.sample() - - then(actual.strMap.containsKey("key")).isTrue() - } - - @Property - fun valueLazy() { - val variable = SUT.giveMeBuilder() - val builder = SUT.giveMeBuilder() - .setKotlinInner { - property("strMap") { - minSize(1) - valueLazy { variable.sample() } - } - } - variable.set("value") - - val actual = builder.sample() - - then(actual.strMap.containsValue("value")).isTrue() - } - - @Property - fun entryLazy() { - val keyVariable = SUT.giveMeBuilder() - val valueVariable = SUT.giveMeBuilder() - val builder = SUT.giveMeBuilder() - .setKotlinInner { - property("strMap") { - minSize(1) - entryLazy({ keyVariable.sample() }, { valueVariable.sample() }) - } - } - keyVariable.set("key") - valueVariable.set("value") - - val actual = builder.sample() - - then(actual.strMap["key"]).isEqualTo("value") - } - - @Property - fun keyLazyNullThrows() { - thenThrownBy { - SUT.giveMeBuilder() - .setKotlinInner { - property("strMap") { - minSize(1) - keyLazy { null } - } - } - .sample() - }.isExactlyInstanceOf(IllegalArgumentException::class.java) - .hasMessageContaining("Map key cannot be null.") - } - - @Property - fun allKeyLazy() { - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("integerMap") { - allKeyLazy { Arbitraries.integers().between(0, 100) } - } - } - .sample() - - then(actual.integerMap.keys).allMatch { it in 0..100 } - } - - @Property - fun allValueLazy() { - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("integerMap") { - allValueLazy { Arbitraries.integers().between(0, 100) } - } - } - .sample() - - then(actual.integerMap.values).allMatch { it in 0..100 } - } - - @Property - fun allEntry() { - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("integerMap") { - allEntry( - { Arbitraries.integers().between(0, 100) }, - 100 - ) - } - } - .sample() - - then(actual.integerMap.keys).allMatch { it in 0..100 } - then(actual.integerMap.values).allMatch { it == 100 } - } - - @Property - fun allEntryLazy() { - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("integerMap") { - allEntryLazy( - { Arbitraries.integers().between(0, 100) }, - { Arbitraries.integers().between(0, 100) } - ) - } - } - .sample() - - then(actual.integerMap.keys).allMatch { it in 0..100 } - then(actual.integerMap.values).allMatch { it in 0..100 } - } - - @Property - fun allKey() { - val expected = "test" - - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("objectKeyMap") { - allKey { property("str", expected) } - } - } - .sample() - .objectKeyMap - .keys - .map { it.str } - - then(actual).allMatch { it == expected } - } - - @Property - fun allValue() { - val expected = "test" - - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("strMap") { - allValue(expected) - } - } - .sample() - .strMap - .values - - then(actual).allMatch { it == expected } - } - - @Property - fun allValueInner() { - val expected = "test" - - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("objectValueMap") { - allValue { property("str", expected) } - } - } - .sample() - .objectValueMap - .values - .map { it.str } - - then(actual).allMatch { it == expected } - } - - @Property - fun allListElement() { - val expected = "test" - - // when - val actual = SUT.giveMeBuilder>() - .setKotlinInner { - allListElement(expected) - } - .sample() - - then(actual).allMatch { it == expected } - } - - @Property - fun allListElementInnerSpec() { - val expected = "test" - - // when - val actual = SUT.giveMeBuilder>>() - .setKotlinInner { - allListElement { allListElement(expected) } - } - .sample() - .flatten() - - then(actual).allMatch { it == expected } - } - - @Property - fun setPostCondition() { - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("str") { - postCondition { it.length > 5 } - } - } - .sample() - - then(actual.str).hasSizeGreaterThan(5) - } - - @Property - fun inner() { - val innerSpec = kotlinInnerSpec { property("str", "test") } - - val actual = SUT.giveMeBuilder() - .setKotlinInner { - inner(innerSpec.toInnerSpec()) - } - .sample() - - then(actual.str).isEqualTo("test") - } - - @Property - fun propertyInner() { - val innerSpec = kotlinInnerSpec { property("str", "test") } - - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("value", innerSpec.toInnerSpec()) - } - .sample() - - then(actual.value.str).isEqualTo("test") - } - - @Property - fun listElementInMaxSize() { - val expected = "expected" - - val actual = SUT.giveMeBuilder>() - .setKotlinInner { - maxSize(2) - listElement(0, expected) - listElement(1, expected) - } - .sample() - - then(actual).allMatch { it == expected } - } - - @Property - fun setAfterSizeReturnsSet() { - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("values") { size(2) } - property("values", ArrayList()) - } - .sample() - .values - - then(actual).isEmpty() - } - - @Property - fun sizeAfterSetReturnsSize() { - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("values", ArrayList()) - property("values") { size(2) } - } - .sample() - .values - - then(actual).hasSize(2) - } - - @Property - fun sizeAfterSetWithSeparateInnerSpecReturnsSize() { - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("values", ArrayList()) - } - .setKotlinInner { - property("values") { size(2) } - } - .sample() - .values - - then(actual).hasSize(2) - } - - @Property - fun setAfterSetWithSeparateInnerSpecReturnsSet() { - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("values") { size(2) } - } - .setKotlinInner { - property("values", ArrayList()) - } - .sample() - .values - - then(actual).isEmpty() - } - - @Property - fun innerSpecIncrementsSequence() { - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("values") { size(1) } - property("values") { size(2) } - property("values") { size(3) } - } - .size("values", 5) - .sample() - - then(actual.values).hasSize(5) - } - - @Property - fun setNotNull() { - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("str", NOT_NULL) - } - .sample() - .str - - then(actual).isNotNull() - } - - @Property - fun keysForCollection() { - val keyList = listOf("key1", "key2", "key3") - - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("strMap") { - keys(keyList) - size(3) - } - } - .sample() - .strMap - - then(actual.keys).containsAll(keyList) - } - - @Property - fun valuesForCollection() { - val valueList = listOf("value1", "value2", "value3") - - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("strMap") { - values(valueList) - size(3) - } - } - .sample() - .strMap - - then(actual.values).containsAll(valueList) - } - - @Property - fun entriesForCollection() { - val entries = listOf("key1", "value1", "key2", "value2") - - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("strMap") { - entries(entries) - size(2) - } - } - .sample() - .strMap - - then(actual["key1"]).isEqualTo("value1") - then(actual["key2"]).isEqualTo("value2") - } - - @Property - fun supportSupplierWrapping() { - val expected = "test" - - // when - val actual = SUT.giveMeBuilder>() - .setKotlinInner { - property("str", expected) - } - .sample() - .get() - .str - - then(actual).isEqualTo(expected) - } - - @Property - fun supportSupplierObjectField() { - val expected = Supplier { "test" } - - // when - val actual = SUT.giveMeBuilder() - .setKotlinInner { - property("value", Values.just(expected)) - } - .sample() - .value - - then(actual).isEqualTo(expected) - } - - companion object { - val SUT = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .defaultNotNull(true) - .build() - } -} diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/LambdaAdapterTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/LambdaAdapterTest.kt deleted file mode 100644 index f1cd118aa4..0000000000 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/LambdaAdapterTest.kt +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.kotlin.adapter - -import com.navercorp.fixturemonkey.FixtureMonkey -import com.navercorp.fixturemonkey.kotlin.KotlinNodeTreeAdapterPlugin -import com.navercorp.fixturemonkey.customizer.Values -import com.navercorp.fixturemonkey.kotlin.KotlinPlugin -import com.navercorp.fixturemonkey.kotlin.giveMeBuilder -import com.navercorp.fixturemonkey.kotlin.giveMeOne -import com.navercorp.fixturemonkey.kotlin.setExp -import org.assertj.core.api.BDDAssertions.then -import org.assertj.core.api.BDDAssertions.thenNoException -import org.junit.jupiter.api.Test - -class LambdaAdapterTest { - @Test - fun kotlinLambda() { - // given - class KotlinLambdaValue(val lambda: (String, String, String) -> Unit) - - // when - val actual: KotlinLambdaValue = SUT.giveMeOne() - - then(actual.lambda).isNotNull - } - - @Test - fun kotlinLambdaOnlyReturnType() { - // given - class KotlinLambdaValue(val lambda: () -> String) - - // when - val actual: KotlinLambdaValue = SUT.giveMeOne() - - then(actual.lambda.invoke()).isNotNull - } - - @Test - fun decomposeKotlinLambdaOnlyReturnType() { - // given - class KotlinLambdaValue(val lambda: () -> String) - - // when - val actual = SUT.giveMeBuilder() - .thenApply { _, _ -> } - .sample() - - then(actual.lambda.invoke()).isNotNull - } - - @Test - fun kotlinLambdaReturnType() { - // given - class KotlinLambdaValue(val lambda: (String) -> String) - - // when - val actual: KotlinLambdaValue = SUT.giveMeOne() - - then(actual.lambda.invoke("test")).isNotNull - } - - @Test - fun decomposeKotlinLambdaReturnType() { - // given - class KotlinLambdaValue(val lambda: (String) -> String) - - // when - val actual = SUT.giveMeBuilder() - .thenApply { _, _ -> } - .sample() - - then(actual.lambda.invoke("test")).isNotNull - } - - @Test - fun setJustKotlinLambda() { - // given - class KotlinLambdaValue(val lambda: (String, String, String) -> Unit) - - val expected: (String, String, String) -> Unit = { _, _, _ -> } - - // when - val actual = SUT.giveMeBuilder() - .setExp(KotlinLambdaValue::lambda, Values.just(expected)) - .sample() - - then(actual.lambda).isNotNull - } - - @Test - fun sampleFunctionalObject() { - data class FunctionObject( - val value: () -> Int - ) - - val actual = SUT.giveMeOne().value() - - then(actual).isNotNull() - } - - @Test - fun toStringFunctionalObjectNotThrows() { - data class FunctionObject( - val value: () -> Int - ) - - thenNoException() - .isThrownBy { SUT.giveMeOne().toString() } - } - - companion object { - private val SUT: FixtureMonkey = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - } -} diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/OptionAdapterTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/OptionAdapterTest.kt deleted file mode 100644 index 1dddac014e..0000000000 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/OptionAdapterTest.kt +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.kotlin.adapter - -import com.navercorp.fixturemonkey.FixtureMonkey -import com.navercorp.fixturemonkey.kotlin.KotlinNodeTreeAdapterPlugin -import com.navercorp.fixturemonkey.api.constraint.JavaConstraintGenerator -import com.navercorp.fixturemonkey.api.constraint.JavaDateTimeConstraint -import com.navercorp.fixturemonkey.api.generator.ArbitraryGeneratorContext - -import com.navercorp.fixturemonkey.api.introspector.ConstructorArbitraryIntrospector -import com.navercorp.fixturemonkey.api.introspector.ConstructorArbitraryIntrospector.ConstructorWithParameterNames -import com.navercorp.fixturemonkey.javax.validation.plugin.JavaxValidationPlugin -import com.navercorp.fixturemonkey.kotlin.KotlinPlugin -import com.navercorp.fixturemonkey.kotlin.giveMeOne -import com.navercorp.fixturemonkey.tests.TestEnvironment.ADAPTER_TEST_COUNT -import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.RepeatedTest -import java.io.File -import java.lang.reflect.Modifier -import java.time.Instant -import java.time.LocalDateTime -import java.time.OffsetTime -import javax.validation.constraints.FutureOrPresent - -class OptionAdapterTest { - @RepeatedTest(ADAPTER_TEST_COUNT) - fun customizeJavaConstraintGenerators() { - // given - class InstantObject(@field:FutureOrPresent val value: Instant) - - val offset = OffsetTime.now().offset - val thisYearInstant = Instant.now() - - val nextYear = LocalDateTime.now().plusYears(1L) - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(JavaxValidationPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .pushJavaConstraintGeneratorCustomizer { - object : JavaConstraintGenerator by it { - override fun generateDateTimeConstraint(context: ArbitraryGeneratorContext?): JavaDateTimeConstraint? { - val constraint = it.generateDateTimeConstraint(context)!! - - return JavaDateTimeConstraint( - { constraint.min }, - { nextYear }, - ) - } - } - } - .build() - - // when - val actual = sut.giveMeOne().value - - // then - val nextYearInstant = nextYear.toInstant(offset) - then(actual).isBetween(thisYearInstant, nextYearInstant) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun customizeJavaConstraintGeneratorsTwice() { - // given - class InstantObject(@field:FutureOrPresent val value: Instant) - - val offset = OffsetTime.now().offset - val thisYear = LocalDateTime.now() - val thisYearInstant = Instant.now() - - val nextYear = LocalDateTime.now().plusYears(1L) - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .pushJavaConstraintGeneratorCustomizer { - object : JavaConstraintGenerator by it { - override fun generateDateTimeConstraint(context: ArbitraryGeneratorContext?): JavaDateTimeConstraint { - return JavaDateTimeConstraint( - null, - ) { nextYear } - } - } - } - .pushJavaConstraintGeneratorCustomizer { - object : JavaConstraintGenerator by it { - override fun generateDateTimeConstraint(context: ArbitraryGeneratorContext?): JavaDateTimeConstraint { - val constraint = it.generateDateTimeConstraint(context)!! - return JavaDateTimeConstraint( - { thisYear }, - { constraint.max }, - ) - } - } - } - .build() - - // when - val actual = sut.giveMeOne().value - - // then - val nextYearInstant = nextYear.toInstant(offset) - then(actual).isBetween(thisYearInstant, nextYearInstant) - } - - - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun requiredPropertyGenerator() { - val sut = FixtureMonkey.builder() - .objectIntrospector( - ConstructorArbitraryIntrospector( - ConstructorWithParameterNames( - File::class.java.declaredConstructors.first { Modifier.isPublic(it.modifiers) }, - listOf(), - ), - ), - ) - .plugin(KotlinNodeTreeAdapterPlugin()) - .defaultNotNull(true) - .build() - - val actual: File = sut.giveMeOne() - - then(actual).isNotNull - } -} diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/PluginAdapterTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/PluginAdapterTest.kt deleted file mode 100644 index dfaba8843e..0000000000 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/PluginAdapterTest.kt +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.kotlin.adapter - -import com.navercorp.fixturemonkey.FixtureMonkey -import com.navercorp.fixturemonkey.kotlin.KotlinNodeTreeAdapterPlugin -import com.navercorp.fixturemonkey.api.matcher.AssignableTypeMatcher -import com.navercorp.fixturemonkey.api.matcher.MatcherOperator -import com.navercorp.fixturemonkey.api.plugin.InterfacePlugin -import com.navercorp.fixturemonkey.api.property.ConcreteTypeCandidateConcretePropertyResolver -import com.navercorp.fixturemonkey.api.property.PropertyUtils -import com.navercorp.fixturemonkey.kotlin.KotlinPlugin -import com.navercorp.fixturemonkey.kotlin.giveMeBuilder -import com.navercorp.fixturemonkey.kotlin.giveMeOne -import com.navercorp.fixturemonkey.tests.TestEnvironment.ADAPTER_TEST_COUNT -import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.RepeatedTest -import org.junit.jupiter.api.Test -import java.time.Instant -import java.util.LinkedList -import java.util.TreeSet - -class PluginAdapterTest { - @RepeatedTest(ADAPTER_TEST_COUNT) - fun propertyCandidateResolverReturnsConcreteListType() { - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .plugin { - it.candidateConcretePropertyResolvers( - listOf( - MatcherOperator.exactTypeMatchOperator( - List::class.java, - ConcreteTypeCandidateConcretePropertyResolver(listOf(LinkedList::class.java)) - ) - ) - ) - } - .build() - - val actual: List = sut.giveMeOne() - - then(actual).isInstanceOf(LinkedList::class.java) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun nestedPropertyCandidateResolverReturnsConcreteListType() { - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .plugin { - it.candidateConcretePropertyResolvers( - listOf( - MatcherOperator.exactTypeMatchOperator( - Collection::class.java, - ConcreteTypeCandidateConcretePropertyResolver(listOf(List::class.java)) - ), - MatcherOperator.exactTypeMatchOperator( - List::class.java, - ConcreteTypeCandidateConcretePropertyResolver(listOf(LinkedList::class.java)) - ) - ) - ) - } - .build() - - val actual: Collection = sut.giveMeOne() - - then(actual).isInstanceOf(LinkedList::class.java) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun propertyCandidateResolverReturnsConcreteSetType() { - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .plugin { - it.candidateConcretePropertyResolvers( - listOf( - MatcherOperator.exactTypeMatchOperator( - Set::class.java, - ConcreteTypeCandidateConcretePropertyResolver(listOf(TreeSet::class.java)) - ) - ) - ) - } - .build() - - val actual: Set = sut.giveMeOne() - - then(actual).isInstanceOf(TreeSet::class.java) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun nestedPropertyCandidateResolverReturnsConcreteSetType() { - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .plugin { - it.candidateConcretePropertyResolvers( - listOf( - MatcherOperator.exactTypeMatchOperator( - Collection::class.java, - ConcreteTypeCandidateConcretePropertyResolver(listOf(Set::class.java)) - ), - MatcherOperator.exactTypeMatchOperator( - Set::class.java, - ConcreteTypeCandidateConcretePropertyResolver(listOf(TreeSet::class.java)) - ) - ) - ) - } - .build() - - val actual: Collection = sut.giveMeOne() - - then(actual).isInstanceOf(TreeSet::class.java) - } - - - @Test - fun complexAbstractExtendsReturnsFirst() { - abstract class ParentAbstractClass - - abstract class FirstAbstractClass : ParentAbstractClass() - abstract class SecondAbstractClass : ParentAbstractClass() - - class FirstConcreteClass : FirstAbstractClass() - class SecondConcreteClass : SecondAbstractClass() - - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .plugin( - InterfacePlugin() - .abstractClassExtends( - AssignableTypeMatcher(ParentAbstractClass::class.java) - ) { property -> - when (property.type) { - FirstAbstractClass::class.java -> listOf(PropertyUtils.toProperty(FirstConcreteClass::class.java)) - SecondAbstractClass::class.java -> listOf(PropertyUtils.toProperty(SecondConcreteClass::class.java)) - else -> throw NotImplementedError() - } - } - - ) - .build() - - val actual: FirstAbstractClass = sut.giveMeOne() - - then(actual).isInstanceOf(FirstConcreteClass::class.java) - } - - @Test - fun complexAbstractExtendsReturnsSecond() { - abstract class ParentAbstractClass - - abstract class FirstAbstractClass : ParentAbstractClass() - abstract class SecondAbstractClass : ParentAbstractClass() - - class FirstConcreteClass : FirstAbstractClass() - class SecondConcreteClass : SecondAbstractClass() - - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .plugin( - InterfacePlugin() - .abstractClassExtends( - AssignableTypeMatcher(ParentAbstractClass::class.java) - ) { property -> - when (property.type) { - FirstAbstractClass::class.java -> listOf(PropertyUtils.toProperty(FirstConcreteClass::class.java)) - SecondAbstractClass::class.java -> listOf(PropertyUtils.toProperty(SecondConcreteClass::class.java)) - else -> throw NotImplementedError() - } - } - - ) - .build() - - val actual: SecondAbstractClass = sut.giveMeOne() - - then(actual).isInstanceOf(SecondConcreteClass::class.java) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setConcreteTypeChildReturnsExactlyConcreteTypeChildType() { - // given - abstract class AbstractClass - open class ConcreteType(val parentValue: String) : AbstractClass() - class ConcreteTypeChild(val childValue: String) : ConcreteType("parent") - - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .plugin( - InterfacePlugin() - .abstractClassExtends( - AbstractClass::class.java, - listOf(ConcreteType::class.java, ConcreteTypeChild::class.java) - ) - ) - .build() - - // when - val actual = sut.giveMeBuilder() - .set("$", ConcreteTypeChild("")) - .sample() - - then(actual).isExactlyInstanceOf(ConcreteTypeChild::class.java) - } - - @Test - fun setReturnsImplementation() { - // given - abstract class ParentAbstractClass - - data class FirstConcreteClass(val string: String) : ParentAbstractClass() - data class SecondConcreteClass(val string: String) : ParentAbstractClass() - - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .plugin( - InterfacePlugin() - .abstractClassExtends( - ParentAbstractClass::class.java, - listOf(FirstConcreteClass::class.java, SecondConcreteClass::class.java) - ) - - ) - .build() - - val expected = SecondConcreteClass("expected") - - // when - val actual: SecondConcreteClass = sut.giveMeBuilder() - .set(expected) - .sample() as SecondConcreteClass - - then(actual).isEqualTo(expected) - } - - @Test - fun setReturnsLastImplementation() { - // given - abstract class ParentAbstractClass - - data class FirstConcreteClass(val string: String) : ParentAbstractClass() - data class SecondConcreteClass(val string: String) : ParentAbstractClass() - - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .plugin( - InterfacePlugin() - .abstractClassExtends( - ParentAbstractClass::class.java, - listOf(FirstConcreteClass::class.java, SecondConcreteClass::class.java) - ) - - ) - .build() - - val notExpected = FirstConcreteClass("notExpected") - val expected = SecondConcreteClass("expected") - - // when - val actual: SecondConcreteClass = sut.giveMeBuilder() - .set(notExpected) - .set(expected) - .sample() as SecondConcreteClass - - then(actual).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setComplexReturnsSimple() { - // given - abstract class ParentAbstractClass - - data class FirstConcreteClass(val string: String, val int: Int, val instant: Instant) : ParentAbstractClass() - data class SecondConcreteClass(val string: String, val long: Long) : ParentAbstractClass() - - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .plugin( - InterfacePlugin() - .abstractClassExtends( - ParentAbstractClass::class.java, - listOf(FirstConcreteClass::class.java, SecondConcreteClass::class.java) - ) - - ) - .build() - - val expected = FirstConcreteClass("expected", 1, Instant.now()) - val notExpected = SecondConcreteClass("notExpected", 2L) - - // when - val actual = sut.giveMeBuilder() - .set(expected) - .set(notExpected) - .set(expected) - .sample() as FirstConcreteClass - - then(actual).isEqualTo(expected) - } -} diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/PropertySelectorAdapterTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/PropertySelectorAdapterTest.kt deleted file mode 100644 index f2d34435af..0000000000 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/PropertySelectorAdapterTest.kt +++ /dev/null @@ -1,694 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.kotlin.adapter - -import com.navercorp.fixturemonkey.FixtureMonkey -import com.navercorp.fixturemonkey.api.experimental.JavaGetterMethodPropertySelector.javaGetter -import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector -import com.navercorp.fixturemonkey.kotlin.KotlinNodeTreeAdapterPlugin -import com.navercorp.fixturemonkey.kotlin.KotlinPlugin -import com.navercorp.fixturemonkey.kotlin.expression.root -import com.navercorp.fixturemonkey.kotlin.get -import com.navercorp.fixturemonkey.kotlin.giveMeExperimentalBuilder -import com.navercorp.fixturemonkey.kotlin.giveMeKotlinBuilder -import com.navercorp.fixturemonkey.kotlin.instantiator.instantiateBy -import com.navercorp.fixturemonkey.kotlin.into -import com.navercorp.fixturemonkey.kotlin.intoGetter -import com.navercorp.fixturemonkey.kotlin.pushExactTypeArbitraryIntrospector -import com.navercorp.fixturemonkey.kotlin.setExp -import com.navercorp.fixturemonkey.kotlin.setExpGetter -import com.navercorp.fixturemonkey.kotlin.setNotNull -import com.navercorp.fixturemonkey.kotlin.setNull -import com.navercorp.fixturemonkey.kotlin.sizeExp -import com.navercorp.fixturemonkey.kotlin.sizeExpGetter -import com.navercorp.fixturemonkey.tests.TestEnvironment.ADAPTER_TEST_COUNT -import com.navercorp.fixturemonkey.tests.kotlin.ImmutableJavaTestSpecs.ArrayObject -import com.navercorp.fixturemonkey.tests.kotlin.ImmutableJavaTestSpecs.JavaStringObject -import com.navercorp.fixturemonkey.tests.kotlin.ImmutableJavaTestSpecs.NestedArrayObject -import com.navercorp.fixturemonkey.tests.kotlin.ImmutableJavaTestSpecs.RootJavaStringObject -import com.navercorp.fixturemonkey.tests.kotlin.InnerSpecTestSpecs.ComplexObject -import com.navercorp.fixturemonkey.tests.kotlin.InnerSpecTestSpecs.ComplexObjectObject -import com.navercorp.fixturemonkey.tests.kotlin.InnerSpecTestSpecs.ListStringObject -import com.navercorp.fixturemonkey.tests.kotlin.InnerSpecTestSpecs.SimpleObject -import com.navercorp.fixturemonkey.tests.kotlin.JavaConstructorTestSpecs.JavaTypeObject -import org.assertj.core.api.BDDAssertions.then -import org.assertj.core.api.BDDAssertions.thenThrownBy -import org.junit.jupiter.api.RepeatedTest -import org.junit.jupiter.api.Test - -class PropertySelectorAdapterTest { - @Test - fun kotlinObjectUseJavaGetterThrows() { - class KotlinObject(val value: String) - - thenThrownBy { - SUT.giveMeKotlinBuilder() - .set(javaGetter(KotlinObject::value), "test") - .sample() - .value - }.cause() - .isExactlyInstanceOf(IllegalArgumentException::class.java) - .hasMessageContaining("Kotlin type could not resolve property name.") - } - - @Test - fun javaGetter() { - val expected = "test" - - val actual = SUT.giveMeExperimentalBuilder() - .instantiateBy { - constructor { - parameter("string") - parameter() - } - } - .set(javaGetter(JavaTypeObject::getString), expected) - .sample() - .string - - then(actual).isEqualTo(expected) - } - - @Test - fun setExpArrayElement() { - // given - class ArrayObject(val array: Array) - - val expected = "test" - - // when - val actual = SUT.giveMeKotlinBuilder() - .sizeExp(ArrayObject::array, 1) - .setExp(ArrayObject::array[0], expected) - .sample() - .array[0] - - // then - then(actual).isEqualTo(expected) - } - - @Test - fun setExpNestedArrayElement() { - // given - class ArrayObject(val array: Array) - class NestedArrayObject(val obj: ArrayObject) - - val expected = "test" - - // when - val actual = SUT.giveMeKotlinBuilder() - .sizeExp(NestedArrayObject::obj into ArrayObject::array, 1) - .setExp(NestedArrayObject::obj into ArrayObject::array[0], expected) - .sample() - .obj - .array[0] - - // then - then(actual).isEqualTo(expected) - } - - @Test - fun setExpGetterArrayElement() { - // given - val expected = "test" - - // when - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - constructor { - parameter>(parameterName = "array") - } - } - .sizeExpGetter(ArrayObject::getArray, 1) - .setExpGetter(ArrayObject::getArray[0], expected) - .sample() - .array[0] - - // then - then(actual).isEqualTo(expected) - } - - @Test - fun setExpGetterNestedArrayElement() { - // given - val expected = "test" - - // when - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - constructor { - parameter(parameterName = "obj") - } - constructor { - parameter>(parameterName = "array") - } - } - .sizeExp(NestedArrayObject::getObj intoGetter ArrayObject::getArray, 1) - .setExp(NestedArrayObject::getObj intoGetter ArrayObject::getArray[0], expected) - .sample() - .obj - .array[0] - - // then - then(actual).isEqualTo(expected) - } - - @Test - fun setRootExp() { - val expected = "test" - - val actual = SUT.giveMeKotlinBuilder() - .set(String::root, expected) - .sample() - - then(actual).isEqualTo(expected) - } - - @Test - fun setLazyRootExp() { - val expected = "test" - - val actual = SUT.giveMeKotlinBuilder() - .setLazy(String::root) { expected } - .sample() - - then(actual).isEqualTo(expected) - } - - @Test - fun setNullRootExp() { - val actual = SUT.giveMeKotlinBuilder() - .setNull(String::root) - .sample() - - then(actual).isNull() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setNotNullRootExp() { - val actual = SUT.giveMeKotlinBuilder() - .setNotNull(String::root) - .sample() - - then(actual).isNotNull() - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sizeRootExp() { - val actual = SUT.giveMeKotlinBuilder>() - .size(List::root, 1) - .sample() - - then(actual).hasSize(1) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sizeRangeRootExp() { - val actual = SUT.giveMeKotlinBuilder>() - .size(List::root, 1, 3) - .sample() - - then(actual).hasSizeBetween(1, 3) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun minSizeRootExp() { - val actual = SUT.giveMeKotlinBuilder>() - .minSize(List::root, 1) - .sample() - - then(actual).hasSizeGreaterThanOrEqualTo(1) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun maxSizeRootExp() { - val actual = SUT.giveMeKotlinBuilder>() - .maxSize(List::root, 1) - .sample() - - then(actual).hasSizeLessThanOrEqualTo(1) - } - - @Test - fun setPostConditionRootExp() { - val actual = SUT.giveMeKotlinBuilder() - .setPostCondition(String::root) { it.length < 5 } - .sample() - - then(actual).hasSizeLessThan(5) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setRootElementExp() { - val expected = "test" - - val actual = SUT.giveMeKotlinBuilder>() - .size(List::root, 1) - .set(List::root[0], expected) - .sample() - - then(actual[0]).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setRootArrayElementExp() { - val expected = "test" - - val actual = SUT.giveMeKotlinBuilder>() - .size(Array::root, 1) - .set(Array::root[0], expected) - .sample() - - then(actual[0]).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setRootAllElementExp() { - val expected = "test" - - val actual = SUT.giveMeKotlinBuilder>() - .size(List::root, 3) - .set(List::root["*"], expected) - .sample() - - then(actual).allMatch { it == expected } - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setRootArrayAllElementExp() { - val expected = "test" - - val actual = SUT.giveMeKotlinBuilder>() - .size(Array::root, 3) - .set(Array::root["*"], expected) - .sample() - - then(actual).allMatch { it == expected } - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setRootNestedListElementExp() { - val expected = "test" - - val actual = SUT.giveMeKotlinBuilder>>() - .size(List>::root, 1) - .size(List>::root[0], 1) - .set(List>::root[0][0], expected) - .sample()[0][0] - - then(actual).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setRootNestedListAllElementExp() { - val expected = "test" - - val actual = SUT.giveMeKotlinBuilder>>() - .size(List>::root, 3) - .size(List>::root["*"], 3) - .set(List>::root["*"]["*"], expected) - .sample() - - then(actual).allMatch { list -> list.all { it == expected } } - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setRootNestedArrayElementExp() { - val expected = "test" - - val actual = SUT.giveMeKotlinBuilder>>() - .size(Array>::root, 1) - .size(Array>::root[0], 1) - .set(Array>::root[0][0], expected) - .sample()[0][0] - - then(actual).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setRootNestedArrayAllElementExp() { - val expected = "test" - - val actual = SUT.giveMeKotlinBuilder>>() - .size(Array>::root, 3) - .size(Array>::root["*"], 3) - .set(Array>::root["*"]["*"], expected) - .sample() - .flatten() - - then(actual).allMatch { it == expected } - } - - @Test - fun setRootPropertyExp() { - val expected = "expected" - - class StringObject(val string: String) - - val actual = SUT.giveMeKotlinBuilder() - .set(StringObject::root into StringObject::string, expected) - .sample() - .string - - then(actual).isEqualTo(expected) - } - - @Test - fun typedKotlinPropertySelector() { - // given - class StringObject(val string: String) - - val expected = "test" - - // when - val actual = SUT.giveMeKotlinBuilder() - .customizeProperty(StringObject::string) { - it.map { _ -> expected } - } - .sample() - .string - - // then - then(actual).isEqualTo(expected) - } - - @Test - fun typedKotlinPropertySelectorRecursively() { - // given - class StringObject(val string: String) - - val expected = "test" - - // when - val actual = SUT.giveMeKotlinBuilder() - .customizeProperty(StringObject::string) { - it.map { _ -> expected } - }.customizeProperty(StringObject::string) { - it.map { _ -> expected } - } - .sample() - - // then - then(actual.string).isEqualTo(expected) - } - - @Test - fun typedNestedKotlinPropertySelector() { - // given - class StringObject(val string: String) - - class NestedStringObject(val obj: StringObject) - - val expected = "test" - - // when - val actual = SUT.giveMeKotlinBuilder() - .customizeProperty(NestedStringObject::obj into StringObject::string) { - it.map { _ -> expected } - } - .sample() - .obj - .string - - // then - then(actual).isEqualTo(expected) - } - - @Test - fun typedJavaPropertySelector() { - // given - val expected = "test" - - val sut = FixtureMonkey.builder() - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build(); - - // when - val actual = sut.giveMeKotlinBuilder() - .customizeProperty(JavaStringObject::getString) { - it.map { _ -> expected } - } - .sample() - .string - - // then - then(actual).isEqualTo(expected) - } - - @Test - fun typedJavaPropertySelectorRecursively() { - // given - val expected = "test" - - val sut = FixtureMonkey.builder() - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build(); - - // when - val actual = sut.giveMeKotlinBuilder() - .customizeProperty(JavaStringObject::getString) { - it.map { _ -> expected } - }.customizeProperty(JavaStringObject::getString) { - it.map { _ -> expected } - } - .sample() - .string - - // then - then(actual).isEqualTo(expected) - } - - @Test - fun typedRootIsKotlinNestedJavaPropertySelector() { - // given - class RootJavaStringObject(val obj: JavaStringObject) - - val expected = "test" - - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .pushExactTypeArbitraryIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build(); - - // when - val actual = sut.giveMeKotlinBuilder() - .customizeProperty(RootJavaStringObject::obj intoGetter JavaStringObject::getString) { - it.map { _ -> expected } - } - .sample() - .obj - .string - - // then - then(actual).isEqualTo(expected) - } - - @Test - fun typedRootIsJavaNestedJavaPropertySelector() { - // given - val expected = "test" - - val sut = FixtureMonkey.builder() - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build(); - - // when - val actual = sut.giveMeKotlinBuilder() - .customizeProperty(RootJavaStringObject::getObj intoGetter JavaStringObject::getString) { - it.map { _ -> expected } - } - .sample() - .obj - .string - - // then - then(actual).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun threeLevelDeepSetShouldPreventAllAncestorNull() { - // given - val expected = "test" - - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .defaultNullInjectGenerator { 1.0 } - .build() - - // when - val result = sut.giveMeKotlinBuilder() - .setExp(ComplexObjectObject::value into ComplexObject::value into SimpleObject::str, expected) - .sample() - - // then - then(result).isNotNull - then(result.value).isNotNull - then(result.value.value).isNotNull - then(result.value.value.str).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setContainerElementShouldPreventParentNull() { - // given - val expected = "test" - - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .defaultNullInjectGenerator { 1.0 } - .build() - - // when - val result = sut.giveMeKotlinBuilder() - .sizeExp(ListStringObject::values, 1) - .setExp(ListStringObject::values[0], expected) - .sample() - - // then - then(result).isNotNull - then(result.values).isNotNull - then(result.values[0]).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setMultipleSiblingPathsShouldPreventParentNull() { - // given - val expectedStr = "test" - val expectedInt = 42 - - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .defaultNullInjectGenerator { 1.0 } - .build() - - // when - val result = sut.giveMeKotlinBuilder() - .setExp(ComplexObjectObject::value into ComplexObject::value into SimpleObject::str, expectedStr) - .setExp(ComplexObjectObject::value into ComplexObject::value into SimpleObject::integer, expectedInt) - .sample() - - // then - then(result).isNotNull - then(result.value).isNotNull - then(result.value.value).isNotNull - then(result.value.value.str).isEqualTo(expectedStr) - then(result.value.value.integer).isEqualTo(expectedInt) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sizeOnlyContainerShouldPreventParentNull() { - // given - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .defaultNullInjectGenerator { 1.0 } - .build() - - // when - val result = sut.giveMeKotlinBuilder() - .sizeExp(ListStringObject::values, 2) - .sample() - - // then - then(result).isNotNull - then(result.values).isNotNull - then(result.values).hasSize(2) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setNotNullNestedPathShouldPreventAncestorNull() { - // given - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .defaultNullInjectGenerator { 1.0 } - .build() - - // when - val result = sut.giveMeKotlinBuilder() - .setNotNullExp(ComplexObjectObject::value into ComplexObject::value) - .sample() - - // then - then(result).isNotNull - then(result.value).isNotNull - then(result.value.value).isNotNull - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun customizePropertyNestedPathShouldPreventParentNull() { - // given - val expected = "test" - - val sut = FixtureMonkey.builder() - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .defaultNullInjectGenerator { 1.0 } - .build() - - // when - val result = sut.giveMeKotlinBuilder() - .customizeProperty(RootJavaStringObject::getObj intoGetter JavaStringObject::getString) { - it.map { _ -> expected } - } - .sample() - - // then - then(result).isNotNull - then(result.obj).isNotNull - then(result.obj.string).isEqualTo(expected) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setExpChildPathShouldPreventParentNull() { - // given - val expected = "test" - - val sut = FixtureMonkey.builder() - .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .defaultNullInjectGenerator { 1.0 } - .build() - - // when - val result = sut.giveMeKotlinBuilder() - .setExp(RootJavaStringObject::getObj intoGetter JavaStringObject::getString, expected) - .sample() - - // then - then(result).isNotNull - then(result.obj).isNotNull - then(result.obj.string).isEqualTo(expected) - } - - companion object { - private val SUT: FixtureMonkey = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - } -} diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/SimpleValueJqwikPluginAdapterTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/SimpleValueJqwikPluginAdapterTest.kt deleted file mode 100644 index 861e154dd0..0000000000 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/SimpleValueJqwikPluginAdapterTest.kt +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.kotlin.adapter - -import com.navercorp.fixturemonkey.FixtureMonkey -import com.navercorp.fixturemonkey.kotlin.KotlinNodeTreeAdapterPlugin -import com.navercorp.fixturemonkey.api.plugin.SimpleValueJqwikPlugin -import com.navercorp.fixturemonkey.javax.validation.plugin.JavaxValidationPlugin -import com.navercorp.fixturemonkey.kotlin.KotlinPlugin -import com.navercorp.fixturemonkey.kotlin.giveMeKotlinBuilder -import com.navercorp.fixturemonkey.kotlin.giveMeOne -import com.navercorp.fixturemonkey.tests.TestEnvironment.ADAPTER_TEST_COUNT -import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.RepeatedTest -import org.junit.jupiter.api.Test -import java.time.Instant -import java.time.LocalDateTime -import java.time.temporal.ChronoUnit -import javax.validation.constraints.Max -import javax.validation.constraints.Min - -class SimpleValueJqwikPluginAdapterTest { - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleInt() { - val sut = FixtureMonkey.builder() - .plugin(SimpleValueJqwikPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val actual: Int = sut.giveMeOne() - - then(actual).isBetween(-10000, 10000) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun modifyNumberValue() { - val sut = FixtureMonkey.builder() - .plugin( - SimpleValueJqwikPlugin() - .minNumberValue(-1) - .maxNumberValue(1) - ) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val actual: Int = sut.giveMeOne() - - then(actual).isBetween(-1, 1) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun modifyStringLength() { - val sut = FixtureMonkey.builder() - .plugin( - SimpleValueJqwikPlugin() - .minStringLength(2) - .maxStringLength(3) - ) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val actual: String = sut.giveMeOne() - - then(actual).hasSizeBetween(2, 3) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun modifyCharacterPredicate() { - val sut = FixtureMonkey.builder() - .plugin( - SimpleValueJqwikPlugin() - .characterPredicate { 50.toChar() <= it && it <= 100.toChar() } - ) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val actual: String = sut.giveMeOne() - - then(actual.chars()).allMatch { it in 50..100 } - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun modifyContainerSize() { - val sut = FixtureMonkey.builder() - .plugin( - SimpleValueJqwikPlugin() - .minContainerSize(2) - .maxContainerSize(3) - ) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val actual: List = sut.giveMeOne() - - then(actual).hasSizeBetween(2, 3) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun modifyDate() { - val sut = FixtureMonkey.builder() - .plugin( - SimpleValueJqwikPlugin() - .plusDaysFromToday(1L) - .minusDaysFromToday(1L) - ) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - val yesterday = Instant.now().minus(1, ChronoUnit.DAYS) - - val actual: Instant = sut.giveMeOne() - - val tomorrow = Instant.now().plus(1, ChronoUnit.DAYS) - then(actual).isBetween(yesterday, tomorrow) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun withValidationPlugin() { - // given - class JavaxValidationAnnotationValue( - @field:Min(20) @field:Max(30) val annotatedInt: Int, - val notAnnotatedInt: Int - ) - - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(JavaxValidationPlugin()) - .plugin(SimpleValueJqwikPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - // when - val actual: JavaxValidationAnnotationValue = sut.giveMeOne() - - then(actual.annotatedInt).isBetween(20, 30) - then(actual.notAnnotatedInt).isBetween(-10000, 10000) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleSetObject() { - class SetObject(val integers: Set) - - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(SimpleValueJqwikPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val setObject = sut.giveMeKotlinBuilder() - .size("integers", 3) - .sample() - - - then(setObject).isNotNull - then(setObject.integers).hasSize(3) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun sampleByte() { - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(SimpleValueJqwikPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val actual: Byte = sut.giveMeOne() - - then(actual).isBetween(Byte.MIN_VALUE, Byte.MAX_VALUE) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun modifyNumberValueByte() { - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin( - SimpleValueJqwikPlugin() - .minNumberValue(-1) - .maxNumberValue(1) - ) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val actual: Byte = sut.giveMeOne() - - then(actual).isBetween(-1, 1) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun modifyOutOfRangeNumberValueByte() { - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin( - SimpleValueJqwikPlugin() - .minNumberValue(-129) - .maxNumberValue(129) - ) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val actual: Byte = sut.giveMeOne() - - then(actual).isBetween(Byte.MIN_VALUE, Byte.MAX_VALUE) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setPositiveMinNumberReturnsPositive() { - val sut = FixtureMonkey.builder() - .plugin(SimpleValueJqwikPlugin().minNumberValue(0)) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val actual: Long = sut.giveMeOne() - - then(actual).isGreaterThanOrEqualTo(0); - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun setNegativeMaxNumberReturnsNegative() { - val sut = FixtureMonkey.builder() - .plugin(SimpleValueJqwikPlugin().maxNumberValue(-0)) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val actual: Long = sut.giveMeOne() - - then(actual).isLessThanOrEqualTo(0); - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun modifyPositiveDecimalNumberRange() { - val sut = FixtureMonkey.builder() - .plugin( - SimpleValueJqwikPlugin() - .minNumberValue(1) - .maxNumberValue(10) - ) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val actual: Double = sut.giveMeOne() - - then(actual).isBetween(1.0, 10.0) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun modifyNegativeDecimalNumberRange() { - val sut = FixtureMonkey.builder() - .plugin( - SimpleValueJqwikPlugin() - .minNumberValue(-10) - .maxNumberValue(-1) - ) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val actual: Double = sut.giveMeOne() - - then(actual).isBetween(-10.0, -1.0) - } - - @RepeatedTest(ADAPTER_TEST_COUNT) - fun modifyMixedDecimalNumberRange() { - val sut = FixtureMonkey.builder() - .plugin( - SimpleValueJqwikPlugin() - .minNumberValue(-5) - .maxNumberValue(5) - ) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - val actual: Double = sut.giveMeOne() - - then(actual).isBetween(-5.0, 5.0) - } - - @Test - fun simpleValueJqwikPluginOnlyGreaterThan() { - // given - val expected = 10001L - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin( - SimpleValueJqwikPlugin() - .minNumberValue(expected) - ) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - // when - val actual: Long = sut.giveMeOne() - - // then - then(actual).isGreaterThanOrEqualTo(expected) - } - - @Test - fun simpleValueJqwikPluginMinStringLengthGreaterThanDefault() { - // given - val expected = 10L - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin( - SimpleValueJqwikPlugin() - .minStringLength(expected) - ) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - // when - val actual: String = sut.giveMeOne() - - // then - then(actual.length).isGreaterThanOrEqualTo(expected.toInt()) - } - - @Test - fun simpleValueJqwikPluginMinContainerSizeGreaterThanDefault() { - // given - val expected = 5 - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin( - SimpleValueJqwikPlugin() - .minContainerSize(expected) - ) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - // when - val actual: List = sut.giveMeOne>() - - // then - then(actual.size).isGreaterThanOrEqualTo(expected) - } - - @Test - fun simpleValueJqwikPluginMinusDaysFromTodayGreaterThanDefault() { - // given - val expected = 400L - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin( - SimpleValueJqwikPlugin() - .minusDaysFromToday(expected) - ) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - // when - val actual: LocalDateTime = sut.giveMeOne() - - // then - val expectedMinDate = LocalDateTime.now().minusDays(expected) - val expectedMaxDate = LocalDateTime.now().plusDays(expected + 30L) - then(actual).isBetween(expectedMinDate, expectedMaxDate) - } -} diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/ValidationAdapterTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/ValidationAdapterTest.kt deleted file mode 100644 index fd31e9341f..0000000000 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/ValidationAdapterTest.kt +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.kotlin.adapter - -import com.navercorp.fixturemonkey.FixtureMonkey -import com.navercorp.fixturemonkey.kotlin.KotlinNodeTreeAdapterPlugin -import com.navercorp.fixturemonkey.api.expression.TypedExpressionGenerator -import com.navercorp.fixturemonkey.javax.validation.plugin.JavaxValidationPlugin -import com.navercorp.fixturemonkey.javax.validation.validator.JavaxArbitraryValidator -import com.navercorp.fixturemonkey.kotlin.KotlinPlugin -import com.navercorp.fixturemonkey.kotlin.giveMeBuilder -import com.navercorp.fixturemonkey.kotlin.giveMeOne -import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.Test -import javax.validation.Valid -import javax.validation.constraints.Size - -class ValidationAdapterTest { - @Test - fun sizeZero() { - // given - class StringWithSizeZero( - @field:Size(min = 0, max = 0) - val value: String, - ) - - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(JavaxValidationPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - - // when - val actual = sut.giveMeOne().value - - // then - then(actual).isEqualTo("") - } - - @Test - fun customizerValidOnly() { - // given - class StringWithSizeZero( - @field:Size(min = 0, max = 0) - val value: String, - ) - - class Wrapper(@field:Valid val value: StringWithSizeZero) - - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .plugin { it.defaultArbitraryValidator(JavaxArbitraryValidator()) } - .pushCustomizeValidOnly( - { it.annotations.any { annotation -> annotation.annotationClass == Size::class } }, - false - ) - .build() - - // when - val actual = sut.giveMeBuilder() - .customizeProperty(TypedExpressionGenerator.typedString("value.value")) { it.filter { str -> str.length > 1 } } - .sample() - - // then - then(actual).isNotNull - } - - @Test - fun customizerValidOnlyBuilderValidOnlyFirst() { - // given - class StringWithSizeZero( - @field:Size(min = 0, max = 0) - val value: String, - ) - - class Wrapper(@field:Valid val value: StringWithSizeZero) - - val sut = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .plugin { it.defaultArbitraryValidator(JavaxArbitraryValidator()) } - .pushCustomizeValidOnly( - { it.annotations.any { annotation -> annotation.annotationClass == Size::class } }, - true - ) - .build() - - // when - val actual = sut.giveMeBuilder() - .customizeProperty(TypedExpressionGenerator.typedString("value.value")) { it.filter { str -> str.length > 1 } } - .validOnly(false) - .sample() - - // then - then(actual).isNotNull - } -} diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/ValueClassAdapterTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/ValueClassAdapterTest.kt deleted file mode 100644 index 03f8c3cfef..0000000000 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/adapter/ValueClassAdapterTest.kt +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tests.kotlin.adapter - -import com.navercorp.fixturemonkey.FixtureMonkey -import com.navercorp.fixturemonkey.kotlin.KotlinNodeTreeAdapterPlugin -import com.navercorp.fixturemonkey.kotlin.KotlinPlugin -import com.navercorp.fixturemonkey.kotlin.giveMeKotlinBuilder -import com.navercorp.fixturemonkey.kotlin.giveMeOne -import com.navercorp.fixturemonkey.kotlin.instantiator.instantiateBy -import org.assertj.core.api.BDDAssertions.then -import org.junit.jupiter.api.Test - -class ValueClassAdapterTest { - @Test - fun foo() { - val foo: Foo = SUT.giveMeOne() - - then(foo.bar).isNotNull - } - - @Test - fun valueClassProperty() { - class ValueClassObject(val foo: Foo) - - val actual: ValueClassObject = SUT.giveMeOne() - - then(actual).isNotNull - then(actual.foo).isNotNull - } - - @Test - fun setValueClassProperty() { - class ValueClassObject(val foo: Foo) - - val settingFoo = Foo("hello") - - val actual: ValueClassObject = SUT.giveMeKotlinBuilder() - .set(ValueClassObject::foo, settingFoo) - .sample() - - then(actual.foo).isEqualTo(settingFoo) - } - - @Test - fun valueClassPropertyFixed() { - class ValueClassObject(val foo: Foo) - - val actual: ValueClassObject = SUT.giveMeKotlinBuilder() - .fixed() - .sample() - - then(actual).isNotNull - then(actual.foo).isNotNull - } - - @Test - fun privateConstructorValueClassProperty() { - class ValueClassObject(val foo: FooWithPrivateConstructor) - - val actual: ValueClassObject = SUT.giveMeOne() - - then(actual).isNotNull - then(actual.foo).isNotNull - } - - @Test - fun privateConstructorValueClassPropertyFixed() { - class ValueClassObject(val foo: FooWithPrivateConstructor) - - val actual: ValueClassObject = SUT.giveMeKotlinBuilder() - .fixed() - .sample() - - then(actual).isNotNull - then(actual.foo).isNotNull - } - - @Test - fun factoryParameterValueClass() { - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { factory("factory") } - .sample() - - then(actual).isNotNull - } - - @Test - fun factoryParameterWithTypeValueClass() { - val actual = SUT.giveMeKotlinBuilder() - .instantiateBy { - factory("factory") { - parameter("id") - } - } - .sample() - - then(actual).isNotNull - } - - @JvmInline - value class Foo( - val bar: String, - ) - - @JvmInline - value class FooWithPrivateConstructor private constructor( - val bar: String - ) - - interface Interface { - val foo: Foo - } - - class ConcreteClass private constructor(override val foo: Foo) : Interface { - companion object { - fun factory(id: Foo): ConcreteClass = ConcreteClass(id) - } - } - - companion object { - private val SUT = FixtureMonkey.builder() - .plugin(KotlinPlugin()) - .plugin(KotlinNodeTreeAdapterPlugin()) - .build() - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/ArbitraryBuilders.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/ArbitraryBuilders.java index 9669c218f7..356135c618 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/ArbitraryBuilders.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/ArbitraryBuilders.java @@ -23,9 +23,13 @@ import java.util.function.BiFunction; import java.util.function.Function; +import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; + import net.jqwik.api.Combinators.F3; import net.jqwik.api.Combinators.F4; +@API(since = "1.1.20", status = Status.MAINTAINED) public final class ArbitraryBuilders { public static ArbitraryBuilder zip( ArbitraryBuilder a1, diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/Constants.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/Constants.java index eff38954e3..ed6dc04302 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/Constants.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/Constants.java @@ -18,6 +18,10 @@ package com.navercorp.fixturemonkey; + +import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; +@API(since = "1.1.20", status = Status.MAINTAINED) public final class Constants { public static final int DEFAULT_ELEMENT_MIN_SIZE = 0; public static final int DEFAULT_ELEMENT_MAX_SIZE = 3; diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/FixtureMonkey.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/FixtureMonkey.java index 39ac21babd..c9ae367d89 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/FixtureMonkey.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/FixtureMonkey.java @@ -34,8 +34,6 @@ import net.jqwik.api.Arbitrary; -import com.navercorp.fixturemonkey.adapter.NodeTreeAdapter; -import com.navercorp.fixturemonkey.adapter.tracing.AdapterTracer; import com.navercorp.fixturemonkey.api.ObjectBuilder; import com.navercorp.fixturemonkey.api.context.MonkeyContext; import com.navercorp.fixturemonkey.api.matcher.NamedMatcher; @@ -47,16 +45,19 @@ import com.navercorp.fixturemonkey.api.property.TypeParameterProperty; import com.navercorp.fixturemonkey.api.type.LazyAnnotatedType; import com.navercorp.fixturemonkey.api.type.TypeReference; +import com.navercorp.fixturemonkey.api.type.Types; import com.navercorp.fixturemonkey.builder.ArbitraryBuilderContext; import com.navercorp.fixturemonkey.builder.ArbitraryBuilderContextProvider; import com.navercorp.fixturemonkey.builder.DefaultArbitraryBuilder; import com.navercorp.fixturemonkey.builder.JavaTypeDefaultTypeArbitraryBuilder; -import com.navercorp.fixturemonkey.customizer.ArbitraryManipulator; import com.navercorp.fixturemonkey.customizer.MonkeyManipulatorFactory; +import com.navercorp.fixturemonkey.customizer.PathDirective; import com.navercorp.fixturemonkey.experimental.ExperimentalArbitraryBuilder; -import com.navercorp.fixturemonkey.expression.MonkeyExpressionFactory; +import com.navercorp.fixturemonkey.planner.AssemblyPlanner; import com.navercorp.fixturemonkey.resolver.ArbitraryResolver; import com.navercorp.fixturemonkey.resolver.ManipulatorOptimizer; +import com.navercorp.fixturemonkey.tracing.AssemblyTracer; +import com.navercorp.objectfarm.api.expression.PathExpression; @API(since = "0.4.0", status = Status.MAINTAINED) public final class FixtureMonkey { @@ -65,11 +66,10 @@ public final class FixtureMonkey { private final ManipulatorOptimizer manipulatorOptimizer; private final MonkeyContext monkeyContext; private final MonkeyManipulatorFactory monkeyManipulatorFactory; - private final MonkeyExpressionFactory monkeyExpressionFactory; - private final @Nullable NodeTreeAdapter nodeTreeAdapter; + private final AssemblyPlanner assemblyPlanner; - private final AdapterTracer adapterTracer; + private final AssemblyTracer tracer; private final Map, Set> inferredPropertiesCache = new ConcurrentHashMap<>(); public FixtureMonkey( @@ -77,7 +77,6 @@ public FixtureMonkey( ManipulatorOptimizer manipulatorOptimizer, List>>> registeredBuilders, MonkeyManipulatorFactory monkeyManipulatorFactory, - MonkeyExpressionFactory monkeyExpressionFactory, Map>>> namedMatchers ) { this( @@ -85,10 +84,9 @@ public FixtureMonkey( manipulatorOptimizer, registeredBuilders, monkeyManipulatorFactory, - monkeyExpressionFactory, namedMatchers, null, - AdapterTracer.noOp() + AssemblyTracer.noOp() ); } @@ -97,19 +95,17 @@ public FixtureMonkey( ManipulatorOptimizer manipulatorOptimizer, List>>> registeredBuilders, MonkeyManipulatorFactory monkeyManipulatorFactory, - MonkeyExpressionFactory monkeyExpressionFactory, Map>>> namedMatchers, - @Nullable NodeTreeAdapter nodeTreeAdapter + @Nullable AssemblyPlanner assemblyPlanner ) { this( fixtureMonkeyOptions, manipulatorOptimizer, registeredBuilders, monkeyManipulatorFactory, - monkeyExpressionFactory, namedMatchers, - nodeTreeAdapter, - AdapterTracer.noOp() + assemblyPlanner, + AssemblyTracer.noOp() ); } @@ -118,18 +114,18 @@ public FixtureMonkey( ManipulatorOptimizer manipulatorOptimizer, List>>> registeredBuilders, MonkeyManipulatorFactory monkeyManipulatorFactory, - MonkeyExpressionFactory monkeyExpressionFactory, Map>>> namedMatchers, - @Nullable NodeTreeAdapter nodeTreeAdapter, - AdapterTracer adapterTracer + @Nullable AssemblyPlanner assemblyPlanner, + AssemblyTracer tracer ) { this.fixtureMonkeyOptions = fixtureMonkeyOptions; this.manipulatorOptimizer = manipulatorOptimizer; this.monkeyContext = MonkeyContext.builder(fixtureMonkeyOptions).build(); this.monkeyManipulatorFactory = monkeyManipulatorFactory; - this.monkeyExpressionFactory = monkeyExpressionFactory; - this.nodeTreeAdapter = nodeTreeAdapter; - this.adapterTracer = adapterTracer; + this.assemblyPlanner = assemblyPlanner != null + ? assemblyPlanner + : new AssemblyPlanner(System.nanoTime()); + this.tracer = tracer; initializeRegisteredArbitraryBuilders(registeredBuilders); initializeNamedArbitraryBuilderMap(namedMatchers); } @@ -149,7 +145,9 @@ public ArbitraryBuilder giveMeBuilder(Class type) { } public ArbitraryBuilder giveMeBuilder(TypeReference type) { - TreeRootProperty rootProperty = new RootProperty(new TypeParameterProperty(type.getAnnotatedType())); + TreeRootProperty rootProperty = new RootProperty( + new TypeParameterProperty(type.getJvmType()) + ); List> standByContexts = monkeyContext .getRegisteredArbitraryBuilders() @@ -169,15 +167,12 @@ public ArbitraryBuilder giveMeBuilder(TypeReference type) { return new DefaultArbitraryBuilder<>( rootProperty, new ArbitraryResolver( - manipulatorOptimizer, - monkeyManipulatorFactory, monkeyContext, - nodeTreeAdapter, - adapterTracer, + assemblyPlanner, + tracer, inferredPropertiesCache ), monkeyManipulatorFactory, - monkeyExpressionFactory, newActiveBuilderContext, standByContexts, monkeyContext, @@ -188,24 +183,23 @@ public ArbitraryBuilder giveMeBuilder(TypeReference type) { public ArbitraryBuilder giveMeBuilder(T value) { ArbitraryBuilderContext newActiveBuilderContext = ArbitraryBuilderContext.newBuilderContext(monkeyContext); - ArbitraryManipulator arbitraryManipulator = monkeyManipulatorFactory.newArbitraryManipulator( - monkeyExpressionFactory.from("$").toNodeResolver(), + PathDirective directive = monkeyManipulatorFactory.newDirective( + PathExpression.root(), value ); - newActiveBuilderContext.addManipulator(arbitraryManipulator); + newActiveBuilderContext.addDirective(directive); return new DefaultArbitraryBuilder<>( - new RootProperty(new TypeParameterProperty(new LazyAnnotatedType<>(() -> value))), + new RootProperty(new TypeParameterProperty( + Types.toJvmType(new LazyAnnotatedType<>(() -> value), Collections.emptyList()) + )), new ArbitraryResolver( - manipulatorOptimizer, - monkeyManipulatorFactory, monkeyContext, - nodeTreeAdapter, - adapterTracer, + assemblyPlanner, + tracer, inferredPropertiesCache ), monkeyManipulatorFactory, - monkeyExpressionFactory, newActiveBuilderContext, Collections.emptyList(), monkeyContext, diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/FixtureMonkeyBuilder.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/FixtureMonkeyBuilder.java index dea306cba9..5be0deeb5d 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/FixtureMonkeyBuilder.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/FixtureMonkeyBuilder.java @@ -31,9 +31,8 @@ import org.apiguardian.api.API; import org.apiguardian.api.API.Status; +import org.jspecify.annotations.Nullable; -import com.navercorp.fixturemonkey.adapter.NodeTreeAdapter; -import com.navercorp.fixturemonkey.adapter.tracing.AdapterTracer; import com.navercorp.fixturemonkey.api.constraint.JavaConstraintGenerator; import com.navercorp.fixturemonkey.api.container.DecomposedContainerValueFactory; import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfoGenerator; @@ -63,12 +62,12 @@ import com.navercorp.fixturemonkey.buildergroup.ArbitraryBuilderGroup; import com.navercorp.fixturemonkey.customizer.MonkeyManipulatorFactory; import com.navercorp.fixturemonkey.experimental.ExperimentalFixtureMonkeyOptions; -import com.navercorp.fixturemonkey.expression.ArbitraryExpressionFactory; -import com.navercorp.fixturemonkey.expression.MonkeyExpressionFactory; -import com.navercorp.fixturemonkey.expression.StrictModeMonkeyExpressionFactory; +import com.navercorp.fixturemonkey.planner.AssemblyPlanner; +import com.navercorp.fixturemonkey.plugin.JvmTypeSystemPlugin; import com.navercorp.fixturemonkey.resolver.ManipulatorOptimizer; import com.navercorp.fixturemonkey.resolver.NoneManipulatorOptimizer; import com.navercorp.fixturemonkey.seed.SeedFileLoader; +import com.navercorp.fixturemonkey.tracing.AssemblyTracer; @SuppressWarnings("unused") @API(since = "0.4.0", status = Status.MAINTAINED) @@ -84,9 +83,10 @@ public final class FixtureMonkeyBuilder { private final Map>>> registeredPriorityMatchersByName = new HashMap<>(); private ManipulatorOptimizer manipulatorOptimizer = new NoneManipulatorOptimizer(); - private MonkeyExpressionFactory monkeyExpressionFactory = new ArbitraryExpressionFactory(); private boolean experimentalFileSeedEnabled = false; private long seed = System.nanoTime(); + private @Nullable AssemblyPlanner assemblyPlanner; + private @Nullable AssemblyTracer tracer; public FixtureMonkeyBuilder pushPropertyGenerator(MatcherOperator propertyGenerator) { fixtureMonkeyOptionsBuilder.insertFirstPropertyGenerator(propertyGenerator); @@ -298,7 +298,7 @@ public FixtureMonkeyBuilder addExceptGenerateClasses(Class... types) { public FixtureMonkeyBuilder addExceptGeneratePackage(String exceptGeneratePackage) { return pushExceptGenerateType( property -> { - Package pkg = Types.primitiveToWrapper(Types.getActualType(property.getType())).getPackage(); + Package pkg = Types.primitiveToWrapper(property.getJvmType().getRawType()).getPackage(); return pkg != null && pkg.getName().startsWith(exceptGeneratePackage); } ); @@ -439,6 +439,9 @@ public FixtureMonkeyBuilder registerGroup(ArbitraryBuilderGroup... arbitraryBuil public FixtureMonkeyBuilder plugin(Plugin plugin) { fixtureMonkeyOptionsBuilder.plugin(plugin); + if (plugin instanceof JvmTypeSystemPlugin) { + ((JvmTypeSystemPlugin)plugin).configure(planner -> this.assemblyPlanner = planner); + } return this; } @@ -580,6 +583,18 @@ public FixtureMonkeyBuilder seed(long seed) { return this; } + /** + * Sets a tracer that captures adapter resolution events for debugging. + * Replace by passing {@link AssemblyTracer#noOp()} (the default) when not debugging. + * + * @param tracer tracer to use + * @return this builder + */ + public FixtureMonkeyBuilder tracer(AssemblyTracer tracer) { + this.tracer = tracer; + return this; + } + public FixtureMonkey build() { if (defaultPropertyNameResolver != null) { fixtureMonkeyOptionsBuilder.defaultPropertyNameResolver(defaultPropertyNameResolver); @@ -593,50 +608,27 @@ public FixtureMonkey build() { MonkeyManipulatorFactory monkeyManipulatorFactory = new MonkeyManipulatorFactory( new AtomicInteger(), fixtureMonkeyOptions.getDecomposedContainerValueFactory(), - fixtureMonkeyOptions.getContainerPropertyGenerators() + fixtureMonkeyOptions.getContainerPropertyGenerators(), + expressionStrictMode ); - MonkeyExpressionFactory monkeyExpressionFactory = newExpressionFactory(fixtureMonkeyOptions); + Randoms.applyBuilderSeed(seed); - Randoms.setSeed(seed); + AssemblyTracer resolvedTracer = this.tracer != null ? this.tracer : AssemblyTracer.noOp(); - Object rawTracer = fixtureMonkeyOptions.getAdapterTracer(); - AdapterTracer adapterTracer = rawTracer instanceof AdapterTracer - ? (AdapterTracer)rawTracer - : AdapterTracer.noOp(); + AssemblyPlanner resolvedPlanner = this.assemblyPlanner != null + ? this.assemblyPlanner + : new AssemblyPlanner(seed); return new FixtureMonkey( fixtureMonkeyOptions, manipulatorOptimizer, registeredArbitraryBuildersWithPriority, monkeyManipulatorFactory, - monkeyExpressionFactory, registeredPriorityMatchersByName, - (NodeTreeAdapter)fixtureMonkeyOptions.getNodeTreeAdapter(), - adapterTracer + resolvedPlanner, + resolvedTracer ); } - private MonkeyExpressionFactory newExpressionFactory(FixtureMonkeyOptions fixtureMonkeyOptions) { - if (!expressionStrictMode) { - return this.monkeyExpressionFactory; - } - - PropertyNameResolver compositePropertyNameResolver = newCompositePropertyNameResolver(fixtureMonkeyOptions); - - return new StrictModeMonkeyExpressionFactory( - new ArbitraryExpressionFactory(), - compositePropertyNameResolver - ); - } - - private PropertyNameResolver newCompositePropertyNameResolver( - FixtureMonkeyOptions fixtureMonkeyOptions - ) { - return property -> fixtureMonkeyOptions.getPropertyNameResolvers().stream() - .filter(it -> it.getMatcher().match(property)) - .findFirst() - .map(it -> it.getOperator().resolve(property)) - .orElseGet(() -> fixtureMonkeyOptions.getDefaultPropertyNameResolver().resolve(property)); - } } diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/JavaTypeArbitraryBuilder.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/JavaTypeArbitraryBuilder.java index bf2fbaea55..efd09b1d6d 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/JavaTypeArbitraryBuilder.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/JavaTypeArbitraryBuilder.java @@ -43,7 +43,7 @@ import com.navercorp.fixturemonkey.api.type.TypeReference; import com.navercorp.fixturemonkey.customizer.InnerSpec; -@API(since = "1.1.0", status = Status.EXPERIMENTAL) +@API(since = "1.1.0", status = Status.MAINTAINED) public interface JavaTypeArbitraryBuilder extends ArbitraryBuilder { @Override JavaTypeArbitraryBuilder set(String expression, @Nullable Object value); diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/DefaultNodeTreeAdapter.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/DefaultNodeTreeAdapter.java deleted file mode 100644 index e312976fbd..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/DefaultNodeTreeAdapter.java +++ /dev/null @@ -1,1063 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.adapter; - -import java.lang.reflect.Modifier; -import java.util.AbstractMap; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.OptionalInt; -import java.util.Random; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.UnaryOperator; -import java.util.stream.Collectors; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; -import org.jspecify.annotations.Nullable; - -import com.navercorp.fixturemonkey.adapter.analysis.AdaptationResult; -import com.navercorp.fixturemonkey.adapter.analysis.AnalysisResult; -import com.navercorp.fixturemonkey.adapter.analysis.ManipulatorAnalyzer; -import com.navercorp.fixturemonkey.adapter.converter.ContainerInfoResolverConverter; -import com.navercorp.fixturemonkey.adapter.converter.PredicatePathConverter; -import com.navercorp.fixturemonkey.adapter.nodecandidate.ContainerPropertyGeneratorNodeGenerator; -import com.navercorp.fixturemonkey.adapter.nodecandidate.InterfaceMethodNodeCandidateGenerator; -import com.navercorp.fixturemonkey.adapter.nodecandidate.NameResolvingNodeCandidateGenerator; -import com.navercorp.fixturemonkey.adapter.nodecandidate.PropertyGeneratorNodeCandidateGenerator; -import com.navercorp.fixturemonkey.adapter.projection.ValueProjection; -import com.navercorp.fixturemonkey.adapter.property.JvmNodePropertyFactory; -import com.navercorp.fixturemonkey.adapter.tracing.TraceContext; -import com.navercorp.fixturemonkey.adapter.tracing.TraceContextResolutionListener; -import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfo; -import com.navercorp.fixturemonkey.api.generator.ArbitraryGenerator; -import com.navercorp.fixturemonkey.api.generator.ContainerPropertyGenerator; -import com.navercorp.fixturemonkey.api.introspector.ArbitraryIntrospector; -import com.navercorp.fixturemonkey.api.matcher.MatcherOperator; -import com.navercorp.fixturemonkey.api.option.FixtureMonkeyOptions; -import com.navercorp.fixturemonkey.api.property.CandidateConcretePropertyResolver; -import com.navercorp.fixturemonkey.api.property.FieldProperty; -import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.api.property.PropertyGenerator; -import com.navercorp.fixturemonkey.api.property.PropertyNameResolver; -import com.navercorp.fixturemonkey.api.type.TypeCache; -import com.navercorp.fixturemonkey.api.type.Types; -import com.navercorp.fixturemonkey.customizer.ArbitraryManipulator; -import com.navercorp.fixturemonkey.customizer.ContainerInfoManipulator; -import com.navercorp.fixturemonkey.customizer.ManipulatorSet; -import com.navercorp.objectfarm.api.expression.PathExpression; -import com.navercorp.objectfarm.api.input.ContainerDetector; -import com.navercorp.objectfarm.api.node.AbstractTypeNodePromoter; -import com.navercorp.objectfarm.api.node.ContainerSizeResolver; -import com.navercorp.objectfarm.api.node.GenericTypeResolver; -import com.navercorp.objectfarm.api.node.InterfaceResolver; -import com.navercorp.objectfarm.api.node.JavaDefaultNodePromoter; -import com.navercorp.objectfarm.api.node.JavaMapEntryNodePromoter; -import com.navercorp.objectfarm.api.node.JavaMapNodePromoter; -import com.navercorp.objectfarm.api.node.JavaNodeContext; -import com.navercorp.objectfarm.api.node.JavaObjectNodePromoter; -import com.navercorp.objectfarm.api.node.JvmNodeContext; -import com.navercorp.objectfarm.api.node.JvmNodePromoter; -import com.navercorp.objectfarm.api.node.LeafTypeResolver; -import com.navercorp.objectfarm.api.node.SeedState; -import com.navercorp.objectfarm.api.nodecandidate.JavaFieldNodeCandidateGenerator; -import com.navercorp.objectfarm.api.nodecandidate.JvmNodeCandidateGenerator; -import com.navercorp.objectfarm.api.tree.ExpansionContext; -import com.navercorp.objectfarm.api.tree.JvmNodeCandidateTree; -import com.navercorp.objectfarm.api.tree.JvmNodeCandidateTreeContext; -import com.navercorp.objectfarm.api.tree.JvmNodeSubtreeContext; -import com.navercorp.objectfarm.api.tree.JvmNodeTree; -import com.navercorp.objectfarm.api.tree.JvmNodeTreeTransformer; -import com.navercorp.objectfarm.api.tree.PathInterfaceResolver; -import com.navercorp.objectfarm.api.tree.PathResolver; -import com.navercorp.objectfarm.api.tree.PathResolverContext; -import com.navercorp.objectfarm.api.tree.ResolutionListener; -import com.navercorp.objectfarm.api.type.JavaType; -import com.navercorp.objectfarm.api.type.JvmType; -import com.navercorp.objectfarm.api.type.WildcardRawType; - -/** - * Default implementation of NodeTreeAdapter. - *

- * This adapter: - *

    - *
  1. Analyzes ArbitraryManipulator to extract interface/generic type resolution info
  2. - *
  3. Converts ContainerInfoManipulator to ContainerSizeResolver
  4. - *
  5. Builds a JvmNodeCandidateTree from the root type
  6. - *
  7. Transforms the candidate tree to JvmNodeTree with resolved types and container sizes
  8. - *
- *

- * The transformation respects the manipulatingSequence order of ContainerInfoManipulators. - */ -@API(since = "1.1.17", status = Status.EXPERIMENTAL) -public final class DefaultNodeTreeAdapter implements NodeTreeAdapter { - private static final ContainerDetector CONTAINER_DETECTOR = ContainerDetector.standard(); - - private final SeedState seedState; - private final JvmNodeCandidateTreeContext treeContext; - - // Performance optimization caches - keyed by (type, options identity) - // NOTE: AdaptationResult/JvmNodeTree are NOT cached because container sizes must vary on each call. - private final Map nodeContextCache; - private final Map candidateTreeCache; - - // Cache for concrete type JvmNodeCandidateTrees (used when generating with interface implementations) - private final Map concreteTypeCandidateTreeCache; - - // Cache for promoted POJO subtree snapshots — reuses immutable node structures across transform() calls - private final JvmNodeSubtreeContext subtreeContext = - new JvmNodeSubtreeContext(); - // Cross-call cache for assembly node metadata (Property, resolvers, isContainerType) - // Type-erased here since CachedNodeMetadata is package-private in projection package - private final ConcurrentHashMap nodeMetadataCache = new ConcurrentHashMap<>(); - - // Additional node promoters (e.g., KotlinNodePromoter for Kotlin support) - private final List additionalPromoters; - - // Additional leaf type resolvers (e.g., KotlinLeafTypeResolver for Kotlin support) - private final List additionalLeafTypeResolvers; - - // Wraps a JvmNodeCandidateGenerator with platform-specific isSupported checks - // (e.g., KotlinNodeCandidateGenerator that only supports Kotlin types) - private final @Nullable UnaryOperator candidateGeneratorWrapper; - - private final ContainerSizeResolverFactory containerSizeResolverFactory; - private final ContainerValuePruner containerValuePruner; - - // Thread-local storage for the current PathResolverContext during adaptation. - // Set in buildAdaptationResult(), read in createAnonymousNodeTree() during assembly. - @SuppressWarnings({"type.argument", "assignment"}) - private final ThreadLocal currentResolverContext = new ThreadLocal<>(); - - /** - * Creates a new adapter with the specified seed. - * - * @param seed the seed for random generation - */ - public DefaultNodeTreeAdapter(long seed) { - this(seed, new JvmNodeCandidateTreeContext(), Collections.emptyList(), Collections.emptyList(), null); - } - - /** - * Creates a new adapter with all configurable components. - * - * @param seed the seed for random generation - * @param treeContext the tree context for caching subtree information - * @param additionalPromoters additional node promoters (e.g., KotlinNodePromoter) - * @param additionalLeafTypeResolvers additional leaf type resolvers (e.g., KotlinLeafTypeResolver) - * @param candidateGeneratorWrapper wraps the candidate generator with platform-specific - * isSupported checks (e.g., KotlinNodeCandidateGenerator) - */ - public DefaultNodeTreeAdapter( - long seed, - JvmNodeCandidateTreeContext treeContext, - List additionalPromoters, - List additionalLeafTypeResolvers, - @Nullable UnaryOperator candidateGeneratorWrapper - ) { - this.seedState = new SeedState(seed); - this.treeContext = treeContext; - this.nodeContextCache = new ConcurrentHashMap<>(); - this.candidateTreeCache = new ConcurrentHashMap<>(); - this.concreteTypeCandidateTreeCache = new ConcurrentHashMap<>(); - this.additionalPromoters = additionalPromoters != null ? additionalPromoters : Collections.emptyList(); - this.additionalLeafTypeResolvers = - additionalLeafTypeResolvers != null ? additionalLeafTypeResolvers : Collections.emptyList(); - this.candidateGeneratorWrapper = candidateGeneratorWrapper; - this.containerSizeResolverFactory = new ContainerSizeResolverFactory(seedState); - this.containerValuePruner = new ContainerValuePruner(CONTAINER_DETECTOR); - } - - @Override - public AdaptationResult adapt(JvmType rootType, ManipulatorSet manipulatorSet) { - return adapt(rootType, manipulatorSet, null); - } - - @Override - public AdaptationResult adapt( - JvmType rootType, ManipulatorSet manipulatorSet, @Nullable FixtureMonkeyOptions options - ) { - // NOTE: AdaptationResult is NOT cached because container sizes must vary on each call. - // JvmNodeCandidateTree and JvmNodeContext are still cached for performance. - if (manipulatorSet.isEmpty()) { - return buildDefaultAdaptationResult(rootType, options, ResolutionListener.noOp(), manipulatorSet.isFixed()); - } - - return buildAdaptationResult(rootType, manipulatorSet, options, ResolutionListener.noOp()); - } - - @Override - public AdaptationResult adapt( - JvmType rootType, - ManipulatorSet manipulatorSet, - @Nullable FixtureMonkeyOptions options, - @Nullable TraceContext traceContext - ) { - // When tracing is enabled, skip caching to ensure all resolution events are captured - ResolutionListener resolutionListener = TraceContextResolutionListener.of(traceContext); - - if (manipulatorSet.isEmpty()) { - return buildDefaultAdaptationResult(rootType, options, resolutionListener, manipulatorSet.isFixed()); - } - - return buildAdaptationResult(rootType, manipulatorSet, options, resolutionListener); - } - - private AdaptationResult buildDefaultAdaptationResult( - JvmType rootType, - @Nullable FixtureMonkeyOptions options, - ResolutionListener resolutionListener, - boolean isFixed - ) { - JvmType resolvedRootType = resolveAbstractType(rootType, options); - - long treeBuildStart = System.nanoTime(); - - JvmNodeContext context = getOrBuildNodeContext( - resolvedRootType, - options, - Collections.emptyMap(), - Collections.emptyMap() - ); - JvmNodeCandidateTree candidateTree = getOrBuildCandidateTree(resolvedRootType, context, options, false); - - PathResolverContext.Builder resolverContextBuilder = PathResolverContext.builder().resolutionListener( - resolutionListener - ); - if (isFixed) { - resolverContextBuilder.defaultContainerSizeResolver( - containerSizeResolverFactory.createFixedContainerSizeResolver(options) - ); - } - PathResolverContext resolverContext = resolverContextBuilder.build(); - - JvmNodeTreeTransformer transformer = new JvmNodeTreeTransformer( - context, - treeContext, - resolverContext, - null, // No expansion context for empty manipulators - subtreeContext - ); - - JvmNodeTree nodeTree = transformer.transform(candidateTree); - long treeBuildTimeNanos = System.nanoTime() - treeBuildStart; - - AnalysisResult analysisResult = ManipulatorAnalyzer.emptyResult(); - ValueProjection valueProjection = ValueProjection.of(nodeTree, Collections.emptyMap()); - - return new AdaptationResult(nodeTree, valueProjection, analysisResult, 0, treeBuildTimeNanos); - } - - private AdaptationResult buildAdaptationResult( - JvmType rootType, - ManipulatorSet manipulatorSet, - @Nullable FixtureMonkeyOptions options, - ResolutionListener resolutionListener - ) { - List arbitraryManipulators = manipulatorSet.getArbitraryManipulators(); - - ManipulatorAnalyzer.DecomposeNameResolver nameResolver = - options != null - ? property -> options.getPropertyNameResolver(property).resolve(property) - : Property::getName; - long analyzeStart = System.nanoTime(); - AnalysisResult analysisResult = ManipulatorAnalyzer.analyze( - arbitraryManipulators, - nameResolver - ); - long analyzeTimeNanos = System.nanoTime() - analyzeStart; - - // Resolve interface/abstract class to concrete implementation - // For non-container abstract types, check if there's a "$" path InterfaceResolver - // from explicit set(concreteValue) - it takes precedence over default resolution - JvmType resolvedRootType = resolveRootTypeWithAnalysisResult(rootType, analysisResult, options); - - List containerManipulators = manipulatorSet.getContainerInfoManipulators(); - - Map containerPathCache = new IdentityHashMap<>(); - for (ContainerInfoManipulator m : containerManipulators) { - containerPathCache.put(m, PredicatePathConverter.convert(m.getNextNodePredicates())); - } - - List> containerResolvers = ContainerInfoResolverConverter.convert( - containerManipulators, - containerPathCache - ); - - Map globalValueSequences = new HashMap<>(analysisResult.getValueOrderByPath()); - - Map prunedValuesByPath = - containerValuePruner.pruneValuesExceedingContainerSize( - analysisResult.getValuesByPath(), - containerManipulators, - globalValueSequences, - containerPathCache - ); - - // Remove child values under just paths — Values.just() makes the value immutable, - // so child path values (e.g., $.string) should not override the just value (e.g., $). - ContainerValuePruner.pruneChildrenOfJustPaths(prunedValuesByPath, analysisResult.getJustPaths()); - - Map> mergedTypedContainerSizes = - inferAndMergeTypedContainerSizes( - manipulatorSet.getTypedValues(), - manipulatorSet.getTypedContainerSizes() - ); - - PathResolverContext resolverContext = createResolverContext( - containerResolvers, - analysisResult, - containerManipulators, - globalValueSequences, - mergedTypedContainerSizes, - resolutionListener, - manipulatorSet.isFixed(), - options, - containerPathCache - ); - - // Use fresh treeContext when propertyConfigurers or introspectorsByType are present - // to avoid caching issues (cached subtrees don't respect custom property generators) - boolean hasCustomConfigurers = - !manipulatorSet.getPropertyConfigurers().isEmpty() - || !manipulatorSet.getArbitraryIntrospectorsByType().isEmpty(); - - JvmNodeContext context = getOrBuildNodeContext( - resolvedRootType, - options, - manipulatorSet.getPropertyConfigurers(), - manipulatorSet.getArbitraryIntrospectorsByType() - ); - - ExpansionContext expansionContext = null; - Set userPaths = analysisResult.getValuesByPath().keySet(); - if (!userPaths.isEmpty()) { - expansionContext = new ExpansionContext(userPaths); - } - - JvmNodeCandidateTreeContext effectiveTreeContext = hasCustomConfigurers - ? new JvmNodeCandidateTreeContext() - : treeContext; - - long treeBuildStart = System.nanoTime(); - JvmNodeCandidateTree candidateTree = getOrBuildCandidateTree( - resolvedRootType, - context, - options, - hasCustomConfigurers - ); - - JvmNodeSubtreeContext effectiveSubtreeContext = hasCustomConfigurers - ? null - : subtreeContext; - - JvmNodeTreeTransformer transformer = new JvmNodeTreeTransformer( - context, - effectiveTreeContext, - resolverContext, - expansionContext, - effectiveSubtreeContext - ); - - JvmNodeTree nodeTree = transformer.transform(candidateTree); - long treeBuildTimeNanos = System.nanoTime() - treeBuildStart; - - ValueProjection valueProjection = ValueProjection.fromPathExpressionMap(nodeTree, prunedValuesByPath); - - currentResolverContext.set(resolverContext); - - return new AdaptationResult(nodeTree, valueProjection, analysisResult, analyzeTimeNanos, treeBuildTimeNanos); - } - - private JvmType resolveAbstractType(JvmType type, @Nullable FixtureMonkeyOptions options) { - if (options == null) { - return type; - } - - JvmType currentType = type; - Set> visited = new HashSet<>(); - int maxDepth = options.getMaxRecursionDepth(); - - for (int depth = 0; depth < maxDepth; depth++) { - Class rawType = currentType.getRawType(); - - if (!visited.add(rawType)) { - return currentType; - } - - if (!Modifier.isInterface(rawType.getModifiers()) && !Modifier.isAbstract(rawType.getModifiers())) { - return currentType; - } - - Property property = JvmNodePropertyFactory.fromType(currentType); - @SuppressWarnings("deprecation") - CandidateConcretePropertyResolver resolver = options.getCandidateConcretePropertyResolver(property); - - if (resolver == null) { - return currentType; - } - - List candidates = resolver.resolve(property); - if (candidates == null || candidates.isEmpty()) { - return currentType; - } - - Random random = seedState.snapshot().randomFor(currentType.hashCode()); - Property selected = candidates.get(random.nextInt(candidates.size())); - - currentType = Types.toJvmType(selected.getAnnotatedType(), selected.getAnnotations()); - } - - return currentType; - } - - /** - * Resolves the root type using InterfaceResolvers from analysis result. - * If there's a "$" path InterfaceResolver (from explicit set(concreteValue)), - * it takes precedence over the default resolution. - *

- * This only applies to non-container abstract/interface types. - * Container types (List, Set, Map) should use the default resolution. - */ - private JvmType resolveRootTypeWithAnalysisResult( - JvmType rootType, - AnalysisResult analysisResult, - @Nullable FixtureMonkeyOptions options - ) { - Class rawType = rootType.getRawType(); - - if (!Modifier.isInterface(rawType.getModifiers()) && !Modifier.isAbstract(rawType.getModifiers())) { - return rootType; - } - - if (Collection.class.isAssignableFrom(rawType) || Map.class.isAssignableFrom(rawType)) { - return resolveAbstractType(rootType, options); - } - - // Check if there's a "$" path InterfaceResolver from explicit set(concreteValue). - // Iterate from the end so the last set() call wins. - PathExpression rootPath = PathExpression.of("$"); - List> resolvers = analysisResult.getInterfaceResolvers(); - for (int i = resolvers.size() - 1; i >= 0; i--) { - PathResolver resolver = resolvers.get(i); - if (resolver.matches(rootPath)) { - JvmType resolved = resolver.getCustomizer().resolve(rootType); - if (resolved != null) { - return resolved; - } - } - } - - return resolveAbstractType(rootType, options); - } - - private PathResolverContext createResolverContext( - List> containerResolvers, - AnalysisResult analysisResult, - List containerManipulators, - Map globalValueSequences, - Map> typedContainerSizes, - ResolutionListener resolutionListener, - boolean isFixed, - @Nullable FixtureMonkeyOptions options, - Map containerPathCache - ) { - PathResolverContext.Builder builder = PathResolverContext.builder().resolutionListener(resolutionListener); - - Map sizeSequenceByPath = containerSizeResolverFactory.collectSizeSequences( - containerManipulators, - containerPathCache - ); - - List> wildcardSizeSequences = new ArrayList<>(); - for (Map.Entry entry : sizeSequenceByPath.entrySet()) { - if (entry.getKey().hasWildcard()) { - wildcardSizeSequences.add(new AbstractMap.SimpleEntry<>(entry.getKey(), entry.getValue())); - } - } - - for (PathResolver resolver : containerResolvers) { - builder.addContainerSizeResolver(resolver); - } - - containerSizeResolverFactory.addLazyContainerSizeResolvers( - builder, - analysisResult, - sizeSequenceByPath, - wildcardSizeSequences - ); - containerSizeResolverFactory.addManipulatorContainerSizeResolvers( - builder, - containerManipulators, - globalValueSequences, - sizeSequenceByPath, - containerPathCache - ); - - Map valueOrderByPath = analysisResult.getValueOrderByPath(); - for (PathResolver resolver : analysisResult.getInterfaceResolvers()) { - // Skip interface resolvers for container paths where a later size() constraint exists. - // When set("values", singletonList(X)) creates a List → SingletonList resolver, - // but size("values", 1, 10) comes later, the concrete type should not be locked. - if (resolver instanceof PathInterfaceResolver) { - PathExpression resolverPath = ((PathInterfaceResolver)resolver).getPattern(); - Integer sizeSeq = sizeSequenceByPath.get(resolverPath); - Integer valueSeq = valueOrderByPath.get(resolverPath); - if (sizeSeq != null && valueSeq != null && sizeSeq > valueSeq) { - continue; - } - } - builder.addInterfaceResolver(resolver); - } - - for (PathResolver resolver : analysisResult.getGenericTypeResolvers()) { - builder.addGenericTypeResolver(resolver); - } - - containerSizeResolverFactory.addTypedContainerSizeResolvers(builder, typedContainerSizes); - - if (isFixed) { - builder.defaultContainerSizeResolver( - containerSizeResolverFactory.createFixedContainerSizeResolver(options) - ); - } - - return builder.build(); - } - - private Map> inferAndMergeTypedContainerSizes( - Map> typedValues, - Map> explicitTypedContainerSizes - ) { - Map> merged = new HashMap<>(explicitTypedContainerSizes); - - for (Map.Entry> typeEntry : typedValues.entrySet()) { - JvmType ownerType = typeEntry.getKey(); - for (Map.Entry fieldEntry : typeEntry.getValue().entrySet()) { - String fieldName = fieldEntry.getKey(); - Object value = fieldEntry.getValue(); - - OptionalInt containerSize = CONTAINER_DETECTOR.getContainerSize(value); - if (!containerSize.isPresent()) { - continue; - } - - int size = containerSize.getAsInt(); - merged.computeIfAbsent(ownerType, k -> new HashMap<>()) - .putIfAbsent(fieldName, new ArbitraryContainerInfo(size, size)); - } - } - return merged; - } - - private JvmNodeCandidateTree getOrBuildCandidateTree( - JvmType resolvedRootType, - JvmNodeContext context, - @Nullable FixtureMonkeyOptions options, - boolean hasCustomConfigurers - ) { - if (hasCustomConfigurers) { - return buildCandidateTree(resolvedRootType, context, new JvmNodeCandidateTreeContext()); - } - - ContextCacheKey cacheKey = new ContextCacheKey(resolvedRootType, options); - return candidateTreeCache.computeIfAbsent(cacheKey, key -> - buildCandidateTree(resolvedRootType, context, treeContext) - ); - } - - private JvmNodeCandidateTree buildCandidateTree( - JvmType type, - JvmNodeContext context, - JvmNodeCandidateTreeContext candidateTreeContext - ) { - return new JvmNodeCandidateTree.Builder(type, context) - .withTreeContext(candidateTreeContext) - .withPreBuildResolvedTypes(true) - .build(); - } - - private JvmNodeContext getOrBuildNodeContext( - JvmType rootType, - @Nullable FixtureMonkeyOptions options, - Map, List> propertyConfigurers, - Map, ArbitraryIntrospector> introspectorsByType - ) { - if (!propertyConfigurers.isEmpty() || !introspectorsByType.isEmpty()) { - return buildNodeContext(rootType, options, propertyConfigurers, introspectorsByType); - } - - ContextCacheKey cacheKey = new ContextCacheKey(rootType, options); - return nodeContextCache.computeIfAbsent(cacheKey, key -> - buildNodeContext(rootType, options, propertyConfigurers, introspectorsByType) - ); - } - - private JvmNodeContext buildNodeContext( - JvmType rootType, - @Nullable FixtureMonkeyOptions options, - Map, List> propertyConfigurers, - Map, ArbitraryIntrospector> introspectorsByType - ) { - ContainerSizeResolver containerSizeResolver = containerSizeResolverFactory.createContainerSizeResolver(options); - List allPromoters = createNodePromoters(); - - JavaNodeContext.Builder builder = JavaNodeContext.builder() - .seedState(seedState) - .nodePromoters(Collections.singletonList(new JavaDefaultNodePromoter(allPromoters))) - .containerSizeResolver(containerSizeResolver); - - if (options != null) { - ArbitraryGenerator defaultGenerator = options.getDefaultArbitraryGenerator(); - Property rootProperty = JvmNodePropertyFactory.fromType(rootType); - PropertyGenerator rootPropertyGenerator = defaultGenerator.getRequiredPropertyGenerator(rootProperty); - - // Build the name resolver from options (e.g., @JsonProperty support via JacksonPropertyNameResolver). - // Always non-null: type-specific resolvers may exist even when the default is IDENTITY. - NameResolvingNodeCandidateGenerator.ChildNameResolver nameResolver = createNodeNameResolver(options); - - if (rootPropertyGenerator != null) { - // Create a per-type delegating PropertyGenerator instead of binding to the root type. - // This ensures each type gets the correct PropertyGenerator from the introspector chain - // (e.g., PriorityConstructorArbitraryIntrospector creates per-type ConstructorArbitraryIntrospectors). - PropertyGenerator fallbackPropertyGenerator = options.getDefaultPropertyGenerator(); - - PropertyGenerator basePropertyGenerator = property -> { - PropertyGenerator gen = defaultGenerator.getRequiredPropertyGenerator(property); - if (gen != null) { - List children = gen.generateChildProperties(property); - if (children != null) { - return children; - } - } - return fallbackPropertyGenerator.generateChildProperties(property); - }; - List> propertyGenerators = options.getPropertyGenerators(); - - PropertyGenerator compositeGenerator = createCompositePropertyGenerator( - basePropertyGenerator, - propertyConfigurers, - introspectorsByType, - propertyGenerators - ); - JvmNodeCandidateGenerator candidateGenerator = new PropertyGeneratorNodeCandidateGenerator( - compositeGenerator - ); - candidateGenerator = new NameResolvingNodeCandidateGenerator(candidateGenerator, nameResolver); - if (candidateGeneratorWrapper != null) { - // Wrap with platform-specific isSupported check - // (e.g., KotlinNodeCandidateGenerator that only supports Kotlin types). - // With first-match-wins in buildTree, the wrapped generator handles supported types. - builder.addCustomGenerator(candidateGeneratorWrapper.apply(candidateGenerator)); - // Also set as objectPropertyGenerator for non-Kotlin types (e.g., Java's File class) - // that need the introspector's requiredPropertyGenerator. - builder.objectPropertyGenerator(candidateGenerator); - } else { - builder.objectPropertyGenerator(candidateGenerator); - } - - // Exclude types from leaf treatment if any extra generator recognizes them. - // This allows Java standard types (e.g., java.io.File, java.sql.Timestamp) to be expanded - // when using constructor-based introspectors with a requiredPropertyGenerator. - builder.leafTypeExclusion(jvmType -> { - Class rawType = jvmType.getRawType(); - if (rawType.isPrimitive() || rawType.isArray() || rawType.isEnum()) { - return false; - } - - if (propertyConfigurers.containsKey(rawType) || introspectorsByType.containsKey(rawType)) { - return true; - } - - if (!propertyGenerators.isEmpty()) { - Property property = JvmNodePropertyFactory.fromType(jvmType); - for (MatcherOperator op : propertyGenerators) { - if (op.match(property)) { - return true; - } - } - } - - // Check if the global objectIntrospector (via basePropertyGenerator) - // produces children for this type. This handles cases like - // PriorityConstructorArbitraryIntrospector expanding java.sql.Timestamp - // via its Timestamp(long) constructor. - try { - Property property = JvmNodePropertyFactory.fromType(jvmType); - List children = basePropertyGenerator.generateChildProperties(property); - if (children != null && !children.isEmpty()) { - return true; - } - } catch (Exception e) { - // Keep as leaf if generator fails (e.g., inaccessible constructor) - } - - return false; - }); - } else { - JvmNodeCandidateGenerator candidateGenerator = new NameResolvingNodeCandidateGenerator( - new JavaFieldNodeCandidateGenerator(), - nameResolver - ); - if (candidateGeneratorWrapper != null) { - builder.addCustomGenerator(candidateGeneratorWrapper.apply(candidateGenerator)); - builder.objectPropertyGenerator(candidateGenerator); - } else { - builder.objectPropertyGenerator(candidateGenerator); - } - } - - builder.interfaceResolver(createGlobalInterfaceResolver(options)); - - builder.maxDepth(options.getMaxRecursionDepth()); - - // Convert ContainerPropertyGenerators to a single fallback JvmContainerNodeGenerator. - // This generator is added as a custom generator but only matches types - // not already handled by the default generators (Array, Collection, Map, etc.). - List> containerPropertyGenerators = - options.getContainerPropertyGenerators(); - if (!containerPropertyGenerators.isEmpty()) { - builder.addContainerNodeGenerator( - new ContainerPropertyGeneratorNodeGenerator(containerPropertyGenerators) - ); - } - - // Marker types used by dedicated introspectors in DEFAULT_ARBITRARY_INTROSPECTORS. - // In the non-adapter path, these are handled by short-circuit introspectors - // that produce values directly without child property generation. - builder.addLeafTypeResolver(jvmType -> { - Class rt = jvmType.getRawType(); - return (rt == Types.GeneratingWildcardType.class - || rt == Types.UnidentifiableType.class - || rt == WildcardRawType.class); - }); - - for (LeafTypeResolver leafTypeResolver : additionalLeafTypeResolvers) { - builder.addLeafTypeResolver(leafTypeResolver); - } - } - - return builder.build(); - } - - /** - * Creates a ChildNameResolver that resolves property names using FixtureMonkeyOptions. - *

- * To give the resolver access to field-level information (name + annotations like {@code @JsonProperty}), - * a {@link FieldProperty} is reflectively created from the parent class and candidate name. - * If the field is not found (e.g., constructor-only parameters), falls back to - * {@link JvmNodePropertyFactory#fromType(JvmType)} which provides annotations but no name. - * - * @return the child name resolver - */ - private static NameResolvingNodeCandidateGenerator.ChildNameResolver createNodeNameResolver( - FixtureMonkeyOptions options - ) { - return (parentType, childType, candidateName) -> { - Property parentProperty = JvmNodePropertyFactory.fromType(parentType); - PropertyNameResolver resolver = options.getPropertyNameResolver(parentProperty); - - Property childProperty = null; - if (candidateName != null) { - java.lang.reflect.Field field = TypeCache.getFieldsByName(parentType.getRawType()).get(candidateName); - if (field != null) { - childProperty = new FieldProperty(field); - } - } - if (childProperty == null) { - childProperty = JvmNodePropertyFactory.fromType(childType); - } - return resolver.resolve(childProperty); - }; - } - - /** - * Creates the combined list of node promoters. - * Additional promoters (e.g., KotlinNodePromoter) are checked first to allow language-specific handling. - */ - private List createNodePromoters() { - List basePromoters = Arrays.asList( - new JavaMapNodePromoter(), - new JavaMapEntryNodePromoter(), - new AbstractTypeNodePromoter(), - new JavaObjectNodePromoter() - ); - - if (additionalPromoters.isEmpty()) { - return basePromoters; - } - - List allPromoters = new ArrayList<>(additionalPromoters.size() + basePromoters.size()); - allPromoters.addAll(additionalPromoters); - allPromoters.addAll(basePromoters); - return allPromoters; - } - - /** - * Creates a composite PropertyGenerator that checks configurations in order: - * 1. propertyConfigurers (explicit property list from instantiate()) - * 2. introspectorsByType (introspector's getRequiredPropertyGenerator()) - * 3. propertyGenerators (from pushExactTypePropertyGenerator()) - * 4. baseGenerator (default behavior) - */ - private PropertyGenerator createCompositePropertyGenerator( - PropertyGenerator baseGenerator, - Map, List> propertyConfigurers, - Map, ArbitraryIntrospector> introspectorsByType, - List> propertyGenerators - ) { - if (propertyConfigurers.isEmpty() && introspectorsByType.isEmpty() && propertyGenerators.isEmpty()) { - return baseGenerator; - } - - return property -> { - Class actualType = Types.getActualType(property.getType()); - - List configuredProperties = propertyConfigurers.get(actualType); - if (configuredProperties != null) { - return configuredProperties; - } - - ArbitraryIntrospector introspector = introspectorsByType.get(actualType); - if (introspector != null) { - PropertyGenerator introspectorGenerator = introspector.getRequiredPropertyGenerator(property); - if (introspectorGenerator != null) { - List introspectorProperties = introspectorGenerator.generateChildProperties(property); - if (introspectorProperties != null) { - return introspectorProperties; - } - } - } - - if (!propertyGenerators.isEmpty()) { - for (MatcherOperator matcherOperator : propertyGenerators) { - if (matcherOperator.match(property)) { - List matchedProperties = matcherOperator - .getOperator() - .generateChildProperties(property); - if (matchedProperties != null) { - return matchedProperties; - } - } - } - } - - return baseGenerator.generateChildProperties(property); - }; - } - - private InterfaceResolver createGlobalInterfaceResolver(FixtureMonkeyOptions options) { - return new InterfaceResolver() { - @Override - public @Nullable JvmType resolve(JvmType type) { - List candidates = resolveAll(type); - if (candidates.isEmpty()) { - return null; - } - Random typeRandom = seedState.snapshot().randomFor(type.hashCode()); - return candidates.get(typeRandom.nextInt(candidates.size())); - } - - @Override - public List resolveAll(JvmType type) { - Class rawType = type.getRawType(); - if (!Modifier.isInterface(rawType.getModifiers()) && !Modifier.isAbstract(rawType.getModifiers())) { - return Collections.emptyList(); - } - - Property property = JvmNodePropertyFactory.fromType(type); - @SuppressWarnings("deprecation") - CandidateConcretePropertyResolver resolver = options.getCandidateConcretePropertyResolver(property); - - if (resolver == null) { - return Collections.emptyList(); - } - - List candidates = resolver.resolve(property); - if (candidates == null || candidates.isEmpty()) { - return Collections.emptyList(); - } - - return candidates - .stream() - .map(p -> Types.toJvmType(p.getAnnotatedType(), p.getAnnotations())) - .collect(Collectors.toList()); - } - }; - } - - /** - * {@inheritDoc} - * - *

JvmNodeCandidateTree is cached, but JvmNodeTree is created fresh - * each time to ensure container sizes vary.

- */ - @Override - public @Nullable JvmNodeTree createConcreteNodeTree(JvmType concreteType, @Nullable FixtureMonkeyOptions options) { - if (options == null) { - return null; - } - - ContextCacheKey cacheKey = new ContextCacheKey(concreteType, options); - - JvmNodeContext context = getOrBuildNodeContext( - concreteType, - options, - Collections.emptyMap(), - Collections.emptyMap() - ); - - JvmNodeCandidateTree candidateTree = concreteTypeCandidateTreeCache.computeIfAbsent(cacheKey, key -> - buildCandidateTree(concreteType, context, treeContext) - ); - - PathResolverContext resolverContext = PathResolverContext.builder().build(); - - JvmNodeTreeTransformer transformer = new JvmNodeTreeTransformer( - context, - treeContext, - resolverContext, - null, - subtreeContext - ); - - return transformer.transform(candidateTree); - } - - @Override - public @Nullable JvmNodeTree createAnonymousNodeTree( - JvmType interfaceType, - @Nullable FixtureMonkeyOptions options - ) { - if (options == null) { - return null; - } - - JavaNodeContext baseContext = (JavaNodeContext)getOrBuildNodeContext( - interfaceType, - options, - Collections.emptyMap(), - Collections.emptyMap() - ); - - JavaNodeContext anonymousContext = baseContext.withAdditionalGenerator( - new InterfaceMethodNodeCandidateGenerator() - ); - - JvmNodeCandidateTree candidateTree = new JvmNodeCandidateTree.Builder(interfaceType, anonymousContext) - .withTreeContext(treeContext) - .withPreBuildResolvedTypes(true) - .withSkipAbstractLeafCheck(true) - .build(); - - PathResolverContext resolverContext = currentResolverContext.get(); - if (resolverContext == null) { - resolverContext = PathResolverContext.builder().build(); - } - - JvmNodeTreeTransformer transformer = new JvmNodeTreeTransformer( - anonymousContext, - treeContext, - resolverContext, - null, - subtreeContext - ); - - return transformer.transform(candidateTree); - } - - @Override - public boolean isLeafType(Class type) { - if (Types.isJavaType(type)) { - return true; - } - - JvmType jvmType = new JavaType(type); - for (LeafTypeResolver resolver : additionalLeafTypeResolvers) { - if (resolver.isLeafType(jvmType)) { - return true; - } - } - - return false; - } - - public void clearCache() { - nodeContextCache.clear(); - candidateTreeCache.clear(); - concreteTypeCandidateTreeCache.clear(); - subtreeContext.clear(); - nodeMetadataCache.clear(); - } - - @Override - public ConcurrentHashMap getNodeMetadataCache() { - return nodeMetadataCache; - } - - /** - * Cache key for JvmNodeCandidateTree and empty manipulator results. - * Uses options identity hash because for the same FixtureMonkey instance, - * options is always the same object reference. - */ - private static final class ContextCacheKey { - - private final JvmType type; - private final int optionsIdentity; - private final int hashCode; - - ContextCacheKey(JvmType type, @Nullable FixtureMonkeyOptions options) { - this.type = type; - this.optionsIdentity = options != null ? System.identityHashCode(options) : 0; - this.hashCode = computeHashCode(); - } - - private int computeHashCode() { - int result = type.hashCode(); - result = 31 * result + optionsIdentity; - return result; - } - - @Override - public boolean equals(@Nullable Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - ContextCacheKey that = (ContextCacheKey)obj; - return optionsIdentity == that.optionsIdentity && Objects.equals(type, that.type); - } - - @Override - public int hashCode() { - return hashCode; - } - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/JavaNodeTreeAdapterPlugin.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/JavaNodeTreeAdapterPlugin.java deleted file mode 100644 index 204f7f0acd..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/JavaNodeTreeAdapterPlugin.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.adapter; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import com.navercorp.fixturemonkey.adapter.tracing.AdapterTracer; -import com.navercorp.fixturemonkey.api.option.FixtureMonkeyOptionsBuilder; -import com.navercorp.fixturemonkey.api.plugin.Plugin; - -/** - * A plugin for configuring the node tree adapter for Java types in FixtureMonkey. - *

- * This plugin allows configuration of the adapter layer, which provides - * an alternative object generation path using JvmNodeTree. - * - *

{@code
- * FixtureMonkey.builder()
- *     .plugin(new JavaNodeTreeAdapterPlugin()
- *         .enabled(true)
- *         .seed(12345L)
- *         .tracer(AdapterTracer.console()))
- *     .build();
- * }
- * - * For Kotlin support, use {@code KotlinNodeTreeAdapterPlugin} instead. - * - * @see NodeTreeAdapter - * @see AdapterTracer - * @since 1.1.17 - */ -@API(since = "1.1.17", status = Status.EXPERIMENTAL) -public class JavaNodeTreeAdapterPlugin implements Plugin { - private boolean enabled = true; - private long seed = System.nanoTime(); - private AdapterTracer tracer = AdapterTracer.noOp(); - - /** - * Enables or disables the node tree adapter. - *

- * When enabled, the default {@link DefaultNodeTreeAdapter} will be used - * for object generation using JvmNodeTree. - * - * @param enabled true to enable the adapter, false to disable - * @return this plugin for method chaining - */ - public JavaNodeTreeAdapterPlugin enabled(boolean enabled) { - this.enabled = enabled; - return this; - } - - /** - * Sets the seed for random value generation in the adapter. - *

- * Using a fixed seed value ensures reproducible test results. - * - * @param seed the seed value for random generation - * @return this plugin for method chaining - */ - public JavaNodeTreeAdapterPlugin seed(long seed) { - this.seed = seed; - return this; - } - - /** - * Sets the tracer for debugging resolution process. - *

- * The tracer receives detailed information about how values are resolved - * during fixture generation, including manipulator analysis and assembly steps. - * - * @param tracer the tracer to use for debugging - * @return this plugin for method chaining - * @see AdapterTracer#console() - * @see AdapterTracer#consoleJson() - */ - public JavaNodeTreeAdapterPlugin tracer(AdapterTracer tracer) { - this.tracer = tracer; - return this; - } - - @Override - public void accept(FixtureMonkeyOptionsBuilder optionsBuilder) { - if (enabled) { - optionsBuilder.nodeTreeAdapter(new DefaultNodeTreeAdapter(seed)); - } - optionsBuilder.adapterTracer(tracer); - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/NodeTreeAdapter.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/NodeTreeAdapter.java deleted file mode 100644 index 13e23cf4f6..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/NodeTreeAdapter.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.adapter; - -import java.util.concurrent.ConcurrentHashMap; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; -import org.jspecify.annotations.Nullable; - -import com.navercorp.fixturemonkey.adapter.analysis.AdaptationResult; -import com.navercorp.fixturemonkey.adapter.tracing.TraceContext; -import com.navercorp.fixturemonkey.api.option.FixtureMonkeyOptions; -import com.navercorp.fixturemonkey.customizer.ManipulatorSet; -import com.navercorp.objectfarm.api.tree.JvmNodeTree; -import com.navercorp.objectfarm.api.type.JvmType; - -/** - * Adapter interface for converting fixture-monkey's ManipulatorSet information - * to object-farm-api's JvmNodeTree. - *

- * This adapter bridges the gap between fixture-monkey's ArbitraryManipulator-based - * customization system and object-farm-api's immutable JvmNodeTree structure. - *

- * The adapter analyzes the ManipulatorSet to extract: - *

    - *
  • Container size information from ContainerInfoManipulator
  • - *
  • Interface resolution from NodeSetDecomposedValueManipulator
  • - *
  • Generic type hints from value types
  • - *
- *

- * Example usage: - *

{@code
- * NodeTreeAdapter adapter = new DefaultNodeTreeAdapter(seed);
- * AdaptationResult result = adapter.adapt(rootType, manipulatorSet, options);
- * }
- * - * @see DefaultNodeTreeAdapter - * @see ManipulatorSet - * @see JvmNodeTree - */ -@API(since = "1.1.17", status = Status.EXPERIMENTAL) -public interface NodeTreeAdapter { - /** - * Converts a root type and ManipulatorSet into an AdaptationResult containing - * the JvmNodeTree and extracted value information. - * - * @param rootType the root JvmType to create the tree for - * @param manipulatorSet the ManipulatorSet containing customization information - * @return an AdaptationResult containing the JvmNodeTree and value information - */ - AdaptationResult adapt(JvmType rootType, ManipulatorSet manipulatorSet); - - /** - * Converts a root type and ManipulatorSet into an AdaptationResult with options. - *

- * This overload allows passing FixtureMonkeyOptions for container size generation. - * - * @param rootType the root JvmType to create the tree for - * @param manipulatorSet the ManipulatorSet containing customization information - * @param options the FixtureMonkey options for container info generation (nullable) - * @return an AdaptationResult containing the JvmNodeTree and value information - */ - AdaptationResult adapt( - JvmType rootType, - ManipulatorSet manipulatorSet, - @Nullable FixtureMonkeyOptions options - ); - - /** - * Converts a root type and ManipulatorSet into an AdaptationResult with tracing support. - *

- * This overload allows passing a TraceContext to capture resolution decisions - * (interface resolution, container size resolution) during tree transformation. - * - * @param rootType the root JvmType to create the tree for - * @param manipulatorSet the ManipulatorSet containing customization information - * @param options the FixtureMonkey options for container info generation (nullable) - * @param traceContext the trace context for capturing resolution decisions (nullable) - * @return an AdaptationResult containing the JvmNodeTree and value information - */ - AdaptationResult adapt( - JvmType rootType, - ManipulatorSet manipulatorSet, - @Nullable FixtureMonkeyOptions options, - @Nullable TraceContext traceContext - ); - - /** - * Creates a JvmNodeTree for the given concrete type. - *

- * Used when generating with interface/abstract implementations to obtain - * the proper tree structure with child nodes. The underlying JvmNodeCandidateTree - * may be cached, but the JvmNodeTree is created fresh each time to ensure - * container sizes vary across calls. - * - * @param concreteType the concrete JvmType to create the tree for - * @param options the FixtureMonkey options for tree building - * @return the JvmNodeTree, or null if not available - */ - @Nullable - JvmNodeTree createConcreteNodeTree(JvmType concreteType, FixtureMonkeyOptions options); - - /** - * Creates a JvmNodeTree for an anonymous instance of the given interface/abstract type. - *

- * The tree has children derived from no-argument methods of the interface, - * enabling anonymous proxy generation with path-based value customization. - * Always created fresh (no caching). - * - * @param interfaceType the interface/abstract JvmType to create the tree for - * @param options the FixtureMonkey options for tree building - * @return the JvmNodeTree for anonymous instance generation, or null if not available - */ - @Nullable - JvmNodeTree createAnonymousNodeTree(JvmType interfaceType, FixtureMonkeyOptions options); - - /** - * Checks whether the given type is a leaf type that should not be expanded further. - *

- * Leaf types (e.g., Java standard library types, Kotlin standard types) are terminal nodes - * in the object tree and their internal fields should not be traversed. - * - * @param type the class to check - * @return true if the type is a leaf type - */ - boolean isLeafType(Class type); - - /** - * Returns the cross-call node metadata cache for assembly optimization. - *

- * This cache maps JvmNode instances to their derived metadata (Property, resolvers, etc.) - * across multiple assembly calls. Returns null if caching is not supported or disabled. - * - * @return the node metadata cache, or null if not available - */ - @Nullable - ConcurrentHashMap getNodeMetadataCache(); -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/converter/ContainerInfoResolverConverter.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/converter/ContainerInfoResolverConverter.java deleted file mode 100644 index 5c2d86d8ee..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/converter/ContainerInfoResolverConverter.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.adapter.converter; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.annotation.Nullable; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import com.navercorp.fixturemonkey.customizer.ContainerInfoManipulator; -import com.navercorp.objectfarm.api.expression.PathExpression; -import com.navercorp.objectfarm.api.node.ContainerSizeResolver; -import com.navercorp.objectfarm.api.tree.PathContainerSizeResolver; -import com.navercorp.objectfarm.api.tree.PathResolver; -import com.navercorp.objectfarm.api.type.JvmType; - -/** - * Converts ContainerInfoManipulator to TransformPathResolver for container size resolution. - *

- * This converter analyzes ContainerInfoManipulator instances and creates corresponding - * TransformPathResolver instances that can be used during tree transformation to determine - * container sizes at specific paths. - *

- * The converter: - *

    - *
  • Sorts manipulators by manipulatingSequence to ensure correct order of application
  • - *
  • Calls {@link ContainerInfoManipulator#fixed()} to determine the container size
  • - *
  • Creates ContainerSizeResolver instances with the fixed size
  • - *
- */ -@API(since = "1.1.17", status = Status.EXPERIMENTAL) -public final class ContainerInfoResolverConverter { - private ContainerInfoResolverConverter() { - } - - /** - * Converts a list of ContainerInfoManipulators to TransformPathResolvers. - *

- * The manipulators are sorted by manipulatingSequence before conversion. - * When multiple manipulators target the same path, only the last one is kept - * (the one with the highest manipulatingSequence). - * - * @param manipulators the list of ContainerInfoManipulators to convert - * @return a list of TransformPathResolvers for container size resolution - */ - public static List> convert(List manipulators) { - // Sort by manipulatingSequence to ensure correct override order - List sorted = new ArrayList<>(manipulators); - sorted.sort(Comparator.comparingInt(ContainerInfoManipulator::getManipulatingSequence)); - - // Keep only the last resolver for each path (last one wins) - Map> resolverByPath = new LinkedHashMap<>(); - - for (ContainerInfoManipulator manipulator : sorted) { - String pathExpression = PredicatePathConverter.toExpression(manipulator.getNextNodePredicates()); - PathResolver resolver = convertSingle(manipulator); - resolverByPath.put(pathExpression, resolver); // Later entries override earlier ones - } - - return new ArrayList<>(resolverByPath.values()); - } - - /** - * Converts a list of ContainerInfoManipulators to TransformPathResolvers, - * using pre-computed PathExpression cache to avoid redundant predicate conversions. - * - * @param manipulators the list of ContainerInfoManipulators to convert - * @param pathCache pre-computed PathExpression for each manipulator - * @return a list of TransformPathResolvers for container size resolution - */ - public static List> convert( - List manipulators, - Map pathCache - ) { - List sorted = new ArrayList<>(manipulators); - sorted.sort(Comparator.comparingInt(ContainerInfoManipulator::getManipulatingSequence)); - - Map> resolverByPath = new LinkedHashMap<>(); - - for (ContainerInfoManipulator manipulator : sorted) { - PathExpression cachedPath = pathCache.get(manipulator); - String pathString = - cachedPath != null - ? cachedPath.toExpression() - : PredicatePathConverter.toExpression(manipulator.getNextNodePredicates()); - PathResolver resolver = convertSingle(manipulator, cachedPath); - resolverByPath.put(pathString, resolver); - } - - return new ArrayList<>(resolverByPath.values()); - } - - /** - * Converts a single ContainerInfoManipulator to a TransformPathResolver. - * - * @param manipulator the ContainerInfoManipulator to convert - * @return a TransformPathResolver for this manipulator - */ - public static PathResolver convertSingle(ContainerInfoManipulator manipulator) { - return convertSingle(manipulator, null); - } - - private static PathResolver convertSingle( - ContainerInfoManipulator manipulator, - @Nullable PathExpression cachedPattern - ) { - // Create a copy and fix the size - ContainerInfoManipulator copy = manipulator.copy(); - copy.fixed(); - - int fixedSize = copy.getContainerInfo().getElementMinSize(); - - PathExpression pattern = - cachedPattern != null ? cachedPattern : PredicatePathConverter.convert(manipulator.getNextNodePredicates()); - - ContainerSizeResolver sizeResolver = containerType -> { - int requestedSize = fixedSize; - - // For Set or Map, clamp to enum cardinality - if (containerType != null) { - Class rawType = containerType.getRawType(); - Class enumType = getEnumElementType(rawType, containerType); - if (enumType != null) { - Object[] enumConstants = enumType.getEnumConstants(); - if (enumConstants != null) { - int enumSize = enumConstants.length; - requestedSize = Math.min(requestedSize, enumSize); - } - } - } - - return requestedSize; - }; - - return new PathContainerSizeResolver(pattern, sizeResolver); - } - - /** - * Gets the enum element type from a container type if applicable. - * For Set, returns the element type if it's an enum. - * For Map, returns the key type if it's an enum. - * - * @param rawType the raw container type - * @param containerType the full container type with generics - * @return the enum class if found, null otherwise - */ - @Nullable - private static Class getEnumElementType(Class rawType, JvmType containerType) { - List typeVariables = containerType.getTypeVariables(); - if (typeVariables.isEmpty()) { - return null; - } - - // For Set, check if E is an enum - if (Set.class.isAssignableFrom(rawType)) { - Class elementType = typeVariables.get(0).getRawType(); - if (elementType.isEnum()) { - return elementType; - } - } - - // For Map, check if K is an enum - if (Map.class.isAssignableFrom(rawType)) { - Class keyType = typeVariables.get(0).getRawType(); - if (keyType.isEnum()) { - return keyType; - } - } - - return null; - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/converter/PredicatePathConverter.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/converter/PredicatePathConverter.java deleted file mode 100644 index 06f7032d56..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/converter/PredicatePathConverter.java +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.adapter.converter; - -import java.util.ArrayList; -import java.util.List; - -import javax.annotation.Nullable; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import com.navercorp.fixturemonkey.Constants; -import com.navercorp.fixturemonkey.adapter.analysis.ManipulatorAnalyzer.DecomposeNameResolver; -import com.navercorp.fixturemonkey.tree.ApplyStrictModeResolver; -import com.navercorp.fixturemonkey.tree.CompositeNodeResolver; -import com.navercorp.fixturemonkey.tree.ContainerElementPredicate; -import com.navercorp.fixturemonkey.tree.NextNodePredicate; -import com.navercorp.fixturemonkey.tree.NodeAllElementPredicate; -import com.navercorp.fixturemonkey.tree.NodeElementPredicate; -import com.navercorp.fixturemonkey.tree.NodeKeyPredicate; -import com.navercorp.fixturemonkey.tree.NodePredicateResolver; -import com.navercorp.fixturemonkey.tree.NodeResolver; -import com.navercorp.fixturemonkey.tree.NodeTypePredicate; -import com.navercorp.fixturemonkey.tree.NodeValuePredicate; -import com.navercorp.fixturemonkey.tree.PropertyNameNodePredicate; -import com.navercorp.fixturemonkey.tree.PropertyPredicate; -import com.navercorp.fixturemonkey.tree.StartNodePredicate; -import com.navercorp.objectfarm.api.expression.PathExpression; - -/** - * Converts NextNodePredicate chains to PathExpression. - *

- * This converter translates fixture-monkey's path predicates to object-farm-api's - * path expressions for use in tree transformation. - *

- * Mapping rules: - *

    - *
  • {@link StartNodePredicate} → {@code $} (root)
  • - *
  • {@link PropertyPredicate} → {@code .propertyName}
  • - *
  • {@link PropertyNameNodePredicate} → {@code .propertyName}
  • - *
  • {@link NodeAllElementPredicate} → {@code [*]}
  • - *
  • {@link NodeElementPredicate} → {@code [n]}
  • - *
  • {@link NodeKeyPredicate} → {@code [key]}
  • - *
  • {@link NodeValuePredicate} → {@code [value]}
  • - *
- */ -@API(since = "1.1.17", status = Status.EXPERIMENTAL) -public final class PredicatePathConverter { - private PredicatePathConverter() { - } - - /** - * Converts a list of NextNodePredicates to a PathExpression. - *

- * This method builds a PathExpression using the builder API directly, - * supporting predicates like {@link NodeTypePredicate} that cannot be - * represented as plain strings. - * - * @param predicates the list of predicates representing the path - * @return the corresponding PathExpression - */ - public static PathExpression convert(List predicates) { - return convert(predicates, null); - } - - /** - * Converts a list of NextNodePredicates to a PathExpression, using the given name resolver - * for PropertyPredicate names. - *

- * When a {@link DecomposeNameResolver} is provided, {@link PropertyPredicate} nodes use - * the resolver to determine property names (e.g., Jackson {@code @JsonProperty} names) - * instead of the Java field name. - * - * @param predicates the list of predicates representing the path - * @param nameResolver optional resolver for property names - * @return the corresponding PathExpression - */ - public static PathExpression convert( - List predicates, - @Nullable DecomposeNameResolver nameResolver - ) { - PathExpression path = PathExpression.root(); - - for (NextNodePredicate predicate : predicates) { - path = appendPredicateToPath(path, predicate, nameResolver); - } - - return path; - } - - /** - * Converts a list of NextNodePredicates to a path expression string. - * - * @param predicates the list of predicates representing the path - * @return the path expression string (e.g., "$.items[*]") - */ - public static String toExpression(List predicates) { - StringBuilder sb = new StringBuilder("$"); - - for (NextNodePredicate predicate : predicates) { - appendPredicate(sb, predicate); - } - - return sb.toString(); - } - - private static void appendPredicate(StringBuilder sb, NextNodePredicate predicate) { - if (predicate instanceof StartNodePredicate) { - // Root is already represented by "$" - return; - } - - if (predicate instanceof PropertyPredicate) { - PropertyPredicate propertyPredicate = (PropertyPredicate)predicate; - String propertyName = propertyPredicate.getProperty().getName(); - sb.append(".").append(propertyName); - return; - } - - if (predicate instanceof PropertyNameNodePredicate) { - PropertyNameNodePredicate namePredicate = (PropertyNameNodePredicate)predicate; - String propertyName = namePredicate.getPropertyName(); - // "*" means all fields (field wildcard), not all elements (array wildcard) - // So it should be converted to ".*" not "[*]" - sb.append(".").append(propertyName); - return; - } - - if (predicate instanceof NodeAllElementPredicate) { - sb.append("[*]"); - return; - } - - if (predicate instanceof NodeElementPredicate) { - NodeElementPredicate elementPredicate = (NodeElementPredicate)predicate; - int index = elementPredicate.getIndex(); - sb.append("[").append(index).append("]"); - return; - } - - if (predicate instanceof NodeKeyPredicate) { - sb.append("[key]"); - return; - } - - if (predicate instanceof NodeValuePredicate) { - sb.append("[value]"); - return; - } - - if (predicate instanceof ContainerElementPredicate) { - ContainerElementPredicate elementPredicate = (ContainerElementPredicate)predicate; - int sequence = elementPredicate.getSequence(); - if (sequence == Constants.NO_OR_ALL_INDEX_INTEGER_VALUE) { - sb.append("[*]"); - } else { - sb.append("[").append(sequence).append("]"); - } - return; - } - - throw new IllegalArgumentException("Unknown predicate type: " + predicate.getClass().getName()); - } - - /** - * Extracts NextNodePredicates from a NodeResolver by unwrapping composite and - * strict-mode wrappers recursively. - * - * @param nodeResolver the resolver to extract predicates from - * @return the list of extracted predicates - */ - public static List extractPredicates(NodeResolver nodeResolver) { - List predicates = new ArrayList<>(); - extractPredicatesRecursive(nodeResolver, predicates); - return predicates; - } - - private static void extractPredicatesRecursive(NodeResolver nodeResolver, List predicates) { - if (nodeResolver instanceof ApplyStrictModeResolver) { - ApplyStrictModeResolver strictResolver = (ApplyStrictModeResolver)nodeResolver; - extractPredicatesRecursive(strictResolver.getNodeResolver(), predicates); - } else if (nodeResolver instanceof CompositeNodeResolver) { - CompositeNodeResolver composite = (CompositeNodeResolver)nodeResolver; - for (NodeResolver childResolver : composite.getNodeResolvers()) { - extractPredicatesRecursive(childResolver, predicates); - } - } else if (nodeResolver instanceof NodePredicateResolver) { - NextNodePredicate predicate = ((NodePredicateResolver)nodeResolver).getNextNodePredicate(); - if (predicate != null) { - predicates.add(predicate); - } - } - } - - private static PathExpression appendPredicateToPath( - PathExpression path, - NextNodePredicate predicate, - @Nullable DecomposeNameResolver nameResolver - ) { - if (predicate instanceof StartNodePredicate) { - return path; - } - - if (predicate instanceof PropertyPredicate) { - PropertyPredicate propertyPredicate = (PropertyPredicate)predicate; - String propertyName = - nameResolver != null - ? nameResolver.resolve(propertyPredicate.getProperty()) - : propertyPredicate.getProperty().getName(); - if (propertyName == null) { - return path; - } - return path.child(propertyName); - } - - if (predicate instanceof PropertyNameNodePredicate) { - PropertyNameNodePredicate namePredicate = (PropertyNameNodePredicate)predicate; - return path.child(namePredicate.getPropertyName()); - } - - if (predicate instanceof NodeAllElementPredicate) { - return path.wildcard(); - } - - if (predicate instanceof NodeElementPredicate) { - NodeElementPredicate elementPredicate = (NodeElementPredicate)predicate; - return path.index(elementPredicate.getIndex()); - } - - if (predicate instanceof NodeKeyPredicate) { - return path.key(); - } - - if (predicate instanceof NodeValuePredicate) { - return path.value(); - } - - if (predicate instanceof ContainerElementPredicate) { - ContainerElementPredicate elementPredicate = (ContainerElementPredicate)predicate; - int sequence = elementPredicate.getSequence(); - if (sequence == Constants.NO_OR_ALL_INDEX_INTEGER_VALUE) { - return path.wildcard(); - } - return path.index(sequence); - } - - if (predicate instanceof NodeTypePredicate) { - NodeTypePredicate typePredicate = (NodeTypePredicate)predicate; - return path.type(typePredicate.getType(), typePredicate.isExact()); - } - - throw new IllegalArgumentException("Unknown predicate type: " + predicate.getClass().getName()); - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/builder/ArbitraryBuilderContext.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/builder/ArbitraryBuilderContext.java index da9e474ae8..bdaf2ed87a 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/builder/ArbitraryBuilderContext.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/builder/ArbitraryBuilderContext.java @@ -21,12 +21,10 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.stream.Collectors; import org.apiguardian.api.API; import org.apiguardian.api.API.Status; @@ -39,22 +37,14 @@ import com.navercorp.fixturemonkey.api.generator.ArbitraryGenerator; import com.navercorp.fixturemonkey.api.introspector.ArbitraryIntrospector; import com.navercorp.fixturemonkey.api.matcher.MatcherOperator; -import com.navercorp.fixturemonkey.api.matcher.PriorityMatcherOperator; -import com.navercorp.fixturemonkey.api.option.FixtureMonkeyOptions; import com.navercorp.fixturemonkey.api.property.LazyPropertyGenerator; import com.navercorp.fixturemonkey.api.property.Property; import com.navercorp.fixturemonkey.api.property.PropertyGenerator; -import com.navercorp.fixturemonkey.api.property.TreeRootProperty; -import com.navercorp.fixturemonkey.api.tree.TraverseContext; -import com.navercorp.fixturemonkey.api.tree.TreeNodeManipulator; -import com.navercorp.fixturemonkey.api.type.Types; -import com.navercorp.fixturemonkey.customizer.ArbitraryManipulator; -import com.navercorp.fixturemonkey.customizer.ContainerInfoManipulator; -import com.navercorp.fixturemonkey.tree.GenerateFixtureContext; -import com.navercorp.fixturemonkey.tree.ObjectTree; +import com.navercorp.fixturemonkey.customizer.PathDirective; +import com.navercorp.fixturemonkey.customizer.SizeDirective; /** - * {@link FixtureMonkey} → {@link ArbitraryBuilder} → {@link ObjectTree} → {@link CombinableArbitrary} + * {@link FixtureMonkey} → {@link ArbitraryBuilder} → adapter pipeline → {@link CombinableArbitrary} * 1:N 1:N 1:1 *

* It is a context within {@link ArbitraryBuilder}. It represents a status of the {@link ArbitraryBuilder}. @@ -64,8 +54,7 @@ */ @API(since = "0.4.0", status = Status.INTERNAL) public final class ArbitraryBuilderContext { - private final List manipulators; - private final List containerInfoManipulators; + private final List directives; private final Map, List> propertyConfigurers; private final Map, ArbitraryIntrospector> arbitraryIntrospectorsByType; private final MonkeyContext monkeyContext; @@ -78,16 +67,14 @@ public final class ArbitraryBuilderContext { private @Nullable CombinableArbitrary fixedCombinableArbitrary; private ArbitraryBuilderContext( - List manipulators, - List containerInfoManipulators, + List directives, Map, List> propertyConfigurers, Map, ArbitraryIntrospector> arbitraryIntrospectorsByType, @Nullable FixedState fixedState, @Nullable CombinableArbitrary fixedCombinableArbitrary, MonkeyContext monkeyContext ) { - this.manipulators = manipulators; - this.containerInfoManipulators = containerInfoManipulators; + this.directives = directives; this.propertyConfigurers = propertyConfigurers; this.arbitraryIntrospectorsByType = arbitraryIntrospectorsByType; this.fixedState = fixedState; @@ -102,7 +89,6 @@ private ArbitraryBuilderContext( @Deprecated public static ArbitraryBuilderContext newBuilderContext(MonkeyContext monkeyContext) { return new ArbitraryBuilderContext( - new ArrayList<>(), new ArrayList<>(), new HashMap<>(), new HashMap<>(), @@ -112,13 +98,10 @@ public static ArbitraryBuilderContext newBuilderContext(MonkeyContext monkeyCont } public ArbitraryBuilderContext copy() { - List copiedContainerInfoManipulators = this.containerInfoManipulators.stream() - .map(ContainerInfoManipulator::copy) - .collect(Collectors.toList()); + List copiedDirectives = new ArrayList<>(this.directives); ArbitraryBuilderContext copiedContext = new ArbitraryBuilderContext( - new ArrayList<>(this.manipulators), - copiedContainerInfoManipulators, + copiedDirectives, new HashMap<>(propertyConfigurers), new HashMap<>(arbitraryIntrospectorsByType), fixedState, @@ -132,28 +115,43 @@ public ArbitraryBuilderContext copy() { return copiedContext; } - public void addManipulator(ArbitraryManipulator arbitraryManipulator) { - this.manipulators.add(arbitraryManipulator); - } - - public void addManipulators(Collection arbitraryManipulators) { - this.manipulators.addAll(arbitraryManipulators); + public void addDirective(PathDirective directive) { + this.directives.add(directive); } - public List getManipulators() { - return Collections.unmodifiableList(manipulators); + public void addDirectives(Collection directives) { + this.directives.addAll(directives); } - public void addContainerInfoManipulator(ContainerInfoManipulator containerInfo) { - this.containerInfoManipulators.add(containerInfo); + public List getDirectives() { + return Collections.unmodifiableList(directives); } - public void addContainerInfoManipulators(List containerInfoManipulators) { - this.containerInfoManipulators.addAll(containerInfoManipulators); + /** + * Filters this context's directives down to {@link SizeDirective}s. Used by adapter consumers + * that only care about container-size manipulation. + */ + public List getSizeDirectives() { + List sizes = new ArrayList<>(); + for (PathDirective directive : directives) { + if (directive instanceof SizeDirective) { + sizes.add((SizeDirective)directive); + } + } + return sizes; } - public List getContainerInfoManipulators() { - return Collections.unmodifiableList(containerInfoManipulators); + /** + * Locks every {@link SizeDirective} on this context to a single random size — used by + * {@code ArbitraryBuilder.fixed()} so subsequent samples produce deterministic container sizes. + */ + public void fixContainerSizes() { + for (int i = 0; i < directives.size(); i++) { + PathDirective directive = directives.get(i); + if (directive instanceof SizeDirective) { + directives.set(i, ((SizeDirective)directive).fix()); + } + } } public void putPropertyConfigurer(Class type, List propertyConfigurer) { @@ -193,14 +191,12 @@ public boolean isValidOnly() { public void markFixed() { FixedState fixedStateLocal = fixedState; - if (fixedStateLocal != null - && fixedStateLocal.getFixedManipulateSize() == this.manipulators.size()) { - if (fixedStateLocal.getFixedContainerManipulatorSize() == this.containerInfoManipulators.size()) { - return; - } + if (fixedStateLocal != null + && fixedStateLocal.getFixedManipulateSize() == this.directives.size()) { + return; } - fixedState = new FixedState(this.manipulators.size(), this.containerInfoManipulators.size()); + fixedState = new FixedState(this.directives.size()); fixedCombinableArbitrary = null; } @@ -210,8 +206,7 @@ public boolean isFixed() { @SuppressWarnings({"dereference.of.nullable", "argument"}) public boolean fixedExpired() { - return manipulators.size() > Objects.requireNonNull(fixedState).getFixedManipulateSize() - || containerInfoManipulators.size() > fixedState.getFixedContainerManipulatorSize(); + return directives.size() > Objects.requireNonNull(fixedState).getFixedManipulateSize(); } public void renewFixed(CombinableArbitrary fixedCombinableArbitrary) { @@ -223,93 +218,16 @@ public void renewFixed(CombinableArbitrary fixedCombinableArbitrary) { return fixedCombinableArbitrary; } - public TraverseContext newTraverseContext( - TreeRootProperty rootProperty, - Map, List> registeredPropertyConfigurer - ) { - List>> registeredTreeNodeManipulators = - monkeyContext.getRegisteredArbitraryBuilders() - .stream() - .sorted(Comparator.comparingInt(PriorityMatcherOperator::getPriority)) - .map(it -> new MatcherOperator<>( - it.getMatcher(), - ((ArbitraryBuilderContextProvider)it.getOperator()).getActiveContext() - .getContainerInfoManipulators() - )) - .collect(Collectors.toList()); // TODO: Fragmented registered - - TreeNodeManipulator registeredRootTreeManipulator = registeredTreeNodeManipulators.stream() - .filter(it -> it.match(rootProperty)) - .flatMap(it -> it.getOperator().stream()) - .findFirst() - .orElse(null); - - List activeTreeNodeManipulators = new ArrayList<>(this.getContainerInfoManipulators()); - if (registeredRootTreeManipulator != null) { - activeTreeNodeManipulators.add(0, registeredRootTreeManipulator); - } - - FixtureMonkeyOptions fixtureMonkeyOptions = this.monkeyContext.getFixtureMonkeyOptions(); - Map, List> concatPropertyConfigurer = new HashMap<>(this.getPropertyConfigurers()); - concatPropertyConfigurer.putAll(registeredPropertyConfigurer); - concatPropertyConfigurer = Collections.unmodifiableMap(concatPropertyConfigurer); - - return new TraverseContext( - rootProperty, - new ArrayList<>(), - activeTreeNodeManipulators, - registeredTreeNodeManipulators, - concatPropertyConfigurer, - this.isValidOnly(), - initializeResolvedPropertyGenerator( - concatPropertyConfigurer, - fixtureMonkeyOptions.getPropertyGenerators(), - fixtureMonkeyOptions.getDefaultArbitraryGenerator(), - fixtureMonkeyOptions.getDefaultPropertyGenerator() - ), - fixtureMonkeyOptions.getObjectPropertyGenerators(), - fixtureMonkeyOptions.getDefaultObjectPropertyGenerator(), - fixtureMonkeyOptions.getContainerPropertyGenerators(), - fixtureMonkeyOptions.getPropertyNameResolvers(), - fixtureMonkeyOptions.getDefaultPropertyNameResolver(), - fixtureMonkeyOptions.getCandidateConcretePropertyResolvers(), - fixtureMonkeyOptions.getArbitraryContainerInfoGenerators(), - fixtureMonkeyOptions.getDefaultArbitraryContainerInfoGenerator(), - fixtureMonkeyOptions.getNullInjectGenerators(), - fixtureMonkeyOptions.getDefaultNullInjectGenerator() - ); - } - - public GenerateFixtureContext newGenerateFixtureContext( - Map, ArbitraryIntrospector> registeredArbitraryIntrospectorsByType - ) { - Map, ArbitraryIntrospector> concat = new HashMap<>(arbitraryIntrospectorsByType); - concat.putAll(registeredArbitraryIntrospectorsByType); - concat = Collections.unmodifiableMap(concat); - - return new GenerateFixtureContext( - concat, - this::isValidOnly, - monkeyContext - ); - } - private static class FixedState { private final int fixedManipulateSize; - private final int fixedContainerManipulatorSize; - public FixedState(int fixedManipulateSize, int fixedContainerManipulatorSize) { + public FixedState(int fixedManipulateSize) { this.fixedManipulateSize = fixedManipulateSize; - this.fixedContainerManipulatorSize = fixedContainerManipulatorSize; } public int getFixedManipulateSize() { return fixedManipulateSize; } - - public int getFixedContainerManipulatorSize() { - return fixedContainerManipulatorSize; - } } private static LazyPropertyGenerator initializeResolvedPropertyGenerator( @@ -319,7 +237,7 @@ private static LazyPropertyGenerator initializeResolvedPropertyGenerator( PropertyGenerator defaultPropertyGenerator ) { PropertyGenerator resolvedPropertyGenerator = property -> { - Class type = Types.getActualType(property.getType()); + Class type = property.getJvmType().getRawType(); List propertyConfigurer = propertyConfigurers.get(type); if (propertyConfigurer != null) { return propertyConfigurer; diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/builder/DefaultArbitraryBuilder.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/builder/DefaultArbitraryBuilder.java index 225cc76bff..2bd49b1115 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/builder/DefaultArbitraryBuilder.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/builder/DefaultArbitraryBuilder.java @@ -27,6 +27,7 @@ import java.lang.reflect.AnnotatedType; import java.lang.reflect.Type; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.function.BiConsumer; import java.util.function.BiFunction; @@ -63,21 +64,17 @@ import com.navercorp.fixturemonkey.api.property.RootProperty; import com.navercorp.fixturemonkey.api.property.TreeRootProperty; import com.navercorp.fixturemonkey.api.property.TypeParameterProperty; -import com.navercorp.fixturemonkey.api.tree.TreeNodeManipulator; import com.navercorp.fixturemonkey.api.type.LazyAnnotatedType; import com.navercorp.fixturemonkey.api.type.TypeReference; import com.navercorp.fixturemonkey.api.type.Types; -import com.navercorp.fixturemonkey.customizer.ArbitraryManipulator; -import com.navercorp.fixturemonkey.customizer.ContainerInfoManipulator; import com.navercorp.fixturemonkey.customizer.InnerSpec; import com.navercorp.fixturemonkey.customizer.ManipulatorSet; import com.navercorp.fixturemonkey.customizer.MonkeyManipulatorFactory; +import com.navercorp.fixturemonkey.customizer.PathDirective; +import com.navercorp.fixturemonkey.customizer.SizeDirective; import com.navercorp.fixturemonkey.experimental.ExperimentalArbitraryBuilder; -import com.navercorp.fixturemonkey.expression.MonkeyExpression; -import com.navercorp.fixturemonkey.expression.MonkeyExpressionFactory; import com.navercorp.fixturemonkey.resolver.ArbitraryResolver; -import com.navercorp.fixturemonkey.tree.NextNodePredicate; -import com.navercorp.fixturemonkey.tree.NodeResolver; +import com.navercorp.objectfarm.api.expression.PathExpression; @SuppressFBWarnings("NM_SAME_SIMPLE_NAME_AS_SUPERCLASS") @API(since = "0.4.0", status = Status.MAINTAINED) @@ -86,7 +83,6 @@ public final class DefaultArbitraryBuilder implements ArbitraryBuilder, Ex private final TreeRootProperty rootProperty; private final ArbitraryResolver resolver; private final MonkeyManipulatorFactory monkeyManipulatorFactory; - private final MonkeyExpressionFactory monkeyExpressionFactory; /** * It is actual active context for the builder. * It has the actual applied manipulators. @@ -108,7 +104,6 @@ public DefaultArbitraryBuilder( TreeRootProperty rootProperty, ArbitraryResolver resolver, MonkeyManipulatorFactory monkeyManipulatorFactory, - MonkeyExpressionFactory monkeyExpressionFactory, ArbitraryBuilderContext context, List> standbyContexts, MonkeyContext monkeyContext, @@ -118,11 +113,10 @@ public DefaultArbitraryBuilder( this.resolver = resolver; this.activeContext = context; this.monkeyManipulatorFactory = monkeyManipulatorFactory; - this.monkeyExpressionFactory = monkeyExpressionFactory; this.monkeyContext = monkeyContext; this.standbyContexts = standbyContexts; this.instantiatorProcessor = instantiatorProcessor; - this.rootClass = Types.getActualType(rootProperty.getType()); + this.rootClass = rootProperty.getJvmType().getRawType(); } @Override @@ -155,13 +149,13 @@ public ArbitraryBuilder set(@Nullable Object value) { @Override public ArbitraryBuilder set(PropertySelector propertySelector, @Nullable Object value, int limit) { - NodeResolver nodeResolver = toMonkeyExpression(propertySelector).toNodeResolver(); + PathExpression nodeResolver = toPathExpression(propertySelector); if (value instanceof InnerSpec) { this.setInner((InnerSpec)value); } else { - ArbitraryManipulator arbitraryManipulator = - monkeyManipulatorFactory.newArbitraryManipulator(nodeResolver, value, limit); - this.activeContext.addManipulator(arbitraryManipulator); + PathDirective directive = + monkeyManipulatorFactory.newDirective(nodeResolver, value, limit); + this.activeContext.addDirective(directive); } return this; } @@ -183,10 +177,10 @@ public ArbitraryBuilder setLazy(String expression, @Nullable Supplier supp @Override public ArbitraryBuilder setLazy(PropertySelector propertySelector, @Nullable Supplier supplier, int limit) { - NodeResolver nodeResolver = toMonkeyExpression(propertySelector).toNodeResolver(); - ArbitraryManipulator arbitraryManipulator = - monkeyManipulatorFactory.newArbitraryManipulator(nodeResolver, supplier, limit); - this.activeContext.addManipulator(arbitraryManipulator); + PathExpression nodeResolver = toPathExpression(propertySelector); + PathDirective directive = + monkeyManipulatorFactory.newDirective(nodeResolver, supplier, limit); + this.activeContext.addDirective(directive); return this; } @@ -198,11 +192,7 @@ public ArbitraryBuilder setLazy(PropertySelector propertySelector, @Nullable @Override public ArbitraryBuilder setInner(InnerSpec innerSpec) { ManipulatorSet manipulatorSet = innerSpec.getManipulatorSet(monkeyManipulatorFactory); - List arbitraryManipulators = manipulatorSet.getArbitraryManipulators(); - List containerInfoManipulators = manipulatorSet.getContainerInfoManipulators(); - - this.activeContext.addManipulators(arbitraryManipulators); - this.activeContext.addContainerInfoManipulators(containerInfoManipulators); + this.activeContext.addDirectives(manipulatorSet.getDirectives()); return this; } @@ -248,21 +238,28 @@ public ArbitraryBuilder size(PropertySelector propertySelector, int minSize, throw new IllegalArgumentException("should be min <= max, min : " + minSize + " max : " + maxSize); } - List nextNodePredicates = toMonkeyExpression(propertySelector).toNextNodePredicate(); - ContainerInfoManipulator containerInfoManipulator = - monkeyManipulatorFactory.newContainerInfoManipulator( - nextNodePredicates, - minSize, - maxSize - ); - this.activeContext.addContainerInfoManipulator(containerInfoManipulator); + PathExpression sizePath = toPathExpression(propertySelector); + validateStrictModeSizePath(sizePath); + SizeDirective sizeDirective = monkeyManipulatorFactory.newSizeDirective(sizePath, minSize, maxSize); + this.activeContext.addDirective(sizeDirective); return this; } + private void validateStrictModeSizePath(PathExpression path) { + if (!monkeyManipulatorFactory.isExpressionStrictMode()) { + return; + } + if (!StrictModeSizeValidator.validate(rootProperty.getJvmType(), path)) { + throw new IllegalArgumentException( + "No matching results for given container expression. Invalid path: " + path.toExpression() + ); + } + } + @Override public ArbitraryBuilder fixed() { - this.activeContext.getContainerInfoManipulators().forEach(TreeNodeManipulator::fixed); + this.activeContext.fixContainerSizes(); this.activeContext.markFixed(); return this; @@ -270,7 +267,7 @@ public ArbitraryBuilder fixed() { @Override public ArbitraryBuilder thenApply(BiConsumer> biConsumer) { - this.activeContext.getContainerInfoManipulators().forEach(TreeNodeManipulator::fixed); + this.activeContext.fixContainerSizes(); ArbitraryBuilder appliedBuilder = this.copy(); @@ -283,10 +280,10 @@ public ArbitraryBuilder thenApply(BiConsumer> biConsum } ); - NodeResolver nodeResolver = monkeyExpressionFactory.from("$").toNodeResolver(); - ArbitraryManipulator arbitraryManipulator = - monkeyManipulatorFactory.newArbitraryManipulator(nodeResolver, lazyArbitrary); - this.activeContext.addManipulator(arbitraryManipulator); + PathExpression nodeResolver = PathExpression.root(); + PathDirective directive = + monkeyManipulatorFactory.newDirective(nodeResolver, lazyArbitrary); + this.activeContext.addDirective(directive); return this; } @@ -309,10 +306,10 @@ public ArbitraryBuilder setNull(String expression) { @Override public ArbitraryBuilder setNull(PropertySelector propertySelector) { - NodeResolver nodeResolver = toMonkeyExpression(propertySelector).toNodeResolver(); - ArbitraryManipulator arbitraryManipulator = - monkeyManipulatorFactory.newArbitraryManipulator(nodeResolver, null); - this.activeContext.addManipulator(arbitraryManipulator); + PathExpression nodeResolver = toPathExpression(propertySelector); + PathDirective directive = + monkeyManipulatorFactory.newDirective(nodeResolver, null); + this.activeContext.addDirective(directive); return this; } @@ -323,19 +320,19 @@ public ArbitraryBuilder setNotNull(String expression) { @Override public ArbitraryBuilder setNotNull(PropertySelector propertySelector) { - NodeResolver nodeResolver = toMonkeyExpression(propertySelector).toNodeResolver(); + PathExpression nodeResolver = toPathExpression(propertySelector); - ArbitraryManipulator arbitraryManipulator = - monkeyManipulatorFactory.newArbitraryManipulator(nodeResolver, NOT_NULL); + PathDirective directive = + monkeyManipulatorFactory.newDirective(nodeResolver, NOT_NULL); - this.activeContext.addManipulator(arbitraryManipulator); + this.activeContext.addDirective(directive); return this; } @SuppressWarnings("unchecked") @Override public ArbitraryBuilder setPostCondition(Predicate predicate) { - return this.setPostCondition(HEAD_NAME, (Class)Types.getActualType(rootProperty.getType()), predicate); + return this.setPostCondition(HEAD_NAME, (Class)rootProperty.getJvmType().getRawType(), predicate); } @Override @@ -364,10 +361,10 @@ public ArbitraryBuilder setPostCondition( Predicate predicate, int limit ) { - NodeResolver nodeResolver = toMonkeyExpression(propertySelector).toNodeResolver(); - ArbitraryManipulator arbitraryManipulator = - monkeyManipulatorFactory.newArbitraryManipulator(nodeResolver, type, predicate, limit); - this.activeContext.addManipulator(arbitraryManipulator); + PathExpression nodeResolver = toPathExpression(propertySelector); + PathDirective directive = + monkeyManipulatorFactory.newDirective(nodeResolver, type, predicate, limit); + this.activeContext.addDirective(directive); return this; } @@ -442,12 +439,12 @@ public ArbitraryBuilder instantiate(Instantiator instantiator) { new TypeReference() { @Override public Type getType() { - return rootProperty.getType(); + return rootProperty.getJvmType().getRawType(); } @Override public AnnotatedType getAnnotatedType() { - return rootProperty.getAnnotatedType(); + return Types.toAnnotatedType(rootProperty.getJvmType()); } }, instantiator @@ -482,9 +479,9 @@ public ArbitraryBuilder customizeProperty( TypedPropertySelector propertySelector, Function, CombinableArbitrary> combinableArbitraryCustomizer ) { - NodeResolver nodeResolver = toMonkeyExpression(propertySelector).toNodeResolver(); - activeContext.addManipulator( - monkeyManipulatorFactory.newArbitraryManipulator(nodeResolver, combinableArbitraryCustomizer) + PathExpression nodeResolver = toPathExpression(propertySelector); + activeContext.addDirective( + monkeyManipulatorFactory.newDirective(nodeResolver, combinableArbitraryCustomizer) ); return this; } @@ -519,7 +516,6 @@ public ArbitraryBuilder copy() { rootProperty, resolver, monkeyManipulatorFactory, - monkeyExpressionFactory, activeContext.copy(), standbyContexts, monkeyContext, @@ -542,8 +538,8 @@ private CombinableArbitrary resolveArbitrary(ArbitraryBuilderContext activeCo ) .combined(); - NodeResolver nodeResolver = monkeyExpressionFactory.from("$").toNodeResolver(); - activeContext.addManipulator(monkeyManipulatorFactory.newArbitraryManipulator(nodeResolver, fixed)); + PathExpression nodeResolver = PathExpression.root(); + activeContext.addDirective(monkeyManipulatorFactory.newDirective(nodeResolver, fixed)); activeContext.renewFixed(CombinableArbitrary.from(fixed)); } CombinableArbitrary fixedArbitrary = activeContext.getFixedCombinableArbitrary(); @@ -563,16 +559,17 @@ private CombinableArbitrary resolveArbitrary(ArbitraryBuilderContext activeCo private DefaultArbitraryBuilder generateArbitraryBuilderLazily(LazyArbitrary lazyArbitrary) { ArbitraryBuilderContext context = ArbitraryBuilderContext.newBuilderContext(monkeyContext); - NodeResolver nodeResolver = monkeyExpressionFactory.from("$").toNodeResolver(); - ArbitraryManipulator arbitraryManipulator = - monkeyManipulatorFactory.newArbitraryManipulator(nodeResolver, lazyArbitrary); - context.addManipulator(arbitraryManipulator); + PathExpression nodeResolver = PathExpression.root(); + PathDirective directive = + monkeyManipulatorFactory.newDirective(nodeResolver, lazyArbitrary); + context.addDirective(directive); return new DefaultArbitraryBuilder<>( - new RootProperty(new TypeParameterProperty(new LazyAnnotatedType<>(lazyArbitrary::getValue))), + new RootProperty(new TypeParameterProperty( + Types.toJvmType(new LazyAnnotatedType<>(lazyArbitrary::getValue), Collections.emptyList()) + )), resolver, monkeyManipulatorFactory, - monkeyExpressionFactory, context, standbyContexts, monkeyContext, @@ -584,7 +581,7 @@ private static ExpressionGenerator toExpressionGenerator(String expression) { return propertyNameResolver -> expression; } - private MonkeyExpression toMonkeyExpression(PropertySelector propertySelector) { + private PathExpression toPathExpression(PropertySelector propertySelector) { if (propertySelector instanceof ExpressionGenerator) { String stringExpression = ((ExpressionGenerator)propertySelector).generate(property -> { PropertyNameResolver propertyNameResolver = monkeyContext.getFixtureMonkeyOptions() @@ -592,7 +589,7 @@ private MonkeyExpression toMonkeyExpression(PropertySelector propertySelector) { return propertyNameResolver.resolve(property); }); - return monkeyExpressionFactory.from(stringExpression, rootClass); + return PathExpression.of(stringExpression); } throw new UnsupportedOperationException( diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/builder/StrictModeSizeValidator.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/builder/StrictModeSizeValidator.java new file mode 100644 index 0000000000..83109d6f30 --- /dev/null +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/builder/StrictModeSizeValidator.java @@ -0,0 +1,125 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.builder; + +import java.lang.reflect.AnnotatedType; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.jspecify.annotations.Nullable; + +import com.navercorp.fixturemonkey.api.type.TypeCache; +import com.navercorp.objectfarm.api.expression.IndexSelector; +import com.navercorp.objectfarm.api.expression.KeySelector; +import com.navercorp.objectfarm.api.expression.NameSelector; +import com.navercorp.objectfarm.api.expression.PathExpression; +import com.navercorp.objectfarm.api.expression.Segment; +import com.navercorp.objectfarm.api.expression.Selector; +import com.navercorp.objectfarm.api.expression.ValueSelector; +import com.navercorp.objectfarm.api.expression.WildcardSelector; +import com.navercorp.objectfarm.api.type.JvmType; +import com.navercorp.objectfarm.api.type.JvmTypes; + +/** + * Validates that a size() path is reachable on a root type. Used by + * {@link DefaultArbitraryBuilder} when {@code expressionStrictMode} is enabled. + *

+ * Replaces the legacy {@code StrictModeNextNodePredicateContainer} validation that + * lived inside the deleted {@code MonkeyExpression} chain. + */ +final class StrictModeSizeValidator { + private StrictModeSizeValidator() { + } + + static boolean validate(JvmType rootType, PathExpression path) { + JvmType current = rootType; + + for (Segment segment : path.getSegments()) { + Selector selector = segment.isSingleSelector() ? segment.getFirstSelector() : null; + if (selector == null) { + return true; + } + + if (selector instanceof NameSelector) { + String name = ((NameSelector)selector).getName(); + JvmType resolved = childByName(current, name); + if (resolved == null) { + return false; + } + current = resolved; + } else if (selector instanceof IndexSelector || selector instanceof WildcardSelector) { + JvmType element = elementType(current); + if (element == null) { + return false; + } + current = element; + } else if (selector instanceof KeySelector) { + JvmType element = mapTypeArg(current, 0); + if (element == null) { + return false; + } + current = element; + } else if (selector instanceof ValueSelector) { + JvmType element = mapTypeArg(current, 1); + if (element == null) { + return false; + } + current = element; + } else { + return true; + } + } + return true; + } + + private static @Nullable JvmType childByName(JvmType type, String name) { + Class raw = type.getRawType(); + Field field = TypeCache.getFieldsByName(raw).get(name); + if (field == null) { + return null; + } + AnnotatedType annotatedType = field.getAnnotatedType(); + return JvmTypes.resolveJvmType(type, annotatedType.getType(), Arrays.asList(field.getAnnotations())); + } + + private static @Nullable JvmType elementType(JvmType type) { + Class raw = type.getRawType(); + if (raw.isArray()) { + return type.getComponentType(); + } + if (Collection.class.isAssignableFrom(raw)) { + List args = type.getTypeVariables(); + return args != null && !args.isEmpty() ? args.get(0) : null; + } + return null; + } + + private static @Nullable JvmType mapTypeArg(JvmType type, int index) { + Class raw = type.getRawType(); + if (Map.class.isAssignableFrom(raw)) { + List args = type.getTypeVariables(); + return args != null && args.size() > index ? args.get(index) : null; + } + return null; + } + +} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/ApplyNodeCountManipulator.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/ApplyNodeCountManipulator.java deleted file mode 100644 index 3e84c3cecc..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/ApplyNodeCountManipulator.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.customizer; - -import com.navercorp.fixturemonkey.tree.ObjectNode; - -public final class ApplyNodeCountManipulator implements NodeManipulator { - private final NodeManipulator nodeManipulator; - private int count; - - public ApplyNodeCountManipulator(NodeManipulator nodeManipulator, int count) { - this.nodeManipulator = nodeManipulator; - this.count = count; - } - - /** - * Returns the underlying node manipulator. - * - * @return the node manipulator being count-limited - */ - public NodeManipulator getNodeManipulator() { - return nodeManipulator; - } - - /** - * Returns the remaining count limit. - * - * @return the current count value - */ - public int getCount() { - return count; - } - - @Override - public void manipulate(ObjectNode objectNode) { - if (count > 0) { - count--; - nodeManipulator.manipulate(objectNode); - } - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/ArbitraryManipulator.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/ArbitraryManipulator.java deleted file mode 100644 index 6a8c9e15d2..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/ArbitraryManipulator.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.customizer; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import com.navercorp.fixturemonkey.tree.NodeResolver; -import com.navercorp.fixturemonkey.tree.ObjectTree; - -@API(since = "0.4.0", status = Status.MAINTAINED) -public final class ArbitraryManipulator { - private final NodeResolver nodeResolver; - private final NodeManipulator nodeManipulator; - - ArbitraryManipulator(NodeResolver nodeResolver, NodeManipulator nodeManipulator) { - this.nodeResolver = nodeResolver; - this.nodeManipulator = nodeManipulator; - } - - public NodeResolver getNodeResolver() { - return nodeResolver; - } - - public NodeManipulator getNodeManipulator() { - return nodeManipulator; - } - - public void manipulate(ObjectTree tree) { - tree.manipulate(nodeResolver, nodeManipulator); - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/CompositeNodeManipulator.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/CompositeNodeManipulator.java deleted file mode 100644 index 3f7e5c97c0..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/CompositeNodeManipulator.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.customizer; - -import java.util.Arrays; -import java.util.List; - -import com.navercorp.fixturemonkey.tree.ObjectNode; - -public final class CompositeNodeManipulator implements NodeManipulator { - private final List manipulators; - - public CompositeNodeManipulator(NodeManipulator... manipulators) { - this.manipulators = Arrays.asList(manipulators); - } - - /** - * Returns the list of manipulators contained in this composite. - * - * @return unmodifiable list of node manipulators - */ - public List getManipulators() { - return manipulators; - } - - @Override - public void manipulate(ObjectNode objectNode) { - for (NodeManipulator manipulator : manipulators) { - manipulator.manipulate(objectNode); - } - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/ContainerInfoManipulator.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/ContainerInfoManipulator.java deleted file mode 100644 index 5c61ee60a8..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/ContainerInfoManipulator.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.customizer; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfo; -import com.navercorp.fixturemonkey.api.generator.ObjectProperty; -import com.navercorp.fixturemonkey.api.tree.TraverseNodePredicate; -import com.navercorp.fixturemonkey.api.tree.TreeNodeManipulator; -import com.navercorp.fixturemonkey.tree.NextNodePredicate; -import com.navercorp.fixturemonkey.tree.PropertyPredicate; -import com.navercorp.fixturemonkey.tree.StartNodePredicate; - -@API(since = "0.4.0", status = Status.MAINTAINED) -public final class ContainerInfoManipulator extends TreeNodeManipulator { - private final List nextNodePredicates; - private ArbitraryContainerInfo containerInfo; - /** - * The sequence of a size manipulation. - * It may dismiss if a sequence of set is bigger. - */ - private final int manipulatingSequence; - - public ContainerInfoManipulator( - List nextNodePredicates, - ArbitraryContainerInfo containerInfo, - int manipulatingSequence - ) { - super(nextNodePredicates.stream().map(TraverseNodePredicate.class::cast).collect(Collectors.toList()), - containerInfo, - manipulatingSequence); - this.nextNodePredicates = nextNodePredicates; - this.containerInfo = containerInfo; - this.manipulatingSequence = manipulatingSequence; - } - - public ContainerInfoManipulator copy() { - return new ContainerInfoManipulator( - this.getNextNodePredicates(), - new ArbitraryContainerInfo( - containerInfo.getElementMinSize(), - containerInfo.getElementMaxSize() - ), - manipulatingSequence - ); - } - - public List getNextNodePredicates() { - return nextNodePredicates; - } - - public ArbitraryContainerInfo getContainerInfo() { - return containerInfo; - } - - public ContainerInfoManipulator withPrependNextNodePredicate(NextNodePredicate nextNodePredicate) { - List nodePredicatesWithoutRoot = this.nextNodePredicates.stream() - .filter(it -> !(it instanceof StartNodePredicate)) - .collect(Collectors.toList()); - - List newNextNodePredicates = new ArrayList<>(); - newNextNodePredicates.add(nextNodePredicate); - newNextNodePredicates.addAll(nodePredicatesWithoutRoot); - - return new ContainerInfoManipulator( - newNextNodePredicates, - this.containerInfo, - manipulatingSequence - ); - } - - public int getManipulatingSequence() { - return manipulatingSequence; - } - - public void fixed() { - int fixedSize = this.containerInfo.getRandomSize(); - - this.containerInfo = new ArbitraryContainerInfo( - fixedSize, - fixedSize - ); - } - - public boolean isMatch(List objectProperties) { - int objectPropertiesSize = objectProperties.size(); - int nextNodePredicateSize = nextNodePredicates.size(); - - boolean registered = nextNodePredicates.get(0) instanceof PropertyPredicate; - if (!registered && nextNodePredicateSize != objectPropertiesSize) { - return false; - } - - for (int i = 0; i < nextNodePredicateSize; i++) { - int reversedNextNodePredicateIndex = nextNodePredicateSize - 1 - i; - int reversedCurrentObjectPropertyIndex = objectPropertiesSize - 1 - i; - NextNodePredicate nextNodePredicate = nextNodePredicates.get(reversedNextNodePredicateIndex); - ObjectProperty objectProperty = objectProperties.get(reversedCurrentObjectPropertyIndex); - - if (!nextNodePredicate.test(objectProperty)) { - return false; - } - } - return true; - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/CustomizerDirective.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/CustomizerDirective.java new file mode 100644 index 0000000000..4b7c7eed52 --- /dev/null +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/CustomizerDirective.java @@ -0,0 +1,85 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.customizer; + +import java.util.function.Function; + +import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; + +import com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary; +import com.navercorp.objectfarm.api.expression.PathExpression; + +/** + * Applies a {@link CombinableArbitrary} transformer to the value generated at a path. + */ +@API(since = "0.4.0", status = Status.EXPERIMENTAL) +public final class CustomizerDirective implements PathDirective { + private final PathExpression path; + private final int sequence; + private final int limit; + private final boolean strict; + private final boolean registered; + private final Function, CombinableArbitrary> customizer; + + public CustomizerDirective( + PathExpression path, + int sequence, + int limit, + boolean strict, + boolean registered, + Function, CombinableArbitrary> customizer + ) { + this.path = path; + this.sequence = sequence; + this.limit = limit; + this.strict = strict; + this.registered = registered; + this.customizer = customizer; + } + + @Override + public PathExpression path() { + return path; + } + + @Override + public int sequence() { + return sequence; + } + + @Override + public int limit() { + return limit; + } + + @Override + public boolean strict() { + return strict; + } + + @Override + public boolean registered() { + return registered; + } + + public Function, CombinableArbitrary> customizer() { + return customizer; + } +} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/FilterDirective.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/FilterDirective.java new file mode 100644 index 0000000000..c5c8c55657 --- /dev/null +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/FilterDirective.java @@ -0,0 +1,92 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.customizer; + +import java.util.function.Predicate; + +import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; + +import com.navercorp.objectfarm.api.expression.PathExpression; + +/** + * Applies a post-condition predicate to the value generated at a path. + */ +@SuppressWarnings("rawtypes") +@API(since = "0.4.0", status = Status.EXPERIMENTAL) +public final class FilterDirective implements PathDirective { + private final PathExpression path; + private final int sequence; + private final int limit; + private final boolean strict; + private final boolean registered; + private final Class type; + private final Predicate filter; + + public FilterDirective( + PathExpression path, + int sequence, + int limit, + boolean strict, + boolean registered, + Class type, + Predicate filter + ) { + this.path = path; + this.sequence = sequence; + this.limit = limit; + this.strict = strict; + this.registered = registered; + this.type = type; + this.filter = filter; + } + + @Override + public PathExpression path() { + return path; + } + + @Override + public int sequence() { + return sequence; + } + + @Override + public int limit() { + return limit; + } + + @Override + public boolean strict() { + return strict; + } + + @Override + public boolean registered() { + return registered; + } + + public Class type() { + return type; + } + + public Predicate filter() { + return filter; + } +} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/InnerSpec.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/InnerSpec.java index 5255a73f21..98ccf3cbb8 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/InnerSpec.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/InnerSpec.java @@ -667,7 +667,7 @@ private ManipulatorHolderSet traverse(InnerSpec innerSpec) { for (InnerSpec spec : innerSpec.innerSpecs) { ManipulatorHolderSet traversed = traverse(spec); nodeSetManipulatorSnapshots.addAll(traversed.getNodeResolverObjectHolders()); - containerInfoManipulators.addAll(traversed.getContainerInfoManipulators()); + containerInfoManipulators.addAll(traversed.getSizeDirectives()); postConditionManipulators.addAll(traversed.getPostConditionManipulators()); } diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/InnerSpecState.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/InnerSpecState.java index c2800653ca..1e3bb5705e 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/InnerSpecState.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/InnerSpecState.java @@ -26,7 +26,7 @@ import org.jspecify.annotations.Nullable; import com.navercorp.fixturemonkey.expression.DefaultDeclarativeExpression; -import com.navercorp.fixturemonkey.tree.NextNodePredicate; +import com.navercorp.objectfarm.api.expression.PathExpression; @API(since = "0.5.0", status = Status.MAINTAINED) final class InnerSpecState { @@ -118,8 +118,8 @@ int getSequence() { return sequence; } - List getNextNodePredicates() { - return this.declarativeExpression.getNestedNextNodePredicates(); + PathExpression getPath() { + return this.declarativeExpression.getPath(); } int getElementMinSize() { @@ -153,8 +153,8 @@ public int getSequence() { return sequence; } - List getNextNodePredicates() { - return this.declarativeExpression.getNestedNextNodePredicates(); + PathExpression getPath() { + return this.declarativeExpression.getPath(); } Class getType() { @@ -181,8 +181,8 @@ public NodeSetManipulatorSnapshot( this.value = value; } - List getNextNodePredicates() { - return this.declarativeExpression.getNestedNextNodePredicates(); + PathExpression getPath() { + return this.declarativeExpression.getPath(); } Object getValue() { @@ -213,7 +213,7 @@ public List getNodeResolverObjectHolders() { return nodeSetManipulatorSnapshots; } - public List getContainerInfoManipulators() { + public List getSizeDirectives() { return containerInfoManipulators; } diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/JustDirective.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/JustDirective.java new file mode 100644 index 0000000000..3b3ae42555 --- /dev/null +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/JustDirective.java @@ -0,0 +1,88 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.customizer; + +import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; +import org.jspecify.annotations.Nullable; + +import com.navercorp.fixturemonkey.customizer.Values.Just; +import com.navercorp.objectfarm.api.expression.PathExpression; + +/** + * Sets an immutable value at a path. Child values are intentionally ignored. + */ +@API(since = "0.4.0", status = Status.EXPERIMENTAL) +public final class JustDirective implements PathDirective { + private final PathExpression path; + private final int sequence; + private final int limit; + private final boolean strict; + private final boolean registered; + private final Just just; + + public JustDirective( + PathExpression path, + int sequence, + int limit, + boolean strict, + boolean registered, + Just just + ) { + this.path = path; + this.sequence = sequence; + this.limit = limit; + this.strict = strict; + this.registered = registered; + this.just = just; + } + + @Override + public PathExpression path() { + return path; + } + + @Override + public int sequence() { + return sequence; + } + + @Override + public int limit() { + return limit; + } + + @Override + public boolean strict() { + return strict; + } + + @Override + public boolean registered() { + return registered; + } + + public Just just() { + return just; + } + + public @Nullable Object value() { + return just.getValue(); + } +} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/LazyDirective.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/LazyDirective.java new file mode 100644 index 0000000000..c328878233 --- /dev/null +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/LazyDirective.java @@ -0,0 +1,103 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.customizer; + +import java.util.List; + +import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; + +import com.navercorp.fixturemonkey.api.container.DecomposedContainerValueFactory; +import com.navercorp.fixturemonkey.api.generator.ContainerPropertyGenerator; +import com.navercorp.fixturemonkey.api.lazy.LazyArbitrary; +import com.navercorp.fixturemonkey.api.matcher.MatcherOperator; +import com.navercorp.objectfarm.api.expression.PathExpression; + +/** + * Sets a lazily evaluated value at a path. The {@link LazyArbitrary} is invoked at assembly time + * and its result is then decomposed. + */ +@API(since = "0.4.0", status = Status.EXPERIMENTAL) +public final class LazyDirective implements PathDirective { + private final PathExpression path; + private final int sequence; + private final int limit; + private final boolean strict; + private final boolean registered; + private final LazyArbitrary lazyArbitrary; + private final DecomposedContainerValueFactory decomposedContainerValueFactory; + private final List> containerPropertyGenerators; + + public LazyDirective( + PathExpression path, + int sequence, + int limit, + boolean strict, + boolean registered, + LazyArbitrary lazyArbitrary, + DecomposedContainerValueFactory decomposedContainerValueFactory, + List> containerPropertyGenerators + ) { + this.path = path; + this.sequence = sequence; + this.limit = limit; + this.strict = strict; + this.registered = registered; + this.lazyArbitrary = lazyArbitrary; + this.decomposedContainerValueFactory = decomposedContainerValueFactory; + this.containerPropertyGenerators = containerPropertyGenerators; + } + + @Override + public PathExpression path() { + return path; + } + + @Override + public int sequence() { + return sequence; + } + + @Override + public int limit() { + return limit; + } + + @Override + public boolean strict() { + return strict; + } + + @Override + public boolean registered() { + return registered; + } + + public LazyArbitrary lazyArbitrary() { + return lazyArbitrary; + } + + public DecomposedContainerValueFactory decomposedContainerValueFactory() { + return decomposedContainerValueFactory; + } + + public List> containerPropertyGenerators() { + return containerPropertyGenerators; + } +} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/ManipulatorSet.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/ManipulatorSet.java index d093cd1c9b..d457efa9c6 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/ManipulatorSet.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/ManipulatorSet.java @@ -18,6 +18,7 @@ package com.navercorp.fixturemonkey.customizer; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; @@ -29,12 +30,18 @@ import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfo; import com.navercorp.fixturemonkey.api.introspector.ArbitraryIntrospector; import com.navercorp.fixturemonkey.api.property.Property; +import com.navercorp.fixturemonkey.customizer.PathDirective; +import com.navercorp.fixturemonkey.customizer.SizeDirective; import com.navercorp.objectfarm.api.type.JvmType; @API(since = "0.5.0", status = Status.MAINTAINED) public final class ManipulatorSet { - private final List arbitraryManipulators; - private final List containerInfoManipulators; + /** + * All user-issued path directives — set / null / lazy / filter / customizer / size — in + * the order they were declared. Size directives ({@link SizeDirective}) are mixed in + * alongside the others; downstream consumers filter by subtype. + */ + private final List directives; /** * Type-based container sizes from registered builders. @@ -66,13 +73,9 @@ public final class ManipulatorSet { private final Map, ArbitraryIntrospector> arbitraryIntrospectorsByType; private final boolean fixed; - public ManipulatorSet( - List arbitraryManipulators, - List containerInfoManipulators - ) { + public ManipulatorSet(List directives) { this( - arbitraryManipulators, - containerInfoManipulators, + directives, Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap(), @@ -82,16 +85,14 @@ public ManipulatorSet( } public ManipulatorSet( - List arbitraryManipulators, - List containerInfoManipulators, + List directives, Map> typedContainerSizes, Map> typedValues, Map, List> propertyConfigurers, Map, ArbitraryIntrospector> arbitraryIntrospectorsByType, boolean fixed ) { - this.arbitraryManipulators = arbitraryManipulators; - this.containerInfoManipulators = containerInfoManipulators; + this.directives = directives; this.typedContainerSizes = typedContainerSizes; this.typedValues = typedValues; this.propertyConfigurers = propertyConfigurers; @@ -99,12 +100,22 @@ public ManipulatorSet( this.fixed = fixed; } - public List getArbitraryManipulators() { - return arbitraryManipulators; + public List getDirectives() { + return directives; } - public List getContainerInfoManipulators() { - return containerInfoManipulators; + /** + * Filters {@link #directives} down to {@link SizeDirective}s. Used by adapter consumers + * that only need container-size manipulations. + */ + public List getSizeDirectives() { + List sizes = new ArrayList<>(); + for (PathDirective directive : directives) { + if (directive instanceof SizeDirective) { + sizes.add((SizeDirective)directive); + } + } + return sizes; } public Map> getTypedContainerSizes() { @@ -128,8 +139,7 @@ public boolean isFixed() { } public boolean isEmpty() { - return arbitraryManipulators.isEmpty() - && containerInfoManipulators.isEmpty() + return directives.isEmpty() && typedContainerSizes.isEmpty() && typedValues.isEmpty() && propertyConfigurers.isEmpty() diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/MonkeyManipulatorFactory.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/MonkeyManipulatorFactory.java index de000de445..5841f2fa48 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/MonkeyManipulatorFactory.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/MonkeyManipulatorFactory.java @@ -21,11 +21,7 @@ import static java.util.stream.Collectors.toList; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; import java.util.function.Predicate; @@ -43,20 +39,19 @@ import com.navercorp.fixturemonkey.api.generator.ContainerPropertyGenerator; import com.navercorp.fixturemonkey.api.lazy.LazyArbitrary; import com.navercorp.fixturemonkey.api.matcher.MatcherOperator; -import com.navercorp.fixturemonkey.api.matcher.PriorityMatcherOperator; -import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.api.random.Randoms; -import com.navercorp.fixturemonkey.builder.ArbitraryBuilderContext; import com.navercorp.fixturemonkey.builder.DefaultArbitraryBuilder; +import com.navercorp.fixturemonkey.customizer.CustomizerDirective; +import com.navercorp.fixturemonkey.customizer.FilterDirective; import com.navercorp.fixturemonkey.customizer.InnerSpecState.ManipulatorHolderSet; +import com.navercorp.fixturemonkey.customizer.JustDirective; +import com.navercorp.fixturemonkey.customizer.LazyDirective; +import com.navercorp.fixturemonkey.customizer.NullityDirective; +import com.navercorp.fixturemonkey.customizer.PathDirective; +import com.navercorp.fixturemonkey.customizer.SetDirective; +import com.navercorp.fixturemonkey.customizer.SizeDirective; import com.navercorp.fixturemonkey.customizer.Values.Just; import com.navercorp.fixturemonkey.customizer.Values.Unique; -import com.navercorp.fixturemonkey.tree.CompositeNodeResolver; -import com.navercorp.fixturemonkey.tree.NextNodePredicate; -import com.navercorp.fixturemonkey.tree.NodePredicateResolver; -import com.navercorp.fixturemonkey.tree.NodeResolver; -import com.navercorp.fixturemonkey.tree.ObjectNode; -import com.navercorp.fixturemonkey.tree.StaticNodeResolver; +import com.navercorp.objectfarm.api.expression.PathExpression; /** * It is for internal use only. @@ -67,243 +62,188 @@ public final class MonkeyManipulatorFactory { private final AtomicInteger sequence; private final DecomposedContainerValueFactory decomposedContainerValueFactory; private final List> containerPropertyGenerators; + private final boolean expressionStrictMode; public MonkeyManipulatorFactory( AtomicInteger sequence, DecomposedContainerValueFactory decomposedContainerValueFactory, List> containerPropertyGenerators + ) { + this(sequence, decomposedContainerValueFactory, containerPropertyGenerators, false); + } + + public MonkeyManipulatorFactory( + AtomicInteger sequence, + DecomposedContainerValueFactory decomposedContainerValueFactory, + List> containerPropertyGenerators, + boolean expressionStrictMode ) { this.sequence = sequence; this.decomposedContainerValueFactory = decomposedContainerValueFactory; this.containerPropertyGenerators = containerPropertyGenerators; + this.expressionStrictMode = expressionStrictMode; } - public ArbitraryManipulator newArbitraryManipulator(NodeResolver nodeResolver, @Nullable Object value, int limit) { - return new ArbitraryManipulator(nodeResolver, convertToNodeManipulator(value, limit)); + public boolean isExpressionStrictMode() { + return expressionStrictMode; } - public ArbitraryManipulator newArbitraryManipulator(NodeResolver nodeResolver, @Nullable Object value) { - return new ArbitraryManipulator(nodeResolver, convertToNodeManipulator(sequence.getAndIncrement(), value)); + public PathDirective newDirective(PathExpression path, @Nullable Object value, int limit) { + return convertToDirective(path, sequence.getAndIncrement(), value, limit, false); } - public ArbitraryManipulator newArbitraryManipulator( - NodeResolver nodeResolver, + public PathDirective newDirective(PathExpression path, @Nullable Object value) { + return convertToDirective(path, sequence.getAndIncrement(), value, -1, false); + } + + public PathDirective newDirective( + PathExpression path, Class type, Predicate filter, int limit ) { - return new ArbitraryManipulator( - nodeResolver, - new ApplyNodeCountManipulator(new NodeFilterManipulator(type, filter), limit) + return new FilterDirective( + path, + sequence.getAndIncrement(), + limit, + expressionStrictMode, + false, + type, + filter ); } - public ArbitraryManipulator newArbitraryManipulator( - NodeResolver nodeResolver, + public PathDirective newDirective( + PathExpression path, @Nullable Function, CombinableArbitrary> arbitraryCustomizer ) { if (arbitraryCustomizer == null) { - return newArbitraryManipulator(nodeResolver, (Object)null); + return newDirective(path, (Object)null); } - return new ArbitraryManipulator(nodeResolver, new NodeCustomizerManipulator<>(arbitraryCustomizer)); - } - - public ContainerInfoManipulator newContainerInfoManipulator( - List nextNodePredicates, - int min, - int max - ) { - int newSequence = sequence.getAndIncrement(); - - return new ContainerInfoManipulator(nextNodePredicates, new ArbitraryContainerInfo(min, max), newSequence); - } - - public List newRegisteredArbitraryManipulators( // TODO: Fragmented registered - List> standbyContexts, - Map> nodesByType - ) { - List manipulators = new ArrayList<>(); - - for (Entry> nodeByType : nodesByType.entrySet()) { - Property property = nodeByType.getKey(); - List objectNodes = nodeByType.getValue(); - - ArbitraryBuilderContext activeContext = findRegisteredArbitraryBuilderContext(standbyContexts, property); - - if (activeContext == null) { - continue; - } - - List arbitraryManipulators = activeContext - .getManipulators() - .stream() - .map(it -> - new ArbitraryManipulator( - new CompositeNodeResolver(new StaticNodeResolver(objectNodes), it.getNodeResolver()), - it.getNodeManipulator() - ) - ) - .collect(toList()); - - manipulators.addAll(arbitraryManipulators); - } - return manipulators; - } - - private @Nullable ArbitraryBuilderContext findRegisteredArbitraryBuilderContext( - List> standbyContexts, - Property property - ) { - List> priorityOperators = standbyContexts - .stream() - .filter(it -> it.match(property)) - .sorted(Comparator.comparingInt(PriorityMatcherOperator::getPriority)) - .collect(toList()); - - List> highestPriorityOperators = getHighestPriorityOperators( - priorityOperators + return new CustomizerDirective<>( + path, + sequence.getAndIncrement(), + -1, + expressionStrictMode, + false, + arbitraryCustomizer ); - - if (highestPriorityOperators.size() > 1) { - Collections.shuffle(highestPriorityOperators, Randoms.current()); - } - - return highestPriorityOperators.stream().findFirst().map(MatcherOperator::getOperator).orElse(null); } - private List> getHighestPriorityOperators( - List> priorityOperators - ) { - if (priorityOperators.isEmpty()) { - return priorityOperators; - } - - int highestPriority = priorityOperators.get(0).getPriority(); - - return priorityOperators - .stream() - .filter(it -> it.getPriority() == highestPriority) - .collect(toList()); + public SizeDirective newSizeDirective(PathExpression path, int min, int max) { + return new SizeDirective(path, sequence.getAndIncrement(), min, max); } public ManipulatorSet newManipulatorSet(ManipulatorHolderSet manipulatorHolderSet) { int baseSequence = sequence.getAndIncrement(); - List arbitraryManipulators = new ArrayList<>(); + List directives = new ArrayList<>(); - List setArbitraryManipulators = manipulatorHolderSet + List setArbitraryManipulators = manipulatorHolderSet .getNodeResolverObjectHolders() .stream() - .map(it -> { - List nextNodeResolvers = it - .getNextNodePredicates() - .stream() - .map(NodePredicateResolver::new) - .collect(toList()); - - CompositeNodeResolver compositeNodeResolver = new CompositeNodeResolver(nextNodeResolvers); - return new ArbitraryManipulator( - compositeNodeResolver, - convertToNodeManipulator(baseSequence + it.getSequence(), it.getValue()) - ); - }) + .map(it -> convertToDirective( + it.getPath(), + baseSequence + it.getSequence(), + it.getValue(), + -1, + false + )) .collect(toList()); - List filterArbitraryManipulators = manipulatorHolderSet + List filterArbitraryManipulators = manipulatorHolderSet .getPostConditionManipulators() .stream() - .map(it -> { - List nextNodeResolvers = it - .getNextNodePredicates() - .stream() - .map(NodePredicateResolver::new) - .collect(toList()); - - CompositeNodeResolver compositeNodeResolver = new CompositeNodeResolver(nextNodeResolvers); - return new ArbitraryManipulator( - compositeNodeResolver, - new NodeFilterManipulator(it.getType(), it.getPredicate()) - ); - }) + .map(it -> (PathDirective)new FilterDirective( + it.getPath(), + sequence.getAndIncrement(), + -1, + false, + false, + it.getType(), + it.getPredicate() + )) .collect(toList()); - arbitraryManipulators.addAll(setArbitraryManipulators); - arbitraryManipulators.addAll(filterArbitraryManipulators); + directives.addAll(setArbitraryManipulators); + directives.addAll(filterArbitraryManipulators); - List containerInfoManipulators = manipulatorHolderSet - .getContainerInfoManipulators() + List sizeDirectives = manipulatorHolderSet + .getSizeDirectives() .stream() - .map(it -> - new ContainerInfoManipulator( - it.getNextNodePredicates(), - new ArbitraryContainerInfo(it.getElementMinSize(), it.getElementMaxSize()), - baseSequence + it.getSequence() - ) - ) + .map(it -> (PathDirective)new SizeDirective( + it.getPath(), + baseSequence + it.getSequence(), + new ArbitraryContainerInfo(it.getElementMinSize(), it.getElementMaxSize()) + )) .collect(toList()); + directives.addAll(sizeDirectives); - sequence.set(sequence.get() + containerInfoManipulators.size() + arbitraryManipulators.size()); - return new ManipulatorSet(arbitraryManipulators, containerInfoManipulators); + sequence.set(sequence.get() + directives.size()); + return new ManipulatorSet(directives); } public MonkeyManipulatorFactory copy() { return new MonkeyManipulatorFactory( new AtomicInteger(sequence.get()), decomposedContainerValueFactory, - containerPropertyGenerators + containerPropertyGenerators, + expressionStrictMode ); } - private NodeManipulator convertToNodeManipulator(@Nullable Object value, int limit) { - NodeManipulator nodeManipulator = convertToNodeManipulator(sequence.getAndIncrement(), value); - return new ApplyNodeCountManipulator(nodeManipulator, limit); - } - - private NodeManipulator convertToNodeManipulator(int sequence, @Nullable Object value) { + private PathDirective convertToDirective( + PathExpression path, + int seq, + @Nullable Object value, + int limit, + boolean registered + ) { if (value == null) { - return new NodeNullityManipulator(sequence, true); + return new NullityDirective(path, seq, limit, expressionStrictMode, registered, true); } else if (value == Values.NOT_NULL) { - return new NodeNullityManipulator(sequence, false); + return new NullityDirective(path, seq, limit, expressionStrictMode, registered, false); } else if (value instanceof Just) { - return new NodeSetJustManipulator((Just)value); + return new JustDirective(path, seq, limit, expressionStrictMode, registered, (Just)value); } else if (value instanceof Arbitrary) { - return new NodeSetLazyManipulator<>( - sequence, + return new LazyDirective( + path, seq, limit, expressionStrictMode, registered, + LazyArbitrary.lazy(() -> ((Arbitrary)value).sample()), decomposedContainerValueFactory, - containerPropertyGenerators, - LazyArbitrary.lazy(() -> ((Arbitrary)value).sample()) + containerPropertyGenerators ); } else if (value instanceof DefaultArbitraryBuilder) { - return new NodeSetLazyManipulator<>( - sequence, + return new LazyDirective( + path, seq, limit, expressionStrictMode, registered, + LazyArbitrary.lazy(() -> ((DefaultArbitraryBuilder)value).sample()), decomposedContainerValueFactory, - containerPropertyGenerators, - LazyArbitrary.lazy(() -> ((DefaultArbitraryBuilder)value).sample()) + containerPropertyGenerators ); } else if (value instanceof Supplier) { - return new NodeSetLazyManipulator<>( - sequence, + return new LazyDirective( + path, seq, limit, expressionStrictMode, registered, + LazyArbitrary.lazy((Supplier)value), decomposedContainerValueFactory, - containerPropertyGenerators, - LazyArbitrary.lazy((Supplier)value) + containerPropertyGenerators ); } else if (value instanceof LazyArbitrary) { - return new NodeSetLazyManipulator<>( - sequence, + return new LazyDirective( + path, seq, limit, expressionStrictMode, registered, + (LazyArbitrary)value, decomposedContainerValueFactory, - containerPropertyGenerators, - (LazyArbitrary)value + containerPropertyGenerators ); } else if (value instanceof Unique) { - return new NodeSetJustManipulator( + return new JustDirective( + path, seq, limit, expressionStrictMode, registered, Values.just(CombinableArbitrary.from(((Unique)value).getValueSupplier()).unique()) ); } else { - return new NodeSetDecomposedValueManipulator<>( - sequence, + return new SetDirective( + path, seq, limit, expressionStrictMode, registered, + value, decomposedContainerValueFactory, - containerPropertyGenerators, - value + containerPropertyGenerators ); } } diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeCustomizerManipulator.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeCustomizerManipulator.java deleted file mode 100644 index 6c24b85419..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeCustomizerManipulator.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.customizer; - -import java.util.function.Function; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary; -import com.navercorp.fixturemonkey.tree.GenerateFixtureContext; -import com.navercorp.fixturemonkey.tree.ObjectNode; - -@API(since = "1.0.9", status = Status.EXPERIMENTAL) -public final class NodeCustomizerManipulator implements NodeManipulator { - private final Function, CombinableArbitrary> arbitraryCustomizer; - - public NodeCustomizerManipulator( - Function, CombinableArbitrary> arbitraryCustomizer - ) { - this.arbitraryCustomizer = arbitraryCustomizer; - } - - public Function, CombinableArbitrary> getArbitraryCustomizer() { - return arbitraryCustomizer; - } - - @SuppressWarnings({"rawtypes", "unchecked", "argument"}) - @Override - public void manipulate(ObjectNode objectNode) { - GenerateFixtureContext generateFixtureContext = (GenerateFixtureContext)objectNode.getObjectNodeContext(); - if (generateFixtureContext.getArbitrary() != null) { - CombinableArbitrary customized = arbitraryCustomizer.apply( - (CombinableArbitrary)generateFixtureContext.getArbitrary()); - generateFixtureContext.setArbitrary(customized); - } else { - generateFixtureContext.addGeneratedArbitraryCustomizer((Function)arbitraryCustomizer); - } - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeFilterManipulator.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeFilterManipulator.java deleted file mode 100644 index f7d4591315..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeFilterManipulator.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.customizer; - -import static com.navercorp.fixturemonkey.api.type.Types.isAssignable; - -import java.util.function.Predicate; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import com.navercorp.fixturemonkey.api.type.Types; -import com.navercorp.fixturemonkey.tree.ObjectNode; - -@SuppressWarnings("rawtypes") -@API(since = "0.4.0", status = Status.MAINTAINED) -public final class NodeFilterManipulator implements NodeManipulator { - private final Class type; - private final Predicate filter; - - public NodeFilterManipulator(Class type, Predicate filter) { - this.type = type; - this.filter = filter; - } - - /** - * Returns the type that this filter applies to. - * - * @return the filter type - */ - public Class getType() { - return type; - } - - /** - * Returns the filter predicate. - * - * @return the filter predicate - */ - public Predicate getFilter() { - return filter; - } - - @Override - public void manipulate(ObjectNode objectNode) { - Class actualType = Types.getActualType(objectNode.getOriginalProperty().getType()); - if (!isAssignable(actualType, type)) { - throw new IllegalArgumentException( - "Wrong type filter is applied. Expected: " + type + ", Actual: " + actualType - ); - } - objectNode.getObjectNodeContext().addArbitraryFilter(filter); - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeManipulator.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeManipulator.java deleted file mode 100644 index f4cbd7d871..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeManipulator.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.customizer; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import com.navercorp.fixturemonkey.tree.ObjectNode; - -@API(since = "0.4.0", status = Status.MAINTAINED) -@FunctionalInterface -public interface NodeManipulator { - void manipulate(ObjectNode objectNode); -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeNullityManipulator.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeNullityManipulator.java deleted file mode 100644 index b6665236a0..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeNullityManipulator.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.customizer; - -import static com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary.NOT_GENERATED; -import static com.navercorp.fixturemonkey.api.generator.DefaultNullInjectGenerator.ALWAYS_NULL_INJECT; -import static com.navercorp.fixturemonkey.api.generator.DefaultNullInjectGenerator.NOT_NULL_INJECT; - -import com.navercorp.fixturemonkey.tree.GenerateFixtureContext; -import com.navercorp.fixturemonkey.tree.ObjectNode; - -public final class NodeNullityManipulator implements NodeManipulator { - private final int sequence; - private final boolean toNull; - - public NodeNullityManipulator(int sequence, boolean toNull) { - this.sequence = sequence; - this.toNull = toNull; - } - - public int getSequence() { - return sequence; - } - - public boolean isToNull() { - return toNull; - } - - @Override - public void manipulate(ObjectNode objectNode) { - if (toNull) { - objectNode.setNullInject(ALWAYS_NULL_INJECT); - } else { - GenerateFixtureContext generateFixtureContext = (GenerateFixtureContext)objectNode.getObjectNodeContext(); - if (NOT_GENERATED.equals(generateFixtureContext.getArbitrary())) { - generateFixtureContext.setArbitrary(null); // initializing for regenerate - } - objectNode.setNullInject(NOT_NULL_INJECT); - } - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeSetDecomposedValueManipulator.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeSetDecomposedValueManipulator.java deleted file mode 100644 index 7e9fd2f33c..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeSetDecomposedValueManipulator.java +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.customizer; - -import static com.navercorp.fixturemonkey.api.generator.DefaultNullInjectGenerator.ALWAYS_NULL_INJECT; -import static com.navercorp.fixturemonkey.api.generator.DefaultNullInjectGenerator.NOT_NULL_INJECT; -import static com.navercorp.fixturemonkey.api.type.Types.isAssignable; -import static com.navercorp.fixturemonkey.api.type.Types.nullSafe; - -import java.util.List; -import java.util.function.Function; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; -import org.jspecify.annotations.Nullable; - -import com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary; -import com.navercorp.fixturemonkey.api.container.DecomposableJavaContainer; -import com.navercorp.fixturemonkey.api.container.DecomposedContainerValueFactory; -import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfo; -import com.navercorp.fixturemonkey.api.generator.ContainerProperty; -import com.navercorp.fixturemonkey.api.generator.ContainerPropertyGenerator; -import com.navercorp.fixturemonkey.api.generator.ContainerPropertyGeneratorContext; -import com.navercorp.fixturemonkey.api.matcher.MatcherOperator; -import com.navercorp.fixturemonkey.api.property.DefaultTypeDefinition; -import com.navercorp.fixturemonkey.api.property.LazyPropertyGenerator; -import com.navercorp.fixturemonkey.api.property.MapEntryElementProperty; -import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.api.property.TypeDefinition; -import com.navercorp.fixturemonkey.api.tree.TreeNodeManipulator; -import com.navercorp.fixturemonkey.api.type.Types; -import com.navercorp.fixturemonkey.tree.GenerateFixtureContext; -import com.navercorp.fixturemonkey.tree.ObjectNode; - -@API(since = "0.4.0", status = Status.MAINTAINED) -public final class NodeSetDecomposedValueManipulator implements NodeManipulator { - private final int sequence; - private final DecomposedContainerValueFactory decomposedContainerValueFactory; - private final List> containerPropertyGenerators; - private final @Nullable T value; - - public NodeSetDecomposedValueManipulator( - int sequence, - DecomposedContainerValueFactory decomposedContainerValueFactory, - List> containerPropertyGenerators, - @Nullable T value - ) { - this.sequence = sequence; - this.decomposedContainerValueFactory = decomposedContainerValueFactory; - this.containerPropertyGenerators = containerPropertyGenerators; - this.value = value; - } - - public @Nullable T getValue() { - return value; - } - - public DecomposedContainerValueFactory getDecomposedContainerValueFactory() { - return decomposedContainerValueFactory; - } - - public int getSequence() { - return sequence; - } - - @Override - public void manipulate(ObjectNode objectNode) { - Class actualType = Types.getActualType(objectNode.getOriginalProperty().getType()); - if (value != null && !isAssignable(value.getClass(), actualType)) { - Property parentProperty = objectNode.getResolvedParentProperty(); - String parentNodeLogMessage = parentProperty != null - ? String.format( - "parent node type : %s", - parentProperty.getType().getTypeName() - ) - : ""; - throw new IllegalArgumentException( - String.format( - "The value is not of the same type as the property.\n" - + "%s node name: %s, node type: %s, value type: %s", - parentNodeLogMessage, - objectNode.getArbitraryProperty() - .getObjectProperty() - .getResolvedPropertyName(), - objectNode.getOriginalProperty().getType().getTypeName(), - value.getClass().getTypeName() - ) - ); - } - setValue(objectNode, value); - } - - private void setValue(ObjectNode objectNode, @Nullable Object value) { - objectNode.setNullInject(NOT_NULL_INJECT); - GenerateFixtureContext generateFixtureContext = objectNode.getObjectNodeContext(); - if (value == null) { - generateFixtureContext.addManipulator( - node -> node.getObjectNodeContext() - .setArbitrary(CombinableArbitrary.from((Object)null)) - ); - objectNode.setNullInject(ALWAYS_NULL_INJECT); - return; - } - - boolean container = objectNode.getArbitraryProperty().isContainer(); - if (container) { - if (Types.getActualType(objectNode.getResolvedProperty().getType()) == Function.class) { - generateFixtureContext.setArbitrary(CombinableArbitrary.from(value)); - return; - } - - DecomposableJavaContainer decomposableJavaContainer = decomposedContainerValueFactory.from(value); - Object containerValue = decomposableJavaContainer.getJavaContainer(); - int decomposedContainerSize = decomposableJavaContainer.getSize(); - - TreeNodeManipulator appliedContainerInfoManipulator = objectNode.getAppliedTreeNodeManipulator(); - boolean forced = !(objectNode.getOriginalProperty() instanceof MapEntryElementProperty) - && (appliedContainerInfoManipulator == null - || sequence > appliedContainerInfoManipulator.getManipulatingSequence()); - if (forced) { - ArbitraryContainerInfo containerInfo = - new ArbitraryContainerInfo(decomposedContainerSize, decomposedContainerSize); - - ContainerPropertyGenerator containerPropertyGenerator = containerPropertyGenerators.stream() - .filter(it -> it.match(objectNode.getOriginalProperty())) - .map(MatcherOperator::getOperator) - .findFirst() - .orElseThrow( - () -> new IllegalStateException( - "ContainerPropertyGenerator not found given property" + objectNode.getOriginalProperty() - ) - ); - - ContainerProperty containerProperty = containerPropertyGenerator.generate( - new ContainerPropertyGeneratorContext( - objectNode.getOriginalProperty(), - containerInfo, - null - ) - ); - - objectNode.forceExpand( - new DefaultTypeDefinition( - objectNode.getOriginalProperty(), - new LazyPropertyGenerator(p -> containerProperty.getElementProperties()) - ) - ); - } else { - objectNode.expand(); - } - List children = nullSafe(objectNode.getChildren()).asList(); - - if (objectNode.getArbitraryProperty() - .getObjectProperty() - .getProperty() instanceof MapEntryElementProperty) { - decomposedContainerSize *= 2; // key, value - } - - int decomposedNodeSize = Math.min(decomposedContainerSize, children.size()); - - for (int i = 0; i < decomposedNodeSize; i++) { - ObjectNode child = children.get(i); - Property childProperty = child.getOriginalProperty(); - setValue(child, childProperty.getValue(containerValue)); - } - return; - } - - objectNode.expand(); - List children = nullSafe(objectNode.getChildren()).asList(); - if (children.isEmpty() || Types.getActualType(objectNode.getResolvedProperty().getType()).isInterface()) { - CombinableArbitrary combinableArbitrary = CombinableArbitrary.from(value); - generateFixtureContext.addManipulator( - node -> node.getObjectNodeContext().setArbitrary(combinableArbitrary)); - generateFixtureContext.setArbitrary(combinableArbitrary); - return; - } - - objectNode.forceExpand(); - List typeDefinitions = objectNode.getTreeProperty().getTypeDefinitions(); - for (TypeDefinition typeDefinition : typeDefinitions) { - Class actualConcreteType = Types.getActualType(typeDefinition.getResolvedProperty().getType()); - if (isAssignable( - value.getClass(), - actualConcreteType - )) { - if (isAssignable( - actualConcreteType, - value.getClass() - )) { - objectNode.setResolvedTypeDefinition(typeDefinition); - } - - for (ObjectNode child : nullSafe(objectNode.getChildren()).asList()) { - if (!typeDefinition.getResolvedProperty().equals(child.getResolvedParentProperty())) { - continue; - } - Property childProperty = child.getMetadata().getOriginalProperty(); - setValue(child, childProperty.getValue(value)); - } - } - } - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeSetJustManipulator.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeSetJustManipulator.java deleted file mode 100644 index ed1a9fd924..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeSetJustManipulator.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.customizer; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; -import org.jspecify.annotations.Nullable; - -import com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary; -import com.navercorp.fixturemonkey.customizer.Values.Just; -import com.navercorp.fixturemonkey.tree.ObjectNode; - -@API(since = "0.5.1", status = Status.MAINTAINED) -public final class NodeSetJustManipulator implements NodeManipulator { - private final Just value; - - public NodeSetJustManipulator(Just value) { - this.value = value; - } - - public @Nullable Object getValue() { - return value.getValue(); - } - - @Override - public void manipulate(ObjectNode objectNode) { - Object exactValue = value.getValue(); - if (exactValue instanceof CombinableArbitrary) { - objectNode.getObjectNodeContext().setArbitrary((CombinableArbitrary)exactValue); - } else { - objectNode.getObjectNodeContext().setArbitrary(CombinableArbitrary.from(exactValue)); - } - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeSetLazyManipulator.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeSetLazyManipulator.java deleted file mode 100644 index dd8b54944e..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeSetLazyManipulator.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.customizer; - -import java.util.List; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import net.jqwik.api.Arbitrary; - -import com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary; -import com.navercorp.fixturemonkey.api.container.DecomposedContainerValueFactory; -import com.navercorp.fixturemonkey.api.generator.ContainerPropertyGenerator; -import com.navercorp.fixturemonkey.api.lazy.LazyArbitrary; -import com.navercorp.fixturemonkey.api.matcher.MatcherOperator; -import com.navercorp.fixturemonkey.customizer.Values.Just; -import com.navercorp.fixturemonkey.tree.GenerateFixtureContext; -import com.navercorp.fixturemonkey.tree.ObjectNode; - -@API(since = "0.4.0", status = Status.MAINTAINED) -public final class NodeSetLazyManipulator implements NodeManipulator { - - private final int sequence; - private final DecomposedContainerValueFactory decomposedContainerValueFactory; - private final List> containerPropertyGenerators; - private final LazyArbitrary lazyArbitrary; - - public NodeSetLazyManipulator( - int sequence, - DecomposedContainerValueFactory decomposedContainerValueFactory, - List> containerPropertyGenerators, - LazyArbitrary lazyArbitrary - ) { - this.sequence = sequence; - this.decomposedContainerValueFactory = decomposedContainerValueFactory; - this.containerPropertyGenerators = containerPropertyGenerators; - this.lazyArbitrary = lazyArbitrary; - } - - /** - * Returns the LazyArbitrary that will be evaluated at runtime. - * - * @return the LazyArbitrary instance - */ - public LazyArbitrary getLazyArbitrary() { - return lazyArbitrary; - } - - public int getSequence() { - return sequence; - } - - @SuppressWarnings("unchecked") - @Override - public void manipulate(ObjectNode objectNode) { - T value = lazyArbitrary.getValue(); - - if (value == null) { - NodeNullityManipulator nullityManipulator = new NodeNullityManipulator(sequence, true); - nullityManipulator.manipulate(objectNode); - return; - } - - if (value instanceof Arbitrary) { - value = (T) ((Arbitrary) value).sample(); - } - - if (value instanceof Just) { - Just just = (Just) value; - GenerateFixtureContext generateFixtureContext = (GenerateFixtureContext) objectNode.getObjectNodeContext(); - generateFixtureContext.setArbitrary(CombinableArbitrary.from(just::getValue)); - lazyArbitrary.clear(); - return; - } - - NodeSetDecomposedValueManipulator nodeSetDecomposedValueManipulator = - new NodeSetDecomposedValueManipulator<>( - sequence, - decomposedContainerValueFactory, - containerPropertyGenerators, - value - ); - nodeSetDecomposedValueManipulator.manipulate(objectNode); - lazyArbitrary.clear(); - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NullityDirective.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NullityDirective.java new file mode 100644 index 0000000000..2b0798fbcb --- /dev/null +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NullityDirective.java @@ -0,0 +1,82 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.customizer; + +import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; + +import com.navercorp.objectfarm.api.expression.PathExpression; + +/** + * Forces a path to be {@code null} ({@code toNull = true}) or non-null ({@code toNull = false}). + */ +@API(since = "0.4.0", status = Status.EXPERIMENTAL) +public final class NullityDirective implements PathDirective { + private final PathExpression path; + private final int sequence; + private final int limit; + private final boolean strict; + private final boolean registered; + private final boolean toNull; + + public NullityDirective( + PathExpression path, + int sequence, + int limit, + boolean strict, + boolean registered, + boolean toNull + ) { + this.path = path; + this.sequence = sequence; + this.limit = limit; + this.strict = strict; + this.registered = registered; + this.toNull = toNull; + } + + @Override + public PathExpression path() { + return path; + } + + @Override + public int sequence() { + return sequence; + } + + @Override + public int limit() { + return limit; + } + + @Override + public boolean strict() { + return strict; + } + + @Override + public boolean registered() { + return registered; + } + + public boolean toNull() { + return toNull; + } +} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/PathDirective.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/PathDirective.java new file mode 100644 index 0000000000..5810457e09 --- /dev/null +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/PathDirective.java @@ -0,0 +1,64 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.customizer; + +import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; + +import com.navercorp.objectfarm.api.expression.PathExpression; + +/** + * A self-describing record of a single user-issued instruction at a path. + *

+ * Implemented by typed payload classes ({@link SetDirective}, {@link JustDirective}, + * {@link LazyDirective}, {@link NullityDirective}, {@link FilterDirective}, + * {@link CustomizerDirective}). The fold step in + * {@link com.navercorp.fixturemonkey.planner.ManipulatorAnalyzer} dispatches by subtype. + * + * @since 0.4.0 + */ +@API(since = "0.4.0", status = Status.EXPERIMENTAL) +public interface PathDirective { + /** + * The fully resolved path this directive targets. + */ + PathExpression path(); + + /** + * Order index used to determine precedence between directives that target the same path. + */ + int sequence(); + + /** + * Optional application count limit; {@code -1} means unlimited. + */ + int limit(); + + /** + * Whether this directive runs in strict mode. When {@code true}, a non-existent path triggers + * an exception instead of being silently ignored. + */ + boolean strict(); + + /** + * Whether this directive originates from a registered builder. Registered directives are + * skipped by direct path-based analysis and flow through the typed-value path instead. + */ + boolean registered(); +} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/SetDirective.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/SetDirective.java new file mode 100644 index 0000000000..db531c2904 --- /dev/null +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/SetDirective.java @@ -0,0 +1,103 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.customizer; + +import java.util.List; + +import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; +import org.jspecify.annotations.Nullable; + +import com.navercorp.fixturemonkey.api.container.DecomposedContainerValueFactory; +import com.navercorp.fixturemonkey.api.generator.ContainerPropertyGenerator; +import com.navercorp.fixturemonkey.api.matcher.MatcherOperator; +import com.navercorp.objectfarm.api.expression.PathExpression; + +/** + * Sets a decomposable value at a path. Container values are decomposed via the supplied + * {@link DecomposedContainerValueFactory}; objects are decomposed by the analyzer. + */ +@API(since = "0.4.0", status = Status.EXPERIMENTAL) +public final class SetDirective implements PathDirective { + private final PathExpression path; + private final int sequence; + private final int limit; + private final boolean strict; + private final boolean registered; + private final @Nullable Object value; + private final DecomposedContainerValueFactory decomposedContainerValueFactory; + private final List> containerPropertyGenerators; + + public SetDirective( + PathExpression path, + int sequence, + int limit, + boolean strict, + boolean registered, + @Nullable Object value, + DecomposedContainerValueFactory decomposedContainerValueFactory, + List> containerPropertyGenerators + ) { + this.path = path; + this.sequence = sequence; + this.limit = limit; + this.strict = strict; + this.registered = registered; + this.value = value; + this.decomposedContainerValueFactory = decomposedContainerValueFactory; + this.containerPropertyGenerators = containerPropertyGenerators; + } + + @Override + public PathExpression path() { + return path; + } + + @Override + public int sequence() { + return sequence; + } + + @Override + public int limit() { + return limit; + } + + @Override + public boolean strict() { + return strict; + } + + @Override + public boolean registered() { + return registered; + } + + public @Nullable Object value() { + return value; + } + + public DecomposedContainerValueFactory decomposedContainerValueFactory() { + return decomposedContainerValueFactory; + } + + public List> containerPropertyGenerators() { + return containerPropertyGenerators; + } +} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/SizeDirective.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/SizeDirective.java new file mode 100644 index 0000000000..fab6d52010 --- /dev/null +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/SizeDirective.java @@ -0,0 +1,94 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.customizer; + +import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; + +import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfo; +import com.navercorp.objectfarm.api.expression.PathExpression; + +/** + * Sets a container's element count range at a path. {@code min}/{@code max} bound the + * randomly chosen size; once {@link #fix()} is called the directive locks to a single value. + *

+ * Replaces the legacy {@code SizeDirective}. + */ +@API(since = "1.1.18", status = Status.EXPERIMENTAL) +public final class SizeDirective implements PathDirective { + private final PathExpression path; + private final int sequence; + private final ArbitraryContainerInfo containerInfo; + + public SizeDirective(PathExpression path, int sequence, ArbitraryContainerInfo containerInfo) { + this.path = path; + this.sequence = sequence; + this.containerInfo = containerInfo; + } + + public SizeDirective(PathExpression path, int sequence, int min, int max) { + this(path, sequence, new ArbitraryContainerInfo(min, max)); + } + + @Override + public PathExpression path() { + return path; + } + + @Override + public int sequence() { + return sequence; + } + + @Override + public int limit() { + return -1; + } + + @Override + public boolean strict() { + return false; + } + + @Override + public boolean registered() { + return false; + } + + public ArbitraryContainerInfo containerInfo() { + return containerInfo; + } + + public int min() { + return containerInfo.getElementMinSize(); + } + + public int max() { + return containerInfo.getElementMaxSize(); + } + + /** + * Returns a copy locked to a single random size drawn from this directive's current range. + * Used by {@code ArbitraryBuilder.fixed()} to make the size deterministic on subsequent samples. + */ + public SizeDirective fix() { + int fixedSize = containerInfo.getRandomSize(); + return new SizeDirective(path, sequence, new ArbitraryContainerInfo(fixedSize, fixedSize)); + } +} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/ArbitraryExpression.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/ArbitraryExpression.java deleted file mode 100644 index 88b0c052d1..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/ArbitraryExpression.java +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.expression; - -import static com.navercorp.fixturemonkey.Constants.ALL_INDEX_STRING; -import static com.navercorp.fixturemonkey.Constants.HEAD_NAME; -import static com.navercorp.fixturemonkey.Constants.NO_OR_ALL_INDEX_INTEGER_VALUE; -import static java.util.stream.Collectors.toList; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; -import org.jspecify.annotations.Nullable; - -import com.navercorp.fixturemonkey.tree.CompositeNodeResolver; -import com.navercorp.fixturemonkey.tree.ContainerElementPredicate; -import com.navercorp.fixturemonkey.tree.NextNodePredicate; -import com.navercorp.fixturemonkey.tree.NodePredicateResolver; -import com.navercorp.fixturemonkey.tree.NodeResolver; -import com.navercorp.fixturemonkey.tree.PropertyNameNodePredicate; -import com.navercorp.fixturemonkey.tree.StartNodePredicate; - -public final class ArbitraryExpression implements MonkeyExpression, Comparable { - private final List expList; - - private ArbitraryExpression(List expList) { - this.expList = expList; - } - - private ArbitraryExpression(String expression) { - expList = Arrays.stream(expression.split("\\.")) - .map(Exp::new) - .collect(toList()); - } - - public static ArbitraryExpression from(String expression) { - return new ArbitraryExpression(expression); - } - - public ArbitraryExpression addFirst(String expression) { - String newStringExpression = expression + "." + this; - return new ArbitraryExpression(newStringExpression); - } - - public ArbitraryExpression addLast(String expression) { - String newStringExpression = this + "." + expression; - return new ArbitraryExpression(newStringExpression); - } - - @API(since = "0.4.0", status = Status.MAINTAINED) - public ArbitraryExpression pollLast() { - if (expList.isEmpty()) { - return this; - } - - List newExpList = new ArrayList<>(this.expList); - int lastIndex = newExpList.size() - 1; - Exp lastExp = newExpList.get(lastIndex); - newExpList.remove(lastIndex); - - if (!lastExp.indices.isEmpty()) { - List newExpIndexList = new ArrayList<>(lastExp.indices); - newExpIndexList.remove(newExpIndexList.size() - 1); - lastExp = new Exp(lastExp.name, newExpIndexList); - newExpList.add(lastExp); - } - return new ArbitraryExpression(newExpList); - } - - @Override - public int compareTo(ArbitraryExpression arbitraryExpression) { - List oExpList = arbitraryExpression.expList; - - if (expList.size() != oExpList.size()) { - return Integer.compare(expList.size(), oExpList.size()); - } - - for (int i = 0; i < expList.size(); i++) { - Exp exp = expList.get(i); - Exp oExp = oExpList.get(i); - int expCompare = exp.compareTo(oExp); - if (expCompare != 0) { - return expCompare; - } - } - - return 0; - } - - @Override - public boolean equals(@Nullable Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - ArbitraryExpression other = (ArbitraryExpression)obj; - return expList.equals(other.expList); - } - - @Override - public int hashCode() { - return Objects.hash(this.expList); - } - - public String toString() { - return expList.stream() - .map(Exp::toString) - .collect(Collectors.joining(".")); - } - - public NodeResolver toNodeResolver() { - @Nullable NodeResolver nodeResolver = null; - - for (Exp exp : expList) { - if (nodeResolver == null) { - nodeResolver = exp.toNodeResolver(); - } else { - nodeResolver = new CompositeNodeResolver(nodeResolver, exp.toNodeResolver()); - } - } - - if (nodeResolver == null) { - throw new IllegalStateException("expList is empty, cannot create NodeResolver"); - } - return nodeResolver; - } - - @Override - public List toNextNodePredicate() { - List nextNodePredicates = new ArrayList<>(); - nextNodePredicates.add(StartNodePredicate.INSTANCE); - for (Exp exp : expList) { - nextNodePredicates.addAll(exp.toNextNodePredicates()); - } - return nextNodePredicates; - } - - private static final class ExpIndex implements Comparable { - public static final ExpIndex ALL_INDEX_EXP_INDEX = new ExpIndex(NO_OR_ALL_INDEX_INTEGER_VALUE); - - private final int index; - - public ExpIndex(int index) { - this.index = index; - } - - public int getIndex() { - return index; - } - - public boolean equalsIgnoreAllIndex(ExpIndex expIndex) { - return this.index == expIndex.index; - } - - @Override - public int compareTo(ExpIndex expIndex) { - return Integer.compare(this.index, expIndex.index); - } - - @Override - public boolean equals(@Nullable Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - ExpIndex expIndex = (ExpIndex)obj; - return index == expIndex.index || index == NO_OR_ALL_INDEX_INTEGER_VALUE - || expIndex.index == NO_OR_ALL_INDEX_INTEGER_VALUE; - } - - @Override - public int hashCode() { - return 0; // for allIndex, hash always return 0. - } - - public String toString() { - return index == NO_OR_ALL_INDEX_INTEGER_VALUE ? ALL_INDEX_STRING : String.valueOf(index); - } - } - - private static final class Exp implements Comparable { - private final String name; - private final List indices; - - private Exp(String name, List indices) { - this.name = name; - this.indices = indices; - } - - public Exp(String expression) { - indices = new ArrayList<>(); - int li = expression.indexOf('['); - int ri = expression.indexOf(']'); - - if ((li != -1 && ri == -1) || (li == -1 && ri != -1)) { - throw new IllegalArgumentException("expression is invalid. expression : " + expression); - } - - if (li == -1) { - this.name = expression; - } else { - this.name = expression.substring(0, li); - while (li != -1 && ri != -1) { - if (ri - li > 1) { - String indexString = expression.substring(li + 1, ri); - final int indexValue = indexString.equals(ALL_INDEX_STRING) - ? NO_OR_ALL_INDEX_INTEGER_VALUE - : Integer.parseInt(indexString); - this.indices.add(new ExpIndex(indexValue)); - } - expression = expression.substring(ri + 1); - li = expression.indexOf('['); - ri = expression.indexOf(']'); - } - } - } - - public NodeResolver toNodeResolver() { - NodeResolver nodeResolver = new NodePredicateResolver(StartNodePredicate.INSTANCE); - - if (!HEAD_NAME.equals(name)) { - nodeResolver = new CompositeNodeResolver( - nodeResolver, - new NodePredicateResolver(new PropertyNameNodePredicate(name)) - ); - } - - for (ExpIndex index : indices) { - nodeResolver = new CompositeNodeResolver( - nodeResolver, - new NodePredicateResolver(new ContainerElementPredicate(index.getIndex())) - ); - } - return nodeResolver; - } - - public List toNextNodePredicates() { - List nextNodePredicates = new ArrayList<>(); - if (!HEAD_NAME.equals(name)) { - nextNodePredicates.add(new PropertyNameNodePredicate(name)); - } - - for (ExpIndex index : indices) { - nextNodePredicates.add(new ContainerElementPredicate(index.getIndex())); - } - return nextNodePredicates; - } - - public String getName() { - return name; - } - - public List getIndices() { - return indices; - } - - public String toString() { - String indexBrackets = indices.stream() - .map(i -> "[" + i.toString() + "]") - .collect(Collectors.joining()); - return name + indexBrackets; - } - - @Override - public int compareTo(Exp exp) { - List indices = this.getIndices(); - List oIndices = exp.getIndices(); - - if (exp.name.equals(this.name)) { - int indexLength = Math.min(oIndices.size(), indices.size()); - for (int i = 0; i < indexLength; i++) { - ExpIndex index = indices.get(i); - ExpIndex oIndex = oIndices.get(i); - int indexCompare = oIndex.compareTo(index); - if (indexCompare != 0) { - return indexCompare; - } - } - } - return Integer.compare(indices.size(), oIndices.size()); - } - - @Override - public boolean equals(@Nullable Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - Exp exp = (Exp)obj; - return name.equals(exp.name) && indices.equals(exp.indices); - } - - @Override - public int hashCode() { - return Objects.hash(name, indices); - } - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/ArbitraryExpressionFactory.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/ArbitraryExpressionFactory.java deleted file mode 100644 index ffe8f8449d..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/ArbitraryExpressionFactory.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.expression; - -public final class ArbitraryExpressionFactory implements MonkeyExpressionFactory { - @Override - public MonkeyExpression from(String expression) { - return ArbitraryExpression.from(expression); - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/DefaultDeclarativeExpression.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/DefaultDeclarativeExpression.java index 09911b9ead..0be6bd0008 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/DefaultDeclarativeExpression.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/DefaultDeclarativeExpression.java @@ -18,87 +18,62 @@ package com.navercorp.fixturemonkey.expression; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - import org.apiguardian.api.API; import org.apiguardian.api.API.Status; -import com.navercorp.fixturemonkey.tree.NextNodePredicate; -import com.navercorp.fixturemonkey.tree.NodeAllElementPredicate; -import com.navercorp.fixturemonkey.tree.NodeElementPredicate; -import com.navercorp.fixturemonkey.tree.NodeKeyPredicate; -import com.navercorp.fixturemonkey.tree.NodeValuePredicate; -import com.navercorp.fixturemonkey.tree.PropertyNameNodePredicate; -import com.navercorp.fixturemonkey.tree.StartNodePredicate; +import com.navercorp.objectfarm.api.expression.PathExpression; /** - * It is a default implementation of {@link DeclarativeExpression}. + * Default implementation of {@link DeclarativeExpression}. Each builder call returns a new + * instance carrying the accumulated {@link PathExpression}. */ public final class DefaultDeclarativeExpression implements DeclarativeExpression { - private final List nestedNextNodePredicates; + private final PathExpression path; /** - * It is for internal use only. - * It may be removed or changed in a future release. + * It is for internal use only. May be removed or changed in a future release. */ @Deprecated public DefaultDeclarativeExpression() { - this.nestedNextNodePredicates = Collections.singletonList(StartNodePredicate.INSTANCE); + this(PathExpression.root()); } - DefaultDeclarativeExpression(List nestedNextNodePredicates) { - this.nestedNextNodePredicates = nestedNextNodePredicates; + DefaultDeclarativeExpression(PathExpression path) { + this.path = path; } @Override public DefaultDeclarativeExpression property(String propertyName) { - List copied = new ArrayList<>(this.nestedNextNodePredicates); - copied.add(new PropertyNameNodePredicate(propertyName)); - return new DefaultDeclarativeExpression(copied); + return new DefaultDeclarativeExpression(path.child(propertyName)); } @Override public DefaultDeclarativeExpression element(int sequence) { - List copied = new ArrayList<>(this.nestedNextNodePredicates); - copied.add(new NodeElementPredicate(sequence)); - return new DefaultDeclarativeExpression(copied); + return new DefaultDeclarativeExpression(path.index(sequence)); } @Override public DefaultDeclarativeExpression allElement() { - List copied = new ArrayList<>(this.nestedNextNodePredicates); - copied.add(new NodeAllElementPredicate()); - return new DefaultDeclarativeExpression(copied); + return new DefaultDeclarativeExpression(path.wildcard()); } @Override public DefaultDeclarativeExpression key() { - List copied = new ArrayList<>(this.nestedNextNodePredicates); - copied.add(new NodeKeyPredicate()); - return new DefaultDeclarativeExpression(copied); + return new DefaultDeclarativeExpression(path.key()); } @Override public DefaultDeclarativeExpression value() { - List copied = new ArrayList<>(this.nestedNextNodePredicates); - copied.add(new NodeValuePredicate()); - return new DefaultDeclarativeExpression(copied); + return new DefaultDeclarativeExpression(path.value()); } @API(since = "1.1.10", status = Status.INTERNAL) public DefaultDeclarativeExpression prepend(DefaultDeclarativeExpression parentDeclarativeExpression) { - List concat = new ArrayList<>(parentDeclarativeExpression.getNestedNextNodePredicates()); - concat.addAll(this.getNestedNextNodePredicates().stream() - .filter(it -> !(it instanceof StartNodePredicate)) - .collect(Collectors.toList())); - return new DefaultDeclarativeExpression(concat); + return new DefaultDeclarativeExpression(parentDeclarativeExpression.path.append(this.path)); } @API(since = "1.1.10", status = Status.INTERNAL) - public List getNestedNextNodePredicates() { - return nestedNextNodePredicates; + public PathExpression getPath() { + return path; } } diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/MonkeyExpression.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/MonkeyExpression.java deleted file mode 100644 index 658c9df081..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/MonkeyExpression.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.expression; - -import java.util.List; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import com.navercorp.fixturemonkey.tree.NextNodePredicate; -import com.navercorp.fixturemonkey.tree.NodeResolver; - -@API(since = "0.4.0", status = Status.MAINTAINED) -public interface MonkeyExpression { - NodeResolver toNodeResolver(); - - List toNextNodePredicate(); -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/MonkeyExpressionFactory.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/MonkeyExpressionFactory.java deleted file mode 100644 index db87b3d54d..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/MonkeyExpressionFactory.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.expression; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; -import org.jspecify.annotations.Nullable; - -@API(since = "0.4.0", status = Status.MAINTAINED) -@FunctionalInterface -public interface MonkeyExpressionFactory { - MonkeyExpression from(String expression); - - default MonkeyExpression from(String expression, @Nullable Class rootClass) { - return from(expression); - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/StrictModeMonkeyExpressionFactory.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/StrictModeMonkeyExpressionFactory.java deleted file mode 100644 index 9e330d5735..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/StrictModeMonkeyExpressionFactory.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.expression; - -import java.util.List; - -import org.jspecify.annotations.Nullable; - -import com.navercorp.fixturemonkey.api.property.PropertyNameResolver; -import com.navercorp.fixturemonkey.tree.ApplyStrictModeResolver; -import com.navercorp.fixturemonkey.tree.NextNodePredicate; -import com.navercorp.fixturemonkey.tree.NodeResolver; - -public final class StrictModeMonkeyExpressionFactory implements MonkeyExpressionFactory { - private final MonkeyExpressionFactory delegate; - private final PropertyNameResolver propertyNameResolver; - - public StrictModeMonkeyExpressionFactory( - MonkeyExpressionFactory delegate, PropertyNameResolver propertyNameResolver - ) { - this.delegate = delegate; - this.propertyNameResolver = propertyNameResolver; - } - - @Override - public MonkeyExpression from(String expression) { - return from(expression, null); - } - - @Override - public MonkeyExpression from(String expression, @Nullable Class rootClass) { - MonkeyExpression monkeyExpression = delegate.from(expression); - return new StrictModeMonkeyExpression(monkeyExpression, rootClass, propertyNameResolver); - } - - private static final class StrictModeMonkeyExpression implements MonkeyExpression { - private final MonkeyExpression delegate; - private final @Nullable Class rootClass; - private final PropertyNameResolver propertyNameResolver; - - public StrictModeMonkeyExpression( - MonkeyExpression delegate, @Nullable Class rootClass, PropertyNameResolver propertyNameResolver - ) { - this.delegate = delegate; - this.rootClass = rootClass; - this.propertyNameResolver = propertyNameResolver; - } - - @Override - public NodeResolver toNodeResolver() { - return new ApplyStrictModeResolver(delegate.toNodeResolver()); - } - - @Override - public List toNextNodePredicate() { - if (rootClass == null) { - return delegate.toNextNodePredicate(); - } - List predicates = delegate.toNextNodePredicate(); - return new StrictModeNextNodePredicateContainer(predicates, rootClass, propertyNameResolver); - } - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/StrictModeNextNodePredicateContainer.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/StrictModeNextNodePredicateContainer.java deleted file mode 100644 index e29b82f0fc..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/StrictModeNextNodePredicateContainer.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.expression; - -import java.lang.reflect.Field; -import java.util.AbstractList; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; - -import com.navercorp.fixturemonkey.api.property.FieldProperty; -import com.navercorp.fixturemonkey.api.property.PropertyNameResolver; -import com.navercorp.fixturemonkey.api.type.Types; -import com.navercorp.fixturemonkey.tree.NextNodePredicate; -import com.navercorp.fixturemonkey.tree.PropertyNameNodePredicate; - -public final class StrictModeNextNodePredicateContainer extends AbstractList { - private final List delegate; - - public StrictModeNextNodePredicateContainer( - List delegate, Class rootClass, PropertyNameResolver propertyNameResolver - ) { - this.delegate = delegate; - if (!isValidFieldPath(rootClass, delegate, propertyNameResolver)) { - throw new IllegalArgumentException("No matching results for given container expression."); - } - } - - @Override - public NextNodePredicate get(int index) { - return delegate.get(index); - } - - @Override - public int size() { - return delegate.size(); - } - - /** - * Validates if the given expression path corresponds to a valid field path within the root class. - *

- * Currently, this validation only checks for the existence of property names along the path. - * It does not validate array or list indices. - * For example, for an expression like {@code list[1]}, it checks for the existence of the {@code list} field, - * but it does not verify if index {@code 1} is valid for that list. - * This can lead to runtime errors in some edge cases, instead of errors at the validation stage. - * - * @param rootClass The class to start path validation from. - * @param predicates A list of predicates representing the expression path. - * @param propertyNameResolver The resolver used to check property names. - * @return {@code true} if the path is valid, {@code false} otherwise. - */ - private boolean isValidFieldPath( - Class rootClass, List predicates, PropertyNameResolver propertyNameResolver - ) { - if (predicates == null || predicates.isEmpty()) { - return false; - } - Class currentClass = Types.getActualType(rootClass); - for (NextNodePredicate predicate : predicates) { - if (!(predicate instanceof PropertyNameNodePredicate)) { - continue; - } - String fieldName = ((PropertyNameNodePredicate)predicate).getPropertyName(); - Optional field = Arrays.stream(currentClass.getDeclaredFields()) - .filter(f -> propertyNameResolver.resolve(new FieldProperty(f)).equals(fieldName)) - .findFirst(); - - if (!field.isPresent()) { - return false; - } - currentClass = field.get().getType(); - } - return true; - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/nodecandidate/ContainerPropertyGeneratorNodeGenerator.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/nodecandidate/ContainerPropertyGeneratorNodeGenerator.java similarity index 85% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/nodecandidate/ContainerPropertyGeneratorNodeGenerator.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/nodecandidate/ContainerPropertyGeneratorNodeGenerator.java index 53c4630eb8..3ef1e918bc 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/nodecandidate/ContainerPropertyGeneratorNodeGenerator.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/nodecandidate/ContainerPropertyGeneratorNodeGenerator.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter.nodecandidate; +package com.navercorp.fixturemonkey.nodecandidate; import java.util.ArrayList; import java.util.Collection; @@ -35,18 +35,20 @@ import org.apiguardian.api.API.Status; import org.jspecify.annotations.Nullable; -import com.navercorp.fixturemonkey.adapter.property.JvmNodePropertyFactory; import com.navercorp.fixturemonkey.api.generator.ContainerProperty; import com.navercorp.fixturemonkey.api.generator.ContainerPropertyGenerator; import com.navercorp.fixturemonkey.api.generator.ContainerPropertyGeneratorContext; import com.navercorp.fixturemonkey.api.matcher.MatcherOperator; +import com.navercorp.fixturemonkey.api.property.ContainerElementProperty; import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.fixturemonkey.property.JvmNodePropertyFactory; import com.navercorp.objectfarm.api.node.ContainerSizeResolver; import com.navercorp.objectfarm.api.node.JavaNode; import com.navercorp.objectfarm.api.node.JvmContainerNodeGenerator; import com.navercorp.objectfarm.api.node.JvmNode; import com.navercorp.objectfarm.api.node.JvmNodeContext; +import com.navercorp.objectfarm.api.nodecandidate.ContainerElementCreationMethod; +import com.navercorp.objectfarm.api.nodecandidate.CreationMethod; import com.navercorp.objectfarm.api.type.JvmType; /** @@ -101,9 +103,18 @@ public List generateContainerElements( List childProperties = containerProperty.getElementProperties(); List elements = new ArrayList<>(childProperties.size()); - for (Property childProperty : childProperties) { - JvmType elementType = Types.toJvmType(childProperty.getAnnotatedType(), childProperty.getAnnotations()); - elements.add(new JavaNode(elementType, "")); + for (int i = 0; i < childProperties.size(); i++) { + Property childProperty = childProperties.get(i); + JvmType elementType = childProperty.getJvmType(); + int index = i; + if (childProperty instanceof ContainerElementProperty) { + Integer propIndex = ((ContainerElementProperty)childProperty).getIndex(); + if (propIndex != null) { + index = propIndex; + } + } + CreationMethod creationMethod = new ContainerElementCreationMethod(index); + elements.add(new JavaNode(elementType, "[" + index + "]", index, creationMethod)); } return elements; } diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/nodecandidate/InterfaceMethodNodeCandidateGenerator.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/nodecandidate/InterfaceMethodNodeCandidateGenerator.java similarity index 98% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/nodecandidate/InterfaceMethodNodeCandidateGenerator.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/nodecandidate/InterfaceMethodNodeCandidateGenerator.java index 3d642bfd75..04962f2e61 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/nodecandidate/InterfaceMethodNodeCandidateGenerator.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/nodecandidate/InterfaceMethodNodeCandidateGenerator.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter.nodecandidate; +package com.navercorp.fixturemonkey.nodecandidate; import static java.util.stream.Collectors.toMap; diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/nodecandidate/NameResolvingNodeCandidateGenerator.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/nodecandidate/NameResolvingNodeCandidateGenerator.java similarity index 98% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/nodecandidate/NameResolvingNodeCandidateGenerator.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/nodecandidate/NameResolvingNodeCandidateGenerator.java index 692f275b55..7f388e4fde 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/nodecandidate/NameResolvingNodeCandidateGenerator.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/nodecandidate/NameResolvingNodeCandidateGenerator.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter.nodecandidate; +package com.navercorp.fixturemonkey.nodecandidate; import java.util.ArrayList; import java.util.List; diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/nodecandidate/PropertyGeneratorNodeCandidateGenerator.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/nodecandidate/PropertyGeneratorNodeCandidateGenerator.java similarity index 85% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/nodecandidate/PropertyGeneratorNodeCandidateGenerator.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/nodecandidate/PropertyGeneratorNodeCandidateGenerator.java index 27d6c37ce0..ed361ab5ed 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/nodecandidate/PropertyGeneratorNodeCandidateGenerator.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/nodecandidate/PropertyGeneratorNodeCandidateGenerator.java @@ -16,9 +16,8 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter.nodecandidate; +package com.navercorp.fixturemonkey.nodecandidate; -import java.lang.reflect.AnnotatedType; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; @@ -29,14 +28,13 @@ import org.apiguardian.api.API.Status; import org.jspecify.annotations.Nullable; -import com.navercorp.fixturemonkey.adapter.property.JvmNodePropertyFactory; import com.navercorp.fixturemonkey.api.property.CompositeProperty; import com.navercorp.fixturemonkey.api.property.ConstructorProperty; import com.navercorp.fixturemonkey.api.property.FieldProperty; import com.navercorp.fixturemonkey.api.property.Property; import com.navercorp.fixturemonkey.api.property.PropertyDescriptorProperty; import com.navercorp.fixturemonkey.api.property.PropertyGenerator; -import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.fixturemonkey.property.JvmNodePropertyFactory; import com.navercorp.objectfarm.api.nodecandidate.ConstructorParamCreationMethod; import com.navercorp.objectfarm.api.nodecandidate.CreationMethod; import com.navercorp.objectfarm.api.nodecandidate.FieldAccessCreationMethod; @@ -75,7 +73,6 @@ public List generateNextNodeCandidates(JvmType jvmType) { } Property property = JvmNodePropertyFactory.fromType(jvmType); - AnnotatedType parentAnnotatedType = property.getAnnotatedType(); List childProperties = propertyGenerator.generateChildProperties(property); if (childProperties == null || childProperties.isEmpty()) { @@ -84,18 +81,13 @@ public List generateNextNodeCandidates(JvmType jvmType) { List result = new ArrayList<>(childProperties.size()); for (int i = 0; i < childProperties.size(); i++) { - result.add(toNodeCandidate(parentAnnotatedType, childProperties.get(i), i)); + result.add(toNodeCandidate(childProperties.get(i), i)); } return result; } - private JvmNodeCandidate toNodeCandidate(AnnotatedType parentAnnotatedType, Property property, int index) { - // Resolve type variables in the child property's type against the parent's type - AnnotatedType resolvedType = Types.resolveWithTypeReferenceGenerics( - parentAnnotatedType, - property.getAnnotatedType() - ); - JvmType jvmType = Types.toJvmType(resolvedType, property.getAnnotations()); + private JvmNodeCandidate toNodeCandidate(Property property, int index) { + JvmType jvmType = property.getJvmType(); String name = property.getName(); if (name == null) { name = ""; diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/analysis/AnalysisResult.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/AnalysisResult.java similarity index 81% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/analysis/AnalysisResult.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/AnalysisResult.java index 57883e4773..8cd32b2657 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/analysis/AnalysisResult.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/AnalysisResult.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter.analysis; +package com.navercorp.fixturemonkey.planner; import java.util.Collections; import java.util.List; @@ -27,9 +27,9 @@ import org.jspecify.annotations.Nullable; -import com.navercorp.fixturemonkey.adapter.tracing.ResolutionTrace; import com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary; -import com.navercorp.fixturemonkey.api.lazy.LazyArbitrary; +import com.navercorp.fixturemonkey.customizer.SizeDirective; +import com.navercorp.fixturemonkey.tracing.ResolutionTrace; import com.navercorp.objectfarm.api.expression.PathExpression; import com.navercorp.objectfarm.api.node.ContainerSizeResolver; import com.navercorp.objectfarm.api.node.GenericTypeResolver; @@ -37,7 +37,7 @@ import com.navercorp.objectfarm.api.tree.PathResolver; /** - * Result of analyzing a list of ArbitraryManipulators. + * Result of analyzing a list of {@link com.navercorp.fixturemonkey.customizer.PathDirective}s. *

* Path resolution follows the "more specific path wins" rule: * - If both "$.object" and "$.object.str" have values, "$.object.str" takes precedence for that field. @@ -52,10 +52,10 @@ public final class AnalysisResult { private final List> genericTypeResolvers; private final List> containerSizeResolvers; private final Map containerSizeSequenceByPath; + private final Map latestSizeDirectiveByPath; private final List justPaths; private final Set notNullPaths; private final Map valuesByPath; - private final List lazyManipulators; private final Map> filtersByPath; private final Map limitsByPath; private final Map valueOrderByPath; @@ -68,10 +68,10 @@ public final class AnalysisResult { List> genericTypeResolvers, List> containerSizeResolvers, Map containerSizeSequenceByPath, + Map latestSizeDirectiveByPath, List justPaths, Set notNullPaths, Map valuesByPath, - List lazyManipulators, Map> filtersByPath, Map limitsByPath, Map valueOrderByPath, @@ -83,10 +83,10 @@ public final class AnalysisResult { this.genericTypeResolvers = Collections.unmodifiableList(genericTypeResolvers); this.containerSizeResolvers = Collections.unmodifiableList(containerSizeResolvers); this.containerSizeSequenceByPath = Collections.unmodifiableMap(containerSizeSequenceByPath); + this.latestSizeDirectiveByPath = Collections.unmodifiableMap(latestSizeDirectiveByPath); this.justPaths = Collections.unmodifiableList(justPaths); this.notNullPaths = Collections.unmodifiableSet(notNullPaths); this.valuesByPath = Collections.unmodifiableMap(valuesByPath); - this.lazyManipulators = Collections.unmodifiableList(lazyManipulators); this.filtersByPath = Collections.unmodifiableMap(filtersByPath); this.limitsByPath = Collections.unmodifiableMap(limitsByPath); this.valueOrderByPath = Collections.unmodifiableMap(valueOrderByPath); @@ -108,15 +108,25 @@ public List> getContainerSizeResolvers() { } /** - * Returns the sequence (order) of container size resolvers extracted from lazy/decomposed values. + * Returns the sequence (order) of the highest-priority container size resolver per path. *

- * This is used to determine priority when both explicit size() and lazy-derived sizes exist. - * A size with higher sequence should take precedence over one with lower sequence. + * This is used to determine priority across explicit size() and lazy-derived sizes. + * A size with higher sequence takes precedence over one with lower sequence. */ public Map getContainerSizeSequenceByPath() { return containerSizeSequenceByPath; } + /** + * Returns the highest-sequence explicit {@link SizeDirective} per path. Decomposed-value + * size resolvers are intentionally excluded — only directives the user emitted via + * {@code size()} are tracked here. Used by build-time pruning to truncate or expand + * user-provided container values. + */ + public Map getLatestSizeDirectiveByPath() { + return latestSizeDirectiveByPath; + } + /** * Returns paths set via Values.just() which are truly immutable. *

@@ -144,10 +154,6 @@ public Set getNotNullPaths() { return valuesByPath; } - public List getLazyManipulators() { - return lazyManipulators; - } - public Map> getFiltersByPath() { return filtersByPath; } @@ -157,10 +163,8 @@ public Map getLimitsByPath() { } /** - * Returns the order index of each value in valuesByPath. - * Used to determine which values came before/after lazy manipulators. - * A value with order > lazyManipulator.getOrder() came AFTER the lazy manipulator - * and should override the lazy result. + * Returns the sequence index of each value in valuesByPath. Higher sequences override lower + * ones at the same path; consumers compare sequences to decide which directive wins per path. */ public Map getValueOrderByPath() { return valueOrderByPath; @@ -192,38 +196,6 @@ public boolean isStrictMode() { return strictMode; } - /** - * Information about a lazy manipulator that needs to be executed at runtime. - */ - public static final class LazyManipulatorDescriptor { - - private final PathExpression pathExpression; - private final LazyArbitrary lazyArbitrary; - private final int order; - - public LazyManipulatorDescriptor(PathExpression pathExpression, LazyArbitrary lazyArbitrary, int order) { - this.pathExpression = pathExpression; - this.lazyArbitrary = lazyArbitrary; - this.order = order; - } - - public PathExpression getPathExpression() { - return pathExpression; - } - - public LazyArbitrary getLazyArbitrary() { - return lazyArbitrary; - } - - /** - * Returns the order index of this lazy manipulator in the manipulator list. - * Used to determine which explicit values should override the lazy result. - */ - public int getOrder() { - return order; - } - } - /** * Information about a filter (post-condition) to apply to a path. */ diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/analysis/AdaptationResult.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/AssemblyPlan.java similarity index 66% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/analysis/AdaptationResult.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/AssemblyPlan.java index fa6572592f..d17a2e1e81 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/analysis/AdaptationResult.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/AssemblyPlan.java @@ -16,18 +16,21 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter.analysis; +package com.navercorp.fixturemonkey.planner; import org.apiguardian.api.API; import org.apiguardian.api.API.Status; +import org.jspecify.annotations.Nullable; -import com.navercorp.fixturemonkey.adapter.projection.ValueProjection; +import com.navercorp.fixturemonkey.planner.AssemblyPlanner; +import com.navercorp.fixturemonkey.projection.ValueProjection; import com.navercorp.objectfarm.api.tree.JvmNodeTree; +import com.navercorp.objectfarm.api.tree.PathResolverContext; /** - * Result of adapting a ManipulatorSet to a JvmNodeTree. + * Plan produced by {@link AssemblyPlanner} that downstream {@code Assembler}s consume to assemble values. *

- * This class contains: + * This plan contains: *

    *
  • The generated JvmNodeTree with immutable topology
  • *
  • Values projection extracted from manipulators
  • @@ -37,12 +40,12 @@ * Values can be accessed via {@link #getValues()} which returns a {@link ValueProjection} * for node-based and path-based access. * - * @see NodeTreeAdapter + * @see AssemblyPlanner * @see AnalysisResult * @see ValueProjection */ @API(since = "1.1.17", status = Status.EXPERIMENTAL) -public final class AdaptationResult { +public final class AssemblyPlan { private final JvmNodeTree nodeTree; private final ValueProjection values; /** @@ -53,20 +56,21 @@ public final class AdaptationResult { private final long analyzeTimeNanos; private final long treeBuildTimeNanos; private final boolean cacheHit; + private final @Nullable PathResolverContext resolverContext; /** - * Creates a new AdaptationResult. + * Creates a new AssemblyPlan. * * @param nodeTree the generated JvmNodeTree * @param values the values projection extracted from manipulators * @param analysisResult the original analysis result (may be null for default implementations) */ - public AdaptationResult(JvmNodeTree nodeTree, ValueProjection values, AnalysisResult analysisResult) { - this(nodeTree, values, analysisResult, 0, 0, false); + public AssemblyPlan(JvmNodeTree nodeTree, ValueProjection values, AnalysisResult analysisResult) { + this(nodeTree, values, analysisResult, 0, 0, false, null); } /** - * Creates a new AdaptationResult with timing information. + * Creates a new AssemblyPlan with timing information. * * @param nodeTree the generated JvmNodeTree * @param values the values projection extracted from manipulators @@ -74,33 +78,36 @@ public AdaptationResult(JvmNodeTree nodeTree, ValueProjection values, AnalysisRe * @param analyzeTimeNanos time spent in ManipulatorAnalyzer.analyze() in nanoseconds * @param treeBuildTimeNanos time spent building the JvmNodeTree in nanoseconds */ - public AdaptationResult( + public AssemblyPlan( JvmNodeTree nodeTree, ValueProjection values, AnalysisResult analysisResult, long analyzeTimeNanos, long treeBuildTimeNanos ) { - this(nodeTree, values, analysisResult, analyzeTimeNanos, treeBuildTimeNanos, false); + this(nodeTree, values, analysisResult, analyzeTimeNanos, treeBuildTimeNanos, false, null); } /** - * Creates a new AdaptationResult with timing and cache information. + * Creates a new AssemblyPlan with timing, cache, and resolver-context information. * - * @param nodeTree the generated JvmNodeTree - * @param values the values projection extracted from manipulators - * @param analysisResult the original analysis result (may be null for default implementations) - * @param analyzeTimeNanos time spent in ManipulatorAnalyzer.analyze() in nanoseconds + * @param nodeTree the generated JvmNodeTree + * @param values the values projection extracted from manipulators + * @param analysisResult the original analysis result (may be null for default implementations) + * @param analyzeTimeNanos time spent in ManipulatorAnalyzer.analyze() in nanoseconds * @param treeBuildTimeNanos time spent building the JvmNodeTree in nanoseconds - * @param cacheHit whether this result was retrieved from cache + * @param cacheHit whether this result was retrieved from cache + * @param resolverContext the path resolver context produced during planning, used by the + * {@code RuntimeTreeFactory} during assembly */ - public AdaptationResult( + public AssemblyPlan( JvmNodeTree nodeTree, ValueProjection values, AnalysisResult analysisResult, long analyzeTimeNanos, long treeBuildTimeNanos, - boolean cacheHit + boolean cacheHit, + @Nullable PathResolverContext resolverContext ) { this.nodeTree = nodeTree; this.values = values; @@ -108,6 +115,7 @@ public AdaptationResult( this.analyzeTimeNanos = analyzeTimeNanos; this.treeBuildTimeNanos = treeBuildTimeNanos; this.cacheHit = cacheHit; + this.resolverContext = resolverContext; } /** @@ -166,4 +174,16 @@ public long getTreeBuildTimeNanos() { public boolean isCacheHit() { return cacheHit; } + + /** + * Returns the {@link PathResolverContext} produced during planning. + *

    + * This is the same context the {@code RuntimeTreeFactory} should see during assembly so + * that anonymous-tree creation makes the same resolution decisions as the planned tree. + * + * @return the resolver context, or {@code null} when not produced by the planner + */ + public @Nullable PathResolverContext getResolverContext() { + return resolverContext; + } } diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/AssemblyPlanner.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/AssemblyPlanner.java new file mode 100644 index 0000000000..2871620fe3 --- /dev/null +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/AssemblyPlanner.java @@ -0,0 +1,505 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.planner; + +import java.lang.reflect.Modifier; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; +import java.util.function.UnaryOperator; + +import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; +import org.jspecify.annotations.Nullable; + +import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfo; +import com.navercorp.fixturemonkey.api.option.FixtureMonkeyOptions; +import com.navercorp.fixturemonkey.api.property.CandidateConcretePropertyResolver; +import com.navercorp.fixturemonkey.api.property.Property; +import com.navercorp.fixturemonkey.api.random.Randoms; +import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.fixturemonkey.customizer.ManipulatorSet; +import com.navercorp.fixturemonkey.customizer.PathDirective; +import com.navercorp.fixturemonkey.customizer.SizeDirective; +import com.navercorp.fixturemonkey.nodecandidate.InterfaceMethodNodeCandidateGenerator; +import com.navercorp.fixturemonkey.planner.AnalysisResult; +import com.navercorp.fixturemonkey.planner.AssemblyPlan; +import com.navercorp.fixturemonkey.planner.ManipulatorAnalyzer; +import com.navercorp.fixturemonkey.plugin.LeafTypeRegistry; +import com.navercorp.fixturemonkey.projection.ValueProjection; +import com.navercorp.fixturemonkey.resolver.AbstractTypeResolver; +import com.navercorp.fixturemonkey.tracing.TraceContext; +import com.navercorp.fixturemonkey.tracing.TraceContextResolutionListener; +import com.navercorp.objectfarm.api.expression.PathExpression; +import com.navercorp.objectfarm.api.input.ContainerDetector; +import com.navercorp.objectfarm.api.node.InterfaceResolver; +import com.navercorp.objectfarm.api.node.JavaNodeContext; +import com.navercorp.objectfarm.api.node.JvmNodeContext; +import com.navercorp.objectfarm.api.node.JvmNodePromoter; +import com.navercorp.objectfarm.api.node.LeafTypeResolver; +import com.navercorp.objectfarm.api.node.SeedState; +import com.navercorp.objectfarm.api.nodecandidate.JvmNodeCandidateGenerator; +import com.navercorp.objectfarm.api.tree.ExpansionContext; +import com.navercorp.objectfarm.api.tree.JvmNodeCandidateTree; +import com.navercorp.objectfarm.api.tree.JvmNodeCandidateTreeContext; +import com.navercorp.objectfarm.api.tree.JvmNodeSubtreeContext; +import com.navercorp.objectfarm.api.tree.JvmNodeTree; +import com.navercorp.objectfarm.api.tree.JvmNodeTreeTransformer; +import com.navercorp.objectfarm.api.tree.PathResolver; +import com.navercorp.objectfarm.api.tree.PathResolverContext; +import com.navercorp.objectfarm.api.tree.ResolutionListener; +import com.navercorp.objectfarm.api.type.JavaType; +import com.navercorp.objectfarm.api.type.JvmType; + +/** + * Default assembly planner. Also exposes {@link RuntimeTreeFactory} and {@link LeafTypeRegistry}. + *

    + * This implementation: + *

      + *
    1. Analyzes {@link PathDirective}s to extract interface/generic type resolution info, + * including {@link SizeDirective} → {@code ContainerSizeResolver} translation
    2. + *
    3. Builds a {@code JvmNodeCandidateTree} from the root type
    4. + *
    5. Transforms the candidate tree into a {@code JvmNodeTree} with resolved types and + * container sizes
    6. + *
    + *

    + * The {@link PathResolverContext} produced for each plan is carried back inside + * {@link AssemblyPlan} and passed explicitly to {@link RuntimeTreeFactory#createAnonymousNodeTree} + * at the call site, replacing the previous {@code ThreadLocal} smuggling channel. + *

    + * Directive order is preserved end-to-end via {@link PathDirective#sequence()}, so later + * directives override earlier ones at the same path. + */ +@API(since = "1.1.17", status = Status.EXPERIMENTAL) +public final class AssemblyPlanner implements RuntimeTreeFactory, LeafTypeRegistry { + private static final ContainerDetector CONTAINER_DETECTOR = ContainerDetector.standard(); + + private final SeedState seedState; + // Tracks the global Random instance used for the most recent adapt() call. + // When Randoms.newGlobalSeed() creates a new instance (e.g. via @Seed), reference inequality + // triggers a SeedState reset so seeded reruns produce deterministic container sizes. + private @Nullable Random lastSeenRandom; + + // Performance optimization cache for (JvmNodeContext, JvmNodeCandidateTree) — keyed by (type, options identity). + // NOTE: AssemblyPlan/JvmNodeTree are NOT cached because container sizes must vary on each call. + private final TreeContextCache treeCache; + + // Cross-call cache for assembly node metadata (Property, resolvers, isContainerType) + // Type-erased here since CachedNodeMetadata is package-private in projection package + private final ConcurrentHashMap nodeMetadataCache = new ConcurrentHashMap<>(); + + // Additional leaf type resolvers (e.g., KotlinLeafTypeResolver for Kotlin support). + // Held here for isLeafType lookups; node-context construction reads them via NodeContextFactory. + private final List additionalLeafTypeResolvers; + + private final ContainerSizeResolverFactory containerSizeResolverFactory; + private final ContainerValuePruner containerValuePruner; + private final AbstractTypeResolver abstractTypeResolver; + private final PathResolverContextFactory pathResolverContextFactory; + + /** + * Creates a new adapter with the specified seed. + * + * @param seed the seed for random generation + */ + public AssemblyPlanner(long seed) { + this(seed, new JvmNodeCandidateTreeContext(), Collections.emptyList(), Collections.emptyList(), null); + } + + /** + * Creates a new adapter with all configurable components. + * + * @param seed the seed for random generation + * @param treeContext the tree context for caching subtree information + * @param additionalPromoters additional node promoters (e.g., KotlinNodePromoter) + * @param additionalLeafTypeResolvers additional leaf type resolvers (e.g., KotlinLeafTypeResolver) + * @param candidateGeneratorWrapper wraps the candidate generator with platform-specific + * isSupported checks (e.g., KotlinNodeCandidateGenerator) + */ + public AssemblyPlanner( + long seed, + JvmNodeCandidateTreeContext treeContext, + List additionalPromoters, + List additionalLeafTypeResolvers, + @Nullable UnaryOperator candidateGeneratorWrapper + ) { + this.seedState = new SeedState(seed); + List resolvedPromoters = additionalPromoters != null + ? additionalPromoters + : Collections.emptyList(); + this.additionalLeafTypeResolvers = + additionalLeafTypeResolvers != null ? additionalLeafTypeResolvers : Collections.emptyList(); + this.containerSizeResolverFactory = new ContainerSizeResolverFactory(seedState); + this.containerValuePruner = new ContainerValuePruner(CONTAINER_DETECTOR); + NodeContextFactory nodeContextFactory = new NodeContextFactory( + seedState, + containerSizeResolverFactory, + resolvedPromoters, + this.additionalLeafTypeResolvers, + candidateGeneratorWrapper + ); + this.treeCache = new TreeContextCache(treeContext, nodeContextFactory); + this.abstractTypeResolver = new AbstractTypeResolver(seedState); + this.pathResolverContextFactory = new PathResolverContextFactory( + containerSizeResolverFactory, + CONTAINER_DETECTOR + ); + } + + public AssemblyPlan plan( + JvmType rootType, + ManipulatorSet manipulatorSet, + @Nullable FixtureMonkeyOptions options, + @Nullable TraceContext traceContext + ) { + // When tracing is enabled, skip caching to ensure all resolution events are captured + ResolutionListener resolutionListener = TraceContextResolutionListener.of(traceContext); + + resetSeedStateIfRandomChanged(); + if (manipulatorSet.isEmpty()) { + return buildDefaultAssemblyPlan(rootType, options, resolutionListener, manipulatorSet.isFixed()); + } + + return buildAssemblyPlan(rootType, manipulatorSet, options, resolutionListener); + } + + private synchronized void resetSeedStateIfRandomChanged() { + Random current = Randoms.current(); + if (current != lastSeenRandom) { + seedState.reset(Randoms.currentSeed()); + lastSeenRandom = current; + } + } + + private AssemblyPlan buildDefaultAssemblyPlan( + JvmType rootType, + @Nullable FixtureMonkeyOptions options, + ResolutionListener resolutionListener, + boolean isFixed + ) { + JvmType resolvedRootType = walkCandidateChain(rootType, options); + + long treeBuildStart = System.nanoTime(); + + JvmNodeContext context = treeCache.getOrBuildNodeContext( + resolvedRootType, + options, + Collections.emptyMap(), + Collections.emptyMap() + ); + JvmNodeCandidateTree candidateTree = + treeCache.getOrBuildCandidateTree(resolvedRootType, context, options, false); + + PathResolverContext.Builder resolverContextBuilder = PathResolverContext.builder().resolutionListener( + resolutionListener + ); + if (isFixed) { + resolverContextBuilder.defaultContainerSizeResolver( + containerSizeResolverFactory.createFixedContainerSizeResolver(options) + ); + } + PathResolverContext resolverContext = resolverContextBuilder.build(); + + JvmNodeTreeTransformer transformer = new JvmNodeTreeTransformer( + context, + treeCache.getTreeContext(), + resolverContext, + null, // No expansion context for empty manipulators + treeCache.getSubtreeContext() + ); + + JvmNodeTree nodeTree = transformer.transform(candidateTree); + long treeBuildTimeNanos = System.nanoTime() - treeBuildStart; + + AnalysisResult analysisResult = ManipulatorAnalyzer.emptyResult(); + ValueProjection valueProjection = ValueProjection.of(nodeTree, Collections.emptyMap()); + + return new AssemblyPlan( + nodeTree, + valueProjection, + analysisResult, + 0, + treeBuildTimeNanos, + false, + resolverContext + ); + } + + private AssemblyPlan buildAssemblyPlan( + JvmType rootType, + ManipulatorSet manipulatorSet, + @Nullable FixtureMonkeyOptions options, + ResolutionListener resolutionListener + ) { + List directives = manipulatorSet.getDirectives(); + + @SuppressWarnings({"argument", "methodref.return", "return"}) + Function nameResolver = options != null + ? property -> options.getPropertyNameResolver(property).resolve(property) + : (Property p) -> p.getName(); + long analyzeStart = System.nanoTime(); + AnalysisResult analysisResult = ManipulatorAnalyzer.analyze(directives, nameResolver); + long analyzeTimeNanos = System.nanoTime() - analyzeStart; + + // Resolve interface/abstract class to concrete implementation + // For non-container abstract types, check if there's a "$" path InterfaceResolver + // from explicit set(concreteValue) - it takes precedence over default resolution + JvmType resolvedRootType = resolveRootType(rootType, analysisResult, options); + + Map prunedValuesByPath = + containerValuePruner.pruneValuesExceedingContainerSize( + analysisResult.getValuesByPath(), + analysisResult.getLatestSizeDirectiveByPath(), + analysisResult.getValueOrderByPath() + ); + + // Remove child values under just paths — Values.just() makes the value immutable, + // so child path values (e.g., $.string) should not override the just value (e.g., $). + ContainerValuePruner.pruneChildrenOfJustPaths(prunedValuesByPath, analysisResult.getJustPaths()); + + Map> mergedTypedContainerSizes = + pathResolverContextFactory.inferAndMergeTypedContainerSizes( + manipulatorSet.getTypedValues(), + manipulatorSet.getTypedContainerSizes() + ); + + PathResolverContext resolverContext = pathResolverContextFactory.build( + analysisResult, + mergedTypedContainerSizes, + resolutionListener, + manipulatorSet.isFixed(), + options + ); + + // Use fresh treeCache.getTreeContext() when propertyConfigurers or introspectorsByType are present + // to avoid caching issues (cached subtrees don't respect custom property generators) + boolean hasCustomConfigurers = + !manipulatorSet.getPropertyConfigurers().isEmpty() + || !manipulatorSet.getArbitraryIntrospectorsByType().isEmpty(); + + JvmNodeContext context = treeCache.getOrBuildNodeContext( + resolvedRootType, + options, + manipulatorSet.getPropertyConfigurers(), + manipulatorSet.getArbitraryIntrospectorsByType() + ); + + ExpansionContext expansionContext = null; + Set userPaths = analysisResult.getValuesByPath().keySet(); + if (!userPaths.isEmpty()) { + expansionContext = new ExpansionContext(userPaths); + } + + JvmNodeCandidateTreeContext effectiveTreeContext = hasCustomConfigurers + ? new JvmNodeCandidateTreeContext() + : treeCache.getTreeContext(); + + long treeBuildStart = System.nanoTime(); + JvmNodeCandidateTree candidateTree = treeCache.getOrBuildCandidateTree( + resolvedRootType, + context, + options, + hasCustomConfigurers + ); + + JvmNodeSubtreeContext effectiveSubtreeContext = hasCustomConfigurers + ? null + : treeCache.getSubtreeContext(); + + JvmNodeTreeTransformer transformer = new JvmNodeTreeTransformer( + context, + effectiveTreeContext, + resolverContext, + expansionContext, + effectiveSubtreeContext + ); + + JvmNodeTree nodeTree = transformer.transform(candidateTree); + long treeBuildTimeNanos = System.nanoTime() - treeBuildStart; + + ValueProjection valueProjection = ValueProjection.fromPathExpressionMap(nodeTree, prunedValuesByPath); + + return new AssemblyPlan( + nodeTree, + valueProjection, + analysisResult, + analyzeTimeNanos, + treeBuildTimeNanos, + false, + resolverContext + ); + } + + /** + * Resolves the planning-phase root type. + *

    + * For non-container abstract/interface roots, an explicit {@code $}-path + * {@link InterfaceResolver} from {@code set(concreteValue)} takes precedence (last-wins). + * Otherwise — including for {@link Collection}/{@link Map} roots whose element types are + * resolved later by {@link JvmNodeTreeTransformer} — delegates to + * {@link AbstractTypeResolver#resolve}. + */ + private JvmType resolveRootType( + JvmType rootType, + AnalysisResult analysisResult, + @Nullable FixtureMonkeyOptions options + ) { + Class rawType = rootType.getRawType(); + boolean abstractOrInterface = + Modifier.isInterface(rawType.getModifiers()) || Modifier.isAbstract(rawType.getModifiers()); + if (!abstractOrInterface + || Collection.class.isAssignableFrom(rawType) + || Map.class.isAssignableFrom(rawType)) { + return walkCandidateChain(rootType, options); + } + + PathExpression rootPath = PathExpression.of("$"); + List> resolvers = analysisResult.getInterfaceResolvers(); + for (int i = resolvers.size() - 1; i >= 0; i--) { + PathResolver resolver = resolvers.get(i); + if (resolver.matches(rootPath)) { + JvmType resolved = resolver.getCustomizer().resolve(rootType); + if (resolved != null) { + return resolved; + } + } + } + + return walkCandidateChain(rootType, options); + } + + /** + * Adapts {@link FixtureMonkeyOptions} to {@link AbstractTypeResolver#resolve} inputs and + * passes through the input type when {@code options} is null. + */ + private JvmType walkCandidateChain(JvmType type, @Nullable FixtureMonkeyOptions options) { + if (options == null) { + return type; + } + @SuppressWarnings("deprecation") + Function resolverLookup = + options::getCandidateConcretePropertyResolver; + return abstractTypeResolver.resolve(type, resolverLookup, options.getMaxRecursionDepth()); + } + + @Override + public @Nullable JvmNodeTree createConcreteNodeTree(JvmType concreteType, @Nullable FixtureMonkeyOptions options) { + if (options == null) { + return null; + } + + JvmNodeContext context = treeCache.getOrBuildNodeContext( + concreteType, + options, + Collections.emptyMap(), + Collections.emptyMap() + ); + + JvmNodeCandidateTree candidateTree = treeCache.getOrBuildConcreteCandidateTree(concreteType, context, options); + + PathResolverContext localContext = PathResolverContext.builder().build(); + + JvmNodeTreeTransformer transformer = new JvmNodeTreeTransformer( + context, + treeCache.getTreeContext(), + localContext, + null, + treeCache.getSubtreeContext() + ); + + return transformer.transform(candidateTree); + } + + @Override + public @Nullable JvmNodeTree createAnonymousNodeTree( + JvmType interfaceType, + @Nullable FixtureMonkeyOptions options, + PathResolverContext resolverContext + ) { + if (options == null) { + return null; + } + + JavaNodeContext baseContext = (JavaNodeContext)treeCache.getOrBuildNodeContext( + interfaceType, + options, + Collections.emptyMap(), + Collections.emptyMap() + ); + + JavaNodeContext anonymousContext = baseContext.withAdditionalGenerator( + new InterfaceMethodNodeCandidateGenerator() + ); + + JvmNodeCandidateTree candidateTree = new JvmNodeCandidateTree.Builder(interfaceType, anonymousContext) + .withTreeContext(treeCache.getTreeContext()) + .withPreBuildResolvedTypes(true) + .withSkipAbstractLeafCheck(true) + .build(); + + JvmNodeTreeTransformer transformer = new JvmNodeTreeTransformer( + anonymousContext, + treeCache.getTreeContext(), + resolverContext, + null, + treeCache.getSubtreeContext() + ); + + return transformer.transform(candidateTree); + } + + @Override + public boolean isLeafType(Class type) { + if (Types.isJavaType(type)) { + return true; + } + + JvmType jvmType = new JavaType(type); + for (LeafTypeResolver resolver : additionalLeafTypeResolvers) { + if (resolver.isLeafType(jvmType)) { + return true; + } + } + + return false; + } + + public void clearCache() { + treeCache.clear(); + nodeMetadataCache.clear(); + } + + /** + * Returns the cross-call node metadata cache used by {@code Assembler} for assembly optimization. + *

    + * The cache maps {@code JvmType} instances to derived metadata (Property, resolvers, etc.) + * across multiple assembly calls. + * + * @return the node metadata cache + */ + public ConcurrentHashMap nodeMetadataCache() { + return nodeMetadataCache; + } + +} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/ContainerSizeResolverFactory.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/ContainerSizeResolverFactory.java similarity index 62% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/ContainerSizeResolverFactory.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/ContainerSizeResolverFactory.java index 707448e688..94526eb47a 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/ContainerSizeResolverFactory.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/ContainerSizeResolverFactory.java @@ -16,23 +16,21 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.planner; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; import org.jspecify.annotations.Nullable; -import com.navercorp.fixturemonkey.adapter.analysis.AnalysisResult; -import com.navercorp.fixturemonkey.adapter.property.JvmNodePropertyFactory; import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfo; import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfoGenerator; import com.navercorp.fixturemonkey.api.generator.ContainerPropertyGeneratorContext; import com.navercorp.fixturemonkey.api.option.FixtureMonkeyOptions; import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.customizer.ContainerInfoManipulator; +import com.navercorp.fixturemonkey.planner.AnalysisResult; +import com.navercorp.fixturemonkey.property.JvmNodePropertyFactory; import com.navercorp.objectfarm.api.expression.PathExpression; import com.navercorp.objectfarm.api.node.ContainerSizeResolver; import com.navercorp.objectfarm.api.node.SeedSnapshot; @@ -45,7 +43,7 @@ /** * Factory for creating {@link ContainerSizeResolver}s from manipulators and options. * - *

    Extracted from {@link DefaultNodeTreeAdapter} to separate container size + *

    Extracted from {@link AssemblyPlanner} to separate container size * resolution concerns from the main adapt orchestration logic. */ final class ContainerSizeResolverFactory { @@ -58,27 +56,12 @@ final class ContainerSizeResolverFactory { this.seedState = seedState; } - Map collectSizeSequences( - List containerManipulators, - Map containerPathCache - ) { - Map sizeSequenceByPath = new HashMap<>(); - for (ContainerInfoManipulator manipulator : containerManipulators) { - PathExpression path = containerPathCache.get(manipulator); - if (path != null) { - sizeSequenceByPath.put(path, manipulator.getManipulatingSequence()); - } - } - return sizeSequenceByPath; - } - - void addLazyContainerSizeResolvers( + void addAnalysisContainerSizeResolvers( PathResolverContext.Builder builder, AnalysisResult analysisResult, - Map sizeSequenceByPath, List> wildcardSizeSequences ) { - Map lazyContainerSizeSequence = analysisResult.getContainerSizeSequenceByPath(); + Map sequenceByPath = analysisResult.getContainerSizeSequenceByPath(); for (PathResolver resolver : analysisResult.getContainerSizeResolvers()) { PathExpression resolverPath = extractResolverPath(resolver); if (resolverPath == null) { @@ -86,78 +69,26 @@ void addLazyContainerSizeResolvers( continue; } - Integer explicitSizeSequence = sizeSequenceByPath.get(resolverPath); - Integer lazySizeSequence = lazyContainerSizeSequence.get(resolverPath); - - // If no explicit size() call for this exact path, check wildcard matches - if (explicitSizeSequence == null) { - if (lazySizeSequence != null && !wildcardSizeSequences.isEmpty()) { - boolean overriddenByWildcard = false; - for (Map.Entry wildcardEntry : wildcardSizeSequences) { - if ( - wildcardEntry.getKey().matches(resolverPath) && wildcardEntry.getValue() > lazySizeSequence - ) { - overriddenByWildcard = true; - break; - } - } - if (overriddenByWildcard) { - continue; + // Sequence wins: a wildcard resolver with higher sequence shadows any exact-path + // resolver at a matching path. Build-time pruning is what enables this — the runtime + // EXACT-over-WILDCARD precedence in JvmNodeTreeTransformer would otherwise prevent + // the wildcard from taking effect at the shadowed exact path. + if (!resolverPath.hasWildcard() && !wildcardSizeSequences.isEmpty()) { + Integer ownSequence = sequenceByPath.get(resolverPath); + boolean overriddenByWildcard = false; + for (Map.Entry wildcardEntry : wildcardSizeSequences) { + if (wildcardEntry.getKey().matches(resolverPath) + && (ownSequence == null || wildcardEntry.getValue() > ownSequence)) { + overriddenByWildcard = true; + break; } } - builder.addContainerSizeResolver(resolver); - continue; - } - - // If lazy sequence is higher than explicit size sequence, the lazy value should win - if (lazySizeSequence != null && lazySizeSequence > explicitSizeSequence) { - builder.addContainerSizeResolver(resolver); - } - } - } - - void addManipulatorContainerSizeResolvers( - PathResolverContext.Builder builder, - List containerManipulators, - Map globalValueSequences, - Map sizeSequenceByPath, - Map containerPathCache - ) { - for (ContainerInfoManipulator manipulator : containerManipulators) { - PathExpression path = containerPathCache.get(manipulator); - if (path == null) { - continue; - } - - Integer setSequence = globalValueSequences.get(path); - Integer sizeSequence = sizeSequenceByPath.get(path); - - // Skip if set() was called after size() for this path — sequence determines priority - if (setSequence != null && sizeSequence != null && setSequence > sizeSequence) { - continue; - } - - ArbitraryContainerInfo containerInfo = manipulator.getContainerInfo(); - int minSize = containerInfo.getElementMinSize(); - int maxSize = containerInfo.getElementMaxSize(); - - ContainerSizeResolver sizeResolver = containerType -> { - int effectiveMin = minSize; - int effectiveMax = maxSize; - - Integer enumLimit = getEnumSizeLimit(containerType); - if (enumLimit != null) { - effectiveMax = Math.min(effectiveMax, enumLimit); - effectiveMin = Math.min(effectiveMin, effectiveMax); - } - - if (effectiveMin == effectiveMax) { - return effectiveMin; + if (overriddenByWildcard) { + continue; } - return effectiveMin + (int) (Math.random() * (effectiveMax - effectiveMin + 1)); - }; + } - builder.addContainerSizeResolver(new PathContainerSizeResolver(path, sizeResolver)); + builder.addContainerSizeResolver(resolver); } } @@ -175,7 +106,8 @@ void addTypedContainerSizeResolvers( if (minSize == maxSize) { return minSize; } - return minSize + (int) (Math.random() * (maxSize - minSize + 1)); + int range = maxSize - minSize + 1; + return minSize + nextRandomForType(containerType).nextInt(range); }; builder.addTypedContainerSizeResolver(ownerType, fieldEntry.getKey(), resolver); } @@ -184,7 +116,11 @@ void addTypedContainerSizeResolvers( /** * Creates a ContainerSizeResolver based on the given options. - * Each invocation generates a new snapshot from seedState for reproducible randomness. + * + *

    Sizes come from the next {@link SeedState#snapshot()} combined with the container + * type's hash. Each resolve advances the seed sequence, so consecutive calls produce + * varied sizes; two adapters created with the same seed see the same sequence and + * therefore the same sizes for the same call pattern. */ ContainerSizeResolver createContainerSizeResolver(@Nullable FixtureMonkeyOptions options) { if (options != null) { @@ -212,18 +148,29 @@ ContainerSizeResolver createContainerSizeResolver(@Nullable FixtureMonkeyOptions if (minSize == maxSize) { return minSize; } - Random typeRandom = seedState.snapshot().randomFor(containerType.hashCode()); - return minSize + typeRandom.nextInt(maxSize - minSize + 1); + return minSize + nextRandomForType(containerType).nextInt(maxSize - minSize + 1); }; } return containerType -> { int range = DEFAULT_MAX_CONTAINER_SIZE - DEFAULT_MIN_CONTAINER_SIZE + 1; - Random typeRandom = seedState.snapshot().randomFor(containerType.hashCode()); - return DEFAULT_MIN_CONTAINER_SIZE + typeRandom.nextInt(range); + return DEFAULT_MIN_CONTAINER_SIZE + nextRandomForType(containerType).nextInt(range); }; } + private Random nextRandomForType(JvmType containerType) { + // Use the dedicated container-size counter on SeedState so cache hit/miss in other + // snapshot() consumers does not perturb the size sequence. Combining the snapshot + // with the type hash (via SeedSnapshot.seedFor) gives per-call variation plus + // per-type spread. Class.hashCode() is identityHashCode and varies across JVM runs, + // so we hash the fully-qualified class name instead to keep seeds reproducible. + return seedState.containerSizeSnapshot().randomFor(stableTypeHash(containerType)); + } + + private static int stableTypeHash(JvmType containerType) { + return containerType.getRawType().getName().hashCode(); + } + /** * Creates a deterministic ContainerSizeResolver for fixed() mode. * Uses a constant snapshot (sequence=0) so every resolve produces the same sizes. @@ -259,7 +206,7 @@ ContainerSizeResolver createFixedContainerSizeResolver(@Nullable FixtureMonkeyOp return minSize; } int range = maxSize - minSize + 1; - Random typeRandom = fixedSnapshot.randomFor(containerType.hashCode()); + Random typeRandom = fixedSnapshot.randomFor(stableTypeHash(containerType)); return minSize + typeRandom.nextInt(range); }; } diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/ContainerValuePruner.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/ContainerValuePruner.java similarity index 79% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/ContainerValuePruner.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/ContainerValuePruner.java index 4ea95b285c..cb775ed156 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/ContainerValuePruner.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/ContainerValuePruner.java @@ -16,12 +16,11 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.planner; import java.util.AbstractMap; import java.util.ArrayList; import java.util.Collection; -import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -29,7 +28,7 @@ import org.jspecify.annotations.Nullable; import com.navercorp.fixturemonkey.api.type.Types; -import com.navercorp.fixturemonkey.customizer.ContainerInfoManipulator; +import com.navercorp.fixturemonkey.customizer.SizeDirective; import com.navercorp.objectfarm.api.expression.IndexSelector; import com.navercorp.objectfarm.api.expression.PathExpression; import com.navercorp.objectfarm.api.expression.Segment; @@ -38,7 +37,7 @@ /** * Prunes values that exceed container size constraints. * - *

    Extracted from {@link DefaultNodeTreeAdapter} to separate container value + *

    Extracted from {@link AssemblyPlanner} to separate container value * pruning concerns from the main adapt orchestration logic. */ final class ContainerValuePruner { @@ -50,21 +49,15 @@ final class ContainerValuePruner { Map pruneValuesExceedingContainerSize( Map valuesByPath, - List containerManipulators, - Map valueOrderByPath, - Map containerPathCache + Map latestSizeDirectiveByPath, + Map valueOrderByPath ) { - if (valuesByPath.isEmpty() || containerManipulators.isEmpty()) { + if (valuesByPath.isEmpty() || latestSizeDirectiveByPath.isEmpty()) { return new HashMap<>(valuesByPath); } - Map sizeConstraintByPath = collectContainerSizeConstraints( - containerManipulators, - containerPathCache - ); - if (sizeConstraintByPath.isEmpty()) { - return new HashMap<>(valuesByPath); - } + Map sizeConstraintByPath = + toSizeConstraints(latestSizeDirectiveByPath); List> wildcardSizeEntries = new ArrayList<>(); for (Map.Entry entry : sizeConstraintByPath.entrySet()) { @@ -78,7 +71,8 @@ final class ContainerValuePruner { for (PathExpression path : valuesByPath.keySet()) { @Nullable Object value = valuesByPath.get(path); - ContainerSizeConstraint sizeConstraint = sizeConstraintByPath.get(path); + ContainerSizeConstraint sizeConstraint = + resolveEffectiveConstraint(path, sizeConstraintByPath.get(path), wildcardSizeEntries); // Case 1: Exact path match with size constraint if (sizeConstraint != null && containerDetector.isContainer(value)) { @@ -128,7 +122,7 @@ final class ContainerValuePruner { } } - // Case 3: Container without exact/wildcard match — check child manipulators + // Case 3: Container without exact/wildcard match — check child size directives if (containerDetector.isContainer(value) && !keysToRemove.contains(path)) { int effectiveOrder = valueOrderByPath.getOrDefault(path, Integer.MIN_VALUE); if (hasChildManipulatorWithHigherSequence(path, effectiveOrder, sizeConstraintByPath)) { @@ -138,7 +132,7 @@ final class ContainerValuePruner { } // Case 4: Indexed element exceeding container size - if (isIndexedElementOutOfRange(path, sizeConstraintByPath, valueOrderByPath)) { + if (isIndexedElementOutOfRange(path, sizeConstraintByPath, wildcardSizeEntries, valueOrderByPath)) { keysToRemove.add(path); } } @@ -209,9 +203,37 @@ private boolean applyContainerSizeConstraint( return null; } + /** + * Mirrors the runtime precedence applied in {@code PathResolverContextFactory}: a wildcard + * size directive with a strictly higher sequence shadows the exact-path constraint at any + * matching path. Pruning must use the same effective constraint, otherwise a value can be + * truncated based on a constraint the assembler will later ignore. + */ + private static @Nullable ContainerSizeConstraint resolveEffectiveConstraint( + PathExpression path, + @Nullable ContainerSizeConstraint exact, + List> wildcardSizeEntries + ) { + if (path.hasWildcard() || wildcardSizeEntries.isEmpty()) { + return exact; + } + ContainerSizeConstraint effective = exact; + for (Map.Entry wildcardEntry : wildcardSizeEntries) { + if (!wildcardEntry.getKey().matches(path)) { + continue; + } + ContainerSizeConstraint candidate = wildcardEntry.getValue(); + if (effective == null || candidate.sequence > effective.sequence) { + effective = candidate; + } + } + return effective; + } + private static boolean isIndexedElementOutOfRange( PathExpression path, Map sizeConstraintByPath, + List> wildcardSizeEntries, Map valueOrderByPath ) { List segments = path.getSegments(); @@ -223,7 +245,11 @@ private static boolean isIndexedElementOutOfRange( if (lastSegment.isSingleSelector() && lastSegment.getFirstSelector() instanceof IndexSelector) { int index = ((IndexSelector)lastSegment.getFirstSelector()).getIndex(); PathExpression containerPath = path.getParent(); - ContainerSizeConstraint containerSizeConstraint = sizeConstraintByPath.get(containerPath); + ContainerSizeConstraint containerSizeConstraint = resolveEffectiveConstraint( + containerPath, + sizeConstraintByPath.get(containerPath), + wildcardSizeEntries + ); if (containerSizeConstraint != null && index >= containerSizeConstraint.size) { // Only prune if the size constraint has higher sequence than this element's value Integer elementOrder = valueOrderByPath.get(path); @@ -341,28 +367,24 @@ private static Object resizeContainer(Object container, int targetSize) { return container; } - private static Map collectContainerSizeConstraints( - List containerManipulators, - Map containerPathCache + /** + * Converts the analyzer's per-path latest {@link SizeDirective} map into the constraint + * shape this class uses internally. Uses {@code maxSize} (not the {@code fixed()}-resolved + * size) so elements within the max range are preserved — e.g. {@code maxSize(2) + + * listElement(1, value)} keeps {@code $[1]} alive. + */ + private static Map toSizeConstraints( + Map latestSizeDirectiveByPath ) { - Map sizeConstraintByPath = new HashMap<>(); - - List sorted = new ArrayList<>(containerManipulators); - sorted.sort(Comparator.comparingInt(ContainerInfoManipulator::getManipulatingSequence)); - - for (ContainerInfoManipulator manipulator : sorted) { - // Use maxSize for pruning indexed elements — elements within the max range should be preserved. - // Using fixed() (random between min and max) would incorrectly prune elements - // when maxSize > fixedSize (e.g., maxSize(2) + listElement(1, value) should keep $[1]). - int size = manipulator.getContainerInfo().getElementMaxSize(); - int sequence = manipulator.getManipulatingSequence(); - - PathExpression path = containerPathCache.get(manipulator); - if (path != null) { - sizeConstraintByPath.put(path, new ContainerSizeConstraint(size, sequence)); - } + Map sizeConstraintByPath = + new HashMap<>(latestSizeDirectiveByPath.size()); + for (Map.Entry entry : latestSizeDirectiveByPath.entrySet()) { + SizeDirective directive = entry.getValue(); + sizeConstraintByPath.put( + entry.getKey(), + new ContainerSizeConstraint(directive.containerInfo().getElementMaxSize(), directive.sequence()) + ); } - return sizeConstraintByPath; } diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/analysis/ManipulatorAnalyzer.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/ManipulatorAnalyzer.java similarity index 55% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/analysis/ManipulatorAnalyzer.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/ManipulatorAnalyzer.java index 7cd133fad4..d459552868 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/analysis/ManipulatorAnalyzer.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/ManipulatorAnalyzer.java @@ -16,17 +16,18 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter.analysis; +package com.navercorp.fixturemonkey.planner; -import static com.navercorp.fixturemonkey.adapter.analysis.AnalysisResult.LazyManipulatorDescriptor; -import static com.navercorp.fixturemonkey.adapter.analysis.AnalysisResult.PostConditionFilter; -import static com.navercorp.fixturemonkey.adapter.analysis.AnalysisResult.PropertyCustomizer; import static com.navercorp.fixturemonkey.api.property.DefaultPropertyGenerator.FIELD_PROPERTY_GENERATOR; import static com.navercorp.fixturemonkey.api.type.Types.generateAnnotatedTypeWithoutAnnotation; import static com.navercorp.fixturemonkey.api.type.Types.isBoxedPrimitive; import static com.navercorp.fixturemonkey.api.type.Types.isJavaType; +import static com.navercorp.fixturemonkey.api.type.Types.toJvmType; +import static com.navercorp.fixturemonkey.planner.AnalysisResult.PostConditionFilter; +import static com.navercorp.fixturemonkey.planner.AnalysisResult.PropertyCustomizer; import java.lang.reflect.AnnotatedType; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -38,7 +39,6 @@ import java.util.OptionalInt; import java.util.Set; import java.util.function.Function; -import java.util.function.Predicate; import java.util.stream.Stream; import org.apiguardian.api.API; @@ -47,31 +47,24 @@ import net.jqwik.api.Arbitrary; -import com.navercorp.fixturemonkey.adapter.converter.PredicatePathConverter; -import com.navercorp.fixturemonkey.adapter.tracing.ResolutionTrace; import com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary; import com.navercorp.fixturemonkey.api.container.DecomposableJavaContainer; import com.navercorp.fixturemonkey.api.container.DecomposedContainerValueFactory; +import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfo; import com.navercorp.fixturemonkey.api.lazy.LazyArbitrary; +import com.navercorp.fixturemonkey.api.property.FieldProperty; import com.navercorp.fixturemonkey.api.property.Property; import com.navercorp.fixturemonkey.api.property.TypeParameterProperty; -import com.navercorp.fixturemonkey.customizer.ApplyNodeCountManipulator; -import com.navercorp.fixturemonkey.customizer.ArbitraryManipulator; -import com.navercorp.fixturemonkey.customizer.CompositeNodeManipulator; -import com.navercorp.fixturemonkey.customizer.NodeCustomizerManipulator; -import com.navercorp.fixturemonkey.customizer.NodeFilterManipulator; -import com.navercorp.fixturemonkey.customizer.NodeManipulator; -import com.navercorp.fixturemonkey.customizer.NodeNullityManipulator; -import com.navercorp.fixturemonkey.customizer.NodeSetDecomposedValueManipulator; -import com.navercorp.fixturemonkey.customizer.NodeSetJustManipulator; -import com.navercorp.fixturemonkey.customizer.NodeSetLazyManipulator; +import com.navercorp.fixturemonkey.customizer.CustomizerDirective; +import com.navercorp.fixturemonkey.customizer.FilterDirective; +import com.navercorp.fixturemonkey.customizer.JustDirective; +import com.navercorp.fixturemonkey.customizer.LazyDirective; +import com.navercorp.fixturemonkey.customizer.NullityDirective; +import com.navercorp.fixturemonkey.customizer.PathDirective; +import com.navercorp.fixturemonkey.customizer.SetDirective; +import com.navercorp.fixturemonkey.customizer.SizeDirective; import com.navercorp.fixturemonkey.customizer.Values; -import com.navercorp.fixturemonkey.tree.ApplyStrictModeResolver; -import com.navercorp.fixturemonkey.tree.CompositeNodeResolver; -import com.navercorp.fixturemonkey.tree.NextNodePredicate; -import com.navercorp.fixturemonkey.tree.NodePredicateResolver; -import com.navercorp.fixturemonkey.tree.NodeResolver; -import com.navercorp.fixturemonkey.tree.StaticNodeResolver; +import com.navercorp.fixturemonkey.tracing.ResolutionTrace; import com.navercorp.objectfarm.api.expression.PathExpression; import com.navercorp.objectfarm.api.input.ContainerDetector; import com.navercorp.objectfarm.api.input.ExtractedField; @@ -85,12 +78,13 @@ import com.navercorp.objectfarm.api.tree.PathResolver; /** - * Analyzes ArbitraryManipulator instances to extract topology-affecting information. + * Analyzes {@link PathDirective} instances to extract topology-affecting information. *

    - * This analyzer processes ArbitraryManipulators and extracts: + * This analyzer walks the directive list in order and extracts: *

      *
    • Interface resolution information from value setters
    • *
    • Generic type hints from value types
    • + *
    • Container size resolvers (from explicit {@code size()} and decomposed values)
    • *
    • Paths that should be excluded (null paths or just-set paths)
    • *
    */ @@ -100,32 +94,27 @@ private ManipulatorAnalyzer() { } /** - * Analyzes a list of ArbitraryManipulators and extracts topology-affecting information. - * Uses Java field names for decomposed path expressions. - * - * @param manipulators the list of ArbitraryManipulators to analyze - * @return the analysis result containing resolvers and just paths - */ - public static AnalysisResult analyze(List manipulators) { - return analyze(manipulators, Property::getName); - } - - /** - * Analyzes a list of ArbitraryManipulators and extracts topology-affecting information. + * Analyzes a list of {@link PathDirective}s and extracts topology-affecting information. + *

    + * The {@code nameResolver} is used when decomposing {@code set("$", complexObject)} values so + * plugin-specific naming (e.g., Jackson {@code @JsonProperty}) is preserved on the produced + * child paths. Pass {@code null} to fall back to {@link Property#getName()}. * - * @param manipulators the list of ArbitraryManipulators to analyze - * @param nameResolver resolves property names for decomposed path expressions - * @return the analysis result containing resolvers and just paths + * @param directives the list of directives to analyze + * @param nameResolver per-property name resolver applied to decomposed child paths */ - public static AnalysisResult analyze(List manipulators, DecomposeNameResolver nameResolver) { + public static AnalysisResult analyze( + List directives, + @Nullable Function nameResolver + ) { List> interfaceResolvers = new ArrayList<>(); List> genericTypeResolvers = new ArrayList<>(); List> containerSizeResolvers = new ArrayList<>(); Map containerSizeSequenceByPath = new HashMap<>(); + Map latestSizeDirectiveByPath = new HashMap<>(); List justPaths = new ArrayList<>(); Set notNullPaths = new HashSet<>(); Map valuesByPath = new HashMap<>(); - List lazyManipulators = new ArrayList<>(); Map> filtersByPath = new HashMap<>(); Map limitsByPath = new HashMap<>(); Map valueOrderByPath = new HashMap<>(); @@ -133,31 +122,29 @@ public static AnalysisResult analyze(List manipulators, De List nodeCollisions = new ArrayList<>(); boolean strictMode = false; - for (int order = 0; order < manipulators.size(); order++) { - ArbitraryManipulator manipulator = manipulators.get(order); + for (int order = 0; order < directives.size(); order++) { + PathDirective directive = directives.get(order); - // Skip registered manipulators (those using StaticNodeResolver) - // They are handled via type-based resolution, not path-based resolution - if (hasStaticNodeResolver(manipulator.getNodeResolver())) { + // Registered directives are handled via type-based resolution, not path-based resolution + if (directive.registered()) { continue; } - // Check if strict mode is enabled (any manipulator with ApplyStrictModeResolver) - if (!strictMode && hasStrictModeResolver(manipulator.getNodeResolver())) { + if (!strictMode && directive.strict()) { strictMode = true; } - analyzeManipulator( - manipulator, + analyzeDirective( + directive, order, interfaceResolvers, genericTypeResolvers, containerSizeResolvers, containerSizeSequenceByPath, + latestSizeDirectiveByPath, justPaths, notNullPaths, valuesByPath, - lazyManipulators, filtersByPath, limitsByPath, valueOrderByPath, @@ -172,10 +159,10 @@ public static AnalysisResult analyze(List manipulators, De genericTypeResolvers, containerSizeResolvers, containerSizeSequenceByPath, + latestSizeDirectiveByPath, justPaths, notNullPaths, valuesByPath, - lazyManipulators, filtersByPath, limitsByPath, valueOrderByPath, @@ -186,7 +173,7 @@ public static AnalysisResult analyze(List manipulators, De } /** - * Returns an empty AnalysisResult for cases where there are no manipulators. + * Returns an empty AnalysisResult for cases where there are no directives. * This is a performance optimization to avoid creating empty collections repeatedly. */ public static AnalysisResult emptyResult() { @@ -200,10 +187,10 @@ public static AnalysisResult emptyResult() { Collections.emptyList(), Collections.emptyList(), Collections.emptyMap(), + Collections.emptyMap(), Collections.emptyList(), Collections.emptySet(), Collections.emptyMap(), - Collections.emptyList(), Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap(), @@ -212,145 +199,43 @@ public static AnalysisResult emptyResult() { false ); - private static void analyzeManipulator( - ArbitraryManipulator manipulator, + private static void analyzeDirective( + PathDirective directive, int order, List> interfaceResolvers, List> genericTypeResolvers, List> containerSizeResolvers, Map containerSizeSequenceByPath, + Map latestSizeDirectiveByPath, List justPaths, Set notNullPaths, Map valuesByPath, - List lazyManipulators, Map> filtersByPath, Map limitsByPath, Map valueOrderByPath, Map> customizersByPath, List nodeCollisions, - DecomposeNameResolver nameResolver + @Nullable Function nameResolver ) { - NodeResolver nodeResolver = manipulator.getNodeResolver(); - NodeManipulator nodeManipulator = manipulator.getNodeManipulator(); - - List predicates = extractPredicates(nodeResolver); - PathExpression pathExpression = PredicatePathConverter.convert(predicates, nameResolver); - - analyzeNodeManipulator( - nodeManipulator, - pathExpression, - order, - interfaceResolvers, - genericTypeResolvers, - containerSizeResolvers, - containerSizeSequenceByPath, - justPaths, - notNullPaths, - valuesByPath, - lazyManipulators, - filtersByPath, - limitsByPath, - null, - valueOrderByPath, - customizersByPath, - nodeCollisions, - nameResolver - ); - } - - private static void analyzeNodeManipulator( - NodeManipulator nodeManipulator, - PathExpression pathExpression, - int order, - List> interfaceResolvers, - List> genericTypeResolvers, - List> containerSizeResolvers, - Map containerSizeSequenceByPath, - List justPaths, - Set notNullPaths, - Map valuesByPath, - List lazyManipulators, - Map> filtersByPath, - Map limitsByPath, - @Nullable Integer limit, - Map valueOrderByPath, - Map> customizersByPath, - List nodeCollisions, - DecomposeNameResolver nameResolver - ) { - if (nodeManipulator instanceof CompositeNodeManipulator) { - CompositeNodeManipulator composite = (CompositeNodeManipulator)nodeManipulator; - for (NodeManipulator inner : composite.getManipulators()) { - analyzeNodeManipulator( - inner, - pathExpression, - order, - interfaceResolvers, - genericTypeResolvers, - containerSizeResolvers, - containerSizeSequenceByPath, - justPaths, - notNullPaths, - valuesByPath, - lazyManipulators, - filtersByPath, - limitsByPath, - limit, - valueOrderByPath, - customizersByPath, - nodeCollisions, - nameResolver - ); - } - return; - } - - if (nodeManipulator instanceof ApplyNodeCountManipulator) { - ApplyNodeCountManipulator countManipulator = (ApplyNodeCountManipulator)nodeManipulator; - int extractedLimit = countManipulator.getCount(); - if (extractedLimit > 0) { - limitsByPath.put(pathExpression, extractedLimit); - } - analyzeNodeManipulator( - countManipulator.getNodeManipulator(), - pathExpression, - order, - interfaceResolvers, - genericTypeResolvers, - containerSizeResolvers, - containerSizeSequenceByPath, - justPaths, - notNullPaths, - valuesByPath, - lazyManipulators, - filtersByPath, - limitsByPath, - extractedLimit, - valueOrderByPath, - customizersByPath, - nodeCollisions, - nameResolver - ); - return; + PathExpression pathExpression = directive.path(); + int limit = directive.limit(); + if (limit > 0) { + limitsByPath.put(pathExpression, limit); } - if (nodeManipulator instanceof NodeFilterManipulator) { - NodeFilterManipulator filterManipulator = (NodeFilterManipulator)nodeManipulator; - PostConditionFilter filter = extractPostConditionFilter(filterManipulator); - if (filter != null) { - filtersByPath.computeIfAbsent(pathExpression, k -> new ArrayList<>()).add(filter); - } + if (directive instanceof FilterDirective) { + FilterDirective filterDirective = (FilterDirective)directive; + filtersByPath + .computeIfAbsent(pathExpression, k -> new ArrayList<>()) + .add(new PostConditionFilter(filterDirective.type(), filterDirective.filter())); return; } - if (nodeManipulator instanceof NodeCustomizerManipulator) { - @SuppressWarnings("unchecked") - NodeCustomizerManipulator customizerManipulator = (NodeCustomizerManipulator)nodeManipulator; - @SuppressWarnings("unchecked") - Function, CombinableArbitrary> customizer = (Function< - CombinableArbitrary, - CombinableArbitrary - >)(Function)customizerManipulator.getArbitraryCustomizer(); + if (directive instanceof CustomizerDirective) { + CustomizerDirective customizerDirective = (CustomizerDirective)directive; + @SuppressWarnings({"unchecked", "rawtypes"}) + Function, CombinableArbitrary> customizer = + (Function)customizerDirective.customizer(); boolean afterSet = valuesByPath.containsKey(pathExpression); customizersByPath .computeIfAbsent(pathExpression, k -> new ArrayList<>()) @@ -358,10 +243,9 @@ private static void analyzeNodeManipulator( return; } - if (nodeManipulator instanceof NodeSetDecomposedValueManipulator) { - analyzeDecomposedValueManipulator( - (NodeSetDecomposedValueManipulator)nodeManipulator, - pathExpression, + if (directive instanceof SetDirective) { + analyzeSetDirective( + (SetDirective)directive, interfaceResolvers, genericTypeResolvers, containerSizeResolvers, @@ -371,28 +255,25 @@ private static void analyzeNodeManipulator( nodeCollisions, nameResolver ); - } else if (nodeManipulator instanceof NodeSetJustManipulator) { - // Values.just() creates truly immutable values - child values should NOT be applied. - // This is intentional: when a user sets Values.just(object), they want that exact object - // without any modifications. Subsequent set("child", value) calls are ignored. - // This is the ONLY case where child path values are ignored. - NodeSetJustManipulator justManipulator = (NodeSetJustManipulator)nodeManipulator; - Object value = justManipulator.getValue(); + return; + } + + if (directive instanceof JustDirective) { + JustDirective justDirective = (JustDirective)directive; + Object value = justDirective.value(); if (value != null) { recordCollisionIfExists(pathExpression, order, value, valuesByPath, valueOrderByPath, nodeCollisions); valuesByPath.put(pathExpression, value); valueOrderByPath.put(pathExpression, order); } justPaths.add(pathExpression); - } else if (nodeManipulator instanceof NodeNullityManipulator) { - // setNull() just sets the value to null - child values CAN override this. - // Following the "more specific path wins" rule: setNull("object") + set("object.str", "x") - // results in object.str = "x" (the more specific path wins). - // setNotNull() removes any null value that was previously set for this path - // and also sets null injection to 0 for this path. - NodeNullityManipulator nullityManipulator = (NodeNullityManipulator)nodeManipulator; - int nullitySequence = nullityManipulator.getSequence(); - if (nullityManipulator.isToNull()) { + return; + } + + if (directive instanceof NullityDirective) { + NullityDirective nullityDirective = (NullityDirective)directive; + int nullitySequence = nullityDirective.sequence(); + if (nullityDirective.toNull()) { recordCollisionIfExists( pathExpression, nullitySequence, @@ -405,23 +286,18 @@ private static void analyzeNodeManipulator( valueOrderByPath.put(pathExpression, nullitySequence); notNullPaths.remove(pathExpression); } else { - // setNotNull: remove any previously set null value for this path if (valuesByPath.containsKey(pathExpression) && valuesByPath.get(pathExpression) == null) { valuesByPath.remove(pathExpression); valueOrderByPath.remove(pathExpression); } - // Track this path as requiring non-null (null injection = 0) notNullPaths.add(pathExpression); } - } else if (nodeManipulator instanceof NodeSetLazyManipulator) { - NodeSetLazyManipulator lazyManipulator = (NodeSetLazyManipulator)nodeManipulator; - if (limit != null) { - limitsByPath.put(pathExpression, limit); - } - // Evaluate lazy immediately and decompose - same flow as other values - analyzeLazyManipulator( - lazyManipulator, - pathExpression, + return; + } + + if (directive instanceof LazyDirective) { + analyzeLazyDirective( + (LazyDirective)directive, interfaceResolvers, genericTypeResolvers, containerSizeResolvers, @@ -432,12 +308,76 @@ private static void analyzeNodeManipulator( nodeCollisions, nameResolver ); + return; + } + + if (directive instanceof SizeDirective) { + analyzeSizeDirective( + (SizeDirective)directive, + containerSizeResolvers, + containerSizeSequenceByPath, + latestSizeDirectiveByPath + ); } } - private static void analyzeDecomposedValueManipulator( - NodeSetDecomposedValueManipulator manipulator, - PathExpression pathExpression, + private static void analyzeSizeDirective( + SizeDirective directive, + List> containerSizeResolvers, + Map containerSizeSequenceByPath, + Map latestSizeDirectiveByPath + ) { + PathExpression path = directive.path(); + int sequence = directive.sequence(); + + Integer existingSequence = containerSizeSequenceByPath.get(path); + if (existingSequence != null && existingSequence > sequence) { + return; + } + if (existingSequence != null) { + containerSizeResolvers.removeIf(existing -> path.equals(getResolverPath(existing))); + } + containerSizeSequenceByPath.put(path, sequence); + latestSizeDirectiveByPath.put(path, directive); + containerSizeResolvers.add(buildExplicitSizeResolver(directive)); + } + + private static PathResolver buildExplicitSizeResolver(SizeDirective directive) { + ArbitraryContainerInfo containerInfo = directive.containerInfo(); + int fixedSize = containerInfo.getRandomSize(); + + ContainerSizeResolver sizeResolver = containerType -> { + if (containerType == null) { + return fixedSize; + } + Class rawType = containerType.getRawType(); + List typeVariables = containerType.getTypeVariables(); + Class enumType = null; + if (!typeVariables.isEmpty()) { + if (java.util.Set.class.isAssignableFrom(rawType)) { + Class elementType = typeVariables.get(0).getRawType(); + if (elementType.isEnum()) { + enumType = elementType; + } + } else if (Map.class.isAssignableFrom(rawType)) { + Class keyType = typeVariables.get(0).getRawType(); + if (keyType.isEnum()) { + enumType = keyType; + } + } + } + if (enumType == null) { + return fixedSize; + } + Object[] constants = enumType.getEnumConstants(); + return constants != null ? Math.min(fixedSize, constants.length) : fixedSize; + }; + + return new PathContainerSizeResolver(directive.path(), sizeResolver); + } + + private static void analyzeSetDirective( + SetDirective directive, List> interfaceResolvers, List> genericTypeResolvers, List> containerSizeResolvers, @@ -445,15 +385,15 @@ private static void analyzeDecomposedValueManipulator( Map valuesByPath, Map valueOrderByPath, List nodeCollisions, - DecomposeNameResolver nameResolver + @Nullable Function nameResolver ) { - Object value = manipulator.getValue(); + PathExpression pathExpression = directive.path(); + Object value = directive.value(); if (value == null) { return; } - // Use the manipulator's factory sequence for priority comparison - int factorySequence = manipulator.getSequence(); + int factorySequence = directive.sequence(); // Remove existing indexed child paths under this path before adding new values // This handles the case where a container is set multiple times @@ -472,7 +412,7 @@ private static void analyzeDecomposedValueManipulator( .keySet() .removeIf(key -> key.toExpression().startsWith(indexPrefix) && !valuesByPath.containsKey(key)); - DecomposedContainerValueFactory factory = manipulator.getDecomposedContainerValueFactory(); + DecomposedContainerValueFactory factory = directive.decomposedContainerValueFactory(); ContainerDetector containerDetector = createContainerDetector(factory); FieldExtractor fieldExtractor = createFieldExtractor(nameResolver); @@ -538,13 +478,12 @@ private static void analyzeDecomposedValueManipulator( } /** - * Analyzes a lazy manipulator by evaluating it immediately and decomposing the result. - * This follows the same flow as decomposed value manipulators, ensuring consistent + * Analyzes a lazy directive by evaluating it immediately and decomposing the result. + * This follows the same flow as decomposed value directives, ensuring consistent * value ordering and priority handling. */ - private static void analyzeLazyManipulator( - NodeSetLazyManipulator manipulator, - PathExpression pathExpression, + private static void analyzeLazyDirective( + LazyDirective directive, List> interfaceResolvers, List> genericTypeResolvers, List> containerSizeResolvers, @@ -553,9 +492,10 @@ private static void analyzeLazyManipulator( Map valuesByPath, Map valueOrderByPath, List nodeCollisions, - DecomposeNameResolver nameResolver + @Nullable Function nameResolver ) { - LazyArbitrary lazyArbitrary = manipulator.getLazyArbitrary(); + PathExpression pathExpression = directive.path(); + LazyArbitrary lazyArbitrary = directive.lazyArbitrary(); Object value = lazyArbitrary.getValue(); if (value == null) { @@ -563,14 +503,14 @@ private static void analyzeLazyManipulator( // (e.g., Map key null check: "Map key cannot be null.") recordCollisionIfExists( pathExpression, - manipulator.getSequence(), + directive.sequence(), null, valuesByPath, valueOrderByPath, nodeCollisions ); valuesByPath.put(pathExpression, null); - valueOrderByPath.put(pathExpression, manipulator.getSequence()); + valueOrderByPath.put(pathExpression, directive.sequence()); lazyArbitrary.clear(); return; } @@ -581,14 +521,14 @@ private static void analyzeLazyManipulator( if (value == null) { recordCollisionIfExists( pathExpression, - manipulator.getSequence(), + directive.sequence(), null, valuesByPath, valueOrderByPath, nodeCollisions ); valuesByPath.put(pathExpression, null); - valueOrderByPath.put(pathExpression, manipulator.getSequence()); + valueOrderByPath.put(pathExpression, directive.sequence()); lazyArbitrary.clear(); return; } @@ -600,22 +540,21 @@ private static void analyzeLazyManipulator( if (justValue != null) { recordCollisionIfExists( pathExpression, - manipulator.getSequence(), + directive.sequence(), justValue, valuesByPath, valueOrderByPath, nodeCollisions ); valuesByPath.put(pathExpression, justValue); - valueOrderByPath.put(pathExpression, manipulator.getSequence()); + valueOrderByPath.put(pathExpression, directive.sequence()); } justPaths.add(pathExpression); lazyArbitrary.clear(); return; } - // Use the manipulator's factory sequence for priority comparison - int factorySequence = manipulator.getSequence(); + int factorySequence = directive.sequence(); // Remove existing child paths under this path before adding new values // Only remove child paths with lower sequence (older values) @@ -628,7 +567,7 @@ private static void analyzeLazyManipulator( ); valueOrderByPath.keySet().removeIf(key -> key.isChildOf(pathExpression) && !valuesByPath.containsKey(key)); - // Use standard container detector and name-resolving field extractor for lazy values + // Use standard container detector and property-aware field extractor for lazy values ContainerDetector containerDetector = ContainerDetector.standard(); FieldExtractor fieldExtractor = createFieldExtractor(nameResolver); @@ -730,14 +669,19 @@ private static ContainerDetector createContainerDetector(DecomposedContainerValu } /** - * Creates a FieldExtractor that uses Property-based field extraction. - * - * @param nameResolver resolves property names for path expressions + * Creates a FieldExtractor for value decomposition. + *

    + * Uses {@link FieldPropertyGenerator}/{@link com.navercorp.fixturemonkey.api.property.FieldProperty} + * to enumerate child properties so plugin-specific {@link PropertyNameResolver}s (e.g., Jackson + * {@code @JsonProperty}) take effect, but reads each value via direct {@link Field#get(Object)} + * — never through {@code Property.getValue}. */ - private static FieldExtractor createFieldExtractor(DecomposeNameResolver nameResolver) { + @SuppressWarnings({"argument", "type.argument", "methodref.return", "return"}) + private static FieldExtractor createFieldExtractor(@Nullable Function nameResolver) { + Function resolver = nameResolver != null ? nameResolver : Property::getName; return new FieldExtractor() { @Override - public Map extractFields(Object value, String basePath) { + public Map extractFields(@Nullable Object value, String basePath) { List childProperties = getChildProperties(value); if (childProperties == null) { return new HashMap<>(); @@ -745,29 +689,29 @@ public Map extractFields(Object value, String basePath) Map result = new HashMap<>(); for (Property childProperty : childProperties) { - String childPath = basePath + "." + nameResolver.resolve(childProperty); - Class declaredType = com.navercorp.fixturemonkey.api.type.Types.getActualType( - childProperty.getType()); - result.put(childPath, new ExtractedField(childProperty.getValue(value), declaredType)); + String name = resolver.apply(childProperty); + if (name == null) { + continue; + } + String childPath = basePath + "." + name; + Class declaredType = childProperty.getJvmType().getRawType(); + Object fieldValue = readPropertyValue(childProperty, value); + result.put(childPath, new ExtractedField(fieldValue, declaredType)); } return result; } - private @Nullable List getChildProperties(Object value) { + private @Nullable List getChildProperties(@Nullable Object value) { if (value == null) { return null; } - Class clazz = value.getClass(); - if (clazz.isPrimitive() || clazz == String.class || clazz.isEnum() || clazz.isArray()) { return null; } - if (isBoxedPrimitive(clazz)) { return null; } - if ( value instanceof Collection || value instanceof Map @@ -776,16 +720,26 @@ public Map extractFields(Object value, String basePath) ) { return null; } - if (isJavaType(clazz)) { return null; } - - AnnotatedType annotatedType = - generateAnnotatedTypeWithoutAnnotation(clazz); - Property parentProperty = new TypeParameterProperty(annotatedType); + AnnotatedType annotatedType = generateAnnotatedTypeWithoutAnnotation(clazz); + Property parentProperty = new TypeParameterProperty(toJvmType(annotatedType, Collections.emptyList())); return FIELD_PROPERTY_GENERATOR.generateChildProperties(parentProperty); } + + private @Nullable Object readPropertyValue(Property property, @Nullable Object instance) { + if (instance == null || !(property instanceof FieldProperty)) { + return null; + } + Field field = ((FieldProperty)property).getField(); + try { + field.setAccessible(true); + return field.get(instance); + } catch (IllegalAccessException ex) { + return null; + } + } }; } @@ -800,103 +754,4 @@ public Map extractFields(Object value, String basePath) return null; } - private static PostConditionFilter extractPostConditionFilter(NodeFilterManipulator filterManipulator) { - Class type = filterManipulator.getType(); - Predicate filter = filterManipulator.getFilter(); - return new PostConditionFilter(type, filter); - } - - /** - * Checks if any manipulator in the list contains a StaticNodeResolver, - * indicating the presence of registered manipulators. - * - * @param manipulators the list of manipulators to check - * @return true if any manipulator uses StaticNodeResolver - */ - public static boolean hasRegisteredManipulators(List manipulators) { - for (ArbitraryManipulator manipulator : manipulators) { - if (hasStaticNodeResolver(manipulator.getNodeResolver())) { - return true; - } - } - return false; - } - - /** - * Checks if the NodeResolver contains a StaticNodeResolver, indicating this is - * a registered manipulator (from registerBuilder). - * - * @param nodeResolver the node resolver to check - * @return true if it contains a StaticNodeResolver - */ - public static boolean hasStaticNodeResolver(NodeResolver nodeResolver) { - if (nodeResolver instanceof StaticNodeResolver) { - return true; - } else if (nodeResolver instanceof CompositeNodeResolver) { - CompositeNodeResolver composite = (CompositeNodeResolver)nodeResolver; - for (NodeResolver childResolver : composite.getNodeResolvers()) { - if (hasStaticNodeResolver(childResolver)) { - return true; - } - } - } else if (nodeResolver instanceof ApplyStrictModeResolver) { - ApplyStrictModeResolver strict = (ApplyStrictModeResolver)nodeResolver; - return hasStaticNodeResolver(strict.getNodeResolver()); - } - return false; - } - - /** - * Checks if the NodeResolver contains an ApplyStrictModeResolver, indicating this - * manipulator should throw an exception if the path doesn't exist. - */ - private static boolean hasStrictModeResolver(NodeResolver nodeResolver) { - if (nodeResolver instanceof ApplyStrictModeResolver) { - return true; - } else if (nodeResolver instanceof CompositeNodeResolver) { - CompositeNodeResolver composite = (CompositeNodeResolver)nodeResolver; - for (NodeResolver childResolver : composite.getNodeResolvers()) { - if (hasStrictModeResolver(childResolver)) { - return true; - } - } - } - return false; - } - - private static List extractPredicates(NodeResolver nodeResolver) { - List predicates = new ArrayList<>(); - extractPredicatesRecursive(nodeResolver, predicates); - return predicates; - } - - private static void extractPredicatesRecursive(NodeResolver nodeResolver, List predicates) { - if (nodeResolver instanceof ApplyStrictModeResolver) { - // Unwrap strict mode resolver and continue with the inner resolver - ApplyStrictModeResolver strictResolver = (ApplyStrictModeResolver)nodeResolver; - extractPredicatesRecursive(strictResolver.getNodeResolver(), predicates); - } else if (nodeResolver instanceof CompositeNodeResolver) { - CompositeNodeResolver composite = (CompositeNodeResolver)nodeResolver; - for (NodeResolver childResolver : composite.getNodeResolvers()) { - extractPredicatesRecursive(childResolver, predicates); - } - } else if (nodeResolver instanceof NodePredicateResolver) { - NextNodePredicate predicate = ((NodePredicateResolver)nodeResolver).getNextNodePredicate(); - if (predicate != null) { - predicates.add(predicate); - } - } - } - - /** - * Resolves the name of a property for use in decomposed path expressions. - *

    - * This allows plugins (e.g., Jackson) to map Java field names to their - * serialized names (e.g., {@code @JsonProperty} values) during decompose, - * ensuring decomposed paths match the tree node paths built by the assembler. - */ - @FunctionalInterface - public interface DecomposeNameResolver { - @Nullable String resolve(Property property); - } } diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/NodeContextFactory.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/NodeContextFactory.java new file mode 100644 index 0000000000..8122547b11 --- /dev/null +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/NodeContextFactory.java @@ -0,0 +1,396 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.planner; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.function.UnaryOperator; +import java.util.stream.Collectors; + +import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; +import org.jspecify.annotations.Nullable; + +import com.navercorp.fixturemonkey.api.generator.ArbitraryGenerator; +import com.navercorp.fixturemonkey.api.generator.ContainerPropertyGenerator; +import com.navercorp.fixturemonkey.api.introspector.ArbitraryIntrospector; +import com.navercorp.fixturemonkey.api.matcher.MatcherOperator; +import com.navercorp.fixturemonkey.api.option.FixtureMonkeyOptions; +import com.navercorp.fixturemonkey.api.property.CandidateConcretePropertyResolver; +import com.navercorp.fixturemonkey.api.property.FieldProperty; +import com.navercorp.fixturemonkey.api.property.Property; +import com.navercorp.fixturemonkey.api.property.PropertyGenerator; +import com.navercorp.fixturemonkey.api.property.PropertyNameResolver; +import com.navercorp.fixturemonkey.api.type.TypeCache; +import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.fixturemonkey.nodecandidate.ContainerPropertyGeneratorNodeGenerator; +import com.navercorp.fixturemonkey.nodecandidate.NameResolvingNodeCandidateGenerator; +import com.navercorp.fixturemonkey.nodecandidate.PropertyGeneratorNodeCandidateGenerator; +import com.navercorp.fixturemonkey.property.JvmNodePropertyFactory; +import com.navercorp.objectfarm.api.node.AbstractTypeNodePromoter; +import com.navercorp.objectfarm.api.node.ContainerSizeResolver; +import com.navercorp.objectfarm.api.node.InterfaceResolver; +import com.navercorp.objectfarm.api.node.JavaDefaultNodePromoter; +import com.navercorp.objectfarm.api.node.JavaMapEntryNodePromoter; +import com.navercorp.objectfarm.api.node.JavaMapNodePromoter; +import com.navercorp.objectfarm.api.node.JavaNodeContext; +import com.navercorp.objectfarm.api.node.JavaObjectNodePromoter; +import com.navercorp.objectfarm.api.node.JvmNodeContext; +import com.navercorp.objectfarm.api.node.JvmNodePromoter; +import com.navercorp.objectfarm.api.node.LeafTypeResolver; +import com.navercorp.objectfarm.api.node.SeedState; +import com.navercorp.objectfarm.api.nodecandidate.JavaFieldNodeCandidateGenerator; +import com.navercorp.objectfarm.api.nodecandidate.JvmNodeCandidateGenerator; +import com.navercorp.objectfarm.api.type.JvmType; +import com.navercorp.objectfarm.api.type.WildcardRawType; + +/** + * Builds {@link JvmNodeContext} instances configured with promoters, generators, name resolvers, + * leaf type resolvers, and interface resolvers. + *

    + * Construction follows {@link FixtureMonkeyOptions} together with per-call + * {@code propertyConfigurers} and {@code introspectorsByType} overrides. + */ +@API(since = "1.1.17", status = Status.EXPERIMENTAL) +public final class NodeContextFactory { + private final SeedState seedState; + private final ContainerSizeResolverFactory containerSizeResolverFactory; + private final List additionalPromoters; + private final List additionalLeafTypeResolvers; + private final @Nullable UnaryOperator candidateGeneratorWrapper; + + public NodeContextFactory( + SeedState seedState, + ContainerSizeResolverFactory containerSizeResolverFactory, + List additionalPromoters, + List additionalLeafTypeResolvers, + @Nullable UnaryOperator candidateGeneratorWrapper + ) { + this.seedState = seedState; + this.containerSizeResolverFactory = containerSizeResolverFactory; + this.additionalPromoters = additionalPromoters; + this.additionalLeafTypeResolvers = additionalLeafTypeResolvers; + this.candidateGeneratorWrapper = candidateGeneratorWrapper; + } + + /** + * Builds a {@link JvmNodeContext} for the given root type and configuration. + */ + public JvmNodeContext build( + JvmType rootType, + @Nullable FixtureMonkeyOptions options, + Map, List> propertyConfigurers, + Map, ArbitraryIntrospector> introspectorsByType + ) { + ContainerSizeResolver containerSizeResolver = containerSizeResolverFactory.createContainerSizeResolver(options); + List allPromoters = createNodePromoters(); + + JavaNodeContext.Builder builder = JavaNodeContext.builder() + .seedState(seedState) + .nodePromoters(Collections.singletonList(new JavaDefaultNodePromoter(allPromoters))) + .containerSizeResolver(containerSizeResolver); + + if (options != null) { + ArbitraryGenerator defaultGenerator = options.getDefaultArbitraryGenerator(); + Property rootProperty = JvmNodePropertyFactory.fromType(rootType); + PropertyGenerator rootPropertyGenerator = defaultGenerator.getRequiredPropertyGenerator(rootProperty); + + // Build the name resolver from options (e.g., @JsonProperty support via JacksonPropertyNameResolver). + // Always non-null: type-specific resolvers may exist even when the default is IDENTITY. + NameResolvingNodeCandidateGenerator.ChildNameResolver nameResolver = createNodeNameResolver(options); + + if (rootPropertyGenerator != null) { + // Create a per-type delegating PropertyGenerator instead of binding to the root type. + // This ensures each type gets the correct PropertyGenerator from the introspector chain + // (e.g., PriorityConstructorArbitraryIntrospector creates per-type ConstructorArbitraryIntrospectors). + PropertyGenerator fallbackPropertyGenerator = options.getDefaultPropertyGenerator(); + + PropertyGenerator basePropertyGenerator = property -> { + PropertyGenerator gen = defaultGenerator.getRequiredPropertyGenerator(property); + if (gen != null) { + List children = gen.generateChildProperties(property); + if (children != null) { + return children; + } + } + return fallbackPropertyGenerator.generateChildProperties(property); + }; + List> propertyGenerators = options.getPropertyGenerators(); + + PropertyGenerator compositeGenerator = createCompositePropertyGenerator( + basePropertyGenerator, + propertyConfigurers, + introspectorsByType, + propertyGenerators + ); + JvmNodeCandidateGenerator candidateGenerator = new PropertyGeneratorNodeCandidateGenerator( + compositeGenerator + ); + candidateGenerator = new NameResolvingNodeCandidateGenerator(candidateGenerator, nameResolver); + if (candidateGeneratorWrapper != null) { + // Wrap with platform-specific isSupported check + // (e.g., KotlinNodeCandidateGenerator that only supports Kotlin types). + // With first-match-wins in buildTree, the wrapped generator handles supported types. + builder.addCustomGenerator(candidateGeneratorWrapper.apply(candidateGenerator)); + // Also set as objectPropertyGenerator for non-Kotlin types (e.g., Java's File class) + // that need the introspector's requiredPropertyGenerator. + builder.objectPropertyGenerator(candidateGenerator); + } else { + builder.objectPropertyGenerator(candidateGenerator); + } + + // Exclude types from leaf treatment if any extra generator recognizes them. + // This allows Java standard types (e.g., java.io.File, java.sql.Timestamp) to be expanded + // when using constructor-based introspectors with a requiredPropertyGenerator. + builder.leafTypeExclusion(jvmType -> { + Class rawType = com.navercorp.fixturemonkey.api.type.Types.normalizeRawType( + jvmType.getRawType() + ); + if (rawType.isPrimitive() || rawType.isArray() || rawType.isEnum()) { + return false; + } + + if (propertyConfigurers.containsKey(rawType) || introspectorsByType.containsKey(rawType)) { + return true; + } + + if (!propertyGenerators.isEmpty()) { + Property property = JvmNodePropertyFactory.fromType(jvmType); + for (MatcherOperator op : propertyGenerators) { + if (op.match(property)) { + return true; + } + } + } + + // Check if the global objectIntrospector (via basePropertyGenerator) + // produces children for this type. This handles cases like + // PriorityConstructorArbitraryIntrospector expanding java.sql.Timestamp + // via its Timestamp(long) constructor. + try { + Property property = JvmNodePropertyFactory.fromType(jvmType); + List children = basePropertyGenerator.generateChildProperties(property); + if (children != null && !children.isEmpty()) { + return true; + } + } catch (Exception e) { + // Keep as leaf if generator fails (e.g., inaccessible constructor) + } + + return false; + }); + } else { + JvmNodeCandidateGenerator candidateGenerator = new NameResolvingNodeCandidateGenerator( + new JavaFieldNodeCandidateGenerator(), + nameResolver + ); + if (candidateGeneratorWrapper != null) { + builder.addCustomGenerator(candidateGeneratorWrapper.apply(candidateGenerator)); + builder.objectPropertyGenerator(candidateGenerator); + } else { + builder.objectPropertyGenerator(candidateGenerator); + } + } + + builder.interfaceResolver(createGlobalInterfaceResolver(options)); + + builder.maxDepth(options.getMaxRecursionDepth()); + + // Convert ContainerPropertyGenerators to a single fallback JvmContainerNodeGenerator. + // This generator is added as a custom generator but only matches types + // not already handled by the default generators (Array, Collection, Map, etc.). + List> containerPropertyGenerators = + options.getContainerPropertyGenerators(); + if (!containerPropertyGenerators.isEmpty()) { + builder.addContainerNodeGenerator( + new ContainerPropertyGeneratorNodeGenerator(containerPropertyGenerators) + ); + } + + // Marker types used by dedicated introspectors in DEFAULT_ARBITRARY_INTROSPECTORS. + // In the non-adapter path, these are handled by short-circuit introspectors + // that produce values directly without child property generation. + builder.addLeafTypeResolver(jvmType -> { + Class rt = jvmType.getRawType(); + return (rt == Types.GeneratingWildcardType.class + || rt == Types.UnidentifiableType.class + || rt == WildcardRawType.class); + }); + + for (LeafTypeResolver leafTypeResolver : additionalLeafTypeResolvers) { + builder.addLeafTypeResolver(leafTypeResolver); + } + } + + return builder.build(); + } + + /** + * Creates a ChildNameResolver that resolves property names using FixtureMonkeyOptions. + *

    + * To give the resolver access to field-level information (name + annotations like {@code @JsonProperty}), + * a {@link FieldProperty} is reflectively created from the parent class and candidate name. + * If the field is not found (e.g., constructor-only parameters), falls back to + * {@link JvmNodePropertyFactory#fromType(JvmType)} which provides annotations but no name. + * + * @return the child name resolver + */ + private static NameResolvingNodeCandidateGenerator.ChildNameResolver createNodeNameResolver( + FixtureMonkeyOptions options + ) { + return (parentType, childType, candidateName) -> { + Property parentProperty = JvmNodePropertyFactory.fromType(parentType); + PropertyNameResolver resolver = options.getPropertyNameResolver(parentProperty); + + Property childProperty = null; + if (candidateName != null) { + java.lang.reflect.Field field = TypeCache.getFieldsByName(parentType.getRawType()).get(candidateName); + if (field != null) { + childProperty = new FieldProperty(field); + } + } + if (childProperty == null) { + childProperty = JvmNodePropertyFactory.fromType(childType); + } + return resolver.resolve(childProperty); + }; + } + + /** + * Creates the combined list of node promoters. + * Additional promoters (e.g., KotlinNodePromoter) are checked first to allow language-specific handling. + */ + private List createNodePromoters() { + List basePromoters = Arrays.asList( + new JavaMapNodePromoter(), + new JavaMapEntryNodePromoter(), + new AbstractTypeNodePromoter(), + new JavaObjectNodePromoter() + ); + + if (additionalPromoters.isEmpty()) { + return basePromoters; + } + + List allPromoters = new ArrayList<>(additionalPromoters.size() + basePromoters.size()); + allPromoters.addAll(additionalPromoters); + allPromoters.addAll(basePromoters); + return allPromoters; + } + + /** + * Creates a composite PropertyGenerator that checks configurations in order: + * 1. propertyConfigurers (explicit property list from instantiate()) + * 2. introspectorsByType (introspector's getRequiredPropertyGenerator()) + * 3. propertyGenerators (from pushExactTypePropertyGenerator()) + * 4. baseGenerator (default behavior) + */ + private static PropertyGenerator createCompositePropertyGenerator( + PropertyGenerator baseGenerator, + Map, List> propertyConfigurers, + Map, ArbitraryIntrospector> introspectorsByType, + List> propertyGenerators + ) { + if (propertyConfigurers.isEmpty() && introspectorsByType.isEmpty() && propertyGenerators.isEmpty()) { + return baseGenerator; + } + + return property -> { + Class actualType = com.navercorp.fixturemonkey.api.type.Types.normalizeRawType( + property.getJvmType().getRawType() + ); + + List configuredProperties = propertyConfigurers.get(actualType); + if (configuredProperties != null) { + return configuredProperties; + } + + ArbitraryIntrospector introspector = introspectorsByType.get(actualType); + if (introspector != null) { + PropertyGenerator introspectorGenerator = introspector.getRequiredPropertyGenerator(property); + if (introspectorGenerator != null) { + List introspectorProperties = introspectorGenerator.generateChildProperties(property); + if (introspectorProperties != null) { + return introspectorProperties; + } + } + } + + if (!propertyGenerators.isEmpty()) { + for (MatcherOperator matcherOperator : propertyGenerators) { + if (matcherOperator.match(property)) { + List matchedProperties = matcherOperator + .getOperator() + .generateChildProperties(property); + if (matchedProperties != null) { + return matchedProperties; + } + } + } + } + + return baseGenerator.generateChildProperties(property); + }; + } + + private InterfaceResolver createGlobalInterfaceResolver(FixtureMonkeyOptions options) { + return new InterfaceResolver() { + @Override + public @Nullable JvmType resolve(JvmType type) { + List candidates = resolveAll(type); + if (candidates.isEmpty()) { + return null; + } + Random typeRandom = seedState.snapshot().randomFor(type.hashCode()); + return candidates.get(typeRandom.nextInt(candidates.size())); + } + + @Override + public List resolveAll(JvmType type) { + Class rawType = type.getRawType(); + if (!Modifier.isInterface(rawType.getModifiers()) && !Modifier.isAbstract(rawType.getModifiers())) { + return Collections.emptyList(); + } + + Property property = JvmNodePropertyFactory.fromType(type); + @SuppressWarnings("deprecation") + CandidateConcretePropertyResolver resolver = options.getCandidateConcretePropertyResolver(property); + + if (resolver == null) { + return Collections.emptyList(); + } + + List candidates = resolver.resolve(property); + if (candidates == null || candidates.isEmpty()) { + return Collections.emptyList(); + } + + return candidates + .stream() + .map(Property::getJvmType) + .collect(Collectors.toList()); + } + }; + } +} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/PathResolverContextFactory.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/PathResolverContextFactory.java new file mode 100644 index 0000000000..7ffeb65348 --- /dev/null +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/PathResolverContextFactory.java @@ -0,0 +1,152 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.planner; + +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.OptionalInt; + +import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; +import org.jspecify.annotations.Nullable; + +import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfo; +import com.navercorp.fixturemonkey.api.option.FixtureMonkeyOptions; +import com.navercorp.fixturemonkey.planner.AnalysisResult; +import com.navercorp.objectfarm.api.expression.PathExpression; +import com.navercorp.objectfarm.api.input.ContainerDetector; +import com.navercorp.objectfarm.api.node.GenericTypeResolver; +import com.navercorp.objectfarm.api.node.InterfaceResolver; +import com.navercorp.objectfarm.api.tree.PathInterfaceResolver; +import com.navercorp.objectfarm.api.tree.PathResolver; +import com.navercorp.objectfarm.api.tree.PathResolverContext; +import com.navercorp.objectfarm.api.tree.ResolutionListener; +import com.navercorp.objectfarm.api.type.JvmType; + +/** + * Builds a {@link PathResolverContext} from analysis output and registered builder data. + *

    + * Aggregates analysis-derived container size resolvers (with wildcard-vs-exact precedence applied), + * type-scoped container size resolvers, interface resolvers, and generic type resolvers. Optionally + * infers additional type-scoped container sizes from typed values that are themselves containers. + */ +@API(since = "1.1.17", status = Status.EXPERIMENTAL) +public final class PathResolverContextFactory { + private final ContainerSizeResolverFactory containerSizeResolverFactory; + private final ContainerDetector containerDetector; + + public PathResolverContextFactory( + ContainerSizeResolverFactory containerSizeResolverFactory, + ContainerDetector containerDetector + ) { + this.containerSizeResolverFactory = containerSizeResolverFactory; + this.containerDetector = containerDetector; + } + + /** + * Builds a {@link PathResolverContext}. + */ + public PathResolverContext build( + AnalysisResult analysisResult, + Map> typedContainerSizes, + ResolutionListener resolutionListener, + boolean isFixed, + @Nullable FixtureMonkeyOptions options + ) { + PathResolverContext.Builder builder = PathResolverContext.builder().resolutionListener(resolutionListener); + + Map sizeSequenceByPath = analysisResult.getContainerSizeSequenceByPath(); + + List> wildcardSizeSequences = new ArrayList<>(); + for (Map.Entry entry : sizeSequenceByPath.entrySet()) { + if (entry.getKey().hasWildcard()) { + wildcardSizeSequences.add(new AbstractMap.SimpleEntry<>(entry.getKey(), entry.getValue())); + } + } + + containerSizeResolverFactory.addAnalysisContainerSizeResolvers( + builder, + analysisResult, + wildcardSizeSequences + ); + + Map valueOrderByPath = analysisResult.getValueOrderByPath(); + for (PathResolver resolver : analysisResult.getInterfaceResolvers()) { + // Skip interface resolvers for container paths where a later size() constraint exists. + // When set("values", singletonList(X)) creates a List → SingletonList resolver, + // but size("values", 1, 10) comes later, the concrete type should not be locked. + if (resolver instanceof PathInterfaceResolver) { + PathExpression resolverPath = ((PathInterfaceResolver)resolver).getPattern(); + Integer sizeSeq = sizeSequenceByPath.get(resolverPath); + Integer valueSeq = valueOrderByPath.get(resolverPath); + if (sizeSeq != null && valueSeq != null && sizeSeq > valueSeq) { + continue; + } + } + builder.addInterfaceResolver(resolver); + } + + for (PathResolver resolver : analysisResult.getGenericTypeResolvers()) { + builder.addGenericTypeResolver(resolver); + } + + containerSizeResolverFactory.addTypedContainerSizeResolvers(builder, typedContainerSizes); + + if (isFixed) { + builder.defaultContainerSizeResolver( + containerSizeResolverFactory.createFixedContainerSizeResolver(options) + ); + } + + return builder.build(); + } + + /** + * Augments {@code explicitTypedContainerSizes} with sizes inferred from container-typed values + * in {@code typedValues}. Values that are containers contribute a fixed size resolver + * (size, size) for their {@code (ownerType, fieldName)}. + */ + public Map> inferAndMergeTypedContainerSizes( + Map> typedValues, + Map> explicitTypedContainerSizes + ) { + Map> merged = new HashMap<>(explicitTypedContainerSizes); + + for (Map.Entry> typeEntry : typedValues.entrySet()) { + JvmType ownerType = typeEntry.getKey(); + for (Map.Entry fieldEntry : typeEntry.getValue().entrySet()) { + String fieldName = fieldEntry.getKey(); + Object value = fieldEntry.getValue(); + + OptionalInt containerSize = containerDetector.getContainerSize(value); + if (!containerSize.isPresent()) { + continue; + } + + int size = containerSize.getAsInt(); + merged.computeIfAbsent(ownerType, k -> new HashMap<>()) + .putIfAbsent(fieldName, new ArbitraryContainerInfo(size, size)); + } + } + return merged; + } +} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/RuntimeTreeFactory.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/RuntimeTreeFactory.java new file mode 100644 index 0000000000..95ca5fba29 --- /dev/null +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/RuntimeTreeFactory.java @@ -0,0 +1,79 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.planner; + +import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; +import org.jspecify.annotations.Nullable; + +import com.navercorp.fixturemonkey.api.option.FixtureMonkeyOptions; +import com.navercorp.objectfarm.api.tree.JvmNodeTree; +import com.navercorp.objectfarm.api.tree.PathResolverContext; +import com.navercorp.objectfarm.api.type.JvmType; + +/** + * Builds {@link JvmNodeTree}s on demand during assembly. + *

    + * Used when assembly encounters a deferred shape — e.g. when an interface/abstract type + * resolves to a concrete implementation, or when an anonymous proxy must be generated for an + * interface — and a tree needs to be expanded for that runtime-determined type. + *

    + * This is distinct from {@link AssemblyPlanner}: planning happens once up-front, while + * runtime tree construction happens during assembly as concrete types are resolved. + * + * @see AssemblyPlanner + */ +@API(since = "1.1.17", status = Status.EXPERIMENTAL) +public interface RuntimeTreeFactory { + /** + * Creates a {@link JvmNodeTree} for the given concrete type. + *

    + * Used when generating with interface/abstract implementations to obtain + * the proper tree structure with child nodes. The underlying candidate tree + * may be cached, but the JvmNodeTree is created fresh each time so container + * sizes vary across calls. + * + * @param concreteType the concrete JvmType to create the tree for + * @param options the FixtureMonkey options for tree building + * @return the JvmNodeTree, or null if not available + */ + @Nullable + JvmNodeTree createConcreteNodeTree(JvmType concreteType, FixtureMonkeyOptions options); + + /** + * Creates a {@link JvmNodeTree} for an anonymous instance of the given interface/abstract type. + *

    + * The tree has children derived from no-argument methods of the interface, + * enabling anonymous proxy generation with path-based value customization. + * Always created fresh (no caching). The {@code resolverContext} is the same instance produced + * during planning and must be passed in by the caller so anonymous-tree creation sees the + * same resolution decisions. + * + * @param interfaceType the interface/abstract JvmType to create the tree for + * @param options the FixtureMonkey options for tree building + * @param resolverContext the path resolver context produced during planning + * @return the JvmNodeTree for anonymous instance generation, or null if not available + */ + @Nullable + JvmNodeTree createAnonymousNodeTree( + JvmType interfaceType, + FixtureMonkeyOptions options, + PathResolverContext resolverContext + ); +} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/TreeContextCache.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/TreeContextCache.java new file mode 100644 index 0000000000..2b22a0541d --- /dev/null +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/TreeContextCache.java @@ -0,0 +1,196 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.planner; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; + +import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; +import org.jspecify.annotations.Nullable; + +import com.navercorp.fixturemonkey.api.introspector.ArbitraryIntrospector; +import com.navercorp.fixturemonkey.api.option.FixtureMonkeyOptions; +import com.navercorp.fixturemonkey.api.property.Property; +import com.navercorp.objectfarm.api.node.JvmNodeContext; +import com.navercorp.objectfarm.api.tree.JvmNodeCandidateTree; +import com.navercorp.objectfarm.api.tree.JvmNodeCandidateTreeContext; +import com.navercorp.objectfarm.api.tree.JvmNodeSubtreeContext; +import com.navercorp.objectfarm.api.type.JvmType; + +/** + * Caches reusable {@link JvmNodeContext}s and {@link JvmNodeCandidateTree}s for the planning phase. + *

    + * Caches are keyed by {@code (JvmType, FixtureMonkeyOptions identity)}. Per-call options + * such as {@code propertyConfigurers} or {@code introspectorsByType} bypass the cache and + * trigger a fresh build, since they alter how the context is constructed. + *

    + * Owns the long-lived {@link JvmNodeCandidateTreeContext} (subtree caching for candidate trees) + * and {@link JvmNodeSubtreeContext} (promoted POJO subtree snapshots for tree transformation). + * Both are exposed for use during {@code JvmNodeTreeTransformer} setup. + */ +@API(since = "1.1.17", status = Status.EXPERIMENTAL) +public final class TreeContextCache { + private final JvmNodeCandidateTreeContext treeContext; + private final JvmNodeSubtreeContext subtreeContext; + private final NodeContextFactory nodeContextFactory; + + private final Map nodeContextCache; + private final Map candidateTreeCache; + private final Map concreteTypeCandidateTreeCache; + + public TreeContextCache(JvmNodeCandidateTreeContext treeContext, NodeContextFactory nodeContextFactory) { + this.treeContext = treeContext; + this.subtreeContext = new JvmNodeSubtreeContext(); + this.nodeContextFactory = nodeContextFactory; + this.nodeContextCache = new ConcurrentHashMap<>(); + this.candidateTreeCache = new ConcurrentHashMap<>(); + this.concreteTypeCandidateTreeCache = new ConcurrentHashMap<>(); + } + + public JvmNodeCandidateTreeContext getTreeContext() { + return treeContext; + } + + public JvmNodeSubtreeContext getSubtreeContext() { + return subtreeContext; + } + + /** + * Returns a cached {@link JvmNodeContext} for the given root type and options, or builds and caches one. + *

    + * Bypasses the cache when {@code propertyConfigurers} or {@code introspectorsByType} are non-empty, + * since those alter context construction. + */ + public JvmNodeContext getOrBuildNodeContext( + JvmType rootType, + @Nullable FixtureMonkeyOptions options, + Map, List> propertyConfigurers, + Map, ArbitraryIntrospector> introspectorsByType + ) { + if (!propertyConfigurers.isEmpty() || !introspectorsByType.isEmpty()) { + return nodeContextFactory.build(rootType, options, propertyConfigurers, introspectorsByType); + } + + Key cacheKey = new Key(rootType, options); + return nodeContextCache.computeIfAbsent(cacheKey, key -> + nodeContextFactory.build(rootType, options, propertyConfigurers, introspectorsByType) + ); + } + + /** + * Returns a cached {@link JvmNodeCandidateTree} for the resolved root type, or builds and caches one. + *

    + * When {@code hasCustomConfigurers} is true, uses a fresh {@link JvmNodeCandidateTreeContext} and + * skips caching to avoid leaking per-call configuration into shared state. + */ + public JvmNodeCandidateTree getOrBuildCandidateTree( + JvmType resolvedRootType, + JvmNodeContext context, + @Nullable FixtureMonkeyOptions options, + boolean hasCustomConfigurers + ) { + if (hasCustomConfigurers) { + return buildCandidateTree(resolvedRootType, context, new JvmNodeCandidateTreeContext()); + } + + Key cacheKey = new Key(resolvedRootType, options); + return candidateTreeCache.computeIfAbsent(cacheKey, key -> + buildCandidateTree(resolvedRootType, context, treeContext) + ); + } + + /** + * Returns a cached {@link JvmNodeCandidateTree} for the concrete type produced during interface resolution, + * or builds and caches one. + */ + public JvmNodeCandidateTree getOrBuildConcreteCandidateTree( + JvmType concreteType, + JvmNodeContext context, + @Nullable FixtureMonkeyOptions options + ) { + Key cacheKey = new Key(concreteType, options); + return concreteTypeCandidateTreeCache.computeIfAbsent(cacheKey, key -> + buildCandidateTree(concreteType, context, treeContext) + ); + } + + /** + * Clears all caches and the subtree context. + */ + public void clear() { + nodeContextCache.clear(); + candidateTreeCache.clear(); + concreteTypeCandidateTreeCache.clear(); + subtreeContext.clear(); + } + + private static JvmNodeCandidateTree buildCandidateTree( + JvmType type, + JvmNodeContext context, + JvmNodeCandidateTreeContext candidateTreeContext + ) { + return new JvmNodeCandidateTree.Builder(type, context) + .withTreeContext(candidateTreeContext) + .withPreBuildResolvedTypes(true) + .build(); + } + + /** + * Cache key for {@link JvmNodeCandidateTree} and {@link JvmNodeContext} entries. + * Uses options identity hash because for the same FixtureMonkey instance, + * options is always the same object reference. + */ + private static final class Key { + private final JvmType type; + private final int optionsIdentity; + private final int hashCode; + + Key(JvmType type, @Nullable FixtureMonkeyOptions options) { + this.type = type; + this.optionsIdentity = options != null ? System.identityHashCode(options) : 0; + this.hashCode = computeHashCode(); + } + + private int computeHashCode() { + int result = type.hashCode(); + result = 31 * result + optionsIdentity; + return result; + } + + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + Key that = (Key)obj; + return optionsIdentity == that.optionsIdentity && Objects.equals(type, that.type); + } + + @Override + public int hashCode() { + return hashCode; + } + } +} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/analysis/TypedValueExtractor.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/TypedValueExtractor.java similarity index 70% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/analysis/TypedValueExtractor.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/TypedValueExtractor.java index 797ecee40a..5ce9886bce 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/analysis/TypedValueExtractor.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/planner/TypedValueExtractor.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter.analysis; +package com.navercorp.fixturemonkey.planner; import java.util.AbstractMap; import java.util.ArrayList; @@ -26,24 +26,18 @@ import org.jspecify.annotations.Nullable; -import com.navercorp.fixturemonkey.adapter.converter.PredicatePathConverter; -import com.navercorp.fixturemonkey.adapter.projection.LazyValueHolder; -import com.navercorp.fixturemonkey.customizer.ApplyNodeCountManipulator; -import com.navercorp.fixturemonkey.customizer.ArbitraryManipulator; -import com.navercorp.fixturemonkey.customizer.CompositeNodeManipulator; -import com.navercorp.fixturemonkey.customizer.NodeManipulator; -import com.navercorp.fixturemonkey.customizer.NodeNullityManipulator; -import com.navercorp.fixturemonkey.customizer.NodeSetDecomposedValueManipulator; -import com.navercorp.fixturemonkey.customizer.NodeSetJustManipulator; -import com.navercorp.fixturemonkey.customizer.NodeSetLazyManipulator; -import com.navercorp.fixturemonkey.tree.NextNodePredicate; -import com.navercorp.fixturemonkey.tree.NodeResolver; +import com.navercorp.fixturemonkey.customizer.JustDirective; +import com.navercorp.fixturemonkey.customizer.LazyDirective; +import com.navercorp.fixturemonkey.customizer.NullityDirective; +import com.navercorp.fixturemonkey.customizer.PathDirective; +import com.navercorp.fixturemonkey.customizer.SetDirective; +import com.navercorp.fixturemonkey.projection.LazyValueHolder; import com.navercorp.objectfarm.api.expression.PathExpression; import com.navercorp.objectfarm.api.expression.Segment; import com.navercorp.objectfarm.api.type.JvmType; /** - * Extracts typed values from manipulators and converts them to path expressions. + * Extracts typed values from {@link PathDirective}s and converts them to path expressions. *

    * This class handles the extraction of values set via {@code set()}, {@code setLazy()}, * {@code setNull()} calls in registered builders, and their conversion into @@ -54,83 +48,41 @@ private TypedValueExtractor() { } /** - * Extracts typed values from an ArbitraryManipulator into the accumulated typedValues map. + * Extracts typed values from a {@link PathDirective} into the accumulated typedValues map. * This extracts values set via set() calls in registered builders. *

    * The accumulated map is mutated directly so that thenApply's {@code clear()} on "$" lazy * correctly removes previously accumulated field-level entries for the same type. * - * @param manipulator the manipulator to extract values from + * @param directive the directive to extract values from * @param ownerType the owner type for type-based matching * @param typedValues the accumulated map to populate (mutated directly) */ public static void extract( - ArbitraryManipulator manipulator, + PathDirective directive, JvmType ownerType, Map> typedValues ) { - NodeResolver nodeResolver = manipulator.getNodeResolver(); - NodeManipulator nodeManipulator = manipulator.getNodeManipulator(); - - List predicates = PredicatePathConverter.extractPredicates(nodeResolver); - String pathExpression = PredicatePathConverter.toExpression(predicates); + String pathExpression = directive.path().toExpression(); String fieldPath = pathExpression.startsWith("$.") ? pathExpression.substring(2) : pathExpression; - populateFromNodeManipulator(nodeManipulator, fieldPath, ownerType, typedValues); - } - - /** - * Recursively extracts typed values from a NodeManipulator. - * Uses put() so that later declarations override earlier ones (last-write-wins), - * consistent with the "declaration order" principle used by direct manipulators. - */ - private static void populateFromNodeManipulator( - NodeManipulator nodeManipulator, - String fieldPath, - JvmType ownerType, - Map> typedValues - ) { - if (nodeManipulator instanceof CompositeNodeManipulator) { - CompositeNodeManipulator composite = (CompositeNodeManipulator)nodeManipulator; - for (NodeManipulator inner : composite.getManipulators()) { - populateFromNodeManipulator(inner, fieldPath, ownerType, typedValues); - } - return; - } - - // Unwrap ApplyNodeCountManipulator to get the underlying manipulator - if (nodeManipulator instanceof ApplyNodeCountManipulator) { - ApplyNodeCountManipulator countManipulator = (ApplyNodeCountManipulator)nodeManipulator; - populateFromNodeManipulator(countManipulator.getNodeManipulator(), fieldPath, ownerType, typedValues); - return; - } - - if (nodeManipulator instanceof NodeSetDecomposedValueManipulator) { - NodeSetDecomposedValueManipulator setManipulator = (NodeSetDecomposedValueManipulator< - ? - >)nodeManipulator; - Object value = setManipulator.getValue(); - + if (directive instanceof SetDirective) { + Object value = ((SetDirective)directive).value(); Map fieldValues = typedValues.computeIfAbsent(ownerType, k -> new HashMap<>()); fieldValues.put(fieldPath, value); - } else if (nodeManipulator instanceof NodeSetJustManipulator) { - NodeSetJustManipulator setManipulator = (NodeSetJustManipulator)nodeManipulator; - Object value = setManipulator.getValue(); - + } else if (directive instanceof JustDirective) { + Object value = ((JustDirective)directive).value(); Map fieldValues = typedValues.computeIfAbsent(ownerType, k -> new HashMap<>()); fieldValues.put(fieldPath, value); - } else if (nodeManipulator instanceof NodeNullityManipulator) { - NodeNullityManipulator nullityManipulator = (NodeNullityManipulator)nodeManipulator; - if (nullityManipulator.isToNull()) { + } else if (directive instanceof NullityDirective) { + if (((NullityDirective)directive).toNull()) { Map fieldValues = typedValues.computeIfAbsent(ownerType, k -> new HashMap<>()); fieldValues.put(fieldPath, null); } - } else if (nodeManipulator instanceof NodeSetLazyManipulator) { - NodeSetLazyManipulator lazyManipulator = (NodeSetLazyManipulator)nodeManipulator; - + } else if (directive instanceof LazyDirective) { + LazyDirective lazyDirective = (LazyDirective)directive; Map fieldValues = typedValues.computeIfAbsent(ownerType, k -> new HashMap<>()); - // Use put() instead of putIfAbsent() for lazy manipulators. // thenApply chains produce multiple SetLazy on "$" where each subsequent lazy // captures the previous state (including earlier lazies) in its supplier. // The last lazy in the chain evaluates the entire chain, so it must override earlier ones. @@ -139,7 +91,7 @@ private static void populateFromNodeManipulator( } boolean isRootLevel = "$".equals(fieldPath); fieldValues.put(fieldPath, - new LazyValueHolder(lazyManipulator.getLazyArbitrary(), ownerType.getRawType(), isRootLevel)); + new LazyValueHolder(lazyDirective.lazyArbitrary(), ownerType.getRawType(), isRootLevel)); } } diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/plugin/JvmTypeSystem.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/plugin/JvmTypeSystem.java new file mode 100644 index 0000000000..4229aa712a --- /dev/null +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/plugin/JvmTypeSystem.java @@ -0,0 +1,40 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.plugin; + +import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; + +import com.navercorp.fixturemonkey.planner.AssemblyPlanner; + +/** + * Narrow SPI handed to {@link JvmTypeSystemPlugin#configure} that exposes only the + * registration points a JVM language/type-system plugin needs. Hides the rest of + * {@code FixtureMonkeyBuilder} so end users never see these hooks on the builder type. + */ +@API(since = "1.1.21", status = Status.EXPERIMENTAL) +public interface JvmTypeSystem { + /** + * Installs the {@link AssemblyPlanner} that the resulting {@code FixtureMonkey} uses + * for JVM tree planning and assembly. Language-specific plugins typically supply a + * planner pre-configured with their own {@code JvmNodePromoter}s, {@code LeafTypeResolver}s, + * and {@code JvmNodeCandidateGenerator} decorators. + */ + void assemblyPlanner(AssemblyPlanner planner); +} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/plugin/JvmTypeSystemPlugin.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/plugin/JvmTypeSystemPlugin.java new file mode 100644 index 0000000000..b76a5e9afb --- /dev/null +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/plugin/JvmTypeSystemPlugin.java @@ -0,0 +1,41 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.plugin; + +import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; + +/** + * SPI for configuring JVM language/type-system specific machinery that the standard + * {@link com.navercorp.fixturemonkey.api.plugin.Plugin} cannot reach through + * {@code FixtureMonkeyOptionsBuilder} alone. + *

    + * The typical use case is supplying a customized {@code AssemblyPlanner} with + * language-specific {@code JvmNodePromoter}s, {@code LeafTypeResolver}s, and + * {@code JvmNodeCandidateGenerator} decorators (e.g., Kotlin value classes, Scala + * case classes). + *

    + * Implementations are commonly combined with {@code Plugin} on the same class; a single + * {@code FixtureMonkeyBuilder.plugin(...)} call invokes both SPIs. + */ +@FunctionalInterface +@API(since = "1.1.21", status = Status.EXPERIMENTAL) +public interface JvmTypeSystemPlugin { + void configure(JvmTypeSystem typeSystem); +} diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/NodeList.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/plugin/LeafTypeRegistry.java similarity index 57% rename from fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/NodeList.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/plugin/LeafTypeRegistry.java index 5459b7a88b..4876ad5725 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/tree/NodeList.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/plugin/LeafTypeRegistry.java @@ -16,24 +16,24 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.api.tree; - -import java.util.List; +package com.navercorp.fixturemonkey.plugin; import org.apiguardian.api.API; import org.apiguardian.api.API.Status; /** - * The interface of the list {@link TraverseNode} to avoid type-casting compile errors. + * Determines whether a given type is a leaf type that should not be expanded further. *

    - * It should use the {@link #asList()} instead of {@link NodeList} itself. + * Leaf types (e.g. Java standard library types, Kotlin standard types) are terminal nodes + * in the object tree and their internal fields should not be traversed. */ -@API(since = "1.1.4", status = Status.EXPERIMENTAL) -public interface NodeList { +@API(since = "1.1.17", status = Status.EXPERIMENTAL) +public interface LeafTypeRegistry { /** - * Retrieves the actual list of {@link TraverseNode}. + * Checks whether the given type is a leaf type. * - * @return the actual list of {@link TraverseNode} + * @param type the class to check + * @return true if the type is a leaf type */ - List asList(); + boolean isLeafType(Class type); } diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/projection/AssembleContext.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/AssembleContext.java similarity index 84% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/projection/AssembleContext.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/AssembleContext.java index e72ab8ad1b..47aa01b764 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/projection/AssembleContext.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/AssembleContext.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter.projection; +package com.navercorp.fixturemonkey.projection; import java.util.Collections; import java.util.HashMap; @@ -24,14 +24,12 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import org.apiguardian.api.API; import org.apiguardian.api.API.Status; import org.jspecify.annotations.Nullable; -import com.navercorp.fixturemonkey.adapter.NodeTreeAdapter; -import com.navercorp.fixturemonkey.adapter.analysis.AnalysisResult; -import com.navercorp.fixturemonkey.adapter.tracing.TraceContext; import com.navercorp.fixturemonkey.api.context.MonkeyContext; import com.navercorp.fixturemonkey.api.context.MonkeyGeneratorContext; import com.navercorp.fixturemonkey.api.generator.ArbitraryGeneratorLoggingContext; @@ -39,7 +37,11 @@ import com.navercorp.fixturemonkey.api.option.FixtureMonkeyOptions; import com.navercorp.fixturemonkey.api.option.InterfaceSelectionStrategy; import com.navercorp.fixturemonkey.api.property.TreeRootProperty; +import com.navercorp.fixturemonkey.planner.AnalysisResult; +import com.navercorp.fixturemonkey.planner.RuntimeTreeFactory; +import com.navercorp.fixturemonkey.tracing.TraceContext; import com.navercorp.objectfarm.api.expression.PathExpression; +import com.navercorp.objectfarm.api.tree.PathResolverContext; /** * Context for ValueProjection.assemble() containing all necessary information @@ -129,10 +131,22 @@ public final class AssembleContext { private final Map, ArbitraryIntrospector> introspectorsByType; /** - * NodeTreeAdapter for building concrete type trees. - * Used to get properly structured trees for interface implementations. + * Builds runtime-resolved trees (concrete/anonymous) during assembly. */ - private final @Nullable NodeTreeAdapter nodeTreeAdapter; + private final @Nullable RuntimeTreeFactory runtimeTreeFactory; + + /** + * Path resolver context produced during planning. Passed to + * {@link RuntimeTreeFactory#createAnonymousNodeTree} so the anonymous tree built at + * assembly time sees the same resolution decisions as the planned tree. + */ + private final @Nullable PathResolverContext pathResolverContext; + + /** + * Cross-call cache for assembly node metadata. Type-erased here since {@code CachedTypeMetadata} + * is package-private in this package. + */ + private final @Nullable ConcurrentHashMap nodeMetadataCache; /** * Paths where the user has explicitly set container sizes via size() calls. @@ -156,7 +170,9 @@ private AssembleContext(Builder builder) { this.valueOrderByPath = Collections.unmodifiableMap(new HashMap<>(builder.valueOrderByPath)); this.customizersByPath = Collections.unmodifiableMap(new HashMap<>(builder.customizersByPath)); this.introspectorsByType = Collections.unmodifiableMap(new HashMap<>(builder.introspectorsByType)); - this.nodeTreeAdapter = builder.nodeTreeAdapter; + this.runtimeTreeFactory = builder.runtimeTreeFactory; + this.pathResolverContext = builder.pathResolverContext; + this.nodeMetadataCache = builder.nodeMetadataCache; this.userContainerSizePaths = Collections.unmodifiableSet(new HashSet<>(builder.userContainerSizePaths)); this.typedPathValues = Collections.unmodifiableMap(new HashMap<>(builder.typedPathValues)); this.typedPathOrders = Collections.unmodifiableMap(new HashMap<>(builder.typedPathOrders)); @@ -323,12 +339,32 @@ public Map, ArbitraryIntrospector> getIntrospectorsByType() { } /** - * Returns the NodeTreeAdapter for building concrete type trees. + * Returns the {@link RuntimeTreeFactory} used for building runtime-resolved trees during assembly. + * + * @return the runtime tree factory, or null if not set + */ + public @Nullable RuntimeTreeFactory getRuntimeTreeFactory() { + return runtimeTreeFactory; + } + + /** + * Returns the {@link PathResolverContext} produced during planning. Passed to + * {@link RuntimeTreeFactory#createAnonymousNodeTree} during assembly so anonymous-tree + * construction sees the same resolution decisions as the planned tree. + * + * @return the path resolver context, or null if not set + */ + public @Nullable PathResolverContext getPathResolverContext() { + return pathResolverContext; + } + + /** + * Returns the cross-call assembly node metadata cache. * - * @return the node tree adapter, or null if not set + * @return the metadata cache, or null if not set */ - public @Nullable NodeTreeAdapter getNodeTreeAdapter() { - return nodeTreeAdapter; + public @Nullable ConcurrentHashMap getNodeMetadataCache() { + return nodeMetadataCache; } /** @@ -367,7 +403,9 @@ public static final class Builder { private Map> customizersByPath = Collections.emptyMap(); private Map, ArbitraryIntrospector> introspectorsByType = Collections.emptyMap(); - private @Nullable NodeTreeAdapter nodeTreeAdapter; + private @Nullable RuntimeTreeFactory runtimeTreeFactory; + private @Nullable PathResolverContext pathResolverContext; + private @Nullable ConcurrentHashMap nodeMetadataCache; private Set userContainerSizePaths = Collections.emptySet(); private Map typedPathValues = Collections.emptyMap(); private Map typedPathOrders = Collections.emptyMap(); @@ -496,13 +534,36 @@ public Builder introspectorsByType(Map, ArbitraryIntrospector> introspe } /** - * Sets the NodeTreeAdapter for building concrete type trees. + * Sets the {@link RuntimeTreeFactory} used for building runtime-resolved trees during assembly. + * + * @param runtimeTreeFactory the runtime tree factory + * @return this builder + */ + public Builder runtimeTreeFactory(@Nullable RuntimeTreeFactory runtimeTreeFactory) { + this.runtimeTreeFactory = runtimeTreeFactory; + return this; + } + + /** + * Sets the {@link PathResolverContext} produced during planning, passed through to + * {@link RuntimeTreeFactory#createAnonymousNodeTree} during assembly. + * + * @param pathResolverContext the path resolver context + * @return this builder + */ + public Builder pathResolverContext(@Nullable PathResolverContext pathResolverContext) { + this.pathResolverContext = pathResolverContext; + return this; + } + + /** + * Sets the cross-call assembly node metadata cache. * - * @param nodeTreeAdapter the node tree adapter + * @param nodeMetadataCache the metadata cache * @return this builder */ - public Builder nodeTreeAdapter(@Nullable NodeTreeAdapter nodeTreeAdapter) { - this.nodeTreeAdapter = nodeTreeAdapter; + public Builder nodeMetadataCache(@Nullable ConcurrentHashMap nodeMetadataCache) { + this.nodeMetadataCache = nodeMetadataCache; return this; } diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/AssemblyState.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/AssemblyState.java new file mode 100644 index 0000000000..70c8f7034a --- /dev/null +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/AssemblyState.java @@ -0,0 +1,215 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.projection; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Function; + +import org.jspecify.annotations.Nullable; + +import com.navercorp.fixturemonkey.api.context.MonkeyGeneratorContext; +import com.navercorp.fixturemonkey.api.generator.ArbitraryGeneratorLoggingContext; +import com.navercorp.fixturemonkey.api.introspector.ArbitraryIntrospector; +import com.navercorp.fixturemonkey.api.option.FixtureMonkeyOptions; +import com.navercorp.fixturemonkey.api.option.InterfaceSelectionStrategy; +import com.navercorp.fixturemonkey.api.property.Property; +import com.navercorp.fixturemonkey.api.property.TreeRootProperty; +import com.navercorp.fixturemonkey.planner.AnalysisResult; +import com.navercorp.fixturemonkey.planner.RuntimeTreeFactory; +import com.navercorp.fixturemonkey.property.JvmNodePropertyFactory; +import com.navercorp.fixturemonkey.tracing.TraceContext; +import com.navercorp.objectfarm.api.expression.PathExpression; +import com.navercorp.objectfarm.api.expression.Segment; +import com.navercorp.objectfarm.api.expression.TypeSelector; +import com.navercorp.objectfarm.api.input.ObjectValueExtractor; +import com.navercorp.objectfarm.api.node.JvmNode; +import com.navercorp.objectfarm.api.tree.JvmNodeTree; +import com.navercorp.objectfarm.api.tree.PathResolverContext; +import com.navercorp.objectfarm.api.type.JvmType; + +/** + * Mutable per-call state shared across all helpers cooperating during a single + * {@link ValueProjection#assemble} pass. + * + *

    Package-private and split out from {@link ValueProjectionAssembler} so that helpers + * (path matching, lazy resolution, type metadata, map/interface assembly) can read the same + * state without duplicating the parameter list.

    + */ +final class AssemblyState { + + final JvmNodeTree nodeTree; + final Map candidatesByPath; + final TreeRootProperty rootProperty; + final FixtureMonkeyOptions options; + final MonkeyGeneratorContext monkeyGeneratorContext; + final ArbitraryGeneratorLoggingContext loggingContext; + final Set justPaths; + final Set notNullPaths; + final Map> filtersByPath; + final Map limitsByPath; + final InterfaceSelectionStrategy interfaceSelectionStrategy; + final long assemblySeed; + final AtomicInteger interfaceSelectionCounter; + final Map> customizersByPath; + final TraceContext traceContext; + final Map, ArbitraryIntrospector> introspectorsByType; + + final Map concreteTreeByNode; + + final Map containerTypeCache; + + final Map propertyByNode; + + final Set userContainerSizePaths; + + final PathIndex pathIndex; + + final @Nullable RuntimeTreeFactory runtimeTreeFactory; + + final @Nullable PathResolverContext pathResolverContext; + + final Function nodePropertyFactory; + + final Map propertyPathPropertyByNode; + + final Map nodeByPath; + + final Map resolvedLazyCache; + + final List> wildcardEntries; + + final List> typeSelectorEntries; + + final List> rootTypeSelectors; + + final ValueDecomposer valueDecomposer; + + final @Nullable ConcurrentHashMap typeMetadataCache; + + AssemblyState( + JvmNodeTree nodeTree, + Map candidatesByPath, + TreeRootProperty rootProperty, + FixtureMonkeyOptions options, + MonkeyGeneratorContext monkeyGeneratorContext, + ArbitraryGeneratorLoggingContext loggingContext, + Set justPaths, + Set notNullPaths, + Map> filtersByPath, + Map limitsByPath, + InterfaceSelectionStrategy interfaceSelectionStrategy, + Map> customizersByPath, + TraceContext traceContext, + Map, ArbitraryIntrospector> introspectorsByType, + @Nullable RuntimeTreeFactory runtimeTreeFactory, + @Nullable PathResolverContext pathResolverContext, + @Nullable ConcurrentHashMap nodeMetadataCache, + Set userContainerSizePaths + ) { + this.nodeTree = nodeTree; + this.candidatesByPath = candidatesByPath; + this.rootProperty = rootProperty; + this.options = options; + this.monkeyGeneratorContext = monkeyGeneratorContext; + this.loggingContext = loggingContext; + this.justPaths = justPaths; + this.notNullPaths = notNullPaths; + this.filtersByPath = filtersByPath; + this.limitsByPath = limitsByPath; + this.interfaceSelectionStrategy = interfaceSelectionStrategy; + this.assemblySeed = ThreadLocalRandom.current().nextLong(); + this.interfaceSelectionCounter = new AtomicInteger(0); + this.customizersByPath = customizersByPath; + this.traceContext = traceContext; + this.introspectorsByType = introspectorsByType; + this.runtimeTreeFactory = runtimeTreeFactory; + this.pathResolverContext = pathResolverContext; + + this.containerTypeCache = new HashMap<>(); + this.propertyByNode = new IdentityHashMap<>(); + this.concreteTreeByNode = new IdentityHashMap<>(); + this.propertyPathPropertyByNode = new IdentityHashMap<>(); + this.nodeByPath = new HashMap<>(); + this.resolvedLazyCache = new IdentityHashMap<>(); + this.valueDecomposer = new ValueDecomposer( + candidatesByPath, + limitsByPath, + nodeTree, + new ObjectValueExtractor() + ); + this.userContainerSizePaths = userContainerSizePaths; + this.pathIndex = new PathIndex( + new HashSet<>(candidatesByPath.keySet()), + userContainerSizePaths, + new HashSet<>(customizersByPath.keySet()), + notNullPaths + ); + + List> wildcards = new ArrayList<>(); + List> typeSelectors = new ArrayList<>(); + List> rootTypeOnly = new ArrayList<>(); + for (Map.Entry entry : candidatesByPath.entrySet()) { + PathExpression pattern = entry.getKey(); + if (pattern.hasWildcard()) { + wildcards.add(entry); + } else if (pattern.hasTypeSelector()) { + typeSelectors.add(entry); + List segments = pattern.getSegments(); + if (segments.size() == 1 + && segments.get(0).isSingleSelector() + && segments.get(0).getFirstSelector() instanceof TypeSelector) { + rootTypeOnly.add(entry); + } + } + } + this.wildcardEntries = wildcards; + this.typeSelectorEntries = typeSelectors; + this.rootTypeSelectors = rootTypeOnly; + + this.nodePropertyFactory = new JvmNodePropertyFactory(child -> { + JvmNode parent = nodeTree.getParent(child); + if (parent != null) { + return parent; + } + JvmNodeTree concreteTree = this.concreteTreeByNode.get(child); + if (concreteTree != null) { + return concreteTree.getParent(child); + } + return null; + }); + + if (nodeMetadataCache != null) { + @SuppressWarnings("unchecked") + ConcurrentHashMap typedCache = + (ConcurrentHashMap)nodeMetadataCache; + this.typeMetadataCache = typedCache; + } else { + this.typeMetadataCache = null; + } + } +} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/CachedTypeMetadata.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/CachedTypeMetadata.java new file mode 100644 index 0000000000..c62fae33e1 --- /dev/null +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/CachedTypeMetadata.java @@ -0,0 +1,46 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.projection; + +import com.navercorp.fixturemonkey.api.generator.NullInjectGenerator; +import com.navercorp.fixturemonkey.api.property.PropertyNameResolver; + +/** + * Per-{@code JvmType} memoization of derived assembly metadata. + * Populated once on first encounter and reused across all assembly calls (cross-call cache + * lives on {@code AssemblyPlanner.nodeMetadataCache}). + */ +final class CachedTypeMetadata { + final PropertyNameResolver nameResolver; + final NullInjectGenerator nullInjectGenerator; + final boolean isContainerType; + final boolean hasCandidateConcretePropertyResolvers; + + CachedTypeMetadata( + PropertyNameResolver nameResolver, + NullInjectGenerator nullInjectGenerator, + boolean isContainerType, + boolean hasCandidateConcretePropertyResolvers + ) { + this.nameResolver = nameResolver; + this.nullInjectGenerator = nullInjectGenerator; + this.isContainerType = isContainerType; + this.hasCandidateConcretePropertyResolvers = hasCandidateConcretePropertyResolvers; + } +} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/projection/DecomposeResult.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/DecomposeResult.java similarity index 98% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/projection/DecomposeResult.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/DecomposeResult.java index 9fdaeb8807..e10b567b65 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/projection/DecomposeResult.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/DecomposeResult.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter.projection; +package com.navercorp.fixturemonkey.projection; import java.util.Collections; import java.util.Map; diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/LazyResolver.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/LazyResolver.java new file mode 100644 index 0000000000..6ca62fd28b --- /dev/null +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/LazyResolver.java @@ -0,0 +1,163 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.projection; + +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.util.List; +import java.util.Map; + +import org.jspecify.annotations.Nullable; + +import com.navercorp.fixturemonkey.api.type.TypeCache; +import com.navercorp.objectfarm.api.expression.IndexSelector; +import com.navercorp.objectfarm.api.expression.NameSelector; +import com.navercorp.objectfarm.api.expression.PathExpression; +import com.navercorp.objectfarm.api.expression.Segment; +import com.navercorp.objectfarm.api.expression.Selector; +import com.navercorp.objectfarm.api.expression.TypeSelector; +import com.navercorp.objectfarm.api.node.JvmNode; + +/** + * Helpers around {@link LazyValueHolder} resolution and thenApply ancestor lookup. + * + *

    Stateless: every method takes the {@link AssemblyState} (which owns the per-call + * {@code resolvedLazyCache}) explicitly so the assembler keeps tree-traversal as its sole + * responsibility.

    + */ +final class LazyResolver { + private LazyResolver() { + } + + static @Nullable Object resolveLazyValue(@Nullable Object value, boolean isFromRegister, AssemblyState state) { + if (!(value instanceof LazyValueHolder)) { + return value; + } + // Register lazy: evaluate fresh each time (thenApply wraps entire object). + // User lazy: cached within one sample for consistency (e.g., setLazy with Arbitraries.of()). + return isFromRegister + ? ((LazyValueHolder)value).getValue() + : resolveLazyWithCache((LazyValueHolder)value, state); + } + + static @Nullable Object resolveLazyWithCache(LazyValueHolder holder, AssemblyState state) { + if (state.resolvedLazyCache.containsKey(holder)) { + return state.resolvedLazyCache.get(holder); + } + Object resolved = holder.getValue(); + if (resolved != null && resolved != LazyValueHolder.RECURSION_BLOCKED) { + state.resolvedLazyCache.put(holder, resolved); + } + return resolved; + } + + static @Nullable Object resolveThenApplyAncestorValue( + JvmNode node, + PathExpression currentPath, + AssemblyState state + ) { + if (state.rootTypeSelectors.isEmpty()) { + return null; + } + + for (Map.Entry entry : state.rootTypeSelectors) { + TypeSelector typeSelector = (TypeSelector)entry.getKey().getSegments().get(0).getFirstSelector(); + + if (node.getConcreteType() != null && typeSelector.matchesType(node.getConcreteType().getRawType())) { + Object value = entry.getValue().value; + if (value instanceof LazyValueHolder) { + Object resolved = resolveLazyWithCache((LazyValueHolder)value, state); + if (resolved == LazyValueHolder.RECURSION_BLOCKED) { + return null; + } + return resolved; + } + return value; + } + + List pathSegments = currentPath.getSegments(); + for (int pos = pathSegments.size() - 1; pos >= 0; pos--) { + PathExpression ancestorPath = PathMatcher.buildPathUpTo(currentPath, pos - 1); + JvmNode ancestorNode = PathMatcher.findNodeForPath(ancestorPath, state); + if (ancestorNode != null + && ancestorNode.getConcreteType() != null + && typeSelector.matchesType(ancestorNode.getConcreteType().getRawType())) { + Object value = entry.getValue().value; + Object resolved; + if (value instanceof LazyValueHolder) { + resolved = resolveLazyWithCache((LazyValueHolder)value, state); + if (resolved == LazyValueHolder.RECURSION_BLOCKED || resolved == null) { + return null; + } + } else { + resolved = value; + } + + Object current = resolved; + for (int i = pos; i < pathSegments.size() && current != null; i++) { + Segment pathSeg = pathSegments.get(i); + Selector selector = pathSeg.getFirstSelector(); + + if (selector instanceof NameSelector) { + current = getFieldValueByName(current, ((NameSelector)selector).getName()); + } else if (selector instanceof IndexSelector) { + current = getElementAtIndex(current, ((IndexSelector)selector).getIndex()); + } else { + current = null; + } + } + if (current != null) { + return current; + } + } + } + } + return null; + } + + static @Nullable Object getFieldValueByName(Object obj, String fieldName) { + Field field = TypeCache.getFieldsByName(obj.getClass()).get(fieldName); + if (field == null) { + return null; + } + try { + return field.get(obj); + } catch (IllegalAccessException e) { + return null; + } + } + + static @Nullable Object getElementAtIndex(Object container, int index) { + if (container instanceof List) { + List list = (List)container; + if (index >= 0 && index < list.size()) { + return list.get(index); + } + return null; + } + if (container.getClass().isArray()) { + int length = Array.getLength(container); + if (index >= 0 && index < length) { + return Array.get(container, index); + } + return null; + } + return null; + } +} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/projection/LazyValueHolder.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/LazyValueHolder.java similarity index 98% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/projection/LazyValueHolder.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/LazyValueHolder.java index ac986be852..95d5c732b4 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/projection/LazyValueHolder.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/LazyValueHolder.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter.projection; +package com.navercorp.fixturemonkey.projection; import java.util.HashSet; import java.util.Set; diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/PathIndex.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/PathIndex.java new file mode 100644 index 0000000000..f5e2016984 --- /dev/null +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/PathIndex.java @@ -0,0 +1,108 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.projection; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.regex.Pattern; + +import com.navercorp.objectfarm.api.expression.PathExpression; + +/** + * Pre-built lookup index for paths that have any descendant directives (values, sizes, + * customizers, notNull). Used by the assembler to skip "find best matching path" work when a + * parent path has no relevant descendants. + */ +final class PathIndex { + private static final Pattern INDEX_PATTERN = Pattern.compile("\\[\\d+]"); + + private final Map> childPathsByParent; + private final Set wildcardParentPaths; + private final Set typePatternPaths; + + PathIndex( + Set valuePaths, + Set userContainerSizePaths, + Set customizerPaths, + Set notNullPaths + ) { + this.childPathsByParent = new HashMap<>(); + this.wildcardParentPaths = new HashSet<>(); + this.typePatternPaths = new HashSet<>(); + + indexAncestors(valuePaths); + indexAncestors(userContainerSizePaths); + indexAncestors(customizerPaths); + indexAncestors(notNullPaths); + + for (PathExpression sizePath : userContainerSizePaths) { + childPathsByParent.computeIfAbsent(sizePath, k -> new HashSet<>()); + } + } + + private void indexAncestors(Set paths) { + for (PathExpression path : paths) { + if (path.hasTypeSelector()) { + typePatternPaths.add(path); + continue; + } + + PathExpression ancestor = path.getParent(); + while (ancestor != null && !ancestor.equals(path)) { + childPathsByParent.computeIfAbsent(ancestor, k -> new HashSet<>()).add(path); + PathExpression next = ancestor.getParent(); + if (next != null && next.equals(ancestor)) { + break; + } + ancestor = next; + } + + if (path.hasWildcard()) { + PathExpression wildcardParent = path.getParent(); + if (wildcardParent != null) { + wildcardParentPaths.add(wildcardParent); + } + } + } + } + + boolean hasChildPaths(PathExpression parentPath) { + if (childPathsByParent.containsKey(parentPath)) { + return true; + } + if (wildcardParentPaths.contains(parentPath)) { + return true; + } + String pathStr = parentPath.toExpression(); + // Convert indexed paths ($.list[0]) to wildcard form ($.list[*]) to check wildcard coverage + if (pathStr.contains("[") && !pathStr.contains("[*]")) { + String wildcardForm = INDEX_PATTERN.matcher(pathStr).replaceAll("[*]"); + PathExpression wildcardPath = PathExpression.of(wildcardForm); + return wildcardParentPaths.contains(wildcardPath) + || childPathsByParent.containsKey(wildcardPath); + } + return false; + } + + Set getTypePatternPaths() { + return typePatternPaths; + } +} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/PathMatcher.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/PathMatcher.java new file mode 100644 index 0000000000..29f365b390 --- /dev/null +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/PathMatcher.java @@ -0,0 +1,309 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.projection; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.jspecify.annotations.Nullable; + +import com.navercorp.objectfarm.api.expression.IndexSelector; +import com.navercorp.objectfarm.api.expression.KeySelector; +import com.navercorp.objectfarm.api.expression.PathExpression; +import com.navercorp.objectfarm.api.expression.Segment; +import com.navercorp.objectfarm.api.expression.TypeSelector; +import com.navercorp.objectfarm.api.expression.ValueSelector; +import com.navercorp.objectfarm.api.expression.WildcardSelector; +import com.navercorp.objectfarm.api.node.JvmNode; +import com.navercorp.objectfarm.api.type.JvmType; + +/** + * Stateless path-matching helpers extracted from {@code ValueProjectionAssembler}. + * + *

    Covers: best-path resolution (exact + wildcard + type selector), descendant-path + * existence checks, type-pattern matching, and node lookup by path. All methods are pure + * functions of {@link AssemblyState} or path inputs — no mutation of the state.

    + */ +final class PathMatcher { + private PathMatcher() { + } + + static boolean hasChildPathValues(PathExpression parentPath, PathIndex pathIndex) { + return pathIndex.hasChildPaths(parentPath); + } + + static boolean hasChildCandidateValues( + PathExpression parentPath, + Map candidatesByPath + ) { + String parentStr = parentPath.toExpression(); + for (PathExpression candidatePath : candidatesByPath.keySet()) { + String candidateStr = candidatePath.toExpression(); + if (candidateStr.length() > parentStr.length() && candidateStr.startsWith(parentStr)) { + char nextChar = candidateStr.charAt(parentStr.length()); + if (nextChar == '.' || nextChar == '[') { + return true; + } + } + } + return false; + } + + static boolean isNullSetAfterAllChildren( + ValueOrder nullOrder, + PathExpression parentPath, + Map candidatesByPath + ) { + String parentStr = parentPath.toExpression(); + for (Map.Entry entry : candidatesByPath.entrySet()) { + String candidateStr = entry.getKey().toExpression(); + if (candidateStr.length() > parentStr.length() && candidateStr.startsWith(parentStr)) { + char nextChar = candidateStr.charAt(parentStr.length()); + if (nextChar == '.' || nextChar == '[') { + if (entry.getValue().order.compareTo(nullOrder) >= 0) { + return false; + } + } + } + } + return true; + } + + static @Nullable PathExpression findBestMatchingPath( + Map candidatesByPath, + PathExpression path, + @Nullable AssemblyState state + ) { + PathExpression bestPath = null; + // Sentinel initial values — RegisterOrder.of(MIN_VALUE) loses to any real comparison + ValueOrder bestOrder = ValueOrder.RegisterOrder.of(Integer.MIN_VALUE); + + PathExpression bestTypePath = null; + int bestTypeDepth = -1; + ValueOrder bestTypeOrder = ValueOrder.RegisterOrder.of(Integer.MIN_VALUE); + + ValueCandidate exactCandidate = candidatesByPath.get(path); + if (exactCandidate != null) { + if (exactCandidate.order.compareTo(bestOrder) > 0) { + bestOrder = exactCandidate.order; + bestPath = path; + } + } + + if (state != null) { + for (Map.Entry entry : state.wildcardEntries) { + PathExpression pattern = entry.getKey(); + if (pattern.matches(path)) { + ValueOrder order = entry.getValue().order; + if (order.compareTo(bestOrder) > 0) { + bestOrder = order; + bestPath = pattern; + } + } + } + + for (Map.Entry entry : state.typeSelectorEntries) { + PathExpression pattern = entry.getKey(); + // depth = how deep in the tree the type match occurs; deeper = more specific = wins + int depth = matchesTypePattern(pattern, path, state); + if (depth >= 0) { + ValueOrder order = entry.getValue().order; + if (depth > bestTypeDepth || (depth == bestTypeDepth && order.compareTo(bestTypeOrder) > 0)) { + bestTypeDepth = depth; + bestTypeOrder = order; + bestTypePath = pattern; + } + } + } + } + + if (bestTypePath != null) { + if (bestPath == null || bestTypeOrder.compareTo(bestOrder) > 0) { + return bestTypePath; + } + } + + return bestPath; + } + + static boolean matchesAnyWildcardCandidate(PathExpression childPath, AssemblyState state) { + for (Map.Entry entry : state.wildcardEntries) { + if (entry.getKey().matches(childPath)) { + return true; + } + } + return false; + } + + static int matchesTypePattern(PathExpression pattern, PathExpression path, AssemblyState state) { + List patternSegments = pattern.getSegments(); + List pathSegments = path.getSegments(); + + if (patternSegments.isEmpty()) { + return -1; + } + + int typeSegmentIndex = -1; + TypeSelector typeSelector = null; + for (int i = 0; i < patternSegments.size(); i++) { + Segment seg = patternSegments.get(i); + if (seg.isSingleSelector() && seg.getFirstSelector() instanceof TypeSelector) { + typeSegmentIndex = i; + typeSelector = (TypeSelector)seg.getFirstSelector(); + break; + } + } + + if (typeSelector == null) { + return -1; + } + + int patternSuffixLen = patternSegments.size() - typeSegmentIndex - 1; + + // TypeSelector-only pattern ($[type:T]) — only matches current node's type directly. + // Descendant field matching is handled by resolveThenApplyAncestorValue. + if (patternSuffixLen == 0 && typeSegmentIndex == 0) { + JvmNode currentNode = findNodeForPath(path, state); + if (currentNode != null && typeSelector.matchesType(currentNode.getConcreteType().getRawType())) { + return pathSegments.size(); + } + return -1; + } + + if (patternSuffixLen > pathSegments.size()) { + return -1; + } + + int suffixStartInPath = pathSegments.size() - patternSuffixLen; + for (int i = 0; i < patternSuffixLen; i++) { + Segment patternSeg = patternSegments.get(typeSegmentIndex + 1 + i); + Segment pathSeg = pathSegments.get(suffixStartInPath + i); + if (!patternSeg.equals(pathSeg) + && !(patternSeg.isSingleSelector() + && patternSeg.getFirstSelector() instanceof WildcardSelector + && pathSeg.isSingleSelector() + && (pathSeg.getFirstSelector() instanceof IndexSelector + || pathSeg.getFirstSelector() instanceof KeySelector + || pathSeg.getFirstSelector() instanceof ValueSelector)) + ) { + return -1; + } + } + + int ownerPos = suffixStartInPath - 1; + + PathExpression nodeAtPath; + if (ownerPos < 0) { + nodeAtPath = PathExpression.root(); + } else { + nodeAtPath = buildPathUpTo(path, ownerPos); + } + + JvmNode node = findNodeForPath(nodeAtPath, state); + if (node == null) { + return -1; + } + + if (typeSelector.matchesType(node.getConcreteType().getRawType())) { + return ownerPos + 1; + } + + return -1; + } + + static PathExpression buildPathUpTo(PathExpression fullPath, int segmentIndex) { + List segments = fullPath.getSegments(); + PathExpression result = PathExpression.root(); + for (int i = 0; i <= segmentIndex && i < segments.size(); i++) { + result = result.appendSegment(segments.get(i)); + } + return result; + } + + static boolean isRootTypeSelector(PathExpression path) { + List segments = path.getSegments(); + return (segments.size() == 1 + && segments.get(0).isSingleSelector() + && segments.get(0).getFirstSelector() instanceof TypeSelector); + } + + static boolean hasFieldLevelTypeSelectorSiblings(PathExpression rootTypePath, AssemblyState state) { + TypeSelector rootTypeSelector = (TypeSelector)rootTypePath.getSegments().get(0).getFirstSelector(); + Class rootType = rootTypeSelector.getTargetType(); + + for (PathExpression path : state.candidatesByPath.keySet()) { + if (path.equals(rootTypePath)) { + continue; + } + List segments = path.getSegments(); + if (segments.size() > 1 + && segments.get(0).isSingleSelector() + && segments.get(0).getFirstSelector() instanceof TypeSelector) { + TypeSelector ts = (TypeSelector)segments.get(0).getFirstSelector(); + if (ts.getTargetType().equals(rootType)) { + return true; + } + } + } + return false; + } + + static @Nullable JvmNode findNodeForPath(PathExpression path, AssemblyState state) { + String pathStr = path.toExpression(); + JvmNode node = state.nodeByPath.get(pathStr); + if (node != null) { + return node; + } + if (state.nodeTree != null) { + return state.nodeTree.resolve(path); + } + return null; + } + + static boolean hasMatchingTypeSelector(JvmType nodeType, PathIndex pathIndex) { + Set typePatternPaths = pathIndex.getTypePatternPaths(); + if (typePatternPaths.isEmpty()) { + return false; + } + + Class rawType = nodeType.getRawType(); + for (PathExpression pattern : typePatternPaths) { + List segments = pattern.getSegments(); + for (Segment segment : segments) { + if (segment.isSingleSelector() && segment.getFirstSelector() instanceof TypeSelector) { + TypeSelector typeSelector = (TypeSelector)segment.getFirstSelector(); + if (typeSelector.matchesType(rawType)) { + return true; + } + } + } + } + return false; + } + + static boolean isUnderExcludedPath(PathExpression path, Set excludedPaths) { + for (PathExpression excluded : excludedPaths) { + if (path.isChildOf(excluded)) { + return true; + } + } + return false; + } +} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/TypeMetadataResolver.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/TypeMetadataResolver.java new file mode 100644 index 0000000000..5851d5b730 --- /dev/null +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/TypeMetadataResolver.java @@ -0,0 +1,126 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.projection; + +import java.util.Collection; +import java.util.Map; +import java.util.Optional; +import java.util.OptionalDouble; +import java.util.OptionalInt; +import java.util.OptionalLong; +import java.util.function.Supplier; +import java.util.stream.BaseStream; + +import org.jspecify.annotations.Nullable; + +import com.navercorp.fixturemonkey.api.generator.ContainerPropertyGenerator; +import com.navercorp.fixturemonkey.api.generator.NullInjectGenerator; +import com.navercorp.fixturemonkey.api.matcher.MatcherOperator; +import com.navercorp.fixturemonkey.api.option.FixtureMonkeyOptions; +import com.navercorp.fixturemonkey.api.property.Property; +import com.navercorp.fixturemonkey.api.property.PropertyNameResolver; +import com.navercorp.fixturemonkey.property.JvmNodePropertyFactory; +import com.navercorp.objectfarm.api.node.JvmNode; +import com.navercorp.objectfarm.api.type.JvmType; + +/** + * Stateless helpers around per-type assembly metadata: container detection, name resolver, + * null inject generator, and the {@link CachedTypeMetadata} write-back. + * + *

    All methods are pure functions of {@code AssemblyState} (or {@code FixtureMonkeyOptions}) + * + the input node/type/property. Extracted from {@code ValueProjectionAssembler} to keep + * the assembler focused on tree-traversal driver logic.

    + */ +final class TypeMetadataResolver { + private TypeMetadataResolver() { + } + + static PropertyNameResolver resolveNameResolver(JvmNode node, Property property, AssemblyState state) { + if (state.typeMetadataCache != null) { + CachedTypeMetadata cached = state.typeMetadataCache.get(node.getConcreteType()); + if (cached != null) { + return cached.nameResolver; + } + } + return state.options.getPropertyNameResolver(property); + } + + static NullInjectGenerator resolveNullInjectGenerator(JvmNode node, Property property, AssemblyState state) { + if (state.typeMetadataCache != null) { + CachedTypeMetadata cached = state.typeMetadataCache.get(node.getConcreteType()); + if (cached != null) { + return cached.nullInjectGenerator; + } + } + return state.options.getNullInjectGenerator(property); + } + + @SuppressWarnings("deprecation") + static void writeBackTypeMetadata(JvmNode node, Property property, AssemblyState state) { + if (state.typeMetadataCache == null) { + return; + } + JvmType jvmType = node.getConcreteType(); + if (!state.typeMetadataCache.containsKey(jvmType)) { + PropertyNameResolver resolver = state.options.getPropertyNameResolver(property); + NullInjectGenerator generator = state.options.getNullInjectGenerator(property); + boolean isContainer = computeIsContainerType(jvmType, state.options); + boolean hasCandidateResolvers = state.options.getCandidateConcretePropertyResolver(property) != null; + state.typeMetadataCache.putIfAbsent( + jvmType, + new CachedTypeMetadata(resolver, generator, isContainer, hasCandidateResolvers) + ); + } + } + + static boolean computeIsContainerType(JvmType jvmType, @Nullable FixtureMonkeyOptions options) { + Class rawType = jvmType.getRawType(); + if ( + rawType.isArray() + || Collection.class.isAssignableFrom(rawType) + || Map.class.isAssignableFrom(rawType) + || Map.Entry.class.isAssignableFrom(rawType) + || Iterable.class.isAssignableFrom(rawType) + || BaseStream.class.isAssignableFrom(rawType) + || isSingleElementWrapper(jvmType) + ) { + return true; + } + + if (options != null) { + Property property = JvmNodePropertyFactory.fromType(jvmType); + for (MatcherOperator op : options.getContainerPropertyGenerators()) { + if (op.getMatcher().match(property)) { + return true; + } + } + } + + return false; + } + + static boolean isSingleElementWrapper(JvmType jvmType) { + Class rawType = jvmType.getRawType(); + return (Supplier.class.isAssignableFrom(rawType) + || Optional.class.isAssignableFrom(rawType) + || OptionalInt.class.isAssignableFrom(rawType) + || OptionalLong.class.isAssignableFrom(rawType) + || OptionalDouble.class.isAssignableFrom(rawType)); + } +} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/projection/ValueCandidate.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/ValueCandidate.java similarity index 88% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/projection/ValueCandidate.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/ValueCandidate.java index 9a19e4f299..77cc9f026b 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/projection/ValueCandidate.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/ValueCandidate.java @@ -1,6 +1,6 @@ -package com.navercorp.fixturemonkey.adapter.projection; +package com.navercorp.fixturemonkey.projection; -import javax.annotation.Nullable; +import org.jspecify.annotations.Nullable; /** * Unified value metadata for a single path in the assembly state. @@ -13,8 +13,7 @@ * decomposed paths are recorded in TraceContext.decomposedPaths. */ final class ValueCandidate { - @Nullable - final Object value; + final @Nullable Object value; final ValueOrder order; ValueCandidate(@Nullable Object value, ValueOrder order) { diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/projection/ValueDecomposer.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/ValueDecomposer.java similarity index 99% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/projection/ValueDecomposer.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/ValueDecomposer.java index ccb8cf7500..a5ee193d4c 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/projection/ValueDecomposer.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/ValueDecomposer.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter.projection; +package com.navercorp.fixturemonkey.projection; import java.util.ArrayList; import java.util.Collection; diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/projection/ValueOrder.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/ValueOrder.java similarity index 97% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/projection/ValueOrder.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/ValueOrder.java index 50213e0e74..50745af151 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/projection/ValueOrder.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/ValueOrder.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter.projection; +package com.navercorp.fixturemonkey.projection; /** * Typed ordering for value candidates that encodes source priority. diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/projection/ValueProjection.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/ValueProjection.java similarity index 99% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/projection/ValueProjection.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/ValueProjection.java index 3fd6521f04..ad3c2ae9e0 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/projection/ValueProjection.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/ValueProjection.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter.projection; +package com.navercorp.fixturemonkey.projection; import java.util.ArrayList; import java.util.Collections; diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/projection/ValueProjectionAssembler.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/ValueProjectionAssembler.java similarity index 67% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/projection/ValueProjectionAssembler.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/ValueProjectionAssembler.java index 7e55b3f054..e4d96835e3 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/projection/ValueProjectionAssembler.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/projection/ValueProjectionAssembler.java @@ -16,53 +16,33 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter.projection; +package com.navercorp.fixturemonkey.projection; import java.lang.reflect.Array; -import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.IdentityHashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.Optional; -import java.util.OptionalDouble; -import java.util.OptionalInt; -import java.util.OptionalLong; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ThreadLocalRandom; -import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Predicate; -import java.util.function.Supplier; -import java.util.regex.Pattern; -import java.util.stream.BaseStream; import org.jspecify.annotations.Nullable; -import com.navercorp.fixturemonkey.adapter.NodeTreeAdapter; -import com.navercorp.fixturemonkey.adapter.analysis.AnalysisResult; -import com.navercorp.fixturemonkey.adapter.property.JvmNodePropertyFactory; -import com.navercorp.fixturemonkey.adapter.tracing.TraceContext; import com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary; import com.navercorp.fixturemonkey.api.arbitrary.TraceableCombinableArbitrary; import com.navercorp.fixturemonkey.api.generator.ArbitraryGeneratorContext; import com.navercorp.fixturemonkey.api.generator.ArbitraryProperty; -import com.navercorp.fixturemonkey.api.generator.ContainerPropertyGenerator; -import com.navercorp.fixturemonkey.api.generator.NullInjectGenerator; import com.navercorp.fixturemonkey.api.generator.ObjectProperty; import com.navercorp.fixturemonkey.api.generator.ObjectPropertyGeneratorContext; import com.navercorp.fixturemonkey.api.introspector.ArbitraryIntrospector; import com.navercorp.fixturemonkey.api.introspector.ArbitraryIntrospectorResult; import com.navercorp.fixturemonkey.api.lazy.LazyArbitrary; -import com.navercorp.fixturemonkey.api.matcher.MatcherOperator; import com.navercorp.fixturemonkey.api.option.FixtureMonkeyOptions; import com.navercorp.fixturemonkey.api.option.InterfaceSelectionStrategy; import com.navercorp.fixturemonkey.api.property.CandidateConcretePropertyResolver; @@ -75,18 +55,10 @@ import com.navercorp.fixturemonkey.api.property.PropertyNameResolver; import com.navercorp.fixturemonkey.api.property.PropertyPath; import com.navercorp.fixturemonkey.api.property.RootProperty; -import com.navercorp.fixturemonkey.api.type.TypeCache; import com.navercorp.fixturemonkey.api.type.Types; -import com.navercorp.objectfarm.api.expression.IndexSelector; -import com.navercorp.objectfarm.api.expression.KeySelector; -import com.navercorp.objectfarm.api.expression.NameSelector; +import com.navercorp.fixturemonkey.planner.AnalysisResult; +import com.navercorp.fixturemonkey.property.JvmNodePropertyFactory; import com.navercorp.objectfarm.api.expression.PathExpression; -import com.navercorp.objectfarm.api.expression.Segment; -import com.navercorp.objectfarm.api.expression.Selector; -import com.navercorp.objectfarm.api.expression.TypeSelector; -import com.navercorp.objectfarm.api.expression.ValueSelector; -import com.navercorp.objectfarm.api.expression.WildcardSelector; -import com.navercorp.objectfarm.api.input.ObjectValueExtractor; import com.navercorp.objectfarm.api.node.JavaNode; import com.navercorp.objectfarm.api.node.JvmMapEntryNode; import com.navercorp.objectfarm.api.node.JvmMapNode; @@ -96,6 +68,7 @@ import com.navercorp.objectfarm.api.nodecandidate.FieldAccessCreationMethod; import com.navercorp.objectfarm.api.nodecandidate.MethodInvocationCreationMethod; import com.navercorp.objectfarm.api.tree.JvmNodeTree; +import com.navercorp.objectfarm.api.tree.PathResolverContext; import com.navercorp.objectfarm.api.type.JvmType; final class ValueProjectionAssembler { @@ -155,7 +128,9 @@ CombinableArbitrary assemble() { context.getCustomizersByPath(), context.getTraceContext(), context.getIntrospectorsByType(), - context.getNodeTreeAdapter(), + context.getRuntimeTreeFactory(), + context.getPathResolverContext(), + context.getNodeMetadataCache(), context.getUserContainerSizePaths() ); @@ -191,7 +166,7 @@ private CombinableArbitrary assembleNode( state.nodeByPath.put(currentPath.toExpression(), node); boolean isCurrentTypeContainer = state.containerTypeCache.computeIfAbsent(currentType, type -> - computeIsContainerType(type, options) + TypeMetadataResolver.computeIsContainerType(type, options) ); Class currentRawType = currentType.getRawType(); @@ -203,30 +178,32 @@ private CombinableArbitrary assembleNode( } try { - if (isUnderExcludedPath(currentPath, state.justPaths)) { + if (PathMatcher.isUnderExcludedPath(currentPath, state.justPaths)) { return assembleNodeDefault(node, state, parentContext, parentPath, currentPath, visitedTypes); } boolean isValueSet = state.candidatesByPath.containsKey(currentPath); - boolean hasChildValues = hasChildPathValues(currentPath, state.pathIndex); + boolean hasChildValues = PathMatcher.hasChildPathValues(currentPath, state.pathIndex); // set("field", null) vs child values priority: // If null was set AFTER all child values, null wins. Otherwise children win. if (isValueSet && hasChildValues) { ValueCandidate nullCandidate = state.candidatesByPath.get(currentPath); if (nullCandidate != null && nullCandidate.value == null) { - boolean hasActualChildCandidates = hasChildCandidateValues(currentPath, state.candidatesByPath); + boolean hasActualChildCandidates = + PathMatcher.hasChildCandidateValues(currentPath, state.candidatesByPath); if (!hasActualChildCandidates) { return wrapValueWithFiltersAndCustomizers(null, currentPath, currentRawType, state); } - if (isNullSetAfterAllChildren(nullCandidate.order, currentPath, state.candidatesByPath)) { + if (PathMatcher.isNullSetAfterAllChildren( + nullCandidate.order, currentPath, state.candidatesByPath)) { return wrapValueWithFiltersAndCustomizers(null, currentPath, currentRawType, state); } } } if (!hasChildValues) { - PathExpression bestPath = findBestMatchingPath(state.candidatesByPath, currentPath, state); + PathExpression bestPath = PathMatcher.findBestMatchingPath(state.candidatesByPath, currentPath, state); if (bestPath != null) { if (!bestPath.equals(currentPath)) { Integer remainingLimit = state.limitsByPath.get(bestPath); @@ -248,7 +225,7 @@ private CombinableArbitrary assembleNode( ValueCandidate bestCandidate = state.candidatesByPath.get(bestPath); Object rawValue = bestCandidate.value; boolean wasLazy = rawValue instanceof LazyValueHolder; - Object setValue = resolveLazyValue( + Object setValue = LazyResolver.resolveLazyValue( rawValue, bestCandidate.order instanceof ValueOrder.RegisterOrder, state @@ -268,7 +245,8 @@ private CombinableArbitrary assembleNode( } // Root TypeSelector matched but field-level siblings exist → decompose and fall through - if (isRootTypeSelector(bestPath) && hasFieldLevelTypeSelectorSiblings(bestPath, state)) { + if (PathMatcher.isRootTypeSelector(bestPath) + && PathMatcher.hasFieldLevelTypeSelectorSiblings(bestPath, state)) { state.candidatesByPath.put(currentPath, bestCandidate.withValue(setValue)); isValueSet = true; } else { @@ -319,7 +297,7 @@ private CombinableArbitrary assembleNode( // thenApply fallback: walks ancestors to find $[type:T] lazy, evaluates it, // and navigates the relative path to extract field values. if (!isValueSet && !hasChildValues) { - Object typedValue = resolveThenApplyAncestorValue(node, currentPath, state); + Object typedValue = LazyResolver.resolveThenApplyAncestorValue(node, currentPath, state); if (typedValue != null) { return traceAndReturnValue( typedValue, @@ -374,6 +352,11 @@ private CombinableArbitrary assembleNode( } return wrapValueWithFiltersAndCustomizers(setValue, currentPath, currentRawType, state); } + // AnonymousArbitraryIntrospector's proxy substitutes self for self-type methods, + // so null here is safe and breaks the assembleNodeDefault recursion cycle. + if (isCircular) { + return wrapValueWithFiltersAndCustomizers(null, currentPath, currentRawType, state); + } CombinableArbitrary interfaceResult = assembleInterfaceNode( node, state, @@ -386,8 +369,15 @@ private CombinableArbitrary assembleNode( if (interfaceResult != CombinableArbitrary.NOT_GENERATED) { return interfaceResult; } - if (state.nodeTreeAdapter != null) { - JvmNodeTree anonymousTree = state.nodeTreeAdapter.createAnonymousNodeTree(nodeType, options); + if (state.runtimeTreeFactory != null) { + PathResolverContext resolverContext = state.pathResolverContext != null + ? state.pathResolverContext + : PathResolverContext.builder().build(); + JvmNodeTree anonymousTree = state.runtimeTreeFactory.createAnonymousNodeTree( + nodeType, + options, + resolverContext + ); if (anonymousTree != null) { registerConcreteTree(anonymousTree, state); return assembleNodeDefault( @@ -412,9 +402,10 @@ private CombinableArbitrary assembleNode( } Property nodeProperty = state.propertyByNode.computeIfAbsent(node, state.nodePropertyFactory); - writeBackTypeMetadata(node, nodeProperty, state); + TypeMetadataResolver.writeBackTypeMetadata(node, nodeProperty, state); - PropertyNameResolver nameResolver = resolveNameResolver(node, nodeProperty, state); + PropertyNameResolver nameResolver = + TypeMetadataResolver.resolveNameResolver(node, nodeProperty, state); ObjectProperty objectProperty = new ObjectProperty(nodeProperty, nameResolver, node.getIndex()); @@ -427,14 +418,21 @@ private CombinableArbitrary assembleNode( isCurrentTypeContainer, nameResolver ); - double nullInject = resolveNullInjectGenerator(node, nodeProperty, state).generate(nullInjectContext); + double nullInject = TypeMetadataResolver.resolveNullInjectGenerator(node, nodeProperty, state) + .generate(nullInjectContext); + + // Primitive slots cannot hold null; the introspector would throw IllegalArgumentException + // when the array/setter writes the null produced by injectNull. + if (currentRawType.isPrimitive()) { + nullInject = 0.0; + } if (state.notNullPaths.contains(currentPath)) { nullInject = 0.0; } // Suppress null injection for types targeted by register() to ensure registered values take effect - if (nullInject > 0 && hasMatchingTypeSelector(node.getConcreteType(), state.pathIndex)) { + if (nullInject > 0 && PathMatcher.hasMatchingTypeSelector(node.getConcreteType(), state.pathIndex)) { nullInject = 0.0; } @@ -442,6 +440,13 @@ private CombinableArbitrary assembleNode( nullInject = 0.0; } + // A user-supplied postCondition predicate (setPostCondition) is applied to the + // generated value verbatim, so null injection would invoke the predicate with null + // and typically NPE inside the user lambda. Treat the filter as an implicit not-null. + if (nullInject > 0 && state.filtersByPath.containsKey(currentPath)) { + nullInject = 0.0; + } + List typeDefinitions = Collections.singletonList( new ConcreteTypeDefinition(nodeProperty, Collections.emptyList()) ); @@ -469,7 +474,7 @@ private CombinableArbitrary assembleNode( } else { PathExpression childPath = buildChildPath(currentPath, child, node, state); if ( - hasChildPathValues(childPath, state.pathIndex) + PathMatcher.hasChildPathValues(childPath, state.pathIndex) || state.candidatesByPath.containsKey(childPath) ) { children.add(child); @@ -495,8 +500,9 @@ private CombinableArbitrary assembleNode( PathExpression childPath = buildChildPath(currentPath, childNode, node, state); Property childProperty = state.propertyByNode.computeIfAbsent(childNode, state.nodePropertyFactory); - writeBackTypeMetadata(childNode, childProperty, state); - PropertyNameResolver childNameResolver = resolveNameResolver(childNode, childProperty, state); + TypeMetadataResolver.writeBackTypeMetadata(childNode, childProperty, state); + PropertyNameResolver childNameResolver = + TypeMetadataResolver.resolveNameResolver(childNode, childProperty, state); ObjectProperty childObjectProperty = new ObjectProperty( childProperty, @@ -505,7 +511,7 @@ private CombinableArbitrary assembleNode( ); boolean childIsContainer = state.containerTypeCache.computeIfAbsent(childNode.getConcreteType(), type -> - computeIsContainerType(type, options) + TypeMetadataResolver.computeIsContainerType(type, options) ); ObjectPropertyGeneratorContext childNullInjectContext = new ObjectPropertyGeneratorContext( @@ -515,16 +521,20 @@ private CombinableArbitrary assembleNode( childIsContainer, childNameResolver ); - double childNullInject = resolveNullInjectGenerator(childNode, childProperty, state).generate( + double childNullInject = + TypeMetadataResolver.resolveNullInjectGenerator(childNode, childProperty, state) + .generate( childNullInjectContext ); if (childNullInject > 0) { if ( state.candidatesByPath.containsKey(childPath) - || hasChildPathValues(childPath, state.pathIndex) + || PathMatcher.hasChildPathValues(childPath, state.pathIndex) || state.notNullPaths.contains(childPath) || state.customizersByPath.containsKey(childPath) + || state.filtersByPath.containsKey(childPath) + || PathMatcher.matchesAnyWildcardCandidate(childPath, state) ) { childNullInject = 0.0; } @@ -571,7 +581,9 @@ private CombinableArbitrary assembleNode( state.loggingContext ); - Class actualType = Types.getActualType(nodeProperty.getType()); + Class actualType = com.navercorp.fixturemonkey.api.type.Types.normalizeRawType( + nodeProperty.getJvmType().getRawType() + ); ArbitraryIntrospector typeSpecificIntrospector = state.introspectorsByType.get(actualType); // Do NOT call .injectNull() here — the generator already handles null injection @@ -587,7 +599,6 @@ private CombinableArbitrary assembleNode( result = options.getDefaultArbitraryGenerator().generate(context); } - result = applyFilters(result, currentPath, currentRawType, state); result = applyCustomizers(result, currentPath, state); @@ -669,13 +680,13 @@ private CombinableArbitrary assembleInterfaceNode( int selectedIndex = strategy.selectIndex(candidates.size(), seed, sampleIndex); Property selectedProperty = candidates.get(selectedIndex); - JvmType concreteType = Types.toJvmType(selectedProperty.getAnnotatedType(), selectedProperty.getAnnotations()); + JvmType concreteType = selectedProperty.getJvmType(); // Skip concrete tree for self-recursive types to avoid infinite recursion boolean isSelfRecursive = visitedTypes.contains(concreteType.getRawType()); JvmNodeTree concreteTree = - state.nodeTreeAdapter != null && !isSelfRecursive - ? state.nodeTreeAdapter.createConcreteNodeTree(concreteType, options) + state.runtimeTreeFactory != null && !isSelfRecursive + ? state.runtimeTreeFactory.createConcreteNodeTree(concreteType, options) : null; CombinableArbitrary result; @@ -762,7 +773,9 @@ private CombinableArbitrary generateWithConcreteProperty( ObjectProperty objectProperty = new ObjectProperty(concreteProperty, nameResolver, originalNode.getIndex()); - Class actualType = Types.getActualType(concreteProperty.getType()); + Class actualType = com.navercorp.fixturemonkey.api.type.Types.normalizeRawType( + concreteProperty.getJvmType().getRawType() + ); ArbitraryIntrospector typeSpecificIntrospector = state.introspectorsByType.get(actualType); PropertyGenerator propertyGenerator = options @@ -783,7 +796,7 @@ private CombinableArbitrary generateWithConcreteProperty( JvmType originalType = originalNode.getConcreteType(); boolean isContainer = state.containerTypeCache.computeIfAbsent(originalType, type -> - computeIsContainerType(type, options) + TypeMetadataResolver.computeIsContainerType(type, options) ); Property propertyForNullInject = parentPath == null ? new RootProperty(concreteProperty) : concreteProperty; @@ -815,17 +828,14 @@ private CombinableArbitrary generateWithConcreteProperty( addedToVisited = true; } - JvmType concreteJvmType = Types.toJvmType( - concreteProperty.getAnnotatedType(), - concreteProperty.getAnnotations() - ); + JvmType concreteJvmType = concreteProperty.getJvmType(); Map concreteChildrenByName = buildConcreteChildrenMap(concreteJvmType, state); try { if (!addedToVisited) { List filteredChildren = new ArrayList<>(); for (Property childProp : childProperties) { - Class childRawType = Types.getActualType(childProp.getType()); + Class childRawType = childProp.getJvmType().getRawType(); boolean isRecursiveChild = visitedTypes.contains(childRawType) || childRawType.isAssignableFrom(actualType); if (!isRecursiveChild) { @@ -835,7 +845,7 @@ private CombinableArbitrary generateWithConcreteProperty( String childName = childNr.resolve(childProp); PathExpression childPath = currentPath.child(childName); if ( - hasChildPathValues(childPath, state.pathIndex) + PathMatcher.hasChildPathValues(childPath, state.pathIndex) || state.candidatesByPath.containsKey(childPath) ) { filteredChildren.add(childProp); @@ -858,12 +868,9 @@ private CombinableArbitrary generateWithConcreteProperty( 0 ); - JvmType childJvmType = Types.toJvmType( - childProperty.getAnnotatedType(), - childProperty.getAnnotations() - ); + JvmType childJvmType = childProperty.getJvmType(); boolean childIsContainer = state.containerTypeCache.computeIfAbsent(childJvmType, type -> - computeIsContainerType(type, options) + TypeMetadataResolver.computeIsContainerType(type, options) ); ObjectPropertyGeneratorContext childNullInjectContext = new ObjectPropertyGeneratorContext( @@ -915,11 +922,7 @@ private CombinableArbitrary generateWithConcreteProperty( String childName = childProperty.getName(); JvmNode childNode = childName != null ? concreteChildrenByName.get(childName) : null; if (childNode == null) { - JvmType childType = Types.toJvmType( - childProperty.getAnnotatedType(), - childProperty.getAnnotations() - ); - childNode = new JavaNode(childType, childName != null ? childName : ""); + childNode = new JavaNode(childProperty.getJvmType(), childName != null ? childName : ""); } return assembleNode(childNode, state, currentContext, propertyPath, childPath, visitedTypes); @@ -939,7 +942,7 @@ private CombinableArbitrary generateWithConcreteProperty( result = options.getDefaultArbitraryGenerator().generate(context); } - Class concreteRawType = Types.getActualType(concreteProperty.getType()); + Class concreteRawType = concreteProperty.getJvmType().getRawType(); if (!concreteRawType.isPrimitive()) { result = result.injectNull(nullInject); } @@ -985,7 +988,7 @@ private CombinableArbitrary assembleMapEntryNode( JvmType nodeType = mapEntryNode.getConcreteType(); boolean isNodeContainer = state.containerTypeCache.computeIfAbsent(nodeType, type -> - computeIsContainerType(type, options) + TypeMetadataResolver.computeIsContainerType(type, options) ); Class nodeRawType = nodeType.getRawType(); @@ -1003,7 +1006,8 @@ private CombinableArbitrary assembleMapEntryNode( Property valueProperty = state.propertyByNode.computeIfAbsent(valueNode, state.nodePropertyFactory); Property nodeProperty = state.propertyByNode.computeIfAbsent(mapEntryNode, state.nodePropertyFactory); - PropertyNameResolver nameResolver = resolveNameResolver(mapEntryNode, nodeProperty, state); + PropertyNameResolver nameResolver = + TypeMetadataResolver.resolveNameResolver(mapEntryNode, nodeProperty, state); ObjectProperty objectProperty = new ObjectProperty(nodeProperty, nameResolver, mapEntryNode.getIndex()); @@ -1016,7 +1020,8 @@ private CombinableArbitrary assembleMapEntryNode( isContainer, nameResolver ); - double nullInject = resolveNullInjectGenerator(mapEntryNode, nodeProperty, state).generate( + double nullInject = TypeMetadataResolver.resolveNullInjectGenerator(mapEntryNode, nodeProperty, state) + .generate( nullInjectContext ); @@ -1112,7 +1117,7 @@ private CombinableArbitrary assembleMapLikeNode( JvmType nodeType = mapLikeNode.getConcreteType(); boolean isNodeContainer = state.containerTypeCache.computeIfAbsent(nodeType, type -> - computeIsContainerType(type, options) + TypeMetadataResolver.computeIsContainerType(type, options) ); Class rawType = nodeType.getRawType(); @@ -1362,7 +1367,7 @@ private CombinableArbitrary assembleNodeDefault( JvmType currentType = node.getConcreteType(); boolean isContainer = state.containerTypeCache.computeIfAbsent(currentType, type -> - computeIsContainerType(type, options) + TypeMetadataResolver.computeIsContainerType(type, options) ); Class currentRawType = currentType.getRawType(); @@ -1373,8 +1378,9 @@ private CombinableArbitrary assembleNodeDefault( try { Property nodeProperty = state.propertyByNode.computeIfAbsent(node, state.nodePropertyFactory); - writeBackTypeMetadata(node, nodeProperty, state); - PropertyNameResolver nameResolver = resolveNameResolver(node, nodeProperty, state); + TypeMetadataResolver.writeBackTypeMetadata(node, nodeProperty, state); + PropertyNameResolver nameResolver = + TypeMetadataResolver.resolveNameResolver(node, nodeProperty, state); ObjectProperty objectProperty = new ObjectProperty(nodeProperty, nameResolver, node.getIndex()); @@ -1385,7 +1391,24 @@ private CombinableArbitrary assembleNodeDefault( isContainer, nameResolver ); - double nullInject = resolveNullInjectGenerator(node, nodeProperty, state).generate(nullInjectContext); + double nullInject = TypeMetadataResolver.resolveNullInjectGenerator(node, nodeProperty, state) + .generate(nullInjectContext); + + // Primitive slots cannot hold null; the introspector would throw IllegalArgumentException + // when the array/setter writes the null produced by injectNull. + if (currentRawType.isPrimitive()) { + nullInject = 0.0; + } + + if (state.notNullPaths.contains(currentPath)) { + nullInject = 0.0; + } + + // A path matched by a wildcard candidate (e.g. $.list[*]) but exhausted by limit + // still belongs to the user-targeted set; injecting null contradicts the intent. + if (nullInject > 0 && PathMatcher.matchesAnyWildcardCandidate(currentPath, state)) { + nullInject = 0.0; + } List typeDefinitions = Collections.singletonList( new ConcreteTypeDefinition(nodeProperty, Collections.emptyList()) @@ -1411,8 +1434,9 @@ private CombinableArbitrary assembleNodeDefault( PathExpression childPath = buildChildPath(currentPath, childNode, node, state); Property childProperty = state.propertyByNode.computeIfAbsent(childNode, state.nodePropertyFactory); - writeBackTypeMetadata(childNode, childProperty, state); - PropertyNameResolver childNameResolver = resolveNameResolver(childNode, childProperty, state); + TypeMetadataResolver.writeBackTypeMetadata(childNode, childProperty, state); + PropertyNameResolver childNameResolver = + TypeMetadataResolver.resolveNameResolver(childNode, childProperty, state); ObjectProperty childObjectProperty = new ObjectProperty( childProperty, @@ -1421,7 +1445,7 @@ private CombinableArbitrary assembleNodeDefault( ); boolean childIsContainer = state.containerTypeCache.computeIfAbsent(childNode.getConcreteType(), type -> - computeIsContainerType(type, options) + TypeMetadataResolver.computeIsContainerType(type, options) ); ObjectPropertyGeneratorContext childNullInjectContext = new ObjectPropertyGeneratorContext( @@ -1431,7 +1455,9 @@ private CombinableArbitrary assembleNodeDefault( childIsContainer, childNameResolver ); - double childNullInject = resolveNullInjectGenerator(childNode, childProperty, state).generate( + double childNullInject = + TypeMetadataResolver.resolveNullInjectGenerator(childNode, childProperty, state) + .generate( childNullInjectContext ); @@ -1479,11 +1505,11 @@ private CombinableArbitrary assembleNodeDefault( } private Map buildConcreteChildrenMap(JvmType concreteType, AssemblyState state) { - if (state.nodeTreeAdapter == null || state.options == null) { + if (state.runtimeTreeFactory == null || state.options == null) { return Collections.emptyMap(); } - JvmNodeTree concreteTree = state.nodeTreeAdapter.createConcreteNodeTree(concreteType, state.options); + JvmNodeTree concreteTree = state.runtimeTreeFactory.createConcreteNodeTree(concreteType, state.options); if (concreteTree == null) { return Collections.emptyMap(); } @@ -1555,12 +1581,13 @@ private ArbitraryProperty buildChildArbitraryPropertyCached( AssemblyState state ) { FixtureMonkeyOptions options = state.options; - PropertyNameResolver childNameResolver = resolveNameResolver(childNode, childProperty, state); + PropertyNameResolver childNameResolver = + TypeMetadataResolver.resolveNameResolver(childNode, childProperty, state); ObjectProperty childObjectProperty = new ObjectProperty(childProperty, childNameResolver, childNode.getIndex()); boolean childIsContainer = state.containerTypeCache.computeIfAbsent(childNode.getConcreteType(), type -> - computeIsContainerType(type, options) + TypeMetadataResolver.computeIsContainerType(type, options) ); ObjectPropertyGeneratorContext childNullInjectContext = new ObjectPropertyGeneratorContext( @@ -1570,7 +1597,8 @@ private ArbitraryProperty buildChildArbitraryPropertyCached( childIsContainer, childNameResolver ); - double childNullInject = resolveNullInjectGenerator(childNode, childProperty, state).generate( + double childNullInject = TypeMetadataResolver.resolveNullInjectGenerator(childNode, childProperty, state) + .generate( childNullInjectContext ); @@ -1587,7 +1615,7 @@ private PathExpression buildChildPath( JvmNode parentNode, AssemblyState state ) { - if (isSingleElementWrapper(parentNode.getConcreteType())) { + if (TypeMetadataResolver.isSingleElementWrapper(parentNode.getConcreteType())) { String nodeName = childNode.getNodeName(); Integer index = childNode.getIndex(); @@ -1603,7 +1631,8 @@ private PathExpression buildChildPath( return parentPath.index(index); } else if (nodeName != null) { Property childProperty = state.propertyByNode.computeIfAbsent(childNode, state.nodePropertyFactory); - PropertyNameResolver nameResolver = resolveNameResolver(childNode, childProperty, state); + PropertyNameResolver nameResolver = + TypeMetadataResolver.resolveNameResolver(childNode, childProperty, state); String resolvedName = nameResolver.resolve(childProperty); return parentPath.child(resolvedName); @@ -1612,437 +1641,6 @@ private PathExpression buildChildPath( } } - private boolean isSingleElementWrapper(JvmType jvmType) { - Class rawType = jvmType.getRawType(); - return (Supplier.class.isAssignableFrom(rawType) - || Optional.class.isAssignableFrom(rawType) - || OptionalInt.class.isAssignableFrom(rawType) - || OptionalLong.class.isAssignableFrom(rawType) - || OptionalDouble.class.isAssignableFrom(rawType)); - } - - private boolean computeIsContainerType(JvmType jvmType, @Nullable FixtureMonkeyOptions options) { - Class rawType = jvmType.getRawType(); - if ( - rawType.isArray() - || Collection.class.isAssignableFrom(rawType) - || Map.class.isAssignableFrom(rawType) - || Map.Entry.class.isAssignableFrom(rawType) - || Iterable.class.isAssignableFrom(rawType) - || BaseStream.class.isAssignableFrom(rawType) - || isSingleElementWrapper(jvmType) - ) { - return true; - } - - if (options != null) { - Property property = JvmNodePropertyFactory.fromType(jvmType); - for (MatcherOperator op : options.getContainerPropertyGenerators()) { - if (op.getMatcher().match(property)) { - return true; - } - } - } - - return false; - } - - private PropertyNameResolver resolveNameResolver(JvmNode node, Property property, AssemblyState state) { - if (state.typeMetadataCache != null) { - CachedTypeMetadata cached = state.typeMetadataCache.get(node.getConcreteType()); - if (cached != null) { - return cached.nameResolver; - } - } - return state.options.getPropertyNameResolver(property); - } - - private NullInjectGenerator resolveNullInjectGenerator(JvmNode node, Property property, AssemblyState state) { - if (state.typeMetadataCache != null) { - CachedTypeMetadata cached = state.typeMetadataCache.get(node.getConcreteType()); - if (cached != null) { - return cached.nullInjectGenerator; - } - } - return state.options.getNullInjectGenerator(property); - } - - @SuppressWarnings("deprecation") - private void writeBackTypeMetadata(JvmNode node, Property property, AssemblyState state) { - if (state.typeMetadataCache == null) { - return; - } - JvmType jvmType = node.getConcreteType(); - if (!state.typeMetadataCache.containsKey(jvmType)) { - PropertyNameResolver resolver = state.options.getPropertyNameResolver(property); - NullInjectGenerator generator = state.options.getNullInjectGenerator(property); - boolean isContainer = computeIsContainerType(jvmType, state.options); - boolean hasCandidateResolvers = state.options.getCandidateConcretePropertyResolver(property) != null; - state.typeMetadataCache.putIfAbsent( - jvmType, - new CachedTypeMetadata(resolver, generator, isContainer, hasCandidateResolvers) - ); - } - } - - private boolean hasChildPathValues(PathExpression parentPath, PathIndex pathIndex) { - return pathIndex.hasChildPaths(parentPath); - } - - private static boolean hasChildCandidateValues( - PathExpression parentPath, - Map candidatesByPath - ) { - String parentStr = parentPath.toExpression(); - for (PathExpression candidatePath : candidatesByPath.keySet()) { - String candidateStr = candidatePath.toExpression(); - if (candidateStr.length() > parentStr.length() && candidateStr.startsWith(parentStr)) { - char nextChar = candidateStr.charAt(parentStr.length()); - if (nextChar == '.' || nextChar == '[') { - return true; - } - } - } - return false; - } - - private static boolean isNullSetAfterAllChildren( - ValueOrder nullOrder, - PathExpression parentPath, - Map candidatesByPath - ) { - String parentStr = parentPath.toExpression(); - for (Map.Entry entry : candidatesByPath.entrySet()) { - String candidateStr = entry.getKey().toExpression(); - if (candidateStr.length() > parentStr.length() && candidateStr.startsWith(parentStr)) { - char nextChar = candidateStr.charAt(parentStr.length()); - if (nextChar == '.' || nextChar == '[') { - if (entry.getValue().order.compareTo(nullOrder) >= 0) { - return false; - } - } - } - } - return true; - } - - private @Nullable PathExpression findBestMatchingPath( - Map candidatesByPath, - PathExpression path, - @Nullable AssemblyState state - ) { - PathExpression bestPath = null; - // Sentinel initial values — RegisterOrder.of(MIN_VALUE) loses to any real comparison - ValueOrder bestOrder = ValueOrder.RegisterOrder.of(Integer.MIN_VALUE); - - PathExpression bestTypePath = null; - int bestTypeDepth = -1; - ValueOrder bestTypeOrder = ValueOrder.RegisterOrder.of(Integer.MIN_VALUE); - - ValueCandidate exactCandidate = candidatesByPath.get(path); - if (exactCandidate != null) { - if (exactCandidate.order.compareTo(bestOrder) > 0) { - bestOrder = exactCandidate.order; - bestPath = path; - } - } - - if (state != null) { - for (Map.Entry entry : state.wildcardEntries) { - PathExpression pattern = entry.getKey(); - if (pattern.matches(path)) { - ValueOrder order = entry.getValue().order; - if (order.compareTo(bestOrder) > 0) { - bestOrder = order; - bestPath = pattern; - } - } - } - - for (Map.Entry entry : state.typeSelectorEntries) { - PathExpression pattern = entry.getKey(); - // depth = how deep in the tree the type match occurs; deeper = more specific = wins - int depth = matchesTypePattern(pattern, path, state); - if (depth >= 0) { - ValueOrder order = entry.getValue().order; - if (depth > bestTypeDepth || (depth == bestTypeDepth && order.compareTo(bestTypeOrder) > 0)) { - bestTypeDepth = depth; - bestTypeOrder = order; - bestTypePath = pattern; - } - } - } - } - - if (bestTypePath != null) { - if (bestPath == null || bestTypeOrder.compareTo(bestOrder) > 0) { - return bestTypePath; - } - } - - return bestPath; - } - - private int matchesTypePattern(PathExpression pattern, PathExpression path, AssemblyState state) { - List patternSegments = pattern.getSegments(); - List pathSegments = path.getSegments(); - - if (patternSegments.isEmpty()) { - return -1; - } - - int typeSegmentIndex = -1; - TypeSelector typeSelector = null; - for (int i = 0; i < patternSegments.size(); i++) { - Segment seg = patternSegments.get(i); - if (seg.isSingleSelector() && seg.getFirstSelector() instanceof TypeSelector) { - typeSegmentIndex = i; - typeSelector = (TypeSelector)seg.getFirstSelector(); - break; - } - } - - if (typeSelector == null) { - return -1; - } - - int patternSuffixLen = patternSegments.size() - typeSegmentIndex - 1; - - // TypeSelector-only pattern ($[type:T]) — only matches current node's type directly. - // Descendant field matching is handled by resolveThenApplyAncestorValue. - if (patternSuffixLen == 0 && typeSegmentIndex == 0) { - JvmNode currentNode = findNodeForPath(path, state); - if (currentNode != null && typeSelector.matchesType(currentNode.getConcreteType().getRawType())) { - return pathSegments.size(); - } - return -1; - } - - if (patternSuffixLen > pathSegments.size()) { - return -1; - } - - int suffixStartInPath = pathSegments.size() - patternSuffixLen; - for (int i = 0; i < patternSuffixLen; i++) { - Segment patternSeg = patternSegments.get(typeSegmentIndex + 1 + i); - Segment pathSeg = pathSegments.get(suffixStartInPath + i); - if (!patternSeg.equals(pathSeg) - && !(patternSeg.isSingleSelector() - && patternSeg.getFirstSelector() instanceof WildcardSelector - && pathSeg.isSingleSelector() - && (pathSeg.getFirstSelector() instanceof IndexSelector - || pathSeg.getFirstSelector() instanceof KeySelector - || pathSeg.getFirstSelector() instanceof ValueSelector)) - ) { - return -1; - } - } - - int ownerPos = suffixStartInPath - 1; - - PathExpression nodeAtPath; - if (ownerPos < 0) { - nodeAtPath = PathExpression.root(); - } else { - nodeAtPath = buildPathUpTo(path, ownerPos); - } - - JvmNode node = findNodeForPath(nodeAtPath, state); - if (node == null) { - return -1; - } - - if (typeSelector.matchesType(node.getConcreteType().getRawType())) { - return ownerPos + 1; - } - - return -1; - } - - private PathExpression buildPathUpTo(PathExpression fullPath, int segmentIndex) { - List segments = fullPath.getSegments(); - PathExpression result = PathExpression.root(); - for (int i = 0; i <= segmentIndex && i < segments.size(); i++) { - result = result.appendSegment(segments.get(i)); - } - return result; - } - - private boolean isRootTypeSelector(PathExpression path) { - List segments = path.getSegments(); - return (segments.size() == 1 - && segments.get(0).isSingleSelector() - && segments.get(0).getFirstSelector() instanceof TypeSelector); - } - - private boolean hasFieldLevelTypeSelectorSiblings(PathExpression rootTypePath, AssemblyState state) { - TypeSelector rootTypeSelector = (TypeSelector)rootTypePath.getSegments().get(0).getFirstSelector(); - Class rootType = rootTypeSelector.getTargetType(); - - for (PathExpression path : state.candidatesByPath.keySet()) { - if (path.equals(rootTypePath)) { - continue; - } - List segments = path.getSegments(); - if (segments.size() > 1 - && segments.get(0).isSingleSelector() - && segments.get(0).getFirstSelector() instanceof TypeSelector) { - TypeSelector ts = (TypeSelector)segments.get(0).getFirstSelector(); - if (ts.getTargetType().equals(rootType)) { - return true; - } - } - } - return false; - } - - private @Nullable Object resolveThenApplyAncestorValue( - JvmNode node, - PathExpression currentPath, - AssemblyState state - ) { - if (state.rootTypeSelectors.isEmpty()) { - return null; - } - - for (Map.Entry entry : state.rootTypeSelectors) { - TypeSelector typeSelector = (TypeSelector)entry.getKey().getSegments().get(0).getFirstSelector(); - - if (node.getConcreteType() != null && typeSelector.matchesType(node.getConcreteType().getRawType())) { - Object value = entry.getValue().value; - if (value instanceof LazyValueHolder) { - Object resolved = resolveLazyWithCache((LazyValueHolder)value, state); - if (resolved == LazyValueHolder.RECURSION_BLOCKED) { - return null; - } - return resolved; - } - return value; - } - - List pathSegments = currentPath.getSegments(); - for (int pos = pathSegments.size() - 1; pos >= 0; pos--) { - PathExpression ancestorPath = buildPathUpTo(currentPath, pos - 1); - JvmNode ancestorNode = findNodeForPath(ancestorPath, state); - if (ancestorNode != null - && ancestorNode.getConcreteType() != null - && typeSelector.matchesType(ancestorNode.getConcreteType().getRawType())) { - Object value = entry.getValue().value; - Object resolved; - if (value instanceof LazyValueHolder) { - resolved = resolveLazyWithCache((LazyValueHolder)value, state); - if (resolved == LazyValueHolder.RECURSION_BLOCKED || resolved == null) { - return null; - } - } else { - resolved = value; - } - - Object current = resolved; - for (int i = pos; i < pathSegments.size() && current != null; i++) { - Segment pathSeg = pathSegments.get(i); - Selector selector = pathSeg.getFirstSelector(); - - if (selector instanceof NameSelector) { - current = getFieldValueByName(current, ((NameSelector)selector).getName()); - } else if (selector instanceof IndexSelector) { - current = getElementAtIndex(current, ((IndexSelector)selector).getIndex()); - } else { - current = null; - } - } - if (current != null) { - return current; - } - } - } - } - return null; - } - - private static @Nullable Object getFieldValueByName(Object obj, String fieldName) { - Field field = TypeCache.getFieldsByName(obj.getClass()).get(fieldName); - if (field == null) { - return null; - } - try { - return field.get(obj); - } catch (IllegalAccessException e) { - return null; - } - } - - private static @Nullable Object getElementAtIndex(Object container, int index) { - if (container instanceof List) { - List list = (List)container; - if (index >= 0 && index < list.size()) { - return list.get(index); - } - return null; - } - if (container.getClass().isArray()) { - int length = Array.getLength(container); - if (index >= 0 && index < length) { - return Array.get(container, index); - } - return null; - } - return null; - } - - private @Nullable JvmNode findNodeForPath(PathExpression path, AssemblyState state) { - String pathStr = path.toExpression(); - JvmNode node = state.nodeByPath.get(pathStr); - if (node != null) { - return node; - } - if (state.nodeTree != null) { - return state.nodeTree.resolve(path); - } - return null; - } - - private @Nullable Object resolveLazyWithCache(LazyValueHolder holder, AssemblyState state) { - if (state.resolvedLazyCache.containsKey(holder)) { - return state.resolvedLazyCache.get(holder); - } - Object resolved = holder.getValue(); - if (resolved != null && resolved != LazyValueHolder.RECURSION_BLOCKED) { - state.resolvedLazyCache.put(holder, resolved); - } - return resolved; - } - - private boolean hasMatchingTypeSelector(JvmType nodeType, PathIndex pathIndex) { - Set typePatternPaths = pathIndex.getTypePatternPaths(); - if (typePatternPaths.isEmpty()) { - return false; - } - - Class rawType = nodeType.getRawType(); - for (PathExpression pattern : typePatternPaths) { - List segments = pattern.getSegments(); - for (Segment segment : segments) { - if (segment.isSingleSelector() && segment.getFirstSelector() instanceof TypeSelector) { - TypeSelector typeSelector = (TypeSelector)segment.getFirstSelector(); - if (typeSelector.matchesType(rawType)) { - return true; - } - } - } - } - return false; - } - - private boolean isUnderExcludedPath(PathExpression path, Set excludedPaths) { - for (PathExpression excluded : excludedPaths) { - if (path.isChildOf(excluded)) { - return true; - } - } - return false; - } - @SuppressWarnings({"unchecked", "rawtypes"}) private CombinableArbitrary applyFilters( CombinableArbitrary arbitrary, @@ -2132,7 +1730,7 @@ private Object applyWildcardOverridesToContainer( if (result == null) { result = new ArrayList<>(list); } - result.set(i, resolveLazyValue(entry.getValue().value, false, state)); + result.set(i, LazyResolver.resolveLazyValue(entry.getValue().value, false, state)); break; } } @@ -2157,7 +1755,7 @@ private Object applyWildcardOverridesToContainer( container = copy; modified = true; } - Object resolved = resolveLazyValue(entry.getValue().value, false, state); + Object resolved = LazyResolver.resolveLazyValue(entry.getValue().value, false, state); if (resolved != null) { Array.set(container, i, resolved); } @@ -2169,17 +1767,6 @@ private Object applyWildcardOverridesToContainer( return container; } - private @Nullable Object resolveLazyValue(@Nullable Object value, boolean isFromRegister, AssemblyState state) { - if (!(value instanceof LazyValueHolder)) { - return value; - } - // Register lazy: evaluate fresh each time (thenApply wraps entire object). - // User lazy: cached within one sample for consistency (e.g., setLazy with Arbitraries.of()). - return isFromRegister - ? ((LazyValueHolder)value).getValue() - : resolveLazyWithCache((LazyValueHolder)value, state); - } - private CombinableArbitrary traceAndReturnValue( @Nullable Object value, String source, @@ -2347,253 +1934,4 @@ private String buildDeduplicationKey(JvmNode node) { return "type:" + node.getConcreteType().getRawType().getName(); } } - - private static final class PathIndex { - - private static final Pattern INDEX_PATTERN = Pattern.compile("\\[\\d+]"); - - private final Map> childPathsByParent; - private final Set wildcardParentPaths; - private final Set typePatternPaths; - - PathIndex( - Set valuePaths, - Set userContainerSizePaths, - Set customizerPaths, - Set notNullPaths - ) { - this.childPathsByParent = new HashMap<>(); - this.wildcardParentPaths = new HashSet<>(); - this.typePatternPaths = new HashSet<>(); - - indexAncestors(valuePaths); - indexAncestors(userContainerSizePaths); - indexAncestors(customizerPaths); - indexAncestors(notNullPaths); - - for (PathExpression sizePath : userContainerSizePaths) { - childPathsByParent.computeIfAbsent(sizePath, k -> new HashSet<>()); - } - } - - private void indexAncestors(Set paths) { - for (PathExpression path : paths) { - if (path.hasTypeSelector()) { - typePatternPaths.add(path); - continue; - } - - PathExpression ancestor = path.getParent(); - while (ancestor != null && !ancestor.equals(path)) { - childPathsByParent.computeIfAbsent(ancestor, k -> new HashSet<>()).add(path); - PathExpression next = ancestor.getParent(); - if (next != null && next.equals(ancestor)) { - break; - } - ancestor = next; - } - - if (path.hasWildcard()) { - PathExpression wildcardParent = path.getParent(); - if (wildcardParent != null) { - wildcardParentPaths.add(wildcardParent); - } - } - } - } - - boolean hasChildPaths(PathExpression parentPath) { - if (childPathsByParent.containsKey(parentPath)) { - return true; - } - if (wildcardParentPaths.contains(parentPath)) { - return true; - } - String pathStr = parentPath.toExpression(); - // Convert indexed paths ($.list[0]) to wildcard form ($.list[*]) to check wildcard coverage - if (pathStr.contains("[") && !pathStr.contains("[*]")) { - String wildcardForm = INDEX_PATTERN.matcher(pathStr).replaceAll("[*]"); - PathExpression wildcardPath = PathExpression.of(wildcardForm); - return wildcardParentPaths.contains(wildcardPath) - || childPathsByParent.containsKey(wildcardPath); - } - return false; - } - - Set getTypePatternPaths() { - return typePatternPaths; - } - } - - static final class CachedTypeMetadata { - - final PropertyNameResolver nameResolver; - final NullInjectGenerator nullInjectGenerator; - final boolean isContainerType; - final boolean hasCandidateConcretePropertyResolvers; - - CachedTypeMetadata( - PropertyNameResolver nameResolver, - NullInjectGenerator nullInjectGenerator, - boolean isContainerType, - boolean hasCandidateConcretePropertyResolvers - ) { - this.nameResolver = nameResolver; - this.nullInjectGenerator = nullInjectGenerator; - this.isContainerType = isContainerType; - this.hasCandidateConcretePropertyResolvers = hasCandidateConcretePropertyResolvers; - } - } - - private static final class AssemblyState { - - final JvmNodeTree nodeTree; - final Map candidatesByPath; - final com.navercorp.fixturemonkey.api.property.TreeRootProperty rootProperty; - final FixtureMonkeyOptions options; - final com.navercorp.fixturemonkey.api.context.MonkeyGeneratorContext monkeyGeneratorContext; - final com.navercorp.fixturemonkey.api.generator.ArbitraryGeneratorLoggingContext loggingContext; - final Set justPaths; - final Set notNullPaths; - final Map> filtersByPath; - final Map limitsByPath; - final InterfaceSelectionStrategy interfaceSelectionStrategy; - final long assemblySeed; - final AtomicInteger interfaceSelectionCounter; - final Map> customizersByPath; - final TraceContext traceContext; - final Map, ArbitraryIntrospector> introspectorsByType; - - final Map concreteTreeByNode; - - final Map containerTypeCache; - - final Map propertyByNode; - - final Set userContainerSizePaths; - - final PathIndex pathIndex; - - final @Nullable NodeTreeAdapter nodeTreeAdapter; - - final Function nodePropertyFactory; - - final Map propertyPathPropertyByNode; - - final Map nodeByPath; - - final Map resolvedLazyCache; - - final List> wildcardEntries; - - final List> typeSelectorEntries; - - final List> rootTypeSelectors; - - final ValueDecomposer valueDecomposer; - - final @Nullable ConcurrentHashMap typeMetadataCache; - - AssemblyState( - JvmNodeTree nodeTree, - Map candidatesByPath, - com.navercorp.fixturemonkey.api.property.TreeRootProperty rootProperty, - FixtureMonkeyOptions options, - com.navercorp.fixturemonkey.api.context.MonkeyGeneratorContext monkeyGeneratorContext, - com.navercorp.fixturemonkey.api.generator.ArbitraryGeneratorLoggingContext loggingContext, - Set justPaths, - Set notNullPaths, - Map> filtersByPath, - Map limitsByPath, - InterfaceSelectionStrategy interfaceSelectionStrategy, - Map> customizersByPath, - TraceContext traceContext, - Map, ArbitraryIntrospector> introspectorsByType, - @Nullable NodeTreeAdapter nodeTreeAdapter, - Set userContainerSizePaths - ) { - this.nodeTree = nodeTree; - this.candidatesByPath = candidatesByPath; - this.rootProperty = rootProperty; - this.options = options; - this.monkeyGeneratorContext = monkeyGeneratorContext; - this.loggingContext = loggingContext; - this.justPaths = justPaths; - this.notNullPaths = notNullPaths; - this.filtersByPath = filtersByPath; - this.limitsByPath = limitsByPath; - this.interfaceSelectionStrategy = interfaceSelectionStrategy; - this.assemblySeed = ThreadLocalRandom.current().nextLong(); - this.interfaceSelectionCounter = new AtomicInteger(0); - this.customizersByPath = customizersByPath; - this.traceContext = traceContext; - this.introspectorsByType = introspectorsByType; - this.nodeTreeAdapter = nodeTreeAdapter; - - this.containerTypeCache = new HashMap<>(); - this.propertyByNode = new IdentityHashMap<>(); - this.concreteTreeByNode = new IdentityHashMap<>(); - this.propertyPathPropertyByNode = new IdentityHashMap<>(); - this.nodeByPath = new HashMap<>(); - this.resolvedLazyCache = new IdentityHashMap<>(); - this.valueDecomposer = new ValueDecomposer( - candidatesByPath, - limitsByPath, - nodeTree, - new ObjectValueExtractor() - ); - this.userContainerSizePaths = userContainerSizePaths; - this.pathIndex = new PathIndex( - new HashSet<>(candidatesByPath.keySet()), - userContainerSizePaths, - new HashSet<>(customizersByPath.keySet()), - notNullPaths - ); - - List> wildcards = new ArrayList<>(); - List> typeSelectors = new ArrayList<>(); - List> rootTypeOnly = new ArrayList<>(); - for (Map.Entry entry : candidatesByPath.entrySet()) { - PathExpression pattern = entry.getKey(); - if (pattern.hasWildcard()) { - wildcards.add(entry); - } else if (pattern.hasTypeSelector()) { - typeSelectors.add(entry); - List segments = pattern.getSegments(); - if (segments.size() == 1 - && segments.get(0).isSingleSelector() - && segments.get(0).getFirstSelector() instanceof TypeSelector) { - rootTypeOnly.add(entry); - } - } - } - this.wildcardEntries = wildcards; - this.typeSelectorEntries = typeSelectors; - this.rootTypeSelectors = rootTypeOnly; - - this.nodePropertyFactory = new JvmNodePropertyFactory(child -> { - JvmNode parent = nodeTree.getParent(child); - if (parent != null) { - return parent; - } - JvmNodeTree concreteTree = this.concreteTreeByNode.get(child); - if (concreteTree != null) { - return concreteTree.getParent(child); - } - return null; - }); - - ConcurrentHashMap rawCache = nodeTreeAdapter != null ? nodeTreeAdapter.getNodeMetadataCache() : null; - if (rawCache != null) { - @SuppressWarnings("unchecked") - ConcurrentHashMap typedCache = (ConcurrentHashMap< - JvmType, - CachedTypeMetadata - >)rawCache; - this.typeMetadataCache = typedCache; - } else { - this.typeMetadataCache = null; - } - } - } } diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/property/JvmNodePropertyFactory.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/property/JvmNodePropertyFactory.java similarity index 59% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/property/JvmNodePropertyFactory.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/property/JvmNodePropertyFactory.java index c2d59d959b..3fafeee897 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/property/JvmNodePropertyFactory.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/property/JvmNodePropertyFactory.java @@ -16,16 +16,14 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter.property; +package com.navercorp.fixturemonkey.property; import java.beans.PropertyDescriptor; -import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; import java.util.Arrays; -import java.util.List; +import java.util.Collections; import java.util.function.Function; import org.apiguardian.api.API; @@ -41,12 +39,12 @@ import com.navercorp.fixturemonkey.api.property.TypeNameProperty; import com.navercorp.fixturemonkey.api.property.TypeParameterProperty; import com.navercorp.fixturemonkey.api.type.TypeCache; -import com.navercorp.fixturemonkey.api.type.Types; import com.navercorp.objectfarm.api.node.JvmNode; import com.navercorp.objectfarm.api.nodecandidate.ConstructorParamCreationMethod; import com.navercorp.objectfarm.api.nodecandidate.CreationMethod; import com.navercorp.objectfarm.api.nodecandidate.FieldAccessCreationMethod; import com.navercorp.objectfarm.api.nodecandidate.MethodInvocationCreationMethod; +import com.navercorp.objectfarm.api.type.JavaType; import com.navercorp.objectfarm.api.type.JvmType; /** @@ -79,8 +77,7 @@ public JvmNodePropertyFactory(Function parentLookup) * @return a {@link TypeParameterProperty} wrapping the type */ public static Property fromType(JvmType jvmType) { - AnnotatedType annotatedType = buildAnnotatedType(jvmType); - return new TypeParameterProperty(annotatedType); + return new TypeParameterProperty(jvmType); } /** @@ -102,20 +99,19 @@ public static Property fromType(JvmType jvmType) { @Override public Property apply(JvmNode node) { JvmType jvmType = node.getConcreteType(); - AnnotatedType annotatedType = buildAnnotatedType(jvmType); CreationMethod creationMethod = node.getCreationMethod(); Boolean nullable = jvmType.getNullable(); if (creationMethod == null) { - return new TypeNameProperty(annotatedType, node.getNodeName(), nullable); + return new TypeNameProperty(jvmType, node.getNodeName(), nullable); } switch (creationMethod.getType()) { case FIELD: - return new FieldProperty(annotatedType, ((FieldAccessCreationMethod)creationMethod).getField()); + return new FieldProperty(jvmType, ((FieldAccessCreationMethod)creationMethod).getField(), nullable); case CONSTRUCTOR: ConstructorParamCreationMethod ctorMethod = (ConstructorParamCreationMethod)creationMethod; - java.lang.reflect.Constructor ctor = ctorMethod.getConstructor(); + Constructor ctor = ctorMethod.getConstructor(); // Check if the actual constructor parameter is primitive. // TypeReference boxes int to Integer, losing primitive info and @@ -123,17 +119,23 @@ public Property apply(JvmNode node) { // Match by name since parameterIndex in ConstructorParamCreationMethod // may not correspond to the actual constructor parameter position. Class actualParamType = findConstructorParamType(ctor, node.getNodeName()); + JvmType paramJvmType = jvmType; if (actualParamType != null && actualParamType.isPrimitive()) { - annotatedType = Types.generateAnnotatedTypeWithoutAnnotation(actualParamType); + paramJvmType = new JavaType( + actualParamType, + Collections.emptyList(), + Collections.emptyList(), + false + ); nullable = false; } - Property paramProperty = new TypeNameProperty(annotatedType, node.getNodeName(), nullable); + Property paramProperty = new TypeNameProperty(paramJvmType, node.getNodeName(), nullable); Property fieldProperty = findFieldProperty(ctor.getDeclaringClass(), node.getNodeName()); return new ConstructorProperty(paramProperty, ctor, fieldProperty, nullable); case METHOD: return fromMethodCreation( - annotatedType, + jvmType, node.getNodeName(), (MethodInvocationCreationMethod)creationMethod ); @@ -150,8 +152,8 @@ public Property apply(JvmNode node) { ) { annotationSource = grandParent; } - Property containerProperty = fromTypePreservingAnnotations(annotationSource.getConcreteType()); - Property elementProperty = new TypeNameProperty(annotatedType, node.getNodeName(), null); + Property containerProperty = fromType(annotationSource.getConcreteType()); + Property elementProperty = new TypeNameProperty(jvmType, node.getNodeName(), null); return new DefaultContainerElementProperty( containerProperty, elementProperty, @@ -159,54 +161,14 @@ public Property apply(JvmNode node) { node.getIndex() != null ? node.getIndex() : 0 ); } - return new TypeNameProperty(annotatedType, node.getNodeName(), null); + return new TypeNameProperty(jvmType, node.getNodeName(), null); default: - return new TypeNameProperty(annotatedType, node.getNodeName(), null); + return new TypeNameProperty(jvmType, node.getNodeName(), null); } } - /** - * Creates a {@link TypeParameterProperty} from a {@link JvmType}, ensuring all annotations - * stored in the JvmType are preserved. Unlike {@link #fromType(JvmType)}, this method - * bypasses the cached {@code AnnotatedType} which may not include annotations - * merged from multiple sources (e.g., field + setter annotations via {@code CompositeProperty}). - */ - private static Property fromTypePreservingAnnotations(JvmType jvmType) { - List allAnnotations = jvmType.getAnnotations(); - AnnotatedType baseType = buildAnnotatedType(jvmType); - Type type = baseType.getType(); - - AnnotatedType annotatedType = new AnnotatedType() { - @Override - public Type getType() { - return type; - } - - @Override - @SuppressWarnings({"unchecked", "cast.unsafe"}) - public T getAnnotation(Class annotationClass) { - return (T)allAnnotations - .stream() - .filter(a -> a.annotationType().equals(annotationClass)) - .findFirst() - .orElse(null); - } - - @Override - public Annotation[] getAnnotations() { - return allAnnotations.toArray(new Annotation[0]); - } - - @Override - public Annotation[] getDeclaredAnnotations() { - return getAnnotations(); - } - }; - return new TypeParameterProperty(annotatedType); - } - private Property fromMethodCreation( - AnnotatedType annotatedType, + JvmType jvmType, String name, MethodInvocationCreationMethod method ) { @@ -217,7 +179,7 @@ private Property fromMethodCreation( // so that AnonymousArbitraryIntrospector can recognize them if (declaringClass.isInterface()) { return new InterfaceJavaMethodProperty( - annotatedType, + jvmType, name, invokedMethod.getName(), Arrays.asList(invokedMethod.getAnnotations()) @@ -226,13 +188,13 @@ private Property fromMethodCreation( PropertyDescriptor descriptor = TypeCache.getPropertyDescriptorsByPropertyName(declaringClass).get(name); if (descriptor != null) { - return new PropertyDescriptorProperty(annotatedType, descriptor); + return new PropertyDescriptorProperty(jvmType, descriptor); } - return new TypeNameProperty(annotatedType, name, null); + return new TypeNameProperty(jvmType, name, null); } private static @Nullable Class findConstructorParamType( - java.lang.reflect.Constructor constructor, + Constructor constructor, String paramName ) { if (paramName == null) { @@ -263,103 +225,11 @@ private Property fromMethodCreation( if (fieldName == null) { return null; } - java.lang.reflect.Field field = TypeCache.getFieldsByName(declaringClass).get(fieldName); + Field field = TypeCache.getFieldsByName(declaringClass).get(fieldName); if (field != null) { return new FieldProperty(field); } return null; } - /** - * Builds an {@link AnnotatedType} from a {@link JvmType}. - *

    - * If the JvmType provides an AnnotatedType directly (for backward compatibility), - * it will be used. Otherwise, a new AnnotatedType is constructed from the - * raw type and annotations. - * - * @param jvmType the JvmType to convert - * @return an AnnotatedType representing the JvmType - */ - static AnnotatedType buildAnnotatedType(JvmType jvmType) { - try { - AnnotatedType existing = jvmType.getAnnotatedType(); - if (existing != null) { - return existing; - } - } catch (UnsupportedOperationException ignored) { - } - - Class rawType = jvmType.getRawType(); - List annotations = jvmType.getAnnotations(); - List typeVariables = jvmType.getTypeVariables(); - - final Type type; - if (typeVariables != null && !typeVariables.isEmpty()) { - Type[] typeArgs = typeVariables - .stream() - .map(tv -> buildAnnotatedType(tv).getType()) - .toArray(Type[]::new); - type = new ParameterizedType() { - @Override - public Type[] getActualTypeArguments() { - return typeArgs; - } - - @Override - public Type getRawType() { - return rawType; - } - - @Override - public @Nullable Type getOwnerType() { - return null; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(rawType.getName()); - if (typeArgs.length > 0) { - sb.append("<"); - for (int i = 0; i < typeArgs.length; i++) { - if (i > 0) { - sb.append(", "); - } - sb.append(typeArgs[i].getTypeName()); - } - sb.append(">"); - } - return sb.toString(); - } - }; - } else { - type = rawType; - } - - return new AnnotatedType() { - @Override - public Type getType() { - return type; - } - - @Override - @SuppressWarnings({"unchecked", "cast.unsafe"}) - public T getAnnotation(Class annotationClass) { - return (T)annotations - .stream() - .filter(a -> a.annotationType().equals(annotationClass)) - .findFirst() - .orElse(null); - } - - @Override - public Annotation[] getAnnotations() { - return annotations.toArray(new Annotation[0]); - } - - @Override - public Annotation[] getDeclaredAnnotations() { - return getAnnotations(); - } - }; - } } diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/AbstractTypeResolver.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/AbstractTypeResolver.java new file mode 100644 index 0000000000..17c269561d --- /dev/null +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/AbstractTypeResolver.java @@ -0,0 +1,101 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.resolver; + +import java.lang.reflect.Modifier; +import java.util.HashSet; +import java.util.List; +import java.util.Random; +import java.util.Set; +import java.util.function.Function; + +import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; +import org.jspecify.annotations.Nullable; + +import com.navercorp.fixturemonkey.api.property.CandidateConcretePropertyResolver; +import com.navercorp.fixturemonkey.api.property.Property; +import com.navercorp.fixturemonkey.property.JvmNodePropertyFactory; +import com.navercorp.objectfarm.api.node.SeedState; +import com.navercorp.objectfarm.api.type.JvmType; + +/** + * Walks the {@link CandidateConcretePropertyResolver} chain to resolve an interface or + * abstract type into a concrete type. + *

    + * The walk terminates when a concrete type is reached, a cycle is detected, the recursion + * depth limit is exceeded, or no resolver is configured for the current type. + */ +@API(since = "1.1.17", status = Status.EXPERIMENTAL) +public final class AbstractTypeResolver { + private final SeedState seedState; + + public AbstractTypeResolver(SeedState seedState) { + this.seedState = seedState; + } + + /** + * Walks the candidate-resolver chain until a concrete type is reached or the recursion depth runs out. + * Non-abstract input types are returned unchanged. + * + * @param type the type to resolve + * @param resolverLookup looks up the {@link CandidateConcretePropertyResolver} for a property, + * returning {@code null} when none is configured + * @param maxRecursionDepth maximum number of resolver hops before bailing out + */ + public JvmType resolve( + JvmType type, + Function resolverLookup, + int maxRecursionDepth + ) { + JvmType currentType = type; + Set> visited = new HashSet<>(); + + for (int depth = 0; depth < maxRecursionDepth; depth++) { + Class rawType = currentType.getRawType(); + + if (!visited.add(rawType)) { + return currentType; + } + + if (!Modifier.isInterface(rawType.getModifiers()) && !Modifier.isAbstract(rawType.getModifiers())) { + return currentType; + } + + Property property = JvmNodePropertyFactory.fromType(currentType); + CandidateConcretePropertyResolver resolver = resolverLookup.apply(property); + + if (resolver == null) { + return currentType; + } + + List candidates = resolver.resolve(property); + if (candidates == null || candidates.isEmpty()) { + return currentType; + } + + Random random = seedState.snapshot().randomFor(currentType.hashCode()); + Property selected = candidates.get(random.nextInt(candidates.size())); + + currentType = selected.getJvmType(); + } + + return currentType; + } +} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/ArbitraryResolver.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/ArbitraryResolver.java index c9402a43ab..dbd6493924 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/ArbitraryResolver.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/ArbitraryResolver.java @@ -21,7 +21,6 @@ import static com.navercorp.fixturemonkey.api.property.DefaultPropertyGenerator.FIELD_PROPERTY_GENERATOR; import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -33,22 +32,11 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.stream.Collectors; -import java.util.stream.Stream; import org.apiguardian.api.API; import org.apiguardian.api.API.Status; import org.jspecify.annotations.Nullable; -import com.navercorp.fixturemonkey.adapter.NodeTreeAdapter; -import com.navercorp.fixturemonkey.adapter.analysis.AdaptationResult; -import com.navercorp.fixturemonkey.adapter.analysis.AnalysisResult; -import com.navercorp.fixturemonkey.adapter.analysis.TypedValueExtractor; -import com.navercorp.fixturemonkey.adapter.converter.PredicatePathConverter; -import com.navercorp.fixturemonkey.adapter.projection.AssembleContext; -import com.navercorp.fixturemonkey.adapter.projection.ValueProjection; -import com.navercorp.fixturemonkey.adapter.tracing.AdapterTraceBuilder; -import com.navercorp.fixturemonkey.adapter.tracing.AdapterTracer; -import com.navercorp.fixturemonkey.adapter.tracing.TraceContext; import com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary; import com.navercorp.fixturemonkey.api.context.MonkeyContext; import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfo; @@ -64,17 +52,18 @@ import com.navercorp.fixturemonkey.api.property.TreeRootProperty; import com.navercorp.fixturemonkey.builder.ArbitraryBuilderContext; import com.navercorp.fixturemonkey.builder.ArbitraryBuilderContextProvider; -import com.navercorp.fixturemonkey.customizer.ApplyNodeCountManipulator; -import com.navercorp.fixturemonkey.customizer.ArbitraryManipulator; -import com.navercorp.fixturemonkey.customizer.ContainerInfoManipulator; import com.navercorp.fixturemonkey.customizer.ManipulatorSet; -import com.navercorp.fixturemonkey.customizer.MonkeyManipulatorFactory; -import com.navercorp.fixturemonkey.customizer.NodeManipulator; -import com.navercorp.fixturemonkey.customizer.NodeSetDecomposedValueManipulator; -import com.navercorp.fixturemonkey.customizer.NodeSetLazyManipulator; -import com.navercorp.fixturemonkey.tree.NextNodePredicate; -import com.navercorp.fixturemonkey.tree.ObjectNode; -import com.navercorp.fixturemonkey.tree.ObjectTree; +import com.navercorp.fixturemonkey.customizer.PathDirective; +import com.navercorp.fixturemonkey.customizer.SizeDirective; +import com.navercorp.fixturemonkey.planner.AnalysisResult; +import com.navercorp.fixturemonkey.planner.AssemblyPlan; +import com.navercorp.fixturemonkey.planner.AssemblyPlanner; +import com.navercorp.fixturemonkey.planner.TypedValueExtractor; +import com.navercorp.fixturemonkey.projection.AssembleContext; +import com.navercorp.fixturemonkey.projection.ValueProjection; +import com.navercorp.fixturemonkey.tracing.AssemblyTraceBuilder; +import com.navercorp.fixturemonkey.tracing.AssemblyTracer; +import com.navercorp.fixturemonkey.tracing.TraceContext; import com.navercorp.objectfarm.api.expression.PathExpression; import com.navercorp.objectfarm.api.type.JavaType; import com.navercorp.objectfarm.api.type.JvmType; @@ -83,645 +72,51 @@ @API(since = "0.4.0", status = Status.MAINTAINED) public final class ArbitraryResolver { - private final ManipulatorOptimizer manipulatorOptimizer; - private final MonkeyManipulatorFactory monkeyManipulatorFactory; private final MonkeyContext monkeyContext; - - private final @Nullable NodeTreeAdapter nodeTreeAdapter; - - private final AdapterTracer adapterTracer; + private final AssemblyPlanner assemblyPlanner; + private final AssemblyTracer tracer; private final Map, Set> inferredPropertiesCache; public ArbitraryResolver( - ManipulatorOptimizer manipulatorOptimizer, - MonkeyManipulatorFactory monkeyManipulatorFactory, - MonkeyContext monkeyContext - ) { - this(manipulatorOptimizer, monkeyManipulatorFactory, monkeyContext, null, AdapterTracer.noOp(), null); - } - - public ArbitraryResolver( - ManipulatorOptimizer manipulatorOptimizer, - MonkeyManipulatorFactory monkeyManipulatorFactory, - MonkeyContext monkeyContext, - @Nullable NodeTreeAdapter nodeTreeAdapter - ) { - this( - manipulatorOptimizer, - monkeyManipulatorFactory, - monkeyContext, - nodeTreeAdapter, - AdapterTracer.noOp(), - null - ); - } - - public ArbitraryResolver( - ManipulatorOptimizer manipulatorOptimizer, - MonkeyManipulatorFactory monkeyManipulatorFactory, - MonkeyContext monkeyContext, - @Nullable NodeTreeAdapter nodeTreeAdapter, - AdapterTracer adapterTracer - ) { - this(manipulatorOptimizer, monkeyManipulatorFactory, monkeyContext, nodeTreeAdapter, adapterTracer, null); - } - - public ArbitraryResolver( - ManipulatorOptimizer manipulatorOptimizer, - MonkeyManipulatorFactory monkeyManipulatorFactory, MonkeyContext monkeyContext, - @Nullable NodeTreeAdapter nodeTreeAdapter, - AdapterTracer adapterTracer, + AssemblyPlanner assemblyPlanner, + AssemblyTracer tracer, @Nullable Map, Set> inferredPropertiesCache ) { - this.manipulatorOptimizer = manipulatorOptimizer; - this.monkeyManipulatorFactory = monkeyManipulatorFactory; this.monkeyContext = monkeyContext; - this.nodeTreeAdapter = nodeTreeAdapter; - this.adapterTracer = adapterTracer; + this.assemblyPlanner = assemblyPlanner; + this.tracer = tracer; this.inferredPropertiesCache = inferredPropertiesCache != null ? inferredPropertiesCache : new ConcurrentHashMap<>(); } - @SuppressWarnings("unchecked") public CombinableArbitrary resolve( TreeRootProperty rootProperty, ArbitraryBuilderContext activeContext, List> standbyContexts ) { - FixtureMonkeyOptions fixtureMonkeyOptions = monkeyContext.getFixtureMonkeyOptions(); + FixtureMonkeyOptions options = monkeyContext.getFixtureMonkeyOptions(); + List activeDirectives = activeContext.getDirectives(); - // Early check for adapter path - skip ObjectTree creation entirely - if (nodeTreeAdapter != null) { - return resolveWithAdapter(rootProperty, activeContext, standbyContexts, fixtureMonkeyOptions); - } - - List activeManipulators = activeContext.getManipulators(); - - return new ResolvedCombinableArbitrary<>( + return new RootArbitrary<>( rootProperty, - () -> { - // TODO: Fragmented registered - Set inferredProperties = inferPossibleProperties(rootProperty, new CycleDetector()); - - Map, List> registeredPropertyConfigurer = monkeyContext - .getRegisteredArbitraryBuilders() - .stream() - .filter(it -> inferredProperties.stream().anyMatch(it::match)) - .map(it -> ((ArbitraryBuilderContextProvider)it.getOperator()).getActiveContext()) - .map(ArbitraryBuilderContext::getPropertyConfigurers) - .findFirst() // registered are stored in reverse order, so we take the first one - .orElse(Collections.emptyMap()); - - Map, ArbitraryIntrospector> registeredIntrospectors = monkeyContext - .getRegisteredArbitraryBuilders() - .stream() - .filter(it -> inferredProperties.stream().anyMatch(it::match)) - .map(it -> ((ArbitraryBuilderContextProvider)it.getOperator()).getActiveContext()) - .map(ArbitraryBuilderContext::getArbitraryIntrospectorsByType) - .findFirst() // registered are stored in reverse order, so we take the first one - .orElse(Collections.emptyMap()); - - ObjectTree objectTree = new ObjectTree( - rootProperty, - activeContext.newGenerateFixtureContext(registeredIntrospectors), - activeContext.newTraverseContext(rootProperty, registeredPropertyConfigurer) - ); - - fixtureMonkeyOptions - .getBuilderContextInitializers() - .stream() - .filter(it -> it.match(new DefaultTreeMatcherMetadata(objectTree.getMetadata().getAnnotations()))) - .findFirst() - .map(TreeMatcherOperator::getOperator) - .ifPresent(it -> activeContext.setOptionValidOnly(it.isValidOnly())); - - return objectTree; - }, - objectTree -> { - Map> rootNodesByProperty = Collections.singletonMap( - rootProperty, - Collections.singletonList(objectTree.getMetadata().getRootNode()) - ); - - List registeredRootManipulators = - monkeyManipulatorFactory.newRegisteredArbitraryManipulators(standbyContexts, rootNodesByProperty); - - List> registeredPropertyArbitraryBuilderContexts = - monkeyContext - .getRegisteredArbitraryBuilders() - .stream() - .map(it -> - new PriorityMatcherOperator<>( - it.getMatcher(), - ((ArbitraryBuilderContextProvider)it.getOperator()).getActiveContext(), - it.getPriority() - ) - ) - .collect(Collectors.toList()); - - List registeredPropertyManipulators = - monkeyManipulatorFactory.newRegisteredArbitraryManipulators( - registeredPropertyArbitraryBuilderContexts, - objectTree.getMetadata().getNodesByProperty() - ); - - List registeredManipulators = new ArrayList<>(); - registeredManipulators.addAll(registeredRootManipulators); - registeredManipulators.addAll(registeredPropertyManipulators); - - // Track the count of registered manipulators for filtering later - int registeredManipulatorCount = registeredManipulators.size(); - - List joinedManipulators = Stream.concat( - registeredManipulators.stream(), - activeManipulators.stream() - ).collect(Collectors.toList()); - - // Adapter integration point - analyze manipulators and build JvmNodeTree - if (nodeTreeAdapter != null) { - // Start measuring preparation time - long prepStartTime = System.nanoTime(); - - // Check if there's a root lazy manipulator in active manipulators - // If so, skip registered property container info because the lazy callback will set its own sizes - boolean hasRootLazyManipulator = activeManipulators - .stream() - .anyMatch(m -> { - NodeManipulator nm = m.getNodeManipulator(); - // Unwrap ApplyNodeCountManipulator if present - if (nm instanceof ApplyNodeCountManipulator) { - nm = ((ApplyNodeCountManipulator)nm).getNodeManipulator(); - } - if (nm instanceof NodeSetLazyManipulator) { - List predicates = PredicatePathConverter.extractPredicates( - m.getNodeResolver() - ); - String path = PredicatePathConverter.toExpression(predicates); - return "$".equals(path); - } - return false; - }); - - // Also check if registered root builders have root lazy manipulators - // If so, their container info should not override user's container info - boolean registeredHasRootLazy = standbyContexts - .stream() - .flatMap(ctx -> ctx.getOperator().getManipulators().stream()) - .anyMatch(m -> { - NodeManipulator nm = m.getNodeManipulator(); - if (nm instanceof ApplyNodeCountManipulator) { - nm = ((ApplyNodeCountManipulator)nm).getNodeManipulator(); - } - if (nm instanceof NodeSetLazyManipulator) { - List predicates = PredicatePathConverter.extractPredicates( - m.getNodeResolver() - ); - String path = PredicatePathConverter.toExpression(predicates); - return "$".equals(path); - } - return false; - }); - - // Get active container info first (needed for filtering) - List activeContainerInfoManipulatorsPreview = activeContext - .getContainerInfoManipulators() - .stream() - .filter(it -> it instanceof ContainerInfoManipulator) - .map(it -> (ContainerInfoManipulator)it) - .collect(Collectors.toList()); - - Set activePathsPreview = activeContainerInfoManipulatorsPreview - .stream() - .map(m -> PredicatePathConverter.toExpression(m.getNextNodePredicates())) - .collect(Collectors.toSet()); - - // 1. Registered root builders에서 ContainerInfoManipulator 수집 - List registeredRootContainerInfoManipulators = standbyContexts - .stream() - .map(PriorityMatcherOperator::getOperator) - .flatMap(ctx -> ctx.getContainerInfoManipulators().stream()) - .filter(it -> it instanceof ContainerInfoManipulator) - .map(it -> (ContainerInfoManipulator)it) - .collect(Collectors.toList()); - - // 2. Registered property builders에서 ContainerInfoManipulator 수집 - List registeredPropertyContainerInfoManipulators = - registeredPropertyArbitraryBuilderContexts - .stream() - .filter(it -> - objectTree.getMetadata().getNodesByProperty().keySet().stream().anyMatch(it::match) - ) - .map(PriorityMatcherOperator::getOperator) - .flatMap(ctx -> ctx.getContainerInfoManipulators().stream()) - .filter(it -> it instanceof ContainerInfoManipulator) - .map(it -> (ContainerInfoManipulator)it) - .collect(Collectors.toList()); - - // 3. Active context에서 ContainerInfoManipulator 수집 - List activeContainerInfoManipulators = activeContext - .getContainerInfoManipulators() - .stream() - .filter(it -> it instanceof ContainerInfoManipulator) - .map(it -> (ContainerInfoManipulator)it) - .collect(Collectors.toList()); - - // 4. 모든 ContainerInfoManipulator 병합 (registered -> active 순서) - // Active takes precedence: remove registered entries with same path as active - Set activePaths = activeContainerInfoManipulators - .stream() - .map(m -> PredicatePathConverter.toExpression(m.getNextNodePredicates())) - .collect(Collectors.toSet()); - - List filteredRegisteredRoot = registeredRootContainerInfoManipulators - .stream() - .filter(m -> - !activePaths.contains(PredicatePathConverter.toExpression(m.getNextNodePredicates())) - ) - .collect(Collectors.toList()); - - List filteredRegisteredProperty = - registeredPropertyContainerInfoManipulators - .stream() - .filter(m -> - !activePaths.contains(PredicatePathConverter.toExpression(m.getNextNodePredicates())) - ) - .collect(Collectors.toList()); - - List containerInfoManipulators = new ArrayList<>(); - containerInfoManipulators.addAll(activeContainerInfoManipulators); - containerInfoManipulators.addAll(filteredRegisteredRoot); - containerInfoManipulators.addAll(filteredRegisteredProperty); - - // Compute relevant types to filter register entries - // Only collect register operations for types that exist in the sample target's type tree - Set> relevantTypes = collectRelevantTypes(rootProperty); - - // 5. 타입 기반 컨테이너 크기 수집 (registered property builders에서) - // Skip paths that are already set by active container info manipulators - Map> typedContainerSizes = new HashMap<>(); - for (PriorityMatcherOperator< - ArbitraryBuilderContext - > registered : registeredPropertyArbitraryBuilderContexts) { - Matcher matcher = registered.getMatcher(); - - Class targetType = null; - if (matcher instanceof ExactTypeMatcher) { - targetType = ((ExactTypeMatcher)matcher).getType(); - } else if (matcher instanceof AssignableTypeMatcher) { - targetType = ((AssignableTypeMatcher)matcher).getAnchorType(); - } - - if (targetType == null || !isRelevantType(targetType, matcher, relevantTypes)) { - continue; - } - - JvmType jvmType = resolveJvmTypeForMatcher(targetType, matcher, relevantTypes); - - for (Object cim : registered.getOperator().getContainerInfoManipulators()) { - if (!(cim instanceof ContainerInfoManipulator)) { - continue; - } - ContainerInfoManipulator manipulator = (ContainerInfoManipulator)cim; - - // Extract field name from path (e.g., "$.values" -> "values") - String fieldPath = PredicatePathConverter.toExpression(manipulator.getNextNodePredicates()); - - // Skip if active context has a container info for this path - // Active takes precedence over registered - if (activePaths.contains(fieldPath)) { - continue; - } - - String fieldName = fieldPath.startsWith("$.") ? fieldPath.substring(2) : fieldPath; - - // Get container info (preserving min/max range) - ArbitraryContainerInfo containerInfo = manipulator.getContainerInfo(); - - // Merge with existing info if present (for minSize/maxSize called separately) - Map fieldSizes = typedContainerSizes.computeIfAbsent( - jvmType, - k -> new HashMap<>() - ); - ArbitraryContainerInfo existing = fieldSizes.get(fieldName); - if (existing != null) { - // Merge: take max of mins and min of maxes to find valid range - int mergedMin = Math.max( - existing.getElementMinSize(), - containerInfo.getElementMinSize() - ); - int mergedMax = Math.min( - existing.getElementMaxSize(), - containerInfo.getElementMaxSize() - ); - // Ensure valid range - if (mergedMin > mergedMax) { - mergedMax = mergedMin; - } - containerInfo = new ArbitraryContainerInfo(mergedMin, mergedMax); - } - fieldSizes.put(fieldName, containerInfo); - } - } - - // 6. 타입 기반 set 값 수집 (registered property builders에서) - // Sort by priority (lower number = higher priority) - List> sortedByPriority = new ArrayList<>( - registeredPropertyArbitraryBuilderContexts - ); - // Sort by descending priority (higher number = lower priority processed first). - // populateFromNodeManipulator uses put() (last-write-wins), so higher-priority - // registers (lower number) are processed last and override lower-priority ones. - sortedByPriority.sort( - Comparator.comparingInt( - PriorityMatcherOperator::getPriority - ).reversed() - ); - - Map> typedValues = new HashMap<>(); - for (PriorityMatcherOperator registered : sortedByPriority) { - Matcher matcher = registered.getMatcher(); - - Class targetType = null; - if (matcher instanceof ExactTypeMatcher) { - targetType = ((ExactTypeMatcher)matcher).getType(); - } else if (matcher instanceof AssignableTypeMatcher) { - targetType = ((AssignableTypeMatcher)matcher).getAnchorType(); - } - - if (targetType == null || !isRelevantType(targetType, matcher, relevantTypes)) { - continue; - } - - // Skip if this registered builder has a root lazy manipulator (from thenApply) - // and user has active container info - the lazy would produce wrong container sizes - boolean thisBuilderHasRootLazy = registered - .getOperator() - .getManipulators() - .stream() - .anyMatch(m -> { - NodeManipulator nm = m.getNodeManipulator(); - if (nm instanceof ApplyNodeCountManipulator) { - nm = ((ApplyNodeCountManipulator)nm).getNodeManipulator(); - } - if (nm instanceof NodeSetLazyManipulator) { - List predicates = PredicatePathConverter.extractPredicates( - m.getNodeResolver() - ); - String path = PredicatePathConverter.toExpression(predicates); - return "$".equals(path); - } - return false; - }); - - if (thisBuilderHasRootLazy && !activePathsPreview.isEmpty()) { - // Skip typed values from this builder - user's container sizes should win - continue; - } - - JvmType jvmType = resolveJvmTypeForMatcher(targetType, matcher, relevantTypes); - List manips = registered.getOperator().getManipulators(); - for (ArbitraryManipulator manipulator : manips) { - // Extract values from set() calls - // Higher priority (lower number) wins - don't overwrite existing values - TypedValueExtractor.extract(manipulator, jvmType, typedValues); - } - } - - // Filter out root decomposed value manipulators from REGISTERED builders only - // when: - // 1. Active has a root lazy manipulator (thenApply) - the lazy will produce correct result - // 2. OR active has container info for paths - registered decomposed value may have wrong sizes - // We do NOT filter active manipulators because thenApply creates decomposed values - // that already respect the active container sizes. - List filteredJoinedManipulators = joinedManipulators; - boolean shouldFilterRegisteredDecomposed = hasRootLazyManipulator || !activePaths.isEmpty(); - if (shouldFilterRegisteredDecomposed) { - final int regCount = registeredManipulatorCount; - filteredJoinedManipulators = new ArrayList<>(); - for (int i = 0; i < joinedManipulators.size(); i++) { - ArbitraryManipulator manipulator = joinedManipulators.get(i); - boolean isFromRegistered = i < regCount; - - NodeManipulator nm = manipulator.getNodeManipulator(); - // Unwrap ApplyNodeCountManipulator if present - if (nm instanceof ApplyNodeCountManipulator) { - nm = ((ApplyNodeCountManipulator)nm).getNodeManipulator(); - } - - if (nm instanceof NodeSetDecomposedValueManipulator && isFromRegistered) { - List predicates = PredicatePathConverter.extractPredicates( - manipulator.getNodeResolver() - ); - String path = PredicatePathConverter.toExpression(predicates); - // Skip root decomposed value from registered if: - // - Active has root lazy manipulator (will produce correct result) - // - OR active has container info changes (decomposed value has wrong sizes) - if ("$".equals(path)) { - continue; - } - } - filteredJoinedManipulators.add(manipulator); - } - } - - // Collect registered property configurers (from registered builders) - Map, List> registeredPropertyConfigurers = - registeredPropertyArbitraryBuilderContexts - .stream() - .filter(it -> - objectTree.getMetadata().getNodesByProperty().keySet().stream().anyMatch(it::match) - ) - .map(PriorityMatcherOperator::getOperator) - .map(ArbitraryBuilderContext::getPropertyConfigurers) - .findFirst() - .orElse(Collections.emptyMap()); - - // Merge property configurers: active context takes precedence - Map, List> mergedPropertyConfigurers = new HashMap<>( - registeredPropertyConfigurers - ); - mergedPropertyConfigurers.putAll(activeContext.getPropertyConfigurers()); - - // Collect registered introspectors (from registered builders) - Map, ArbitraryIntrospector> registeredIntrospectors = - registeredPropertyArbitraryBuilderContexts - .stream() - .filter(it -> - objectTree.getMetadata().getNodesByProperty().keySet().stream().anyMatch(it::match) - ) - .map(PriorityMatcherOperator::getOperator) - .map(ArbitraryBuilderContext::getArbitraryIntrospectorsByType) - .findFirst() - .orElse(Collections.emptyMap()); - - // Merge introspectors: active context takes precedence - Map, ArbitraryIntrospector> mergedIntrospectors = new HashMap<>(registeredIntrospectors); - mergedIntrospectors.putAll(activeContext.getArbitraryIntrospectorsByType()); - - ManipulatorSet manipulatorSet = new ManipulatorSet( - filteredJoinedManipulators, - containerInfoManipulators, - typedContainerSizes, - typedValues, - mergedPropertyConfigurers, - mergedIntrospectors, - activeContext.isFixed() - ); - JvmType rootJvmType = toJvmType(rootProperty); - - // Calculate preparation time - long prepTimeNanos = System.nanoTime() - prepStartTime; - - // Create trace context early to capture resolution events - TraceContext traceContext = adapterTracer.createTraceContext(); - - // Measure total adapter time - long adapterStartTime = System.nanoTime(); - - AdaptationResult adaptationResult = nodeTreeAdapter.adapt( - rootJvmType, - manipulatorSet, - fixtureMonkeyOptions, - traceContext - ); - - AnalysisResult analysisResult = adaptationResult.getAnalysisResult(); - - // Get immutable ValueProjection from adaptation result - // Lazy values are now evaluated and decomposed in ManipulatorAnalyzer, - // following the same flow as other values (no special handling needed here) - ValueProjection values = adaptationResult.getValues(); - - // Strict mode validation: check for paths that don't exist in the type structure - if (analysisResult.isStrictMode()) { - Set invalidPaths = values.getUnresolvedNonWildcardPaths(); - if (!invalidPaths.isEmpty()) { - throw new IllegalArgumentException( - "No matching results for given NodeResolvers. " + "Invalid paths: " + invalidPaths - ); - } - } - - // Assemble using ValueProjection - // Path resolution follows "more specific path wins" rule. - // Only justPaths (from Values.just()) are treated as truly immutable. - traceContext.setRootType(rootJvmType.getRawType().getName()); - - Set userContainerSizePaths = activePaths - .stream() - .map(PathExpression::of) - .collect(Collectors.toSet()); - - // Convert typedValues to TypeSelector-based PathExpression entries - TypedValueExtractor.ConversionResult typedPathConversion = - TypedValueExtractor.convertToPathExpressions(typedValues); - - AssembleContext assembleContext = AssembleContext.builder(monkeyContext) - .rootProperty(rootProperty) - .justPaths(new HashSet<>(analysisResult.getJustPaths())) - .notNullPaths(analysisResult.getNotNullPaths()) - .filtersByPath(analysisResult.getFiltersByPath()) - .limitsByPath(new HashMap<>(analysisResult.getLimitsByPath())) - .valueOrderByPath(analysisResult.getValueOrderByPath()) - .customizersByPath(analysisResult.getCustomizersByPath()) - .typedPathValues(typedPathConversion.values) - .typedPathOrders(typedPathConversion.orders) - .introspectorsByType(mergedIntrospectors) - .traceContext(traceContext) - .nodeTreeAdapter((NodeTreeAdapter)fixtureMonkeyOptions.getNodeTreeAdapter()) - .userContainerSizePaths(userContainerSizePaths) - .build(); - - // Measure assembly time - long assemblyStartTime = System.nanoTime(); - CombinableArbitrary result = (CombinableArbitrary)values.assemble(assembleContext); - long assemblyTimeNanos = System.nanoTime() - assemblyStartTime; - - // Calculate total adapter time - long totalAdapterTimeNanos = System.nanoTime() - adapterStartTime; - - // Build and invoke trace with collected data - AdapterTraceBuilder.buildAndInvoke( - traceContext, - filteredJoinedManipulators, - containerInfoManipulators, - analysisResult, - adaptationResult, - prepTimeNanos, - assemblyTimeNanos, - totalAdapterTimeNanos, - typedValues, - typedContainerSizes, - relevantTypes, - activeContext.isFixed(), - adapterTracer - ); - - return result; - } - - List optimizedManipulator = manipulatorOptimizer - .optimize(joinedManipulators) - .getManipulators(); - - for (ArbitraryManipulator manipulator : optimizedManipulator) { - manipulator.manipulate(objectTree); - } - return (CombinableArbitrary)objectTree.generate(); - }, - fixtureMonkeyOptions.getGenerateMaxTries(), - fixtureMonkeyOptions.getDefaultArbitraryValidator(), - activeContext::isValidOnly - ); - } - - /** - * Optimized adapter resolution path that skips ObjectTree creation entirely. - * This is called when nodeTreeAdapter is enabled. - */ - @SuppressWarnings("unchecked") - private CombinableArbitrary resolveWithAdapter( - TreeRootProperty rootProperty, - ArbitraryBuilderContext activeContext, - List> standbyContexts, - FixtureMonkeyOptions fixtureMonkeyOptions - ) { - List activeManipulators = activeContext.getManipulators(); - - // Use AdapterCombinableArbitrary which doesn't require ObjectTree - return new AdapterCombinableArbitrary<>( - rootProperty, - () -> - generateWithAdapter( - rootProperty, - activeContext, - activeManipulators, - standbyContexts, - fixtureMonkeyOptions - ), - fixtureMonkeyOptions.getGenerateMaxTries(), - fixtureMonkeyOptions.getDefaultArbitraryValidator(), + () -> generate(rootProperty, activeContext, activeDirectives, standbyContexts, options), + options.getGenerateMaxTries(), + options.getDefaultArbitraryValidator(), activeContext::isValidOnly, () -> { - } // onRetry - adapter path doesn't need special retry logic + } ); } - /** - * Generate a CombinableArbitrary using the adapter path without ObjectTree. - * This is the core adapter logic extracted from the original resolve method. - */ - @SuppressWarnings("unchecked") - private CombinableArbitrary generateWithAdapter( + private CombinableArbitrary generate( TreeRootProperty rootProperty, ArbitraryBuilderContext activeContext, - List activeManipulators, + List activeDirectives, List> standbyContexts, - FixtureMonkeyOptions fixtureMonkeyOptions + FixtureMonkeyOptions options ) { - // Start measuring preparation time - long prepStartTime = System.nanoTime(); + long prepStart = System.nanoTime(); boolean hasRegisteredBuilders = !monkeyContext.getRegisteredArbitraryBuilders().isEmpty(); boolean hasStandbyContexts = !standbyContexts.isEmpty(); @@ -730,45 +125,44 @@ private CombinableArbitrary generateWithAdapter( // skip all register-related preparation (inferPossibleProperties, collectRelevantTypes, // typed values/container sizes collection, registered property configurers/introspectors) if (!hasRegisteredBuilders && !hasStandbyContexts) { - return generateWithAdapterFastPath( + return generateFastPath( rootProperty, activeContext, - activeManipulators, - fixtureMonkeyOptions, - prepStartTime + activeDirectives, + options, + prepStart ); } - return generateWithAdapterFullPath( + return generateFullPath( rootProperty, activeContext, - activeManipulators, + activeDirectives, standbyContexts, - fixtureMonkeyOptions, - prepStartTime + options, + prepStart ); } /** - * Fast path for adapter generation when no registered builders or standby contexts exist. + * Fast path when no registered builders or standby contexts exist. * Skips all register-related preparation for significantly better performance. */ - @SuppressWarnings("unchecked") - private CombinableArbitrary generateWithAdapterFastPath( + private CombinableArbitrary generateFastPath( TreeRootProperty rootProperty, ArbitraryBuilderContext activeContext, - List activeManipulators, - FixtureMonkeyOptions fixtureMonkeyOptions, - long prepStartTime + List activeDirectives, + FixtureMonkeyOptions options, + long prepStart ) { // Set validOnly from inferred property annotations (only if builderContextInitializers exist) - if (!fixtureMonkeyOptions.getBuilderContextInitializers().isEmpty()) { + if (!options.getBuilderContextInitializers().isEmpty()) { Set inferredProperties = inferPossibleProperties(rootProperty, new CycleDetector()); Set allAnnotations = inferredProperties .stream() .flatMap(p -> p.getAnnotations().stream()) .collect(Collectors.toSet()); - fixtureMonkeyOptions + options .getBuilderContextInitializers() .stream() .filter(it -> it.match(new DefaultTreeMatcherMetadata(allAnnotations))) @@ -778,72 +172,64 @@ private CombinableArbitrary generateWithAdapterFastPath( } // Active context container info only (no registered builders to merge) - List containerInfoManipulators = activeContext - .getContainerInfoManipulators() - .stream() - .filter(it -> it instanceof ContainerInfoManipulator) - .map(it -> (ContainerInfoManipulator)it) - .collect(Collectors.toList()); + List sizeDirectives = new ArrayList<>(activeContext.getSizeDirectives()); - Set activePaths = containerInfoManipulators + Set activePaths = sizeDirectives .stream() - .map(m -> PredicatePathConverter.toExpression(m.getNextNodePredicates())) + .map(m -> m.path().toExpression()) .collect(Collectors.toSet()); Map, ArbitraryIntrospector> introspectorsByType = activeContext.getArbitraryIntrospectorsByType(); ManipulatorSet manipulatorSet = new ManipulatorSet( - new ArrayList<>(activeManipulators), - containerInfoManipulators, + new ArrayList<>(activeDirectives), Collections.emptyMap(), Collections.emptyMap(), activeContext.getPropertyConfigurers(), introspectorsByType, activeContext.isFixed() ); - JvmType rootJvmType = toJvmType(rootProperty); + JvmType rootJvmType = rootProperty.getJvmType(); - long prepTimeNanos = System.nanoTime() - prepStartTime; + long prepNanos = System.nanoTime() - prepStart; return assembleAdapterResult( rootProperty, activeContext, - activeManipulators, - fixtureMonkeyOptions, + activeDirectives, + options, manipulatorSet, rootJvmType, - containerInfoManipulators, + sizeDirectives, activePaths, Collections.emptyMap(), Collections.emptyMap(), Collections.emptySet(), introspectorsByType, - prepTimeNanos + prepNanos ); } /** * Full path for adapter generation with registered builders and standby contexts. */ - @SuppressWarnings("unchecked") - private CombinableArbitrary generateWithAdapterFullPath( + private CombinableArbitrary generateFullPath( TreeRootProperty rootProperty, ArbitraryBuilderContext activeContext, - List activeManipulators, + List activeDirectives, List> standbyContexts, - FixtureMonkeyOptions fixtureMonkeyOptions, - long prepStartTime + FixtureMonkeyOptions options, + long prepStart ) { - // Infer possible properties for type-based matching (without ObjectTree) + // Infer possible properties for type-based matching Set inferredProperties = inferPossibleProperties(rootProperty, new CycleDetector()); - // Set validOnly from all inferred property annotations (matching non-adapter path behavior - // where MetadataCollector.collect() gathers annotations from the entire tree) + // Set validOnly from all inferred property annotations (gathered from the entire tree) Set allAnnotations = inferredProperties .stream() .flatMap(p -> p.getAnnotations().stream()) .collect(Collectors.toSet()); - fixtureMonkeyOptions + options .getBuilderContextInitializers() .stream() .filter(it -> it.match(new DefaultTreeMatcherMetadata(allAnnotations))) @@ -852,7 +238,7 @@ private CombinableArbitrary generateWithAdapterFullPath( .ifPresent(it -> activeContext.setOptionValidOnly(it.isValidOnly())); // Get registered property builders for type-based matching - List> registeredPropertyArbitraryBuilderContexts = + List> registeredPropertyContexts = monkeyContext .getRegisteredArbitraryBuilders() .stream() @@ -865,63 +251,53 @@ private CombinableArbitrary generateWithAdapterFullPath( ) .collect(Collectors.toList()); - // 1. Registered root builders에서 ContainerInfoManipulator 수집 - List registeredRootContainerInfoManipulators = standbyContexts + // 1. Collect SizeDirectives from registered root builders + List standbySizeDirectives = standbyContexts .stream() .map(PriorityMatcherOperator::getOperator) - .flatMap(ctx -> ctx.getContainerInfoManipulators().stream()) - .filter(it -> it instanceof ContainerInfoManipulator) - .map(it -> (ContainerInfoManipulator)it) + .flatMap(ctx -> ctx.getSizeDirectives().stream()) .collect(Collectors.toList()); - // 2. Registered property builders에서 ContainerInfoManipulator 수집 - // Use inferred properties for matching instead of objectTree.getNodesByProperty() - List registeredPropertyContainerInfoManipulators = - registeredPropertyArbitraryBuilderContexts - .stream() - .filter(it -> inferredProperties.stream().anyMatch(it::match)) - .map(PriorityMatcherOperator::getOperator) - .flatMap(ctx -> ctx.getContainerInfoManipulators().stream()) - .filter(it -> it instanceof ContainerInfoManipulator) - .map(it -> (ContainerInfoManipulator)it) - .collect(Collectors.toList()); - - // 3. Active context에서 ContainerInfoManipulator 수집 - List activeContainerInfoManipulators = activeContext - .getContainerInfoManipulators() + // 2. Collect SizeDirectives from registered property builders + // Use inferred properties for matching + List registeredPropertySizeDirectives = registeredPropertyContexts .stream() - .filter(it -> it instanceof ContainerInfoManipulator) - .map(it -> (ContainerInfoManipulator)it) + .filter(it -> inferredProperties.stream().anyMatch(it::match)) + .map(PriorityMatcherOperator::getOperator) + .flatMap(ctx -> ctx.getSizeDirectives().stream()) .collect(Collectors.toList()); - // 4. 모든 ContainerInfoManipulator 병합 (registered -> active 순서) - Set activePaths = activeContainerInfoManipulators + // 3. Collect SizeDirectives from the active context + List activeSizeDirectives = new ArrayList<>(activeContext.getSizeDirectives()); + + // 4. Merge all SizeDirectives (active overrides registered when paths overlap) + Set activePaths = activeSizeDirectives .stream() - .map(m -> PredicatePathConverter.toExpression(m.getNextNodePredicates())) + .map(m -> m.path().toExpression()) .collect(Collectors.toSet()); - List filteredRegisteredRoot = registeredRootContainerInfoManipulators + List nonOverlappingStandbyDirectives = standbySizeDirectives .stream() - .filter(m -> !activePaths.contains(PredicatePathConverter.toExpression(m.getNextNodePredicates()))) + .filter(m -> !activePaths.contains(m.path().toExpression())) .collect(Collectors.toList()); - List filteredRegisteredProperty = registeredPropertyContainerInfoManipulators + List nonOverlappingPropertyDirectives = registeredPropertySizeDirectives .stream() - .filter(m -> !activePaths.contains(PredicatePathConverter.toExpression(m.getNextNodePredicates()))) + .filter(m -> !activePaths.contains(m.path().toExpression())) .collect(Collectors.toList()); - List containerInfoManipulators = new ArrayList<>(); - containerInfoManipulators.addAll(activeContainerInfoManipulators); - containerInfoManipulators.addAll(filteredRegisteredRoot); - containerInfoManipulators.addAll(filteredRegisteredProperty); + List mergedSizeDirectives = new ArrayList<>(); + mergedSizeDirectives.addAll(activeSizeDirectives); + mergedSizeDirectives.addAll(nonOverlappingStandbyDirectives); + mergedSizeDirectives.addAll(nonOverlappingPropertyDirectives); // Compute relevant types to filter register entries // Only collect register operations for types that exist in the sample target's type tree Set> relevantTypes = collectRelevantTypes(rootProperty); - // 5. 타입 기반 컨테이너 크기 수집 + // 5. Collect type-based container sizes Map> typedContainerSizes = new HashMap<>(); - for (PriorityMatcherOperator registered : registeredPropertyArbitraryBuilderContexts) { + for (PriorityMatcherOperator registered : registeredPropertyContexts) { Matcher matcher = registered.getMatcher(); Class targetType = null; @@ -937,13 +313,8 @@ private CombinableArbitrary generateWithAdapterFullPath( JvmType jvmType = resolveJvmTypeForMatcher(targetType, matcher, relevantTypes); - for (Object cim : registered.getOperator().getContainerInfoManipulators()) { - if (!(cim instanceof ContainerInfoManipulator)) { - continue; - } - ContainerInfoManipulator manipulator = (ContainerInfoManipulator)cim; - - String fieldPath = PredicatePathConverter.toExpression(manipulator.getNextNodePredicates()); + for (SizeDirective directive : registered.getOperator().getSizeDirectives()) { + String fieldPath = directive.path().toExpression(); // Note: activePaths check is NOT applied here because typedContainerSizes // are type-scoped (keyed by JvmType). A registered builder for ListStringObject @@ -953,7 +324,7 @@ private CombinableArbitrary generateWithAdapterFullPath( // over type-based resolution (TYPE_BASED) in JvmNodeTreeTransformer. String fieldName = fieldPath.startsWith("$.") ? fieldPath.substring(2) : fieldPath; - ArbitraryContainerInfo containerInfo = manipulator.getContainerInfo(); + ArbitraryContainerInfo containerInfo = directive.containerInfo(); Map fieldSizes = typedContainerSizes.computeIfAbsent(jvmType, k -> new HashMap<>() @@ -971,9 +342,9 @@ private CombinableArbitrary generateWithAdapterFullPath( } } - // 6. 타입 기반 set 값 수집 + // 6. Collect type-based set values List> sortedByPriority = new ArrayList<>( - registeredPropertyArbitraryBuilderContexts + registeredPropertyContexts ); // Sort by descending priority (higher number = lower priority processed first). // populateFromNodeManipulator uses put() (last-write-wins), so higher-priority @@ -1000,18 +371,17 @@ private CombinableArbitrary generateWithAdapterFullPath( // For AssignableTypeMatcher, use the actual relevant subtype as the JvmType key // so that typed values are matched against the concrete type in the tree JvmType jvmType = resolveJvmTypeForMatcher(targetType, matcher, relevantTypes); - List manips = registered.getOperator().getManipulators(); - for (ArbitraryManipulator manipulator : manips) { - TypedValueExtractor.extract(manipulator, jvmType, typedValues); + List directives = registered.getOperator().getDirectives(); + for (PathDirective directive : directives) { + TypedValueExtractor.extract(directive, jvmType, typedValues); } } - // Adapter path: only use activeManipulators (registered manipulators are skipped + // Only use activeDirectives (registered manipulators are skipped // because ManipulatorAnalyzer already handles type-based matching via typedValues) - List filteredJoinedManipulators = new ArrayList<>(activeManipulators); // Collect registered property configurers using inferredProperties - Map, List> registeredPropertyConfigurers = registeredPropertyArbitraryBuilderContexts + Map, List> registeredPropertyConfigurers = registeredPropertyContexts .stream() .filter(it -> inferredProperties.stream().anyMatch(it::match)) .map(PriorityMatcherOperator::getOperator) @@ -1023,7 +393,7 @@ private CombinableArbitrary generateWithAdapterFullPath( mergedPropertyConfigurers.putAll(activeContext.getPropertyConfigurers()); // Collect registered introspectors using inferredProperties - Map, ArbitraryIntrospector> registeredIntrospectors = registeredPropertyArbitraryBuilderContexts + Map, ArbitraryIntrospector> registeredIntrospectors = registeredPropertyContexts .stream() .filter(it -> inferredProperties.stream().anyMatch(it::match)) .map(PriorityMatcherOperator::getOperator) @@ -1034,33 +404,34 @@ private CombinableArbitrary generateWithAdapterFullPath( Map, ArbitraryIntrospector> mergedIntrospectors = new HashMap<>(registeredIntrospectors); mergedIntrospectors.putAll(activeContext.getArbitraryIntrospectorsByType()); + List joinedDirectives = new ArrayList<>(activeDirectives); + joinedDirectives.addAll(mergedSizeDirectives); ManipulatorSet manipulatorSet = new ManipulatorSet( - filteredJoinedManipulators, - containerInfoManipulators, + joinedDirectives, typedContainerSizes, typedValues, mergedPropertyConfigurers, mergedIntrospectors, activeContext.isFixed() ); - JvmType rootJvmType = toJvmType(rootProperty); + JvmType rootJvmType = rootProperty.getJvmType(); - long prepTimeNanos = System.nanoTime() - prepStartTime; + long prepNanos = System.nanoTime() - prepStart; return assembleAdapterResult( rootProperty, activeContext, - filteredJoinedManipulators, - fixtureMonkeyOptions, + activeDirectives, + options, manipulatorSet, rootJvmType, - containerInfoManipulators, + mergedSizeDirectives, activePaths, typedValues, typedContainerSizes, relevantTypes, mergedIntrospectors, - prepTimeNanos + prepNanos ); } @@ -1071,33 +442,33 @@ private CombinableArbitrary generateWithAdapterFullPath( private CombinableArbitrary assembleAdapterResult( TreeRootProperty rootProperty, ArbitraryBuilderContext activeContext, - List manipulators, - FixtureMonkeyOptions fixtureMonkeyOptions, + List directives, + FixtureMonkeyOptions options, ManipulatorSet manipulatorSet, JvmType rootJvmType, - List containerInfoManipulators, + List sizeDirectives, Set activePaths, Map> typedValues, Map> typedContainerSizes, Set> relevantTypes, Map, ArbitraryIntrospector> mergedIntrospectors, - long prepTimeNanos + long prepNanos ) { // Create trace context early to capture resolution events - TraceContext traceContext = adapterTracer.createTraceContext(); + TraceContext traceContext = tracer.createTraceContext(); // Measure total adapter time long adapterStartTime = System.nanoTime(); - AdaptationResult adaptationResult = nodeTreeAdapter.adapt( + AssemblyPlan assemblyPlan = assemblyPlanner.plan( rootJvmType, manipulatorSet, - fixtureMonkeyOptions, + options, traceContext ); - AnalysisResult analysisResult = adaptationResult.getAnalysisResult(); - ValueProjection values = adaptationResult.getValues(); + AnalysisResult analysisResult = assemblyPlan.getAnalysisResult(); + ValueProjection values = assemblyPlan.getValues(); // Strict mode validation if (analysisResult.isStrictMode()) { @@ -1134,7 +505,9 @@ private CombinableArbitrary assembleAdapterResult( .typedPathOrders(typedPathConversion.orders) .introspectorsByType(mergedIntrospectors) .traceContext(traceContext) - .nodeTreeAdapter((NodeTreeAdapter)fixtureMonkeyOptions.getNodeTreeAdapter()) + .runtimeTreeFactory(this.assemblyPlanner) + .pathResolverContext(assemblyPlan.getResolverContext()) + .nodeMetadataCache(this.assemblyPlanner.nodeMetadataCache()) .userContainerSizePaths(userContainerSizePaths) .build(); @@ -1147,27 +520,27 @@ private CombinableArbitrary assembleAdapterResult( long totalAdapterTimeNanos = System.nanoTime() - adapterStartTime; // Build and invoke trace with collected data - AdapterTraceBuilder.buildAndInvoke( + AssemblyTraceBuilder.buildAndInvoke( traceContext, - manipulators, - containerInfoManipulators, + directives, + sizeDirectives, analysisResult, - adaptationResult, - prepTimeNanos, + assemblyPlan, + prepNanos, assemblyTimeNanos, totalAdapterTimeNanos, typedValues, typedContainerSizes, relevantTypes, activeContext.isFixed(), - adapterTracer + tracer ); return result; } private Set inferPossibleProperties(Property property, CycleDetector cycleDetector) { - Class actualType = Types.getActualType(property.getType()); + Class actualType = property.getJvmType().getRawType(); // Check cache for root-level calls (cache key is the actual type) Set cached = inferredPropertiesCache.get(actualType); @@ -1183,13 +556,13 @@ private Set inferPossibleProperties(Property property, CycleDetector c private Set doInferPossibleProperties(Property property, CycleDetector cycleDetector) { Set collectedProperties = new HashSet<>(); - Class actualType = Types.getActualType(property.getType()); + Class actualType = property.getJvmType().getRawType(); if (Types.isJavaType(actualType)) { collectedProperties.add(property); return collectedProperties; } - if (nodeTreeAdapter != null && nodeTreeAdapter.isLeafType(actualType)) { + if (assemblyPlanner.isLeafType(actualType)) { collectedProperties.add(property); return collectedProperties; } @@ -1224,32 +597,28 @@ private void collectRelevantTypesFromProperty( Set> types, Set> visitedForFields ) { - AnnotatedType annotatedType = property.getAnnotatedType(); - Class rawType = Types.getActualType(annotatedType.getType()); + JvmType jvmType = property.getJvmType(); + Class rawType = jvmType.getRawType(); types.add(rawType); // Always recurse into type arguments (e.g., List → StringValue) - if (annotatedType instanceof java.lang.reflect.AnnotatedParameterizedType) { - for (AnnotatedType typeArg : ( - (java.lang.reflect.AnnotatedParameterizedType)annotatedType - ).getAnnotatedActualTypeArguments()) { - Class argType = Types.getActualType(typeArg.getType()); - if (!visitedForFields.contains(argType)) { - collectRelevantTypesFromProperty( - new com.navercorp.fixturemonkey.api.property.TypeParameterProperty(typeArg), - types, - visitedForFields - ); - } else { - types.add(argType); - } + for (JvmType typeArg : jvmType.getTypeVariables()) { + Class argType = typeArg.getRawType(); + if (!visitedForFields.contains(argType)) { + collectRelevantTypesFromProperty( + new com.navercorp.fixturemonkey.api.property.TypeParameterProperty(typeArg), + types, + visitedForFields + ); + } else { + types.add(argType); } } // Recurse into fields of non-Java types to discover nested types if ( !Types.isJavaType(rawType) - && !(nodeTreeAdapter != null && nodeTreeAdapter.isLeafType(rawType)) + && !assemblyPlanner.isLeafType(rawType) && visitedForFields.add(rawType) ) { for (Property child : FIELD_PROPERTY_GENERATOR.generateChildProperties(property)) { @@ -1293,13 +662,6 @@ private JvmType resolveJvmTypeForMatcher(Class targetType, Matcher matcher, S return new JavaType(targetType); } - /** - * Converts a Property to a JvmType. - */ - private JvmType toJvmType(Property property) { - return new JavaType(Types.toTypeReference(property.getAnnotatedType())); - } - private static final class CycleDetector { private final Set properties; diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/DefaultArbitraryBuilderCandidate.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/DefaultArbitraryBuilderCandidate.java index 9814aeb5b0..0a254094c4 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/DefaultArbitraryBuilderCandidate.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/DefaultArbitraryBuilderCandidate.java @@ -26,7 +26,6 @@ import com.navercorp.fixturemonkey.ArbitraryBuilder; import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.type.TypeReference; -import com.navercorp.fixturemonkey.api.type.Types; import com.navercorp.fixturemonkey.buildergroup.ArbitraryBuilderCandidate; class DefaultArbitraryBuilderCandidate implements ArbitraryBuilderCandidate { @@ -55,9 +54,7 @@ public static Builder of(TypeReference typeReference) { @Override public Class getClassType() { - return Types.getActualType( - requireNonNull(this.typeReference).getAnnotatedType() - ); + return requireNonNull(this.typeReference).getJvmType().getRawType(); } @Override diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/ManipulatorOptimizer.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/ManipulatorOptimizer.java index 0b05896aa3..1de16498a0 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/ManipulatorOptimizer.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/ManipulatorOptimizer.java @@ -23,10 +23,10 @@ import org.apiguardian.api.API; import org.apiguardian.api.API.Status; -import com.navercorp.fixturemonkey.customizer.ArbitraryManipulator; +import com.navercorp.fixturemonkey.customizer.PathDirective; @API(since = "0.4.0", status = Status.MAINTAINED) @FunctionalInterface public interface ManipulatorOptimizer { - OptimizedManipulatorResult optimize(List manipulators); + OptimizedManipulatorResult optimize(List manipulators); } diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/NoneManipulatorOptimizer.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/NoneManipulatorOptimizer.java index e6c5159b19..70755cfad2 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/NoneManipulatorOptimizer.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/NoneManipulatorOptimizer.java @@ -23,13 +23,13 @@ import org.apiguardian.api.API; import org.apiguardian.api.API.Status; -import com.navercorp.fixturemonkey.customizer.ArbitraryManipulator; +import com.navercorp.fixturemonkey.customizer.PathDirective; @API(since = "0.4.0", status = Status.MAINTAINED) public final class NoneManipulatorOptimizer implements ManipulatorOptimizer { @Override - public OptimizedManipulatorResult optimize(List manipulators) { + public OptimizedManipulatorResult optimize(List manipulators) { return new OptimizedManipulatorResult(manipulators); } } diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/OptimizedManipulatorResult.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/OptimizedManipulatorResult.java index f466bf424b..236e02b555 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/OptimizedManipulatorResult.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/OptimizedManipulatorResult.java @@ -23,17 +23,17 @@ import org.apiguardian.api.API; import org.apiguardian.api.API.Status; -import com.navercorp.fixturemonkey.customizer.ArbitraryManipulator; +import com.navercorp.fixturemonkey.customizer.PathDirective; @API(since = "0.4.0", status = Status.MAINTAINED) public final class OptimizedManipulatorResult { - private final List manipulators; + private final List directives; - public OptimizedManipulatorResult(List manipulators) { - this.manipulators = manipulators; + public OptimizedManipulatorResult(List directives) { + this.directives = directives; } - public List getManipulators() { - return manipulators; + public List getDirectives() { + return directives; } } diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/ResolvedCombinableArbitrary.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/ResolvedCombinableArbitrary.java deleted file mode 100644 index a9ba92c3d2..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/ResolvedCombinableArbitrary.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.resolver; - -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.function.Supplier; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; -import org.jspecify.annotations.Nullable; - -import com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary; -import com.navercorp.fixturemonkey.api.exception.ContainerSizeFilterMissException; -import com.navercorp.fixturemonkey.api.exception.FixedValueFilterMissException; -import com.navercorp.fixturemonkey.api.exception.RetryableFilterMissException; -import com.navercorp.fixturemonkey.api.lazy.LazyArbitrary; -import com.navercorp.fixturemonkey.api.property.TreeRootProperty; -import com.navercorp.fixturemonkey.api.validator.ArbitraryValidator; -import com.navercorp.fixturemonkey.tree.ObjectTree; - -@API(since = "0.6.9", status = Status.MAINTAINED) -final class ResolvedCombinableArbitrary implements CombinableArbitrary { - private static final int VALIDATION_ANNOTATION_FILTERING_COUNT = 1; - - private final TreeRootProperty rootProperty; - private final LazyArbitrary objectTree; - private final int generateMaxTries; - private final LazyArbitrary> arbitrary; - private final ArbitraryValidator validator; - private final Supplier validOnly; - - private @Nullable Exception lastException = null; - - public ResolvedCombinableArbitrary( - TreeRootProperty rootProperty, - Supplier regenerateTree, - Function> generateArbitrary, - int generateMaxTries, - ArbitraryValidator validator, - Supplier validOnly - ) { - this.rootProperty = rootProperty; - this.objectTree = LazyArbitrary.lazy(regenerateTree); - this.generateMaxTries = generateMaxTries; - this.arbitrary = LazyArbitrary.lazy( - () -> { - ObjectTree objectTree = this.objectTree.getValue(); - return generateArbitrary.apply(objectTree); - } - ); - this.validator = validator; - this.validOnly = validOnly; - } - - @Override - public T combined() { - for (int i = 0; i < generateMaxTries; i++) { - try { - return arbitrary.getValue() - .filter(VALIDATION_ANNOTATION_FILTERING_COUNT, this.validateFilter(validOnly.get())) - .combined(); - } catch (ContainerSizeFilterMissException | RetryableFilterMissException ex) { - lastException = ex; - objectTree.clear(); - } catch (FixedValueFilterMissException ex) { - lastException = ex; - } finally { - arbitrary.clear(); - } - } - - throw new IllegalArgumentException( - String.format( - "Given type %s could not be generated." - + " Check the ArbitraryIntrospector used or the APIs used in the ArbitraryBuilder.", - rootProperty.getType() - ), - lastException - ); - } - - @Override - public Object rawValue() { - for (int i = 0; i < generateMaxTries; i++) { - try { - return arbitrary.getValue() - .filter(VALIDATION_ANNOTATION_FILTERING_COUNT, this.validateFilter(validOnly.get())) - .rawValue(); - } catch (ContainerSizeFilterMissException | RetryableFilterMissException ex) { - lastException = ex; - objectTree.clear(); - } catch (FixedValueFilterMissException ex) { - lastException = ex; - } finally { - arbitrary.clear(); - } - } - - throw new IllegalArgumentException( - String.format( - "Given type %s could not be generated." - + " Check the ArbitraryIntrospector used or the APIs used in the ArbitraryBuilder.", - rootProperty.getType() - ), - lastException - ); - } - - @Override - public void clear() { - - } - - @Override - public CombinableArbitrary unique() { - return arbitrary.getValue().unique(); - } - - @Override - public boolean fixed() { - return false; - } - - private Predicate validateFilter(boolean validOnly) { - return fixture -> { - if (!validOnly) { - return true; - } - - if (fixture == null) { - return true; - } - - this.validator.validate(fixture); - return true; - }; - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/AdapterCombinableArbitrary.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/RootArbitrary.java similarity index 96% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/AdapterCombinableArbitrary.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/RootArbitrary.java index cb8d4b02eb..c0a1df79a8 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/AdapterCombinableArbitrary.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/resolver/RootArbitrary.java @@ -38,7 +38,7 @@ * This is an optimization to skip unnecessary ObjectTree creation when using the adapter. */ @API(since = "1.1.0", status = Status.EXPERIMENTAL) -final class AdapterCombinableArbitrary implements CombinableArbitrary { +final class RootArbitrary implements CombinableArbitrary { private static final int VALIDATION_ANNOTATION_FILTERING_COUNT = 1; private final TreeRootProperty rootProperty; @@ -50,7 +50,7 @@ final class AdapterCombinableArbitrary implements CombinableArbitrary { private @Nullable Exception lastException = null; - public AdapterCombinableArbitrary( + public RootArbitrary( TreeRootProperty rootProperty, Supplier> generateArbitrary, int generateMaxTries, @@ -87,7 +87,7 @@ public T combined() { String.format( "Given type %s could not be generated." + " Check the ArbitraryIntrospector used or the APIs used in the ArbitraryBuilder.", - rootProperty.getType() + rootProperty.getJvmType().getRawType() ), lastException ); @@ -114,7 +114,7 @@ public Object rawValue() { String.format( "Given type %s could not be generated." + " Check the ArbitraryIntrospector used or the APIs used in the ArbitraryBuilder.", - rootProperty.getType() + rootProperty.getJvmType().getRawType() ), lastException ); diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/ActiveTraceContext.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/ActiveTraceContext.java similarity index 99% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/ActiveTraceContext.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/ActiveTraceContext.java index eac6363a79..6fd38f16d6 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/ActiveTraceContext.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/ActiveTraceContext.java @@ -1,4 +1,4 @@ -package com.navercorp.fixturemonkey.adapter.tracing; +package com.navercorp.fixturemonkey.tracing; import java.util.ArrayList; import java.util.EnumMap; @@ -95,7 +95,7 @@ public void recordManipulator( @Nullable Map decomposed, String source ) { - builder.addManipulator(path, type, sequence, value, decomposed, source); + builder.addDirective(path, type, sequence, value, decomposed, source); // Also record for override tracking manipulatorsByPath .computeIfAbsent(path, k -> new ArrayList<>()) @@ -324,7 +324,7 @@ public void recordManipulator( int decomposedMatchedCount, @Nullable String decomposedSourceType ) { - builder.addManipulator( + builder.addDirective( path, type, sequence, diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/AdapterTraceBuilder.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/AssemblyTraceBuilder.java similarity index 72% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/AdapterTraceBuilder.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/AssemblyTraceBuilder.java index 0b2e4f4cb0..df72afb57f 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/AdapterTraceBuilder.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/AssemblyTraceBuilder.java @@ -16,31 +16,27 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter.tracing; +package com.navercorp.fixturemonkey.tracing; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; import org.jspecify.annotations.Nullable; -import com.navercorp.fixturemonkey.adapter.analysis.AdaptationResult; -import com.navercorp.fixturemonkey.adapter.analysis.AnalysisResult; -import com.navercorp.fixturemonkey.adapter.analysis.ManipulatorAnalyzer; -import com.navercorp.fixturemonkey.adapter.converter.PredicatePathConverter; -import com.navercorp.fixturemonkey.adapter.projection.LazyValueHolder; -import com.navercorp.fixturemonkey.adapter.projection.ValueProjection; import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfo; -import com.navercorp.fixturemonkey.customizer.ApplyNodeCountManipulator; -import com.navercorp.fixturemonkey.customizer.ArbitraryManipulator; -import com.navercorp.fixturemonkey.customizer.ContainerInfoManipulator; -import com.navercorp.fixturemonkey.customizer.NodeManipulator; -import com.navercorp.fixturemonkey.customizer.NodeSetDecomposedValueManipulator; -import com.navercorp.fixturemonkey.customizer.NodeSetJustManipulator; -import com.navercorp.fixturemonkey.tree.NextNodePredicate; +import com.navercorp.fixturemonkey.customizer.JustDirective; +import com.navercorp.fixturemonkey.customizer.PathDirective; +import com.navercorp.fixturemonkey.customizer.SetDirective; +import com.navercorp.fixturemonkey.customizer.SizeDirective; +import com.navercorp.fixturemonkey.planner.AnalysisResult; +import com.navercorp.fixturemonkey.planner.AssemblyPlan; +import com.navercorp.fixturemonkey.projection.LazyValueHolder; +import com.navercorp.fixturemonkey.projection.ValueProjection; import com.navercorp.objectfarm.api.expression.PathExpression; import com.navercorp.objectfarm.api.node.JvmNode; import com.navercorp.objectfarm.api.tree.JvmNodeTree; @@ -49,8 +45,9 @@ /** * Builds the resolution trace from collected data and invokes the tracer. */ -public final class AdapterTraceBuilder { - private AdapterTraceBuilder() { +@API(since = "1.1.20", status = Status.EXPERIMENTAL) +public final class AssemblyTraceBuilder { + private AssemblyTraceBuilder() { } /** @@ -62,10 +59,10 @@ private AdapterTraceBuilder() { */ public static void buildAndInvoke( TraceContext traceContext, - List manipulators, - List containerInfoManipulators, + List manipulators, + List sizeDirectives, AnalysisResult analysisResult, - AdaptationResult adaptationResult, + AssemblyPlan adaptationResult, long prepTimeNanos, long assemblyTimeNanos, long totalAdapterTimeNanos, @@ -73,7 +70,7 @@ public static void buildAndInvoke( Map> typedContainerSizes, Set> relevantTypes, boolean isFixed, - AdapterTracer adapterTracer + AssemblyTracer adapterTracer ) { if (!traceContext.isEnabled()) { return; @@ -123,32 +120,17 @@ public static void buildAndInvoke( } } - for (ArbitraryManipulator manipulator : manipulators) { - List predicates = PredicatePathConverter.extractPredicates( - manipulator.getNodeResolver() - ); - String path = PredicatePathConverter.toExpression(predicates); - - boolean isRegistered = ManipulatorAnalyzer.hasStaticNodeResolver(manipulator.getNodeResolver()); + for (PathDirective directive : manipulators) { + String path = directive.path().toExpression(); + boolean isRegistered = directive.registered(); String source = isRegistered ? "REGISTERED_BUILDER" : "DIRECT"; - NodeManipulator nm = manipulator.getNodeManipulator(); - if (nm instanceof ApplyNodeCountManipulator) { - nm = ((ApplyNodeCountManipulator)nm).getNodeManipulator(); - } - - String type = nm.getClass().getSimpleName().replace("Node", "").replace("Manipulator", ""); - Object value = null; - - if (nm instanceof NodeSetJustManipulator) { - value = ((NodeSetJustManipulator)nm).getValue(); - } else if (nm instanceof NodeSetDecomposedValueManipulator) { - value = ((NodeSetDecomposedValueManipulator)nm).getValue(); - } + String type = directive.getClass().getSimpleName().replace("Directive", ""); - if (nm instanceof NodeSetDecomposedValueManipulator) { - Object decomposedValue = ((NodeSetDecomposedValueManipulator)nm).getValue(); - String sourceType = decomposedValue != null ? decomposedValue.getClass().getSimpleName() : null; + if (directive instanceof SetDirective) { + SetDirective setDirective = (SetDirective)directive; + Object value = setDirective.value(); + String sourceType = value != null ? value.getClass().getSimpleName() : null; String pathPrefix = path + "."; int totalDecomposed = 0; @@ -168,7 +150,7 @@ public static void buildAndInvoke( traceContext.recordManipulator( path, - type, + "SetDecomposedValue", sequence++, value, null, @@ -177,43 +159,27 @@ public static void buildAndInvoke( matched, sourceType ); + } else if (directive instanceof JustDirective) { + traceContext.recordManipulator( + path, + "SetJust", + sequence++, + ((JustDirective)directive).value(), + null, + source + ); } else { - traceContext.recordManipulator(path, type, sequence++, value, null, source); + traceContext.recordManipulator(path, type, sequence++, null, null, source); } } - for (ContainerInfoManipulator cim : containerInfoManipulators) { - String path = PredicatePathConverter.toExpression(cim.getNextNodePredicates()); - ArbitraryContainerInfo info = cim.getContainerInfo(); + for (SizeDirective directive : sizeDirectives) { + String path = directive.path().toExpression(); + ArbitraryContainerInfo info = directive.containerInfo(); String sizeInfo = "size=" + info.getElementMinSize() + "-" + info.getElementMaxSize(); traceContext.recordManipulator(path, "ContainerInfo", sequence++, sizeInfo, null, "DIRECT"); } - for (AnalysisResult.LazyManipulatorDescriptor lazyDescriptor : analysisResult.getLazyManipulators()) { - Map decomposed = new HashMap<>(); - for (Map.Entry entry : analysisResult.getValuesByPath().entrySet()) { - PathExpression valuePath = entry.getKey(); - Integer valueOrder = analysisResult.getValueOrderByPath().get(valuePath); - if ( - valueOrder != null - && valueOrder > lazyDescriptor.getOrder() - && valuePath.startsWith(lazyDescriptor.getPathExpression()) - ) { - decomposed.put(valuePath.toExpression(), entry.getValue()); - } - } - if (!decomposed.isEmpty()) { - traceContext.recordManipulator( - lazyDescriptor.getPathExpression().toExpression(), - "Lazy", - sequence++, - "evaluated", - decomposed, - "LAZY_EVALUATED" - ); - } - } - Map valuesByPath = analysisResult.getValuesByPath(); Map valueOrderByPath = analysisResult.getValueOrderByPath(); traceContext.recordValues(valuesByPath, valueOrderByPath); diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/AdapterTracer.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/AssemblyTracer.java similarity index 93% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/AdapterTracer.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/AssemblyTracer.java index 036727e5b8..585df9479d 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/AdapterTracer.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/AssemblyTracer.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter.tracing; +package com.navercorp.fixturemonkey.tracing; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -30,7 +30,7 @@ import org.apiguardian.api.API; import org.apiguardian.api.API.Status; -import com.navercorp.fixturemonkey.adapter.tracing.ResolutionTrace.Timing; +import com.navercorp.fixturemonkey.tracing.ResolutionTrace.Timing; /** * Interface for tracing the resolution process in Fixture Monkey adapter. @@ -40,9 +40,9 @@ * * @see ResolutionTrace */ -@API(since = "1.1.17", status = Status.EXPERIMENTAL) +@API(since = "1.1.17", status = Status.MAINTAINED) @FunctionalInterface -public interface AdapterTracer { +public interface AssemblyTracer { /** * Called when resolution is complete with the collected trace data. * @@ -69,18 +69,18 @@ default TraceContext createTraceContext() { * * @return a tracer that ignores all trace data */ - static AdapterTracer noOp() { - return NoOpAdapterTracer.INSTANCE; + static AssemblyTracer noOp() { + return NoOpAssemblyTracer.INSTANCE; } /** * Singleton NoOp implementation that returns NoOp TraceContext. */ - final class NoOpAdapterTracer implements AdapterTracer { + final class NoOpAssemblyTracer implements AssemblyTracer { - static final NoOpAdapterTracer INSTANCE = new NoOpAdapterTracer(); + static final NoOpAssemblyTracer INSTANCE = new NoOpAssemblyTracer(); - private NoOpAdapterTracer() { + private NoOpAssemblyTracer() { } @Override @@ -99,7 +99,7 @@ public TraceContext createTraceContext() { * * @return a tracer that outputs to System.out */ - static AdapterTracer console() { + static AssemblyTracer console() { return trace -> System.out.println(trace.toTreeFormat()); } @@ -108,7 +108,7 @@ static AdapterTracer console() { * * @return a tracer that outputs JSON to System.out */ - static AdapterTracer consoleJson() { + static AssemblyTracer consoleJson() { return trace -> System.out.println(trace.toJsonFormat()); } @@ -118,7 +118,7 @@ static AdapterTracer consoleJson() { * * @return a tracer that outputs timing data to System.out */ - static AdapterTracer timing() { + static AssemblyTracer timing() { return trace -> { Timing timing = trace.getTiming(); if (timing != null) { @@ -144,7 +144,7 @@ static AdapterTracer timing() { * @param path the file path to write trace output to * @return a tracer that appends trace data to the specified file */ - static AdapterTracer file(Path path) { + static AssemblyTracer file(Path path) { return trace -> { try { Files.write( @@ -154,7 +154,7 @@ static AdapterTracer file(Path path) { StandardOpenOption.APPEND ); } catch (IOException e) { - System.err.println("[AdapterTracer] Failed to write to " + path + ": " + e.getMessage()); + System.err.println("[AssemblyTracer] Failed to write to " + path + ": " + e.getMessage()); } }; } @@ -182,7 +182,7 @@ static SummaryTracer summary() { * */ @API(status = Status.EXPERIMENTAL) - class SummaryTracer implements AdapterTracer { + class SummaryTracer implements AssemblyTracer { private final List traces = new ArrayList<>(); @@ -228,12 +228,12 @@ public void printSummary() { for (int i = 0; i < traces.size(); i++) { ResolutionTrace trace = traces.get(i); - int manipulators = trace.getManipulators().size(); + int directives = trace.getDirectives().size(); int values = trace.getValuesByPath().size(); int merged = trace.getMergedCandidates().size(); int unresolved = trace.getUnresolvedPaths().size(); - totalManipulators += manipulators; + totalManipulators += directives; totalValues += values; totalMerged += merged; totalUnresolved += unresolved; @@ -249,7 +249,7 @@ public void printSummary() { rowFormat, i + 1, trace.getRootType() != null ? trace.getRootType() : "?", - manipulators, + directives, values, merged, unresolved, diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/NoOpTraceContext.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/NoOpTraceContext.java similarity index 98% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/NoOpTraceContext.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/NoOpTraceContext.java index 59305133d7..1bf06f1d98 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/NoOpTraceContext.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/NoOpTraceContext.java @@ -1,4 +1,4 @@ -package com.navercorp.fixturemonkey.adapter.tracing; +package com.navercorp.fixturemonkey.tracing; import java.util.List; import java.util.Map; diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/ResolutionTrace.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/ResolutionTrace.java similarity index 95% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/ResolutionTrace.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/ResolutionTrace.java index 6be43018f6..76243a2aca 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/ResolutionTrace.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/ResolutionTrace.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter.tracing; +package com.navercorp.fixturemonkey.tracing; import java.util.ArrayList; import java.util.Collections; @@ -42,12 +42,12 @@ *
  • Assembly steps - how values were assembled into the final object
  • * * - * @see AdapterTracer + * @see AssemblyTracer */ @API(since = "1.1.17", status = Status.EXPERIMENTAL) public final class ResolutionTrace { private final String rootType; - private final List manipulators; + private final List directives; private final Map valuesByPath; private final Map valueOrderByPath; private final List nodeCollisions; @@ -74,7 +74,7 @@ public final class ResolutionTrace { private ResolutionTrace( String rootType, - List manipulators, + List directives, Map valuesByPath, Map valueOrderByPath, List nodeCollisions, @@ -94,7 +94,7 @@ private ResolutionTrace( List subtreeCacheEvents ) { this.rootType = rootType; - this.manipulators = Collections.unmodifiableList(new ArrayList<>(manipulators)); + this.directives = Collections.unmodifiableList(new ArrayList<>(directives)); this.valuesByPath = Collections.unmodifiableMap(new LinkedHashMap<>(valuesByPath)); this.valueOrderByPath = Collections.unmodifiableMap(new LinkedHashMap<>(valueOrderByPath)); this.nodeCollisions = Collections.unmodifiableList(new ArrayList<>(nodeCollisions)); @@ -118,8 +118,8 @@ public String getRootType() { return rootType; } - public List getManipulators() { - return manipulators; + public List getDirectives() { + return directives; } public Map getValuesByPath() { @@ -219,7 +219,7 @@ public static Builder builder() { return new Builder(); } - public static final class ManipulatorEntry { + public static final class DirectiveEntry { private final String path; private final String type; @@ -237,15 +237,15 @@ public static final class ManipulatorEntry { private final @Nullable String decomposedSourceType; - public ManipulatorEntry(String path, String type) { + public DirectiveEntry(String path, String type) { this(path, type, -1, null, null, null); } - public ManipulatorEntry(String path, String type, @Nullable Object value) { + public DirectiveEntry(String path, String type, @Nullable Object value) { this(path, type, -1, value, null, null); } - public ManipulatorEntry( + public DirectiveEntry( String path, String type, @Nullable Object value, @@ -254,7 +254,7 @@ public ManipulatorEntry( this(path, type, -1, value, decomposed, null); } - public ManipulatorEntry( + public DirectiveEntry( String path, String type, int sequence, @@ -264,7 +264,7 @@ public ManipulatorEntry( this(path, type, sequence, value, decomposed, null); } - public ManipulatorEntry( + public DirectiveEntry( String path, String type, int sequence, @@ -275,7 +275,7 @@ public ManipulatorEntry( this(path, type, sequence, value, decomposed, source, -1, -1, null); } - public ManipulatorEntry( + public DirectiveEntry( String path, String type, int sequence, @@ -604,7 +604,7 @@ public int getPathMatchCount() { public static final class Builder { private String rootType = "Unknown"; - private final List manipulators = new ArrayList<>(); + private final List directives = new ArrayList<>(); private final Map valuesByPath = new LinkedHashMap<>(); private final Map valueOrderByPath = new LinkedHashMap<>(); private final List nodeCollisions = new ArrayList<>(); @@ -644,39 +644,39 @@ public Builder rootType(String rootType) { return this; } - public Builder addManipulator(ManipulatorEntry entry) { - this.manipulators.add(entry); + public Builder addDirective(DirectiveEntry entry) { + this.directives.add(entry); return this; } - public Builder addManipulator(String path, String type) { - return addManipulator(new ManipulatorEntry(path, type)); + public Builder addDirective(String path, String type) { + return addDirective(new DirectiveEntry(path, type)); } - public Builder addManipulator(String path, String type, @Nullable Object value) { - return addManipulator(new ManipulatorEntry(path, type, value)); + public Builder addDirective(String path, String type, @Nullable Object value) { + return addDirective(new DirectiveEntry(path, type, value)); } - public Builder addManipulator( + public Builder addDirective( String path, String type, @Nullable Object value, @Nullable Map decomposed ) { - return addManipulator(new ManipulatorEntry(path, type, value, decomposed)); + return addDirective(new DirectiveEntry(path, type, value, decomposed)); } - public Builder addManipulator( + public Builder addDirective( String path, String type, int sequence, @Nullable Object value, @Nullable Map decomposed ) { - return addManipulator(new ManipulatorEntry(path, type, sequence, value, decomposed)); + return addDirective(new DirectiveEntry(path, type, sequence, value, decomposed)); } - public Builder addManipulator( + public Builder addDirective( String path, String type, int sequence, @@ -684,10 +684,10 @@ public Builder addManipulator( @Nullable Map decomposed, @Nullable String source ) { - return addManipulator(new ManipulatorEntry(path, type, sequence, value, decomposed, source)); + return addDirective(new DirectiveEntry(path, type, sequence, value, decomposed, source)); } - public Builder addManipulator( + public Builder addDirective( String path, String type, int sequence, @@ -698,8 +698,8 @@ public Builder addManipulator( int decomposedMatchedCount, @Nullable String decomposedSourceType ) { - return addManipulator( - new ManipulatorEntry( + return addDirective( + new DirectiveEntry( path, type, sequence, @@ -953,7 +953,7 @@ public ResolutionTrace build() { : null; return new ResolutionTrace( rootType, - manipulators, + directives, valuesByPath, valueOrderByPath, nodeCollisions, diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/ResolutionTraceFormatter.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/ResolutionTraceFormatter.java similarity index 94% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/ResolutionTraceFormatter.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/ResolutionTraceFormatter.java index bf541b7ea4..5f2eac2e34 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/ResolutionTraceFormatter.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/ResolutionTraceFormatter.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter.tracing; +package com.navercorp.fixturemonkey.tracing; import java.util.ArrayList; import java.util.Collections; @@ -28,23 +28,23 @@ import org.jspecify.annotations.Nullable; -import com.navercorp.fixturemonkey.adapter.tracing.ResolutionTrace.AssemblyEntry; -import com.navercorp.fixturemonkey.adapter.tracing.ResolutionTrace.BuilderContextEntry; -import com.navercorp.fixturemonkey.adapter.tracing.ResolutionTrace.CacheStatusEntry; -import com.navercorp.fixturemonkey.adapter.tracing.ResolutionTrace.ContainerSizeEntry; -import com.navercorp.fixturemonkey.adapter.tracing.ResolutionTrace.InterfaceResolutionEntry; -import com.navercorp.fixturemonkey.adapter.tracing.ResolutionTrace.JustPathEntry; -import com.navercorp.fixturemonkey.adapter.tracing.ResolutionTrace.ManipulatorEntry; -import com.navercorp.fixturemonkey.adapter.tracing.ResolutionTrace.ManipulatorOverrideEntry; -import com.navercorp.fixturemonkey.adapter.tracing.ResolutionTrace.ManipulatorRecord; -import com.navercorp.fixturemonkey.adapter.tracing.ResolutionTrace.MergedCandidateEntry; -import com.navercorp.fixturemonkey.adapter.tracing.ResolutionTrace.NodeCollision; -import com.navercorp.fixturemonkey.adapter.tracing.ResolutionTrace.OverriddenSize; -import com.navercorp.fixturemonkey.adapter.tracing.ResolutionTrace.PropertyDiscoveryEntry; -import com.navercorp.fixturemonkey.adapter.tracing.ResolutionTrace.RegisteredBuilderEntry; -import com.navercorp.fixturemonkey.adapter.tracing.ResolutionTrace.SubtreeCacheEntry; -import com.navercorp.fixturemonkey.adapter.tracing.ResolutionTrace.Timing; -import com.navercorp.fixturemonkey.adapter.tracing.ResolutionTrace.UnresolvedPathEntry; +import com.navercorp.fixturemonkey.tracing.ResolutionTrace.AssemblyEntry; +import com.navercorp.fixturemonkey.tracing.ResolutionTrace.BuilderContextEntry; +import com.navercorp.fixturemonkey.tracing.ResolutionTrace.CacheStatusEntry; +import com.navercorp.fixturemonkey.tracing.ResolutionTrace.ContainerSizeEntry; +import com.navercorp.fixturemonkey.tracing.ResolutionTrace.DirectiveEntry; +import com.navercorp.fixturemonkey.tracing.ResolutionTrace.InterfaceResolutionEntry; +import com.navercorp.fixturemonkey.tracing.ResolutionTrace.JustPathEntry; +import com.navercorp.fixturemonkey.tracing.ResolutionTrace.ManipulatorOverrideEntry; +import com.navercorp.fixturemonkey.tracing.ResolutionTrace.ManipulatorRecord; +import com.navercorp.fixturemonkey.tracing.ResolutionTrace.MergedCandidateEntry; +import com.navercorp.fixturemonkey.tracing.ResolutionTrace.NodeCollision; +import com.navercorp.fixturemonkey.tracing.ResolutionTrace.OverriddenSize; +import com.navercorp.fixturemonkey.tracing.ResolutionTrace.PropertyDiscoveryEntry; +import com.navercorp.fixturemonkey.tracing.ResolutionTrace.RegisteredBuilderEntry; +import com.navercorp.fixturemonkey.tracing.ResolutionTrace.SubtreeCacheEntry; +import com.navercorp.fixturemonkey.tracing.ResolutionTrace.Timing; +import com.navercorp.fixturemonkey.tracing.ResolutionTrace.UnresolvedPathEntry; import com.navercorp.objectfarm.api.expression.NameSelector; import com.navercorp.objectfarm.api.expression.PathExpression; import com.navercorp.objectfarm.api.expression.Segment; @@ -74,7 +74,7 @@ static String toTreeFormat(ResolutionTrace trace) { sb.append(" Fixture Monkey Resolution Trace\n"); sb.append(separator).append("\n\n"); - List manipulators = trace.getManipulators(); + List manipulators = trace.getDirectives(); Map valuesByPath = trace.getValuesByPath(); Map valueOrderByPath = trace.getValueOrderByPath(); List nodeCollisions = trace.getNodeCollisions(); @@ -102,10 +102,10 @@ static String toTreeFormat(ResolutionTrace trace) { } // 2. Analysis section - int analysisPathWidth = maxLength(manipulators, ManipulatorEntry::path) + 2; + int analysisPathWidth = maxLength(manipulators, DirectiveEntry::path) + 2; sb.append("\u25b8 Analysis (").append(manipulators.size()).append(" manipulators)\n"); for (int i = 0; i < manipulators.size(); i++) { - ManipulatorEntry manipulatorEntry = manipulators.get(i); + DirectiveEntry manipulatorEntry = manipulators.get(i); boolean isLast = (i == manipulators.size() - 1); String prefix = isLast ? " \u2514\u2500 " : " \u251c\u2500 "; sb.append(prefix) @@ -506,7 +506,7 @@ static String toJsonFormat(ResolutionTrace trace) { StringBuilder sb = new StringBuilder(); sb.append("{\n"); - List manipulators = trace.getManipulators(); + List manipulators = trace.getDirectives(); Map valuesByPath = trace.getValuesByPath(); Map valueOrderByPath = trace.getValueOrderByPath(); List nodeCollisions = trace.getNodeCollisions(); @@ -519,7 +519,7 @@ static String toJsonFormat(ResolutionTrace trace) { sb.append(" \"analysis\": {\n"); sb.append(" \"manipulators\": [\n"); for (int i = 0; i < manipulators.size(); i++) { - ManipulatorEntry manipulatorEntry = manipulators.get(i); + DirectiveEntry manipulatorEntry = manipulators.get(i); sb .append(" {\"path\": \"") .append(escapeJson(manipulatorEntry.path())) diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/TimingSample.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/TimingSample.java similarity index 94% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/TimingSample.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/TimingSample.java index 6a2c10a13b..94bb258c4e 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/TimingSample.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/TimingSample.java @@ -1,4 +1,4 @@ -package com.navercorp.fixturemonkey.adapter.tracing; +package com.navercorp.fixturemonkey.tracing; import org.apiguardian.api.API; import org.apiguardian.api.API.Status; diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/TraceContext.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/TraceContext.java similarity index 99% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/TraceContext.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/TraceContext.java index 4416eab33d..17168dcd77 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/TraceContext.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/TraceContext.java @@ -1,4 +1,4 @@ -package com.navercorp.fixturemonkey.adapter.tracing; +package com.navercorp.fixturemonkey.tracing; import java.util.List; import java.util.Map; @@ -21,7 +21,7 @@ *
  • Micrometer Timer - {@link TimingSample} for timing measurements
  • * * - * @see AdapterTracer + * @see AssemblyTracer * @see TimingSample */ @API(since = "1.1.17", status = Status.EXPERIMENTAL) diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/TraceContextResolutionListener.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/TraceContextResolutionListener.java similarity index 98% rename from fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/TraceContextResolutionListener.java rename to fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/TraceContextResolutionListener.java index 64f08c1e95..afbeb5f08e 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/adapter/tracing/TraceContextResolutionListener.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tracing/TraceContextResolutionListener.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter.tracing; +package com.navercorp.fixturemonkey.tracing; import org.apiguardian.api.API; import org.apiguardian.api.API.Status; diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/ApplyStrictModeResolver.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/ApplyStrictModeResolver.java deleted file mode 100644 index 1d96916240..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/ApplyStrictModeResolver.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tree; - -import java.util.List; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -/** - * A {@link NodeResolver} that applies strict mode. - */ -@API(since = "0.4.0", status = Status.MAINTAINED) -public final class ApplyStrictModeResolver implements NodeResolver { - private final NodeResolver nodeResolver; - - public ApplyStrictModeResolver(NodeResolver nodeResolver) { - this.nodeResolver = nodeResolver; - } - - @Override - public List resolve(ObjectNode nextNode) { - List selectedNodes = nodeResolver.resolve(nextNode); - - if (selectedNodes.isEmpty()) { - throw new IllegalArgumentException("No matching results for given NodeResolvers."); - } - return selectedNodes; - } - - /** - * Returns the wrapped NodeResolver. - * - * @return the inner NodeResolver - */ - public NodeResolver getNodeResolver() { - return nodeResolver; - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/CompositeNodeResolver.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/CompositeNodeResolver.java deleted file mode 100644 index a54a9b2fb1..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/CompositeNodeResolver.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tree; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Objects; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; -import org.jspecify.annotations.Nullable; - -@API(since = "0.4.0", status = Status.MAINTAINED) -public final class CompositeNodeResolver implements NodeResolver { - private final List nodeResolvers; - - public CompositeNodeResolver(NodeResolver... nodeResolvers) { - this(Arrays.asList(nodeResolvers)); - } - - public CompositeNodeResolver(List nodeResolvers) { - this.nodeResolvers = distinct(nodeResolvers); - } - - @Override - public List resolve(ObjectNode nextNode) { - LinkedList nextNodes = new LinkedList<>(); - nextNodes.add(nextNode); - for (NodeResolver nodeResolver : nodeResolvers) { - List resolvedNodes = new LinkedList<>(); - while (!nextNodes.isEmpty()) { - ObjectNode currentNode = nextNodes.pop(); - resolvedNodes.addAll(nodeResolver.resolve(currentNode)); - } - nextNodes.addAll(resolvedNodes); - } - return nextNodes; - } - - public List getNodeResolvers() { - return nodeResolvers; - } - - public List flatten() { - List flatten = new ArrayList<>(); - - for (NodeResolver nodeResolver : nodeResolvers) { - if (nodeResolver instanceof CompositeNodeResolver) { - flatten.addAll(((CompositeNodeResolver)nodeResolver).nodeResolvers); - } else { - flatten.add(nodeResolver); - } - } - - return flatten; - } - - private List distinct(List resolvers) { - if (resolvers.isEmpty()) { - return Collections.emptyList(); - } - - int length = resolvers.size(); - List result = new ArrayList<>(); - result.add(resolvers.get(0)); - - for (int i = 1; i < length; i++) { - NodeResolver resolver = resolvers.get(i); - if (resolver instanceof CompositeNodeResolver) { - CompositeNodeResolver compositeNodeResolver = (CompositeNodeResolver)resolver; - List componentNodeResolvers = compositeNodeResolver.flatten(); - - result.add(new CompositeNodeResolver(componentNodeResolvers)); - } else { - result.add(resolver); - } - } - return result; - } - - @Override - public boolean equals(@Nullable Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - CompositeNodeResolver that = (CompositeNodeResolver)obj; - return nodeResolvers.equals(that.nodeResolvers); - } - - @Override - public int hashCode() { - return Objects.hash(nodeResolvers); - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/ContainerElementPredicate.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/ContainerElementPredicate.java deleted file mode 100644 index 78837947de..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/ContainerElementPredicate.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tree; - -import static com.navercorp.fixturemonkey.Constants.NO_OR_ALL_INDEX_INTEGER_VALUE; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import com.navercorp.fixturemonkey.api.generator.ObjectProperty; -import com.navercorp.fixturemonkey.api.property.ContainerElementProperty; -import com.navercorp.fixturemonkey.api.property.Property; - -@API(since = "0.4.0", status = Status.MAINTAINED) -public final class ContainerElementPredicate implements NextNodePredicate { - - private final int sequence; - - public ContainerElementPredicate(int sequence) { - this.sequence = sequence; - } - - public int getSequence() { - return sequence; - } - - @Override - public boolean test(ObjectProperty currentObjectProperty) { - Property property = currentObjectProperty.getProperty(); - - if (!(property instanceof ContainerElementProperty)) { - throw new IllegalArgumentException("Resolved node is not element type. : " + property); - } - - ContainerElementProperty elementProperty = (ContainerElementProperty)property; - return sequence == NO_OR_ALL_INDEX_INTEGER_VALUE || sequence == elementProperty.getSequence(); - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/GenerateFixtureContext.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/GenerateFixtureContext.java deleted file mode 100644 index ef78bba12b..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/GenerateFixtureContext.java +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tree; - -import static com.navercorp.fixturemonkey.api.type.Types.nullSafe; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; -import org.jspecify.annotations.Nullable; - -import com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary; -import com.navercorp.fixturemonkey.api.context.MonkeyContext; -import com.navercorp.fixturemonkey.api.context.MonkeyGeneratorContext; -import com.navercorp.fixturemonkey.api.generator.ArbitraryGenerator; -import com.navercorp.fixturemonkey.api.generator.ArbitraryGeneratorContext; -import com.navercorp.fixturemonkey.api.generator.ArbitraryGeneratorLoggingContext; -import com.navercorp.fixturemonkey.api.generator.ArbitraryProperty; -import com.navercorp.fixturemonkey.api.generator.CompositeArbitraryGenerator; -import com.navercorp.fixturemonkey.api.generator.IntrospectedArbitraryGenerator; -import com.navercorp.fixturemonkey.api.generator.ValidateArbitraryGenerator; -import com.navercorp.fixturemonkey.api.introspector.ArbitraryIntrospector; -import com.navercorp.fixturemonkey.api.lazy.LazyArbitrary; -import com.navercorp.fixturemonkey.api.option.FixtureMonkeyOptions; -import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.api.tree.TraverseNode; -import com.navercorp.fixturemonkey.api.tree.TraverseNodeContext; -import com.navercorp.fixturemonkey.api.tree.TraverseNodeMetadata; -import com.navercorp.fixturemonkey.api.type.Types; -import com.navercorp.fixturemonkey.customizer.NodeManipulator; - -/** - * It is used to generate an instance of the JVM class. - */ -@API(since = "1.1.4", status = Status.EXPERIMENTAL) -public final class GenerateFixtureContext implements TraverseNodeContext { - private final Map, ArbitraryIntrospector> arbitraryIntrospectorConfigurer; - private final MonkeyContext monkeyContext; - private final Supplier validOnly; - - private @Nullable ObjectNode objectNode = null; - private @Nullable LazyArbitrary childNotCacheable = null; - - private final List manipulators = new ArrayList<>(); - @SuppressWarnings("rawtypes") - private final List arbitraryFilters = new ArrayList<>(); - private final List, CombinableArbitrary>> arbitraryCustomizers = - new ArrayList<>(); - private @Nullable CombinableArbitrary arbitrary; - - public GenerateFixtureContext( - Map, ArbitraryIntrospector> arbitraryIntrospectorConfigurer, - Supplier validOnly, - MonkeyContext monkeyContext - ) { - this.arbitraryIntrospectorConfigurer = arbitraryIntrospectorConfigurer; - this.validOnly = validOnly; - this.monkeyContext = monkeyContext; - } - - private static boolean initializeChildNotCacheable(ObjectNode objectNode) { - objectNode.expand(); - ObjectNodeList children = objectNode.getChildren(); - if (children == null) { - return false; - } - for (ObjectNode child : children.asList()) { - GenerateFixtureContext childGenerateFixtureContext = child.getObjectNodeContext(); - LazyArbitrary childCacheable = childGenerateFixtureContext.childNotCacheable; - if (childGenerateFixtureContext.manipulated() - || (childCacheable != null && childCacheable.getValue()) - || child.getMetadata().getTreeProperty().isContainer()) { - return true; - } - } - - return false; - } - - public void addManipulator(NodeManipulator nodeManipulator) { - this.manipulators.add(nodeManipulator); - } - - @SuppressWarnings("rawtypes") - public List getArbitraryFilters() { - return arbitraryFilters; - } - - @SuppressWarnings("rawtypes") - public void addArbitraryFilter(Predicate filter) { - this.arbitraryFilters.add(filter); - } - - public void addGeneratedArbitraryCustomizer( - Function, CombinableArbitrary> arbitraryCustomizer - ) { - this.arbitraryCustomizers.add(arbitraryCustomizer); - } - - public List, CombinableArbitrary>> getGeneratedArbitraryCustomizers() { - return arbitraryCustomizers; - } - - public void addArbitraryCustomizer(Function, CombinableArbitrary> arbitraryCustomizer) { - this.arbitraryCustomizers.add(arbitraryCustomizer); - } - - public boolean manipulated() { - ObjectNode node = this.objectNode; - if (node == null) { - return false; - } - return !manipulators.isEmpty() || node.getMetadata().manipulated(); - } - - public boolean cacheable() { - ObjectNode node = this.objectNode; - LazyArbitrary notCacheable = this.childNotCacheable; - if (node == null || notCacheable == null) { - return false; - } - return !manipulated() - && !node.getMetadata().getTreeProperty().isContainer() - && !notCacheable.getValue(); - } - - public @Nullable CombinableArbitrary getArbitrary() { - return this.arbitrary; - } - - public void setArbitrary(@Nullable CombinableArbitrary arbitrary) { - this.arbitrary = arbitrary; - } - - @SuppressWarnings({"rawtypes", "unchecked", "dereference.of.nullable"}) - public CombinableArbitrary generate(@Nullable ArbitraryGeneratorContext parentContext) { - FixtureMonkeyOptions fixtureMonkeyOptions = monkeyContext.getFixtureMonkeyOptions(); - - CombinableArbitrary generated; - if (this.getArbitrary() != null) { - generated = this.getArbitrary() - .injectNull(this.objectNode.getMetadata().getNullInject()); - } else { - CombinableArbitrary cached = monkeyContext.getCachedArbitrary( - objectNode.getMetadata().getOriginalProperty()); - - if (this.cacheable() && cached != null) { - generated = cached; - } else { - ArbitraryGeneratorContext childArbitraryGeneratorContext = this.generateContext(parentContext); - ArbitraryIntrospector arbitraryIntrospector = arbitraryIntrospectorConfigurer.get( - Types.getActualType(objectNode.getMetadata().getOriginalProperty().getType()) - ); - generated = getArbitraryGenerator(arbitraryIntrospector) - .generate(childArbitraryGeneratorContext); - - List, CombinableArbitrary>> customizers = - this.getGeneratedArbitraryCustomizers(); - - for (Function, CombinableArbitrary> customizer : customizers) { - generated = customizer.apply(generated); - } - - if (this.cacheable()) { - monkeyContext.putCachedArbitrary( - objectNode.getMetadata().getOriginalProperty(), - generated - ); - } - } - } - - List arbitraryFilters = this.getArbitraryFilters(); - for (Predicate predicate : arbitraryFilters) { - generated = generated.filter(fixtureMonkeyOptions.getGenerateMaxTries(), predicate); - } - - return generated; - } - - private ArbitraryGenerator getArbitraryGenerator(@Nullable ArbitraryIntrospector arbitraryIntrospector) { - FixtureMonkeyOptions fixtureMonkeyOptions = monkeyContext.getFixtureMonkeyOptions(); - ArbitraryGenerator arbitraryGenerator = fixtureMonkeyOptions.getDefaultArbitraryGenerator(); - - if (arbitraryIntrospector != null) { - arbitraryGenerator = new CompositeArbitraryGenerator( - Arrays.asList( - new IntrospectedArbitraryGenerator(arbitraryIntrospector), - arbitraryGenerator - ) - ); - } - - if (validOnly.get()) { - arbitraryGenerator = new CompositeArbitraryGenerator( - Arrays.asList( - arbitraryGenerator, - new ValidateArbitraryGenerator( - fixtureMonkeyOptions.getJavaConstraintGenerator(), - fixtureMonkeyOptions.getDecomposedContainerValueFactory() - ) - ) - ); - } - - return arbitraryGenerator; - } - - public ArbitraryGeneratorContext generateContext( - @Nullable ArbitraryGeneratorContext parentContext - ) { - ObjectNode node = this.objectNode; - if (node == null) { - throw new IllegalStateException("objectNode is not initialized. setTraverseNode() must be called first."); - } - - Map childNodesByArbitraryProperty = new HashMap<>(); - List childrenProperties = new ArrayList<>(); - - ArbitraryProperty arbitraryProperty = - node.getMetadata().getTreeProperty() - .toArbitraryProperty(node.getMetadata().getNullInject()); - Property resolvedParentProperty = node.getMetadata().getResolvedTypeDefinition().getResolvedProperty(); - node.expand(); - List children = nullSafe(node.getChildren()).asList().stream() - .filter(it -> { - Property resolvedParent = it.getMetadata().getResolvedParentProperty(); - return resolvedParent != null && Types.isAssignable( - Types.getActualType(resolvedParentProperty.getType()), - Types.getActualType(resolvedParent.getType())); - }) - .collect(Collectors.toList()); - - for (ObjectNode childNode : children) { - TraverseNodeMetadata childNodeMetadata = childNode.getMetadata(); - ArbitraryProperty childArbitraryProperty = - childNodeMetadata.getTreeProperty().toArbitraryProperty(childNodeMetadata.getNullInject()); - childNodesByArbitraryProperty.put(childArbitraryProperty, childNode); - childrenProperties.add(childArbitraryProperty); - } - - MonkeyGeneratorContext monkeyGeneratorContext = monkeyContext.newGeneratorContext( - node.getMetadata().getRootProperty() - ); - FixtureMonkeyOptions fixtureMonkeyOptions = monkeyContext.getFixtureMonkeyOptions(); - ArbitraryGeneratorLoggingContext loggingContext = new ArbitraryGeneratorLoggingContext( - fixtureMonkeyOptions.isEnableLoggingFail()); - - return new ArbitraryGeneratorContext( - resolvedParentProperty, - arbitraryProperty, - childrenProperties, - parentContext, - (currentContext, prop) -> { - ObjectNode childNode = childNodesByArbitraryProperty.get(prop); - if (childNode == null) { - return CombinableArbitrary.NOT_GENERATED; - } - - return childNode.getObjectNodeContext().generate(currentContext); - }, - node.getMetadata().getLazyPropertyPath(), - monkeyGeneratorContext, - fixtureMonkeyOptions.getGenerateUniqueMaxTries(), - arbitraryProperty.getNullInject(), - loggingContext - ); - } - - @Override - public void setTraverseNode(TraverseNode objectNode) { - ObjectNode node = (ObjectNode)objectNode; - this.objectNode = node; - this.childNotCacheable = LazyArbitrary.lazy(() -> initializeChildNotCacheable(node)); - } - - @Override - public GenerateFixtureContext newChildNodeContext() { - return new GenerateFixtureContext( - this.arbitraryIntrospectorConfigurer, - this.validOnly, - this.monkeyContext - ); - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/MetadataCollector.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/MetadataCollector.java deleted file mode 100644 index a184ee6e38..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/MetadataCollector.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tree; - -import static com.navercorp.fixturemonkey.api.type.Types.nullSafe; - -import java.lang.annotation.Annotation; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import com.navercorp.fixturemonkey.api.property.Property; - -@API(since = "0.4.0", status = Status.MAINTAINED) -final class MetadataCollector { - private final ObjectNode rootNode; - private final Map> nodesByProperty; - private final Set annotations; - - public MetadataCollector(ObjectNode rootNode) { - this.rootNode = rootNode; - this.nodesByProperty = new LinkedHashMap<>(); - this.annotations = new HashSet<>(); - } - - public ObjectTreeMetadata collect() { - rootNode.expand(); - List objectNodes = nullSafe(rootNode.getChildren()).asList(); - for (ObjectNode child : objectNodes) { - collect(child); - } - return new ObjectTreeMetadata( - rootNode, - Collections.unmodifiableMap(nodesByProperty), - Collections.unmodifiableSet(annotations) - ); - } - - private void collect(ObjectNode node) { - Property property = node.getTreeProperty().getObjectProperty().getProperty(); - annotations.addAll(property.getAnnotations()); - - node.expand(); - List children = nullSafe(node.getChildren()).asList(); - for (ObjectNode child : children) { - collect(child); - } - - List list = Collections.singletonList(node); - nodesByProperty.merge( - property, - list, - (prev, now) -> Stream.concat(prev.stream(), now.stream()).collect(Collectors.toList()) - ); - } - -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NextNodePredicate.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NextNodePredicate.java deleted file mode 100644 index 0d849cf442..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NextNodePredicate.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ -package com.navercorp.fixturemonkey.tree; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import com.navercorp.fixturemonkey.api.generator.ObjectProperty; -import com.navercorp.fixturemonkey.api.tree.TraverseNodePredicate; - -@API(since = "0.4.0", status = Status.MAINTAINED) -@FunctionalInterface -public interface NextNodePredicate extends TraverseNodePredicate { - boolean test(ObjectProperty currentObjectProperty); -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodeAllElementPredicate.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodeAllElementPredicate.java deleted file mode 100644 index 4772c67317..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodeAllElementPredicate.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tree; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import com.navercorp.fixturemonkey.api.generator.ObjectProperty; - -@API(since = "0.4.0", status = Status.MAINTAINED) -public final class NodeAllElementPredicate implements NextNodePredicate { - - @Override - public boolean test(ObjectProperty currentObjectProperty) { - if (currentObjectProperty.getElementIndex() == null) { - throw new IllegalArgumentException( - "It is not an element property. now type : " + currentObjectProperty.getProperty() - .getType() - .getTypeName() - ); - } - - return true; - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodeElementPredicate.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodeElementPredicate.java deleted file mode 100644 index b507994661..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodeElementPredicate.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tree; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import com.navercorp.fixturemonkey.api.generator.ObjectProperty; - -@API(since = "0.4.0", status = Status.MAINTAINED) -public final class NodeElementPredicate implements NextNodePredicate { - private final int index; - - public NodeElementPredicate(int index) { - this.index = index; - } - - @Override - public boolean test(ObjectProperty currentObjectProperty) { - Integer elementIndex = currentObjectProperty.getElementIndex(); - if (elementIndex == null) { - throw new IllegalArgumentException( - "It is not an element property. now type : " + currentObjectProperty.getProperty() - .getType() - .getTypeName() - ); - } - - return index == elementIndex; - } - - public int getIndex() { - return index; - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodeKeyPredicate.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodeKeyPredicate.java deleted file mode 100644 index b318012261..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodeKeyPredicate.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tree; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import com.navercorp.fixturemonkey.api.generator.ObjectProperty; -import com.navercorp.fixturemonkey.api.property.MapKeyElementProperty; -import com.navercorp.fixturemonkey.api.property.Property; - -@API(since = "0.4.0", status = Status.MAINTAINED) -public final class NodeKeyPredicate implements NextNodePredicate { - @Override - public boolean test(ObjectProperty currentObjectProperty) { - Property property = currentObjectProperty.getProperty(); - - return property instanceof MapKeyElementProperty; - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodePredicateResolver.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodePredicateResolver.java deleted file mode 100644 index 8b9e642dfe..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodePredicateResolver.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ -package com.navercorp.fixturemonkey.tree; - -import static com.navercorp.fixturemonkey.api.generator.DefaultNullInjectGenerator.NOT_NULL_INJECT; -import static com.navercorp.fixturemonkey.api.type.Types.nullSafe; - -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; -import org.jspecify.annotations.Nullable; - -import com.navercorp.fixturemonkey.api.property.SingleElementProperty; - -/** - * A {@link NodeResolver} that resolves the next nodes by the given {@link NextNodePredicate}. - */ -@API(since = "1.1.4", status = Status.EXPERIMENTAL) -public final class NodePredicateResolver implements NodeResolver { - private final NextNodePredicate nextNodePredicate; - - public NodePredicateResolver(NextNodePredicate nextNodePredicate) { - this.nextNodePredicate = nextNodePredicate; - } - - /** - * Resolves the next nodes by the given {@link NextNodePredicate}. - * If the {@code nextNodePredicate} is {@link StartNodePredicate}, it resolves the given {@code nextNode}. - * - * @param nextNode it may be the root node or the parent node resolved by the previous NodeResolver - * @return the next nodes that satisfy the given {@link NextNodePredicate}, - * or an empty list if there are no such nodes. {@link StartNodePredicate} always returns given {@code nextNode}. - */ - @Override - public List resolve(ObjectNode nextNode) { - if (nextNodePredicate == StartNodePredicate.INSTANCE) { - return Collections.singletonList(resolveStartNode(nextNode)); - } - - nextNode.expand(); - ObjectNodeList children = nextNode.getChildren(); - if (children == null) { - return Collections.emptyList(); - } - List resolved = children.asList().stream() - .filter(it -> nextNodePredicate.test(it.getArbitraryProperty().getObjectProperty())) - .collect(Collectors.toList()); - - nextNode.setNullInject(NOT_NULL_INJECT); - for (ObjectNode node : resolved) { - node.setNullInject(NOT_NULL_INJECT); - } - - return resolved; - } - - @Override - public boolean equals(@Nullable Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - NodePredicateResolver that = (NodePredicateResolver)obj; - return nextNodePredicate.equals(that.nextNodePredicate); - } - - @Override - public int hashCode() { - return Objects.hash(nextNodePredicate); - } - - public NextNodePredicate getNextNodePredicate() { - return nextNodePredicate; - } - - public ObjectNode resolveStartNode(ObjectNode startNode) { - ObjectNode resultNode = getChildNodeIfWrapped(startNode); - resultNode.setNullInject(NOT_NULL_INJECT); - - return resultNode; - } - - private ObjectNode getChildNodeIfWrapped(ObjectNode objectNode) { - ObjectNode searchNode = objectNode; - - searchNode.expand(); - while (isWrappedNode(searchNode)) { - searchNode = nullSafe(searchNode.getChildren()).asList().get(0); - } - - return searchNode; - } - - private boolean isWrappedNode(ObjectNode searchNode) { - List children = nullSafe(searchNode.getChildren()).asList(); - - return children.size() == 1 && children.get(0).getResolvedProperty() instanceof SingleElementProperty; - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodeResolver.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodeResolver.java deleted file mode 100644 index e6a96fe859..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodeResolver.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tree; - -import java.util.List; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -@API(since = "0.4.0", status = Status.MAINTAINED) -public interface NodeResolver { - /** - * Resolves the next nodes. The nextNode can be omitted if it cannot be resolved from traversal. - * - * @param nextNode it may be the root node or the parent node resolved by the previous {@link NodeResolver} - * @return the next nodes - */ - List resolve(ObjectNode nextNode); -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodeTypePredicate.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodeTypePredicate.java deleted file mode 100644 index b4b6fea8b8..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodeTypePredicate.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tree; - -import java.util.Objects; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import com.navercorp.fixturemonkey.api.generator.ObjectProperty; -import com.navercorp.fixturemonkey.api.type.Types; - -@API(since = "1.1.17", status = Status.EXPERIMENTAL) -public final class NodeTypePredicate implements NextNodePredicate { - private final Class type; - private final boolean exact; - - public NodeTypePredicate(Class type) { - this(type, true); - } - - public NodeTypePredicate(Class type, boolean exact) { - this.type = Objects.requireNonNull(type, "type must not be null"); - this.exact = exact; - } - - public Class getType() { - return type; - } - - public boolean isExact() { - return exact; - } - - @Override - public boolean test(ObjectProperty currentObjectProperty) { - Class actualType = Types.getActualType(currentObjectProperty.getProperty().getType()); - if (exact) { - return type == actualType; - } - return type.isAssignableFrom(actualType); - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodeValuePredicate.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodeValuePredicate.java deleted file mode 100644 index 1b157e51c4..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodeValuePredicate.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tree; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import com.navercorp.fixturemonkey.api.generator.ObjectProperty; -import com.navercorp.fixturemonkey.api.property.MapValueElementProperty; -import com.navercorp.fixturemonkey.api.property.Property; - -@API(since = "0.5.0", status = Status.MAINTAINED) -public final class NodeValuePredicate implements NextNodePredicate { - @Override - public boolean test(ObjectProperty currentObjectProperty) { - Property property = currentObjectProperty.getProperty(); - return property instanceof MapValueElementProperty; - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/ObjectNode.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/ObjectNode.java deleted file mode 100644 index 87116d2693..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/ObjectNode.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tree; - -import static com.navercorp.fixturemonkey.api.type.Types.nullSafe; -import static java.util.stream.Collectors.toMap; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; -import org.jspecify.annotations.Nullable; - -import com.navercorp.fixturemonkey.api.generator.ArbitraryProperty; -import com.navercorp.fixturemonkey.api.generator.ObjectProperty; -import com.navercorp.fixturemonkey.api.lazy.LazyArbitrary; -import com.navercorp.fixturemonkey.api.property.Property; -import com.navercorp.fixturemonkey.api.property.PropertyPath; -import com.navercorp.fixturemonkey.api.property.TreeRootProperty; -import com.navercorp.fixturemonkey.api.property.TypeDefinition; -import com.navercorp.fixturemonkey.api.tree.TraverseNode; -import com.navercorp.fixturemonkey.api.tree.TraverseNodeMetadata; -import com.navercorp.fixturemonkey.api.tree.TreeNodeManipulator; -import com.navercorp.fixturemonkey.api.tree.TreeProperty; - -@API(since = "0.4.0", status = Status.MAINTAINED) -public final class ObjectNode implements TraverseNode, TraverseNodeMetadata { - private final TraverseNode traverseNode; - private final GenerateFixtureContext generateFixtureContext; - - private @Nullable ObjectNode parent; - private List children; - - @SuppressWarnings("argument") // passing @UnderInitialization this for storage-only; not a nullability issue - public ObjectNode(TraverseNode traverseNode, GenerateFixtureContext generateFixtureContext) { - this.traverseNode = traverseNode; - this.generateFixtureContext = generateFixtureContext; - this.generateFixtureContext.setTraverseNode(this); - } - - public void setChildren(List newChildren) { - this.children = newChildren; - for (ObjectNode child : this.children) { - child.setParent(this); - } - } - - public void setParent(@Nullable ObjectNode parent) { - this.parent = parent; - } - - @Override - public boolean expand() { - if (!this.traverseNode.expand() && this.children != null) { - return false; - } - - this.setChildren( - nullSafe(this.traverseNode.getChildren()).asList().stream() - .map(it -> new ObjectNode(it, generateFixtureContext.newChildNodeContext())) - .collect(Collectors.toList()) - ); - return true; - } - - @Override - public void forceExpand() { - this.traverseNode.forceExpand(); - this.setChildren( - this.mergeWithNewChildren( - nullSafe(this.traverseNode.getChildren()).asList().stream() - .map(it -> new ObjectNode(it, generateFixtureContext.newChildNodeContext())) - .collect(Collectors.toList()) - ) - ); - } - - @Override - public void forceExpand(TypeDefinition typeDefinition) { - this.traverseNode.forceExpand(typeDefinition); - this.setChildren( - this.mergeWithNewChildren( - nullSafe(this.traverseNode.getChildren()).asList().stream() - .map(it -> new ObjectNode(it, generateFixtureContext.newChildNodeContext())) - .collect(Collectors.toList()) - ) - ); - } - - @Override - public TraverseNodeMetadata getMetadata() { - return traverseNode.getMetadata(); - } - - @Override - public @Nullable ObjectNode getParent() { - return this.parent; - } - - @Override - public @Nullable ObjectNodeList getChildren() { - if (children == null) { - return null; - } - return new ObjectNodeList(children); - } - - public ArbitraryProperty getArbitraryProperty() { - return this.getMetadata().getTreeProperty().toArbitraryProperty(getMetadata().getNullInject()); - } - - @Override - public TreeRootProperty getRootProperty() { - return this.getMetadata().getRootProperty(); - } - - @Override - public @Nullable Property getResolvedParentProperty() { - return this.getMetadata().getResolvedParentProperty(); - } - - public TypeDefinition getResolvedTypeDefinition() { - return this.getMetadata().getResolvedTypeDefinition(); - } - - public Property getResolvedProperty() { - return this.getMetadata().getResolvedTypeDefinition().getResolvedProperty(); - } - - public Property getOriginalProperty() { - return this.getMetadata().getOriginalProperty(); - } - - public void setNullInject(double nullInject) { - this.getMetadata().setNullInject(nullInject); - } - - public TreeProperty getTreeProperty() { - return this.getMetadata().getTreeProperty(); - } - - @Override - public double getNullInject() { - return this.getMetadata().getNullInject(); - } - - @Override - public LazyArbitrary getLazyPropertyPath() { - return this.getMetadata().getLazyPropertyPath(); - } - - @Override - public boolean manipulated() { - return this.getMetadata().manipulated() && getObjectNodeContext().manipulated(); - } - - @Override - public List getTreeNodeManipulators() { - return this.traverseNode.getMetadata().getTreeNodeManipulators(); - } - - @Override - public void addTreeNodeManipulator(TreeNodeManipulator treeNodeManipulator) { - this.traverseNode.getMetadata().addTreeNodeManipulator(treeNodeManipulator); - } - - public void setResolvedTypeDefinition(TypeDefinition typeDefinition) { - this.traverseNode.getMetadata().setResolvedTypeDefinition(typeDefinition); - } - - public @Nullable TreeNodeManipulator getAppliedTreeNodeManipulator() { - return this.traverseNode.getMetadata().getAppliedTreeNodeManipulator(); - } - - public GenerateFixtureContext getObjectNodeContext() { - return generateFixtureContext; - } - - private List mergeWithNewChildren(List newChildren) { - if (this.children == null) { - return newChildren; - } - - boolean shrinkChildNodes = this.children.size() > newChildren.size(); - if (shrinkChildNodes) { - return this.children.subList(0, newChildren.size()); - } - - boolean expandChildNodes = this.children.size() < newChildren.size(); - if (expandChildNodes) { - Map existingNodesByObjectProperty = this.children.stream() - .collect(toMap(it -> it.getMetadata().getTreeProperty().getObjectProperty(), Function.identity())); - - List concatNewChildren = new ArrayList<>(); - for (ObjectNode newChild : newChildren) { - ObjectNode existingNode = - existingNodesByObjectProperty.get(newChild.getMetadata().getTreeProperty().getObjectProperty()); - if (existingNode != null) { - concatNewChildren.add(existingNode); - } else { - concatNewChildren.add(newChild); - } - } - return concatNewChildren; - } - return this.children; - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/ObjectNodeList.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/ObjectNodeList.java deleted file mode 100644 index fedd6ac27e..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/ObjectNodeList.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tree; - -import java.util.List; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import com.navercorp.fixturemonkey.api.tree.NodeList; - -/** - * The list of {@link ObjectNode}. It is just to avoid the compile error, use {@link #asList()}. - * - * @see NodeList - */ -@API(since = "1.1.4", status = Status.EXPERIMENTAL) -public final class ObjectNodeList implements NodeList { - private final List objectNodeList; - - public ObjectNodeList(List objectNodeList) { - this.objectNodeList = objectNodeList; - } - - @Override - public List asList() { - return this.objectNodeList; - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/ObjectTree.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/ObjectTree.java deleted file mode 100644 index 1f3f45eb1f..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/ObjectTree.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tree; - -import java.util.List; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary; -import com.navercorp.fixturemonkey.api.property.TreeRootProperty; -import com.navercorp.fixturemonkey.api.tree.DefaultTraverseNode; -import com.navercorp.fixturemonkey.api.tree.TraverseContext; -import com.navercorp.fixturemonkey.customizer.NodeManipulator; - -@API(since = "0.4.0", status = Status.MAINTAINED) -public final class ObjectTree { - private final ObjectNode rootNode; - private final ObjectTreeMetadata metadata; - private final GenerateFixtureContext generateFixtureContext; - - public ObjectTree( - TreeRootProperty rootProperty, - GenerateFixtureContext generateFixtureContext, - TraverseContext traverseContext - ) { - this.rootNode = new ObjectNode( - DefaultTraverseNode.generateRootNode(rootProperty, traverseContext), - generateFixtureContext - ); - MetadataCollector metadataCollector = new MetadataCollector(rootNode); - this.metadata = metadataCollector.collect(); - this.generateFixtureContext = this.rootNode.getObjectNodeContext(); - } - - public ObjectTreeMetadata getMetadata() { - return metadata; - } - - public void manipulate(NodeResolver nodeResolver, NodeManipulator nodeManipulator) { - List nodes = nodeResolver.resolve(rootNode); - - for (ObjectNode node : nodes) { - nodeManipulator.manipulate(node); - node.getObjectNodeContext().addManipulator(nodeManipulator); - } - } - - public CombinableArbitrary generate() { - return generateFixtureContext.generate(null); - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/ObjectTreeMetadata.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/ObjectTreeMetadata.java deleted file mode 100644 index 9044483055..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/ObjectTreeMetadata.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tree; - -import java.lang.annotation.Annotation; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import com.navercorp.fixturemonkey.api.property.Property; - -@API(since = "0.4.0", status = Status.INTERNAL) -public final class ObjectTreeMetadata { - private final ObjectNode rootNode; - private final Map> nodesByProperty; // matchOperator - private final Set annotations; - - public ObjectTreeMetadata( - ObjectNode rootNode, - Map> propertyNodesByProperty, - Set annotations - ) { - this.rootNode = rootNode; - this.nodesByProperty = propertyNodesByProperty; - this.annotations = annotations; - } - - public ObjectNode getRootNode() { - return rootNode; - } - - public Map> getNodesByProperty() { - return nodesByProperty; - } - - public Set getAnnotations() { - return annotations; - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/PropertyNameNodePredicate.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/PropertyNameNodePredicate.java deleted file mode 100644 index 87162fb3aa..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/PropertyNameNodePredicate.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tree; - -import static com.navercorp.fixturemonkey.Constants.ALL_INDEX_STRING; - -import java.util.Objects; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; -import org.jspecify.annotations.Nullable; - -import com.navercorp.fixturemonkey.api.generator.ObjectProperty; - -@API(since = "0.4.0", status = Status.MAINTAINED) -public final class PropertyNameNodePredicate implements NextNodePredicate { - private final String propertyName; - - public PropertyNameNodePredicate(String propertyName) { - this.propertyName = propertyName; - } - - @Override - public boolean test(ObjectProperty currentObjectProperty) { - String nodePropertyName = currentObjectProperty.getResolvedPropertyName(); - return ALL_INDEX_STRING.equals(propertyName) || propertyName.equals(nodePropertyName); - } - - @Override - public boolean equals(@Nullable Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - PropertyNameNodePredicate that = (PropertyNameNodePredicate)obj; - return propertyName.equals(that.propertyName); - } - - @Override - public int hashCode() { - return Objects.hash(propertyName); - } - - public String getPropertyName() { - return this.propertyName; - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/PropertyPredicate.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/PropertyPredicate.java deleted file mode 100644 index 3910f140a0..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/PropertyPredicate.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tree; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import com.navercorp.fixturemonkey.api.generator.ObjectProperty; -import com.navercorp.fixturemonkey.api.property.Property; - -@API(since = "0.4.0", status = Status.MAINTAINED) -public final class PropertyPredicate implements NextNodePredicate { - private final Property property; - - public PropertyPredicate(Property property) { - this.property = property; - } - - @Override - public boolean test(ObjectProperty currentObjectProperty) { - return property.equals(currentObjectProperty.getProperty()); - } - - public Property getProperty() { - return property; - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/StartNodePredicate.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/StartNodePredicate.java deleted file mode 100644 index ba1ed4700f..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/StartNodePredicate.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tree; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -import com.navercorp.fixturemonkey.api.generator.ObjectProperty; -import com.navercorp.fixturemonkey.api.tree.TraverseNodePredicate.StartTraverseNodePredicate; - -@API(since = "0.4.0", status = Status.MAINTAINED) -public final class StartNodePredicate extends StartTraverseNodePredicate implements NextNodePredicate { - public static final StartNodePredicate INSTANCE = new StartNodePredicate(); - - private StartNodePredicate() { - } - - /** - * It determines if given objectProperty is a first node. - * - * @param currentObjectProperty property to determines - * @return true - */ - @Override - public boolean test(ObjectProperty currentObjectProperty) { - return true; // always returns true since the first node has no constraint - } -} diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/StaticNodeResolver.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/StaticNodeResolver.java deleted file mode 100644 index 3e228c08cf..0000000000 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/StaticNodeResolver.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.tree; - -import java.util.List; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -/** - * A {@link NodeResolver} that resolves the provided nodes statically. - */ -@API(since = "1.1.4", status = Status.EXPERIMENTAL) -public final class StaticNodeResolver implements NodeResolver { - private final List nodes; - - public StaticNodeResolver(List nodes) { - this.nodes = nodes; - } - - /** - * Returns the list of nodes that this resolver will return. - * - * @return the static list of nodes - */ - public List getNodes() { - return nodes; - } - - /** - * Resolves the next nodes statically. It always returns the provided nodes. - * - * @param nextNode it may be the root node or the parent node resolved by the previous {@link NodeResolver} - * @return the provided nodes statically - */ - @Override - public List resolve(ObjectNode nextNode) { - return nodes; - } -} diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ContainerInfoResolverConverterTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ContainerInfoResolverConverterTest.java deleted file mode 100644 index a4defe0607..0000000000 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ContainerInfoResolverConverterTest.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.adapter; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import net.jqwik.api.Property; - -import com.navercorp.fixturemonkey.adapter.converter.ContainerInfoResolverConverter; -import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfo; -import com.navercorp.fixturemonkey.customizer.ContainerInfoManipulator; -import com.navercorp.fixturemonkey.tree.NextNodePredicate; -import com.navercorp.fixturemonkey.tree.PropertyNameNodePredicate; -import com.navercorp.fixturemonkey.tree.StartNodePredicate; -import com.navercorp.objectfarm.api.expression.PathExpression; -import com.navercorp.objectfarm.api.node.ContainerSizeResolver; -import com.navercorp.objectfarm.api.tree.PathResolver; -import com.navercorp.objectfarm.api.type.JavaType; - -class ContainerInfoResolverConverterTest { - - @Property - void convertsContainerInfoManipulatorToResolver() { - List predicates = Arrays.asList( - StartNodePredicate.INSTANCE, - new PropertyNameNodePredicate("items") - ); - ContainerInfoManipulator manipulator = new ContainerInfoManipulator( - predicates, - new ArbitraryContainerInfo(3, 3), - 0 - ); - - PathResolver resolver = - ContainerInfoResolverConverter.convertSingle(manipulator); - - assertThat(resolver).isNotNull(); - - PathExpression path = PathExpression.root().child("items"); - assertThat(resolver.matches(path)).isTrue(); - - ContainerSizeResolver sizeResolver = resolver.getCustomizer(); - int size = sizeResolver.resolveContainerSize(new JavaType(List.class)); - assertThat(size).isEqualTo(3); - } - - @Property - void convertsMultipleManipulatorsSortedBySequence() { - List predicates1 = Arrays.asList( - StartNodePredicate.INSTANCE, - new PropertyNameNodePredicate("items") - ); - List predicates2 = Arrays.asList( - StartNodePredicate.INSTANCE, - new PropertyNameNodePredicate("orders") - ); - - ContainerInfoManipulator manipulator1 = new ContainerInfoManipulator( - predicates1, - new ArbitraryContainerInfo(5, 5), - 1 - ); - ContainerInfoManipulator manipulator2 = new ContainerInfoManipulator( - predicates2, - new ArbitraryContainerInfo(2, 2), - 0 - ); - - List manipulators = Arrays.asList(manipulator1, manipulator2); - List> resolvers = - ContainerInfoResolverConverter.convert(manipulators); - - assertThat(resolvers).hasSize(2); - - PathExpression ordersPath = PathExpression.root().child("orders"); - assertThat(resolvers.get(0).matches(ordersPath)).isTrue(); - assertThat(resolvers.get(0).getCustomizer().resolveContainerSize(new JavaType(List.class))).isEqualTo(2); - - PathExpression itemsPath = PathExpression.root().child("items"); - assertThat(resolvers.get(1).matches(itemsPath)).isTrue(); - assertThat(resolvers.get(1).getCustomizer().resolveContainerSize(new JavaType(List.class))).isEqualTo(5); - } - - @Property - void fixedSizeIsDeterminedFromContainerInfoRange() { - List predicates = Arrays.asList( - StartNodePredicate.INSTANCE, - new PropertyNameNodePredicate("items") - ); - - ContainerInfoManipulator manipulator = new ContainerInfoManipulator( - predicates, - new ArbitraryContainerInfo(1, 5), - 0 - ); - - PathResolver resolver = - ContainerInfoResolverConverter.convertSingle(manipulator); - - ContainerSizeResolver sizeResolver = resolver.getCustomizer(); - int size = sizeResolver.resolveContainerSize(new JavaType(List.class)); - - assertThat(size).isBetween(1, 5); - } - - @Property - void emptyListReturnsEmptyResolvers() { - List manipulators = new ArrayList<>(); - - List> resolvers = - ContainerInfoResolverConverter.convert(manipulators); - - assertThat(resolvers).isEmpty(); - } -} diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/DefaultNodeTreeAdapterTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/DefaultNodeTreeAdapterTest.java deleted file mode 100644 index 76b1ef46fc..0000000000 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/DefaultNodeTreeAdapterTest.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.adapter; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import net.jqwik.api.Property; - -import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfo; -import com.navercorp.fixturemonkey.customizer.ContainerInfoManipulator; -import com.navercorp.fixturemonkey.customizer.ManipulatorSet; -import com.navercorp.fixturemonkey.tree.NextNodePredicate; -import com.navercorp.fixturemonkey.tree.PropertyNameNodePredicate; -import com.navercorp.fixturemonkey.tree.StartNodePredicate; -import com.navercorp.objectfarm.api.node.JvmNode; -import com.navercorp.objectfarm.api.tree.JvmNodeTree; -import com.navercorp.objectfarm.api.type.JavaType; -import com.navercorp.objectfarm.api.type.JvmType; - -class DefaultNodeTreeAdapterTest { - - static class SimpleClass { - - private String name; - private int value; - } - - static class ClassWithList { - - private List items; - } - - static class ClassWithNestedList { - - private List> nestedItems; - } - - static class ClassWithMap { - - private Map data; - } - - @Property - void adaptsSimpleClassWithoutManipulators() { - DefaultNodeTreeAdapter adapter = new DefaultNodeTreeAdapter(12345L); - JvmType rootType = new JavaType(SimpleClass.class); - ManipulatorSet manipulatorSet = new ManipulatorSet(Collections.emptyList(), Collections.emptyList()); - - JvmNodeTree tree = adapter.adapt(rootType, manipulatorSet).getNodeTree(); - - assertThat(tree).isNotNull(); - assertThat(tree.getRootNode()).isNotNull(); - assertThat(tree.getRootNode().getConcreteType().getRawType()).isEqualTo(SimpleClass.class); - - List children = tree.getChildren(tree.getRootNode()); - assertThat(children).hasSize(2); - } - - @Property - void adaptsClassWithListUsingContainerInfoManipulator() { - DefaultNodeTreeAdapter adapter = new DefaultNodeTreeAdapter(12345L); - - JvmType rootType = new JavaType(ClassWithList.class, Collections.emptyList(), Collections.emptyList()); - - List predicates = Arrays.asList( - StartNodePredicate.INSTANCE, - new PropertyNameNodePredicate("items") - ); - ContainerInfoManipulator containerManipulator = new ContainerInfoManipulator( - predicates, - new ArbitraryContainerInfo(3, 3), - 0 - ); - - ManipulatorSet manipulatorSet = new ManipulatorSet( - Collections.emptyList(), - Collections.singletonList(containerManipulator) - ); - - JvmNodeTree tree = adapter.adapt(rootType, manipulatorSet).getNodeTree(); - - assertThat(tree).isNotNull(); - - List children = tree.getChildren(tree.getRootNode()); - JvmNode itemsNode = children - .stream() - .filter(node -> "items".equals(node.getNodeName())) - .findFirst() - .orElse(null); - - assertThat(itemsNode).isNotNull(); - - List itemsChildren = tree.getChildren(itemsNode); - assertThat(itemsChildren).hasSize(3); - } - - @Property - void adaptsClassWithNestedListUsingMultipleContainerInfoManipulators() { - DefaultNodeTreeAdapter adapter = new DefaultNodeTreeAdapter(12345L); - - JvmType rootType = new JavaType(ClassWithNestedList.class); - - List outerPredicates = Arrays.asList( - StartNodePredicate.INSTANCE, - new PropertyNameNodePredicate("nestedItems") - ); - ContainerInfoManipulator outerManipulator = new ContainerInfoManipulator( - outerPredicates, - new ArbitraryContainerInfo(2, 2), - 0 - ); - - ManipulatorSet manipulatorSet = new ManipulatorSet( - Collections.emptyList(), - Collections.singletonList(outerManipulator) - ); - - JvmNodeTree tree = adapter.adapt(rootType, manipulatorSet).getNodeTree(); - - assertThat(tree).isNotNull(); - - List children = tree.getChildren(tree.getRootNode()); - JvmNode nestedItemsNode = children - .stream() - .filter(node -> "nestedItems".equals(node.getNodeName())) - .findFirst() - .orElse(null); - - assertThat(nestedItemsNode).isNotNull(); - - List outerChildren = tree.getChildren(nestedItemsNode); - assertThat(outerChildren).hasSize(2); - } - - @Property - void emptyManipulatorSetProducesTreeWithDefaultContainerSizes() { - DefaultNodeTreeAdapter adapter = new DefaultNodeTreeAdapter(12345L); - - JvmType rootType = new JavaType(ClassWithList.class); - ManipulatorSet manipulatorSet = new ManipulatorSet(Collections.emptyList(), Collections.emptyList()); - - JvmNodeTree tree = adapter.adapt(rootType, manipulatorSet).getNodeTree(); - - assertThat(tree).isNotNull(); - - List children = tree.getChildren(tree.getRootNode()); - JvmNode itemsNode = children - .stream() - .filter(node -> "items".equals(node.getNodeName())) - .findFirst() - .orElse(null); - - assertThat(itemsNode).isNotNull(); - - List itemsChildren = tree.getChildren(itemsNode); - assertThat(itemsChildren.size()).isBetween(0, 3); - } - - @Property - void sameSeedProducesSameTreeStructure() { - long seed = 12345L; - - DefaultNodeTreeAdapter adapter1 = new DefaultNodeTreeAdapter(seed); - DefaultNodeTreeAdapter adapter2 = new DefaultNodeTreeAdapter(seed); - - JvmType rootType = new JavaType(ClassWithList.class); - ManipulatorSet manipulatorSet = new ManipulatorSet(Collections.emptyList(), Collections.emptyList()); - - JvmNodeTree tree1 = adapter1.adapt(rootType, manipulatorSet).getNodeTree(); - JvmNodeTree tree2 = adapter2.adapt(rootType, manipulatorSet).getNodeTree(); - - int itemsChildrenCount1 = tree1 - .getChildren( - tree1 - .getChildren(tree1.getRootNode()) - .stream() - .filter(node -> "items".equals(node.getNodeName())) - .findFirst() - .orElse(null) - ) - .size(); - - int itemsChildrenCount2 = tree2 - .getChildren( - tree2 - .getChildren(tree2.getRootNode()) - .stream() - .filter(node -> "items".equals(node.getNodeName())) - .findFirst() - .orElse(null) - ) - .size(); - - assertThat(itemsChildrenCount1).isEqualTo(itemsChildrenCount2); - } -} diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/PredicatePathConverterTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/PredicatePathConverterTest.java deleted file mode 100644 index 571e4dcf41..0000000000 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/PredicatePathConverterTest.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.adapter; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import net.jqwik.api.Property; - -import com.navercorp.fixturemonkey.adapter.converter.PredicatePathConverter; -import com.navercorp.fixturemonkey.tree.NextNodePredicate; -import com.navercorp.fixturemonkey.tree.NodeAllElementPredicate; -import com.navercorp.fixturemonkey.tree.NodeElementPredicate; -import com.navercorp.fixturemonkey.tree.NodeKeyPredicate; -import com.navercorp.fixturemonkey.tree.NodeValuePredicate; -import com.navercorp.fixturemonkey.tree.PropertyNameNodePredicate; -import com.navercorp.fixturemonkey.tree.StartNodePredicate; -import com.navercorp.objectfarm.api.expression.PathExpression; - -class PredicatePathConverterTest { - - @Property - void startNodePredicateConvertsToRoot() { - List predicates = Collections.singletonList(StartNodePredicate.INSTANCE); - - String expression = PredicatePathConverter.toExpression(predicates); - - assertThat(expression).isEqualTo("$"); - } - - @Property - void propertyNamePredicateConvertsToPropertyName() { - List predicates = Arrays.asList( - StartNodePredicate.INSTANCE, - new PropertyNameNodePredicate("items") - ); - - String expression = PredicatePathConverter.toExpression(predicates); - - assertThat(expression).isEqualTo("$.items"); - } - - @Property - void nodeAllElementPredicateConvertsToWildcard() { - List predicates = Arrays.asList( - StartNodePredicate.INSTANCE, - new PropertyNameNodePredicate("items"), - new NodeAllElementPredicate() - ); - - String expression = PredicatePathConverter.toExpression(predicates); - - assertThat(expression).isEqualTo("$.items[*]"); - } - - @Property - void nodeElementPredicateConvertsToIndex() { - List predicates = Arrays.asList( - StartNodePredicate.INSTANCE, - new PropertyNameNodePredicate("items"), - new NodeElementPredicate(2) - ); - - String expression = PredicatePathConverter.toExpression(predicates); - - assertThat(expression).isEqualTo("$.items[2]"); - } - - @Property - void nodeKeyPredicateConvertsToKey() { - List predicates = Arrays.asList( - StartNodePredicate.INSTANCE, - new PropertyNameNodePredicate("map"), - new NodeElementPredicate(0), - new NodeKeyPredicate() - ); - - String expression = PredicatePathConverter.toExpression(predicates); - - assertThat(expression).isEqualTo("$.map[0][key]"); - } - - @Property - void nodeValuePredicateConvertsToValue() { - List predicates = Arrays.asList( - StartNodePredicate.INSTANCE, - new PropertyNameNodePredicate("map"), - new NodeElementPredicate(0), - new NodeValuePredicate() - ); - - String expression = PredicatePathConverter.toExpression(predicates); - - assertThat(expression).isEqualTo("$.map[0][value]"); - } - - @Property - void complexNestedPathConvertsCorrectly() { - List predicates = Arrays.asList( - StartNodePredicate.INSTANCE, - new PropertyNameNodePredicate("orders"), - new NodeAllElementPredicate(), - new PropertyNameNodePredicate("items"), - new NodeElementPredicate(0), - new PropertyNameNodePredicate("name") - ); - - String expression = PredicatePathConverter.toExpression(predicates); - - assertThat(expression).isEqualTo("$.orders[*].items[0].name"); - } - - @Property - void convertedExpressionCreatesValidPattern() { - List predicates = Arrays.asList( - StartNodePredicate.INSTANCE, - new PropertyNameNodePredicate("items"), - new NodeAllElementPredicate() - ); - - PathExpression pathExpression = PredicatePathConverter.convert(predicates); - - assertThat(pathExpression).isNotNull(); - assertThat(pathExpression.toExpression()).isEqualTo("$.items[*]"); - } - - @Property - void wildcardPropertyNameConvertsToFieldWildcard() { - List predicates = Arrays.asList( - StartNodePredicate.INSTANCE, - new PropertyNameNodePredicate("*") - ); - - String expression = PredicatePathConverter.toExpression(predicates); - - assertThat(expression).isEqualTo("$.*"); - } -} diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/customizer/ManipulatorAnalyzerTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/customizer/ManipulatorAnalyzerTest.java deleted file mode 100644 index f0c7da1549..0000000000 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/customizer/ManipulatorAnalyzerTest.java +++ /dev/null @@ -1,1795 +0,0 @@ -/* - * Fixture Monkey - * - * Copyright (c) 2021-present NAVER Corp. - * - * 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. - */ - -package com.navercorp.fixturemonkey.customizer; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import net.jqwik.api.Property; - -import com.navercorp.fixturemonkey.adapter.analysis.AnalysisResult; -import com.navercorp.fixturemonkey.adapter.analysis.ManipulatorAnalyzer; -import com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary; -import com.navercorp.fixturemonkey.api.container.DecomposedContainerValueFactory; -import com.navercorp.fixturemonkey.api.container.DefaultDecomposedContainerValueFactory; -import com.navercorp.fixturemonkey.customizer.Values.Just; -import com.navercorp.fixturemonkey.tree.CompositeNodeResolver; -import com.navercorp.fixturemonkey.tree.NodePredicateResolver; -import com.navercorp.fixturemonkey.tree.NodeResolver; -import com.navercorp.fixturemonkey.tree.PropertyNameNodePredicate; -import com.navercorp.fixturemonkey.tree.StartNodePredicate; -import com.navercorp.objectfarm.api.expression.PathExpression; -import com.navercorp.objectfarm.api.node.ContainerSizeResolver; -import com.navercorp.objectfarm.api.node.GenericTypeResolver; -import com.navercorp.objectfarm.api.node.InterfaceResolver; -import com.navercorp.objectfarm.api.tree.PathResolver; -import com.navercorp.objectfarm.api.type.JavaType; -import com.navercorp.objectfarm.api.type.JvmType; - -class ManipulatorAnalyzerTest { - @Property - void analyzesNodeSetDecomposedValueManipulator() { - Dog dog = new Dog(); - NodeResolver nodeResolver = createNodeResolver("animal"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - dog - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getInterfaceResolvers()).hasSize(1); - - PathResolver resolver = result.getInterfaceResolvers().get(0); - PathExpression animalPath = PathExpression.root().child("animal"); - assertThat(resolver.matches(animalPath)).isTrue(); - - JvmType resolvedType = resolver.getCustomizer().resolve(new JavaType(Animal.class)); - assertThat(resolvedType).isNotNull(); - assertThat(resolvedType.getRawType()).isEqualTo(Dog.class); - } - - @Property - void analyzesNodeSetJustManipulator() { - NodeResolver nodeResolver = createNodeResolver("value"); - Just justValue = Values.just(CombinableArbitrary.from("test")); - NodeManipulator nodeManipulator = new NodeSetJustManipulator(justValue); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getJustPaths()).hasSize(1); - assertThat(result.getJustPaths().get(0)).isEqualTo(PathExpression.of("$.value")); - } - - @Property - void analyzesNodeNullityManipulatorSetToNull() { - NodeResolver nodeResolver = createNodeResolver("nullable"); - NodeManipulator nodeManipulator = new NodeNullityManipulator(0, true); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getValuesByPath()).containsKey(PathExpression.of("$.nullable")); - assertThat(result.getValuesByPath().get(PathExpression.of("$.nullable"))).isNull(); - } - - @Property - void analyzesNodeNullityManipulatorSetToNotNull() { - NodeResolver nodeResolver = createNodeResolver("required"); - NodeManipulator nodeManipulator = new NodeNullityManipulator(0, false); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getValuesByPath()).doesNotContainKey(PathExpression.of("$.required")); - } - - @Property - void analyzesCompositeNodeManipulator() { - NodeResolver nodeResolver = createNodeResolver("composite"); - - NodeManipulator inner1 = new NodeNullityManipulator(0, true); - NodeManipulator inner2 = new NodeSetJustManipulator(Values.just(CombinableArbitrary.from("test"))); - NodeManipulator compositeManipulator = new CompositeNodeManipulator(inner1, inner2); - - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, compositeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getJustPaths()).containsExactly(PathExpression.of("$.composite")); - assertThat(result.getValuesByPath()).containsKey(PathExpression.of("$.composite")); - } - - @Property - void analyzesApplyNodeCountManipulator() { - NodeResolver nodeResolver = createNodeResolver("counted"); - - NodeManipulator innerManipulator = new NodeNullityManipulator(0, true); - NodeManipulator countManipulator = new ApplyNodeCountManipulator(innerManipulator, 3); - - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, countManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getValuesByPath()).containsKey(PathExpression.of("$.counted")); - assertThat(result.getValuesByPath().get(PathExpression.of("$.counted"))).isNull(); - assertThat(result.getLimitsByPath()).containsKey(PathExpression.of("$.counted")); - assertThat(result.getLimitsByPath().get(PathExpression.of("$.counted"))).isEqualTo(3); - } - - @Property - void analyzesNestedCompositeWithApplyNodeCount() { - NodeResolver nodeResolver = createNodeResolver("nested"); - - NodeManipulator nullity = new NodeNullityManipulator(0, true); - NodeManipulator just = new NodeSetJustManipulator(Values.just(CombinableArbitrary.from("value"))); - NodeManipulator composite = new CompositeNodeManipulator(nullity, just); - NodeManipulator counted = new ApplyNodeCountManipulator(composite, 2); - - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, counted); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getJustPaths()).containsExactly(PathExpression.of("$.nested")); - assertThat(result.getValuesByPath()).containsKey(PathExpression.of("$.nested")); - } - - @Property - void analyzesCompositeContainingApplyNodeCount() { - NodeResolver nodeResolver = createNodeResolver("path"); - - NodeManipulator nullity = new NodeNullityManipulator(0, true); - NodeManipulator counted = new ApplyNodeCountManipulator(nullity, 1); - NodeManipulator just = new NodeSetJustManipulator(Values.just(CombinableArbitrary.from("test"))); - NodeManipulator composite = new CompositeNodeManipulator(counted, just); - - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, composite); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getJustPaths()).containsExactly(PathExpression.of("$.path")); - assertThat(result.getValuesByPath()).containsKey(PathExpression.of("$.path")); - } - - @Property - void analyzesMultipleManipulators() { - ArbitraryManipulator manipulator1 = new ArbitraryManipulator( - createNodeResolver("field1"), - new NodeNullityManipulator(0, true) - ); - - ArbitraryManipulator manipulator2 = new ArbitraryManipulator( - createNodeResolver("field2"), - new NodeSetJustManipulator(Values.just(CombinableArbitrary.from("value"))) - ); - - Dog dog = new Dog(); - ArbitraryManipulator manipulator3 = new ArbitraryManipulator( - createNodeResolver("field3"), - new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - dog - ) - ); - - List manipulators = Arrays.asList(manipulator1, manipulator2, manipulator3); - - AnalysisResult result = ManipulatorAnalyzer.analyze(manipulators); - - assertThat(result.getValuesByPath()).containsKey(PathExpression.of("$.field1")); - assertThat(result.getValuesByPath().get(PathExpression.of("$.field1"))).isNull(); - assertThat(result.getJustPaths()).containsExactly(PathExpression.of("$.field2")); - assertThat(result.getInterfaceResolvers()).hasSize(1); - } - - @Property - void emptyManipulatorsReturnsEmptyResult() { - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.emptyList()); - - assertThat(result.getInterfaceResolvers()).isEmpty(); - assertThat(result.getGenericTypeResolvers()).isEmpty(); - assertThat(result.getContainerSizeResolvers()).isEmpty(); - assertThat(result.getJustPaths()).isEmpty(); - assertThat(result.getValuesByPath()).isEmpty(); - } - - @Property - void analyzesNestedObjectWithAddress() { - Address address = new Address("123 Main St", "Seoul", "12345"); - Person person = new Person("John", 30, address, Arrays.asList("reading", "coding")); - - NodeResolver nodeResolver = createNodeResolver("person"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - person - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - // Person.hobbies (List -> ArrayList) generates an interface resolver for the container field - assertThat(result.getInterfaceResolvers()).hasSize(1); - PathExpression hobbiesPath = PathExpression.of("$.person.hobbies"); - assertThat(result.getInterfaceResolvers().get(0).matches(hobbiesPath)).isTrue(); - } - - @Property - void analyzesListOfStrings() { - List items = new ArrayList<>(Arrays.asList("item1", "item2", "item3")); - - NodeResolver nodeResolver = createNodeResolver("items"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - items - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getInterfaceResolvers()).hasSize(1); - - PathResolver resolver = result.getInterfaceResolvers().get(0); - PathExpression itemsPath = PathExpression.root().child("items"); - assertThat(resolver.matches(itemsPath)).isTrue(); - - InterfaceResolver interfaceResolver = resolver.getCustomizer(); - JvmType resolvedType = interfaceResolver.resolve(new JavaType(List.class)); - assertThat(resolvedType).isNotNull(); - assertThat(List.class.isAssignableFrom(resolvedType.getRawType())).isTrue(); - } - - @Property - void analyzesListOfComplexObjects() { - List items = Arrays.asList(new OrderItem("Product A", 2, 10.0), new OrderItem("Product B", 1, 20.0)); - - NodeResolver nodeResolver = createNodeResolver("orderItems"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - items - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getInterfaceResolvers()).hasSize(1); - - PathResolver resolver = result.getInterfaceResolvers().get(0); - PathExpression path = PathExpression.root().child("orderItems"); - assertThat(resolver.matches(path)).isTrue(); - - PathExpression wrongPath = PathExpression.root().child("otherItems"); - assertThat(resolver.matches(wrongPath)).isFalse(); - } - - @Property - void analyzesMapOfStringToString() { - Map metadata = new HashMap<>(); - metadata.put("key1", "value1"); - metadata.put("key2", "value2"); - - NodeResolver nodeResolver = createNodeResolver("metadata"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - metadata - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getInterfaceResolvers()).hasSize(1); - - PathResolver resolver = result.getInterfaceResolvers().get(0); - InterfaceResolver interfaceResolver = resolver.getCustomizer(); - - JvmType resolvedType = interfaceResolver.resolve(new JavaType(Map.class)); - assertThat(resolvedType).isNotNull(); - assertThat(resolvedType.getRawType()).isEqualTo(HashMap.class); - } - - @Property - void analyzesMapWithComplexValues() { - Map addressMap = new HashMap<>(); - addressMap.put("home", new Address("123 Home St", "Seoul", "11111")); - addressMap.put("work", new Address("456 Work Ave", "Busan", "22222")); - - NodeResolver nodeResolver = createNodeResolver("addresses"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - addressMap - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getInterfaceResolvers()).hasSize(1); - - PathResolver resolver = result.getInterfaceResolvers().get(0); - PathExpression path = PathExpression.root().child("addresses"); - assertThat(resolver.matches(path)).isTrue(); - } - - @Property - void analyzesGenericContainerWithString() { - Container container = new Container<>("test value", "Test Label"); - - NodeResolver nodeResolver = createNodeResolver("container"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - container - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getInterfaceResolvers()).isEmpty(); - } - - @Property - void analyzesGenericContainerWithComplexType() { - Container
    container = new Container<>( - new Address("789 Container St", "Incheon", "33333"), - "Address Container" - ); - - NodeResolver nodeResolver = createNodeResolver("addressContainer"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - container - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getInterfaceResolvers()).isEmpty(); - } - - @Property - void analyzesDeepNestedOrder() { - List items = Arrays.asList(new OrderItem("Laptop", 1, 1500.0), new OrderItem("Mouse", 2, 25.0)); - Map metadata = new HashMap<>(); - metadata.put("source", "web"); - metadata.put("priority", "high"); - - Order order = new Order("ORD-001", items, metadata); - - NodeResolver nodeResolver = createNodeResolver("order"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - order - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - // Order.items (List -> ArrayList) and Order.metadata (Map -> HashMap) generate interface resolvers - assertThat(result.getInterfaceResolvers()).hasSize(2); - } - - @Property - void analyzesInterfaceImplementation() { - Animal animal = new Dog("Labrador"); - - NodeResolver nodeResolver = createNodeResolver("pet"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - animal - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getInterfaceResolvers()).hasSize(1); - - PathResolver resolver = result.getInterfaceResolvers().get(0); - PathExpression petPath = PathExpression.root().child("pet"); - assertThat(resolver.matches(petPath)).isTrue(); - - InterfaceResolver interfaceResolver = resolver.getCustomizer(); - JvmType resolvedType = interfaceResolver.resolve(new JavaType(Animal.class)); - assertThat(resolvedType).isNotNull(); - assertThat(resolvedType.getRawType()).isEqualTo(Dog.class); - } - - @Property - void analyzesListOfInterfaceImplementations() { - List animals = new ArrayList<>(Arrays.asList(new Dog("Poodle"), new Cat())); - - NodeResolver nodeResolver = createNodeResolver("animals"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - animals - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getInterfaceResolvers()).hasSize(3); - - PathResolver containerResolver = result - .getInterfaceResolvers() - .stream() - .filter(r -> r.matches(PathExpression.root().child("animals"))) - .findFirst() - .orElse(null); - assertThat(containerResolver).isNotNull(); - JvmType resolvedType = containerResolver.getCustomizer().resolve(new JavaType(List.class)); - assertThat(resolvedType).isNotNull(); - assertThat(List.class.isAssignableFrom(resolvedType.getRawType())).isTrue(); - } - - @Property - void analyzesNestedListOfLists() { - List> nestedList = Arrays.asList( - Arrays.asList("a", "b", "c"), - Arrays.asList("d", "e"), - Arrays.asList("f") - ); - - NodeResolver nodeResolver = createNodeResolver("matrix"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - nestedList - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getInterfaceResolvers()).hasSize(1); - - PathResolver resolver = result.getInterfaceResolvers().get(0); - PathExpression matrixPath = PathExpression.root().child("matrix"); - assertThat(resolver.matches(matrixPath)).isTrue(); - } - - @Property - void analyzesEmptyCollection() { - List emptyList = new ArrayList<>(); - - NodeResolver nodeResolver = createNodeResolver("emptyList"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - emptyList - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getInterfaceResolvers()).hasSize(1); - - PathResolver resolver = result.getInterfaceResolvers().get(0); - InterfaceResolver interfaceResolver = resolver.getCustomizer(); - - JvmType resolvedType = interfaceResolver.resolve(new JavaType(List.class)); - assertThat(resolvedType).isNotNull(); - assertThat(resolvedType.getRawType()).isEqualTo(ArrayList.class); - } - - @Property - void analyzesEmptyMap() { - Map emptyMap = new HashMap<>(); - - NodeResolver nodeResolver = createNodeResolver("emptyMap"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - emptyMap - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getInterfaceResolvers()).hasSize(1); - - PathResolver resolver = result.getInterfaceResolvers().get(0); - InterfaceResolver interfaceResolver = resolver.getCustomizer(); - - JvmType resolvedType = interfaceResolver.resolve(new JavaType(Map.class)); - assertThat(resolvedType).isNotNull(); - assertThat(resolvedType.getRawType()).isEqualTo(HashMap.class); - } - - @Property - void analyzesNullValue() { - NodeResolver nodeResolver = createNodeResolver("nullField"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - null - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getInterfaceResolvers()).isEmpty(); - } - - @Property - void analyzesPrimitiveWrapperTypes() { - // given - Integer intValue = 42; - - NodeResolver nodeResolver = createNodeResolver("number"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - intValue - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - // when - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - // then - // Primitive wrappers (Integer, Long, etc.) are JDK value types — leaf nodes - // that never get expanded into a node tree. No interface resolver is needed. - assertThat(result.getInterfaceResolvers()).isEmpty(); - } - - @Property - void analyzesMultipleComplexManipulators() { - Person person = new Person("Alice", 25, new Address("1st St", "Tokyo", "10000"), Arrays.asList("music")); - Order order = new Order("ORD-002", Collections.emptyList(), Collections.emptyMap()); - Animal pet = new Cat(); - - ArbitraryManipulator manipulator1 = new ArbitraryManipulator( - createNodeResolver("person"), - new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - person - ) - ); - - ArbitraryManipulator manipulator2 = new ArbitraryManipulator( - createNodeResolver("order"), - new NodeSetDecomposedValueManipulator<>( - 2, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - order - ) - ); - - ArbitraryManipulator manipulator3 = new ArbitraryManipulator( - createNodeResolver("pet"), - new NodeSetDecomposedValueManipulator<>( - 3, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - pet - ) - ); - - List manipulators = Arrays.asList(manipulator1, manipulator2, manipulator3); - - AnalysisResult result = ManipulatorAnalyzer.analyze(manipulators); - - // Person.hobbies(1) + Order.items(1) + Order.metadata(1) + Cat/pet(1) = 4 - assertThat(result.getInterfaceResolvers()).hasSize(4); - - PathExpression petPath = PathExpression.root().child("pet"); - PathResolver petResolver = result.getInterfaceResolvers().stream() - .filter(r -> r.matches(petPath)) - .findFirst() - .orElse(null); - assertThat(petResolver).isNotNull(); - - JvmType resolvedPetType = petResolver.getCustomizer().resolve(new JavaType(Animal.class)); - assertThat(resolvedPetType).isNotNull(); - assertThat(resolvedPetType.getRawType()).isEqualTo(Cat.class); - } - - @Property - void analyzesCompositeWithDecomposedValue() { - Dog dog = new Dog("Shiba"); - - NodeResolver nodeResolver = createNodeResolver("field"); - NodeManipulator decomposed = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - dog - ); - NodeManipulator nullity = new NodeNullityManipulator(0, false); - NodeManipulator composite = new CompositeNodeManipulator(decomposed, nullity); - - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, composite); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getInterfaceResolvers()).hasSize(1); - - PathResolver resolver = result.getInterfaceResolvers().get(0); - PathExpression fieldPath = PathExpression.root().child("field"); - assertThat(resolver.matches(fieldPath)).isTrue(); - - JvmType resolvedType = resolver.getCustomizer().resolve(new JavaType(Animal.class)); - assertThat(resolvedType).isNotNull(); - assertThat(resolvedType.getRawType()).isEqualTo(Dog.class); - } - - @Property - void analyzesApplyNodeCountWithDecomposedValue() { - Dog dog = new Dog("Test Dog"); - - NodeResolver nodeResolver = createNodeResolver("pet"); - NodeManipulator decomposed = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - dog - ); - NodeManipulator counted = new ApplyNodeCountManipulator(decomposed, 5); - - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, counted); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getInterfaceResolvers()).hasSize(1); - - PathResolver resolver = result.getInterfaceResolvers().get(0); - PathExpression petPath = PathExpression.root().child("pet"); - assertThat(resolver.matches(petPath)).isTrue(); - - JvmType resolvedType = resolver.getCustomizer().resolve(new JavaType(Animal.class)); - assertThat(resolvedType).isNotNull(); - assertThat(resolvedType.getRawType()).isEqualTo(Dog.class); - } - - @Property - void analyzesApplyNodeCountWithConcreteClass() { - Address address = new Address("Test St", "Test City", "00000"); - - NodeResolver nodeResolver = createNodeResolver("address"); - NodeManipulator decomposed = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - address - ); - NodeManipulator counted = new ApplyNodeCountManipulator(decomposed, 5); - - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, counted); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getInterfaceResolvers()).isEmpty(); - } - - @Property - void resolverDoesNotMatchIncompatibleTypes() { - Dog dog = new Dog("Corgi"); - - NodeResolver nodeResolver = createNodeResolver("pet"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - dog - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getInterfaceResolvers()).hasSize(1); - - PathResolver resolver = result.getInterfaceResolvers().get(0); - InterfaceResolver interfaceResolver = resolver.getCustomizer(); - - JvmType resolvedType = interfaceResolver.resolve(new JavaType(String.class)); - assertThat(resolvedType).isNull(); - } - - @Property - void extractsGenericTypeFromListOfStrings() { - List items = Arrays.asList("item1", "item2", "item3"); - - NodeResolver nodeResolver = createNodeResolver("items"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - items - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getGenericTypeResolvers()).hasSize(1); - - PathResolver resolver = result.getGenericTypeResolvers().get(0); - PathExpression itemsPath = PathExpression.root().child("items"); - assertThat(resolver.matches(itemsPath)).isTrue(); - - GenericTypeResolver genericResolver = resolver.getCustomizer(); - JvmType resolvedType = genericResolver.resolve(new JavaType(List.class)); - assertThat(resolvedType).isNotNull(); - assertThat(resolvedType.getTypeVariables()).hasSize(1); - assertThat(resolvedType.getTypeVariables().get(0).getRawType()).isEqualTo(String.class); - } - - @Property - void extractsGenericTypeFromListOfIntegers() { - List numbers = Arrays.asList(1, 2, 3, 4, 5); - - NodeResolver nodeResolver = createNodeResolver("numbers"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - numbers - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getGenericTypeResolvers()).hasSize(1); - - PathResolver resolver = result.getGenericTypeResolvers().get(0); - GenericTypeResolver genericResolver = resolver.getCustomizer(); - JvmType resolvedType = genericResolver.resolve(new JavaType(List.class)); - - assertThat(resolvedType.getTypeVariables()).hasSize(1); - assertThat(resolvedType.getTypeVariables().get(0).getRawType()).isEqualTo(Integer.class); - } - - @Property - void extractsGenericTypeFromListOfComplexObjects() { - List orderItems = Arrays.asList( - new OrderItem("Product A", 2, 10.0), - new OrderItem("Product B", 1, 20.0) - ); - - NodeResolver nodeResolver = createNodeResolver("orderItems"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - orderItems - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getGenericTypeResolvers()).hasSize(1); - - PathResolver resolver = result.getGenericTypeResolvers().get(0); - GenericTypeResolver genericResolver = resolver.getCustomizer(); - JvmType resolvedType = genericResolver.resolve(new JavaType(List.class)); - - assertThat(resolvedType.getTypeVariables()).hasSize(1); - assertThat(resolvedType.getTypeVariables().get(0).getRawType()).isEqualTo(OrderItem.class); - } - - @Property - void extractsGenericTypeFromMapOfStringToString() { - Map metadata = new HashMap<>(); - metadata.put("key1", "value1"); - metadata.put("key2", "value2"); - - NodeResolver nodeResolver = createNodeResolver("metadata"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - metadata - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getGenericTypeResolvers()).hasSize(1); - - PathResolver resolver = result.getGenericTypeResolvers().get(0); - PathExpression metadataPath = PathExpression.root().child("metadata"); - assertThat(resolver.matches(metadataPath)).isTrue(); - - GenericTypeResolver genericResolver = resolver.getCustomizer(); - JvmType resolvedType = genericResolver.resolve(new JavaType(Map.class)); - - assertThat(resolvedType.getTypeVariables()).hasSize(2); - assertThat(resolvedType.getTypeVariables().get(0).getRawType()).isEqualTo(String.class); - assertThat(resolvedType.getTypeVariables().get(1).getRawType()).isEqualTo(String.class); - } - - @Property - void extractsGenericTypeFromMapOfStringToInteger() { - Map scores = new HashMap<>(); - scores.put("Alice", 100); - scores.put("Bob", 95); - - NodeResolver nodeResolver = createNodeResolver("scores"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - scores - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getGenericTypeResolvers()).hasSize(1); - - PathResolver resolver = result.getGenericTypeResolvers().get(0); - GenericTypeResolver genericResolver = resolver.getCustomizer(); - JvmType resolvedType = genericResolver.resolve(new JavaType(Map.class)); - - assertThat(resolvedType.getTypeVariables()).hasSize(2); - assertThat(resolvedType.getTypeVariables().get(0).getRawType()).isEqualTo(String.class); - assertThat(resolvedType.getTypeVariables().get(1).getRawType()).isEqualTo(Integer.class); - } - - @Property - void extractsGenericTypeFromMapWithComplexValues() { - Map addressMap = new HashMap<>(); - addressMap.put("home", new Address("123 Home St", "Seoul", "11111")); - addressMap.put("work", new Address("456 Work Ave", "Busan", "22222")); - - NodeResolver nodeResolver = createNodeResolver("addresses"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - addressMap - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getGenericTypeResolvers()).hasSize(1); - - PathResolver resolver = result.getGenericTypeResolvers().get(0); - GenericTypeResolver genericResolver = resolver.getCustomizer(); - JvmType resolvedType = genericResolver.resolve(new JavaType(Map.class)); - - assertThat(resolvedType.getTypeVariables()).hasSize(2); - assertThat(resolvedType.getTypeVariables().get(0).getRawType()).isEqualTo(String.class); - assertThat(resolvedType.getTypeVariables().get(1).getRawType()).isEqualTo(Address.class); - } - - @Property - void doesNotExtractGenericTypeFromEmptyCollection() { - List emptyList = new ArrayList<>(); - - NodeResolver nodeResolver = createNodeResolver("emptyList"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - emptyList - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getGenericTypeResolvers()).isEmpty(); - - assertThat(result.getInterfaceResolvers()).hasSize(1); - } - - @Property - void doesNotExtractGenericTypeFromEmptyMap() { - Map emptyMap = new HashMap<>(); - - NodeResolver nodeResolver = createNodeResolver("emptyMap"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - emptyMap - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getGenericTypeResolvers()).isEmpty(); - - assertThat(result.getInterfaceResolvers()).hasSize(1); - } - - @Property - void doesNotExtractGenericTypeFromNonCollectionTypes() { - Address address = new Address("123 St", "City", "00000"); - - NodeResolver nodeResolver = createNodeResolver("address"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - address - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getGenericTypeResolvers()).isEmpty(); - } - - @Property - void extractsGenericTypeFromListOfInterfaceImplementations() { - List animals = Arrays.asList(new Dog("Poodle"), new Cat()); - - NodeResolver nodeResolver = createNodeResolver("animals"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - animals - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getGenericTypeResolvers()).hasSize(1); - - PathResolver resolver = result.getGenericTypeResolvers().get(0); - GenericTypeResolver genericResolver = resolver.getCustomizer(); - JvmType resolvedType = genericResolver.resolve(new JavaType(List.class)); - - assertThat(resolvedType.getTypeVariables()).hasSize(1); - assertThat(resolvedType.getTypeVariables().get(0).getRawType()).isEqualTo(Dog.class); - } - - @Property - void extractsBothInterfaceAndGenericResolversFromList() { - List items = new ArrayList<>(Arrays.asList("a", "b", "c")); - - NodeResolver nodeResolver = createNodeResolver("items"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - items - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getInterfaceResolvers()).hasSize(1); - assertThat(result.getGenericTypeResolvers()).hasSize(1); - - PathResolver interfaceResolver = result.getInterfaceResolvers().get(0); - JvmType containerType = interfaceResolver.getCustomizer().resolve(new JavaType(List.class)); - assertThat(containerType).isNotNull(); - assertThat(List.class.isAssignableFrom(containerType.getRawType())).isTrue(); - - PathResolver genericResolver = result.getGenericTypeResolvers().get(0); - JvmType resolvedType = genericResolver.getCustomizer().resolve(new JavaType(List.class)); - assertThat(resolvedType.getTypeVariables().get(0).getRawType()).isEqualTo(String.class); - } - - @Property - void extractsGenericTypeFromNestedListOfLists() { - List> nestedList = Arrays.asList(Arrays.asList("a", "b"), Arrays.asList("c", "d")); - - NodeResolver nodeResolver = createNodeResolver("matrix"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - nestedList - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getGenericTypeResolvers()).hasSize(1); - - PathResolver resolver = result.getGenericTypeResolvers().get(0); - GenericTypeResolver genericResolver = resolver.getCustomizer(); - JvmType resolvedType = genericResolver.resolve(new JavaType(List.class)); - - assertThat(resolvedType.getTypeVariables()).hasSize(1); - assertThat(List.class.isAssignableFrom(resolvedType.getTypeVariables().get(0).getRawType())).isTrue(); - } - - @Property - void extractsGenericTypeFromCustomGenericSubclass() { - StringContainer container = new StringContainer("test value", "Test Label"); - - NodeResolver nodeResolver = createNodeResolver("container"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - container - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getGenericTypeResolvers()).hasSize(1); - - PathResolver resolver = result.getGenericTypeResolvers().get(0); - PathExpression containerPath = PathExpression.root().child("container"); - assertThat(resolver.matches(containerPath)).isTrue(); - - GenericTypeResolver genericResolver = resolver.getCustomizer(); - JvmType resolvedType = genericResolver.resolve(new JavaType(Container.class)); - - assertThat(resolvedType.getTypeVariables()).hasSize(1); - assertThat(resolvedType.getTypeVariables().get(0).getRawType()).isEqualTo(String.class); - } - - @Property - void extractsGenericTypeFromCustomGenericSubclassWithComplexType() { - AddressContainer container = new AddressContainer(new Address("123 St", "City", "00000"), "Address Label"); - - NodeResolver nodeResolver = createNodeResolver("addressContainer"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - container - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getGenericTypeResolvers()).hasSize(1); - - PathResolver resolver = result.getGenericTypeResolvers().get(0); - GenericTypeResolver genericResolver = resolver.getCustomizer(); - JvmType resolvedType = genericResolver.resolve(new JavaType(Container.class)); - - assertThat(resolvedType.getTypeVariables()).hasSize(1); - assertThat(resolvedType.getTypeVariables().get(0).getRawType()).isEqualTo(Address.class); - } - - @Property - void extractsGenericTypeFromInterfaceImplementation() { - IntegerWrapper wrapper = new IntegerWrapper(42); - - NodeResolver nodeResolver = createNodeResolver("wrapper"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - wrapper - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getGenericTypeResolvers()).hasSize(1); - - PathResolver resolver = result.getGenericTypeResolvers().get(0); - GenericTypeResolver genericResolver = resolver.getCustomizer(); - JvmType resolvedType = genericResolver.resolve(new JavaType(Wrapper.class)); - - assertThat(resolvedType.getTypeVariables()).hasSize(1); - assertThat(resolvedType.getTypeVariables().get(0).getRawType()).isEqualTo(Integer.class); - } - - @Property - void extractsMultipleGenericTypeArgumentsFromSubclass() { - StringIntPair pair = new StringIntPair("key", 100); - - NodeResolver nodeResolver = createNodeResolver("pair"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - pair - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getGenericTypeResolvers()).hasSize(1); - - PathResolver resolver = result.getGenericTypeResolvers().get(0); - GenericTypeResolver genericResolver = resolver.getCustomizer(); - JvmType resolvedType = genericResolver.resolve(new JavaType(Pair.class)); - - assertThat(resolvedType.getTypeVariables()).hasSize(2); - assertThat(resolvedType.getTypeVariables().get(0).getRawType()).isEqualTo(String.class); - assertThat(resolvedType.getTypeVariables().get(1).getRawType()).isEqualTo(Integer.class); - } - - @Property - void doesNotExtractGenericTypeFromRawGenericType() { - Container container = new Container<>("test", "label"); - - NodeResolver nodeResolver = createNodeResolver("rawContainer"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - container - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getGenericTypeResolvers()).isEmpty(); - } - - @Property - void extractsGenericTypeFromAnonymousSubclass() { - Container container = new Container(3.14, "Pi") { - }; - - NodeResolver nodeResolver = createNodeResolver("anonymousContainer"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - container - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getGenericTypeResolvers()).hasSize(1); - - PathResolver resolver = result.getGenericTypeResolvers().get(0); - GenericTypeResolver genericResolver = resolver.getCustomizer(); - JvmType resolvedType = genericResolver.resolve(new JavaType(Container.class)); - - assertThat(resolvedType.getTypeVariables()).hasSize(1); - assertThat(resolvedType.getTypeVariables().get(0).getRawType()).isEqualTo(Double.class); - } - - @Property - void extractsContainerSizeFromList() { - List items = Arrays.asList("a", "b", "c"); - - NodeResolver nodeResolver = createNodeResolver("items"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - items - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getContainerSizeResolvers()).hasSize(1); - - PathResolver resolver = result.getContainerSizeResolvers().get(0); - PathExpression itemsPath = PathExpression.root().child("items"); - assertThat(resolver.matches(itemsPath)).isTrue(); - - ContainerSizeResolver sizeResolver = resolver.getCustomizer(); - assertThat(sizeResolver.resolveContainerSize(new JavaType(List.class))).isEqualTo(3); - } - - @Property - void extractsContainerSizeFromMap() { - Map scores = new HashMap<>(); - scores.put("Alice", 100); - scores.put("Bob", 95); - - NodeResolver nodeResolver = createNodeResolver("scores"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - scores - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getContainerSizeResolvers()).hasSize(1); - - PathResolver resolver = result.getContainerSizeResolvers().get(0); - ContainerSizeResolver sizeResolver = resolver.getCustomizer(); - assertThat(sizeResolver.resolveContainerSize(new JavaType(Map.class))).isEqualTo(2); - } - - @Property - void extractsContainerSizeFromArray() { - String[] items = {"a", "b", "c", "d"}; - - NodeResolver nodeResolver = createNodeResolver("items"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - items - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getContainerSizeResolvers()).hasSize(1); - - PathResolver resolver = result.getContainerSizeResolvers().get(0); - ContainerSizeResolver sizeResolver = resolver.getCustomizer(); - assertThat(sizeResolver.resolveContainerSize(new JavaType(String[].class))).isEqualTo(4); - } - - @Property - void extractsContainerSizeFromEmptyCollection() { - List emptyList = new ArrayList<>(); - - NodeResolver nodeResolver = createNodeResolver("emptyList"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - emptyList - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getContainerSizeResolvers()).hasSize(1); - - PathResolver resolver = result.getContainerSizeResolvers().get(0); - ContainerSizeResolver sizeResolver = resolver.getCustomizer(); - assertThat(sizeResolver.resolveContainerSize(new JavaType(List.class))).isEqualTo(0); - } - - @Property - void doesNotExtractContainerSizeFromNonContainer() { - Address address = new Address("123 St", "City", "00000"); - - NodeResolver nodeResolver = createNodeResolver("address"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - address - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getContainerSizeResolvers()).isEmpty(); - } - - @Property - void extractsAllThreeResolversFromList() { - List items = new ArrayList<>(Arrays.asList("a", "b", "c")); - - NodeResolver nodeResolver = createNodeResolver("items"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - items - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getContainerSizeResolvers()).hasSize(1); - assertThat(result.getGenericTypeResolvers()).hasSize(1); - assertThat(result.getInterfaceResolvers()).hasSize(1); - - ContainerSizeResolver sizeResolver = result.getContainerSizeResolvers().get(0).getCustomizer(); - assertThat(sizeResolver.resolveContainerSize(new JavaType(List.class))).isEqualTo(3); - - GenericTypeResolver genericResolver = result.getGenericTypeResolvers().get(0).getCustomizer(); - JvmType resolvedGeneric = genericResolver.resolve(new JavaType(List.class)); - assertThat(resolvedGeneric.getTypeVariables().get(0).getRawType()).isEqualTo(String.class); - - InterfaceResolver interfaceResolver = result.getInterfaceResolvers().get(0).getCustomizer(); - JvmType resolvedInterface = interfaceResolver.resolve(new JavaType(List.class)); - assertThat(resolvedInterface).isNotNull(); - } - - @Property - void analyzesNestedContainersExtractsAllLevels() { - List> nestedList = Arrays.asList(Arrays.asList("a", "b"), Arrays.asList("c", "d", "e")); - - NodeResolver nodeResolver = createNodeResolver("matrix"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - nestedList - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getContainerSizeResolvers()).hasSize(3); - assertThat(result.getGenericTypeResolvers()).isNotEmpty(); - assertThat(result.getInterfaceResolvers()).isNotEmpty(); - - PathResolver outerSizeResolver = result - .getContainerSizeResolvers() - .stream() - .filter(r -> r.matches(PathExpression.root().child("matrix"))) - .findFirst() - .orElse(null); - assertThat(outerSizeResolver).isNotNull(); - assertThat(outerSizeResolver.getCustomizer().resolveContainerSize(new JavaType(List.class))).isEqualTo(2); - - PathResolver innerSizeResolver0 = result - .getContainerSizeResolvers() - .stream() - .filter(r -> r.matches(PathExpression.root().child("matrix").index(0))) - .findFirst() - .orElse(null); - assertThat(innerSizeResolver0).isNotNull(); - assertThat(innerSizeResolver0.getCustomizer().resolveContainerSize(new JavaType(List.class))).isEqualTo(2); - - PathResolver innerSizeResolver1 = result - .getContainerSizeResolvers() - .stream() - .filter(r -> r.matches(PathExpression.root().child("matrix").index(1))) - .findFirst() - .orElse(null); - assertThat(innerSizeResolver1).isNotNull(); - assertThat(innerSizeResolver1.getCustomizer().resolveContainerSize(new JavaType(List.class))).isEqualTo(3); - } - - @Property - void analyzesMapWithListValues() { - Map> mapWithLists = new HashMap<>(); - mapWithLists.put("scores", Arrays.asList(100, 95, 88)); - mapWithLists.put("ages", Arrays.asList(25, 30)); - - NodeResolver nodeResolver = createNodeResolver("data"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - mapWithLists - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getContainerSizeResolvers()).hasSize(3); - - PathResolver mapSizeResolver = result - .getContainerSizeResolvers() - .stream() - .filter(r -> r.matches(PathExpression.root().child("data"))) - .findFirst() - .orElse(null); - assertThat(mapSizeResolver).isNotNull(); - assertThat(mapSizeResolver.getCustomizer().resolveContainerSize(new JavaType(Map.class))).isEqualTo(2); - - assertThat(result.getGenericTypeResolvers()).isNotEmpty(); - } - - @Property - void analyzesListOfMaps() { - List> listOfMaps = Arrays.asList(createMap("a", 1, "b", 2), createMap("c", 3)); - - NodeResolver nodeResolver = createNodeResolver("records"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - listOfMaps - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getContainerSizeResolvers()).hasSize(3); - - PathResolver listSizeResolver = result - .getContainerSizeResolvers() - .stream() - .filter(r -> r.matches(PathExpression.root().child("records"))) - .findFirst() - .orElse(null); - assertThat(listSizeResolver).isNotNull(); - assertThat(listSizeResolver.getCustomizer().resolveContainerSize(new JavaType(List.class))).isEqualTo(2); - - PathResolver innerMapResolver0 = result - .getContainerSizeResolvers() - .stream() - .filter(r -> r.matches(PathExpression.root().child("records").index(0))) - .findFirst() - .orElse(null); - assertThat(innerMapResolver0).isNotNull(); - assertThat(innerMapResolver0.getCustomizer().resolveContainerSize(new JavaType(Map.class))).isEqualTo(2); - - PathResolver innerMapResolver1 = result - .getContainerSizeResolvers() - .stream() - .filter(r -> r.matches(PathExpression.root().child("records").index(1))) - .findFirst() - .orElse(null); - assertThat(innerMapResolver1).isNotNull(); - assertThat(innerMapResolver1.getCustomizer().resolveContainerSize(new JavaType(Map.class))).isEqualTo(1); - } - - @Property - void analyzesDeeplyNestedStructure() { - List>> deeplyNested = Arrays.asList( - Arrays.asList(Arrays.asList("a", "b"), Arrays.asList("c")), - Arrays.asList(Arrays.asList("d", "e", "f")) - ); - - NodeResolver nodeResolver = createNodeResolver("cube"); - NodeManipulator nodeManipulator = new NodeSetDecomposedValueManipulator<>( - 1, - createDecomposedContainerValueFactory(), - Collections.emptyList(), - deeplyNested - ); - ArbitraryManipulator manipulator = new ArbitraryManipulator(nodeResolver, nodeManipulator); - - AnalysisResult result = ManipulatorAnalyzer.analyze(Collections.singletonList(manipulator)); - - assertThat(result.getContainerSizeResolvers()).hasSize(6); - - PathResolver rootResolver = result - .getContainerSizeResolvers() - .stream() - .filter(r -> r.matches(PathExpression.root().child("cube"))) - .findFirst() - .orElse(null); - assertThat(rootResolver).isNotNull(); - assertThat(rootResolver.getCustomizer().resolveContainerSize(new JavaType(List.class))).isEqualTo(2); - - PathResolver level1Index0 = result - .getContainerSizeResolvers() - .stream() - .filter(r -> r.matches(PathExpression.root().child("cube").index(0))) - .findFirst() - .orElse(null); - assertThat(level1Index0).isNotNull(); - assertThat(level1Index0.getCustomizer().resolveContainerSize(new JavaType(List.class))).isEqualTo(2); - - PathResolver level1Index1 = result - .getContainerSizeResolvers() - .stream() - .filter(r -> r.matches(PathExpression.root().child("cube").index(1))) - .findFirst() - .orElse(null); - assertThat(level1Index1).isNotNull(); - assertThat(level1Index1.getCustomizer().resolveContainerSize(new JavaType(List.class))).isEqualTo(1); - - PathResolver level2Index00 = result - .getContainerSizeResolvers() - .stream() - .filter(r -> r.matches(PathExpression.root().child("cube").index(0).index(0))) - .findFirst() - .orElse(null); - assertThat(level2Index00).isNotNull(); - assertThat(level2Index00.getCustomizer().resolveContainerSize(new JavaType(List.class))).isEqualTo(2); - - PathResolver level2Index01 = result - .getContainerSizeResolvers() - .stream() - .filter(r -> r.matches(PathExpression.root().child("cube").index(0).index(1))) - .findFirst() - .orElse(null); - assertThat(level2Index01).isNotNull(); - assertThat(level2Index01.getCustomizer().resolveContainerSize(new JavaType(List.class))).isEqualTo(1); - - PathResolver level2Index10 = result - .getContainerSizeResolvers() - .stream() - .filter(r -> r.matches(PathExpression.root().child("cube").index(1).index(0))) - .findFirst() - .orElse(null); - assertThat(level2Index10).isNotNull(); - assertThat(level2Index10.getCustomizer().resolveContainerSize(new JavaType(List.class))).isEqualTo(3); - } - - private Map createMap(Object... keyValues) { - Map map = new HashMap<>(); - for (int i = 0; i < keyValues.length; i += 2) { - map.put((String)keyValues[i], (Integer)keyValues[i + 1]); - } - return map; - } - - private NodeResolver createNodeResolver(String propertyName) { - return new CompositeNodeResolver( - new NodePredicateResolver(StartNodePredicate.INSTANCE), - new NodePredicateResolver(new PropertyNameNodePredicate(propertyName)) - ); - } - - private DecomposedContainerValueFactory createDecomposedContainerValueFactory() { - return new DefaultDecomposedContainerValueFactory(value -> null); - } - - interface Animal { - String getName(); - } - - static class Dog implements Animal { - - private String breed; - - public Dog() { - } - - public Dog(String breed) { - this.breed = breed; - } - - @Override - public String getName() { - return "Dog"; - } - - public String getBreed() { - return breed; - } - } - - static class Cat implements Animal { - - @Override - public String getName() { - return "Cat"; - } - } - - static class Person { - - private String name; - private int age; - private Address address; - private List hobbies; - - public Person() { - } - - public Person(String name, int age, Address address, List hobbies) { - this.name = name; - this.age = age; - this.address = address; - this.hobbies = hobbies; - } - - public String getName() { - return name; - } - - public int getAge() { - return age; - } - - public Address getAddress() { - return address; - } - - public List getHobbies() { - return hobbies; - } - } - - static class Address { - - private String street; - private String city; - private String zipCode; - - public Address() { - } - - public Address(String street, String city, String zipCode) { - this.street = street; - this.city = city; - this.zipCode = zipCode; - } - - public String getStreet() { - return street; - } - - public String getCity() { - return city; - } - - public String getZipCode() { - return zipCode; - } - } - - static class Container { - - private T value; - private String label; - - public Container() { - } - - public Container(T value, String label) { - this.value = value; - this.label = label; - } - - public T getValue() { - return value; - } - - public String getLabel() { - return label; - } - } - - static class StringContainer extends Container { - - public StringContainer() { - super(); - } - - public StringContainer(String value, String label) { - super(value, label); - } - } - - static class AddressContainer extends Container
    { - - public AddressContainer() { - super(); - } - - public AddressContainer(Address value, String label) { - super(value, label); - } - } - - interface Wrapper { - T unwrap(); - } - - static class IntegerWrapper implements Wrapper { - - private Integer value; - - public IntegerWrapper(Integer value) { - this.value = value; - } - - @Override - public Integer unwrap() { - return value; - } - } - - static class Pair { - - private K first; - private V second; - - public Pair() { - } - - public Pair(K first, V second) { - this.first = first; - this.second = second; - } - - public K getFirst() { - return first; - } - - public V getSecond() { - return second; - } - } - - static class StringIntPair extends Pair { - - public StringIntPair() { - super(); - } - - public StringIntPair(String first, Integer second) { - super(first, second); - } - } - - static class Order { - - private String orderId; - private List items; - private Map metadata; - - public Order() { - } - - public Order(String orderId, List items, Map metadata) { - this.orderId = orderId; - this.items = items; - this.metadata = metadata; - } - - public String getOrderId() { - return orderId; - } - - public List getItems() { - return items; - } - - public Map getMetadata() { - return metadata; - } - } - - static class OrderItem { - - private String productName; - private int quantity; - private double price; - - public OrderItem() { - } - - public OrderItem(String productName, int quantity, double price) { - this.productName = productName; - this.quantity = quantity; - this.price = price; - } - - public String getProductName() { - return productName; - } - - public int getQuantity() { - return quantity; - } - - public double getPrice() { - return price; - } - } -} diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/resolver/AbstractTypeResolverTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/resolver/AbstractTypeResolverTest.java new file mode 100644 index 0000000000..2befa356dd --- /dev/null +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/resolver/AbstractTypeResolverTest.java @@ -0,0 +1,207 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.fixturemonkey.resolver; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import java.util.Collections; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.junit.jupiter.api.Test; + +import com.navercorp.fixturemonkey.api.property.CandidateConcretePropertyResolver; +import com.navercorp.fixturemonkey.api.property.Property; +import com.navercorp.fixturemonkey.property.JvmNodePropertyFactory; +import com.navercorp.objectfarm.api.node.SeedState; +import com.navercorp.objectfarm.api.type.JavaType; +import com.navercorp.objectfarm.api.type.JvmType; + +class AbstractTypeResolverTest { + + interface Animal { + } + + interface Mammal extends Animal { + } + + static class Dog implements Mammal { + } + + static class Cat implements Animal { + } + + abstract static class Bird { + } + + static class Sparrow extends Bird { + } + + private final AbstractTypeResolver resolver = new AbstractTypeResolver(new SeedState(0)); + private static final Function NO_LOOKUP = p -> null; + + @Test + void concreteInputReturnsUnchanged() { + // given + JvmType input = new JavaType(Dog.class); + + // when + JvmType result = resolver.resolve(input, NO_LOOKUP, 10); + + // then + assertThat(result.getRawType()).isEqualTo(Dog.class); + } + + @Test + void abstractInputWithoutLookupReturnsUnchanged() { + // given + JvmType input = new JavaType(Animal.class); + + // when + JvmType result = resolver.resolve(input, NO_LOOKUP, 10); + + // then + assertThat(result.getRawType()).isEqualTo(Animal.class); + } + + @Test + void interfaceResolvesToConcrete() { + // given + Function lookup = property -> + property.getJvmType().getRawType() == Animal.class ? candidates(Dog.class) : null; + + // when + JvmType result = resolver.resolve(new JavaType(Animal.class), lookup, 10); + + // then + assertThat(result.getRawType()).isEqualTo(Dog.class); + } + + @Test + void abstractClassResolvesToConcrete() { + // given + Function lookup = property -> + property.getJvmType().getRawType() == Bird.class ? candidates(Sparrow.class) : null; + + // when + JvmType result = resolver.resolve(new JavaType(Bird.class), lookup, 10); + + // then + assertThat(result.getRawType()).isEqualTo(Sparrow.class); + } + + @Test + void multiHopChainResolves() { + // given + Function lookup = property -> { + Class raw = property.getJvmType().getRawType(); + if (raw == Animal.class) { + return candidates(Mammal.class); + } + if (raw == Mammal.class) { + return candidates(Dog.class); + } + return null; + }; + + // when + JvmType result = resolver.resolve(new JavaType(Animal.class), lookup, 10); + + // then + assertThat(result.getRawType()).isEqualTo(Dog.class); + } + + @Test + void selfCycleTerminates() { + // given + Function lookup = property -> + property.getJvmType().getRawType() == Animal.class ? candidates(Animal.class) : null; + + // when + JvmType result = resolver.resolve(new JavaType(Animal.class), lookup, 10); + + // then + assertThat(result.getRawType()).isEqualTo(Animal.class); + } + + @Test + void depthLimitStopsBeforeReachingConcrete() { + // given + Function lookup = property -> { + Class raw = property.getJvmType().getRawType(); + if (raw == Animal.class) { + return candidates(Mammal.class); + } + if (raw == Mammal.class) { + return candidates(Dog.class); + } + return null; + }; + + // when + JvmType result = resolver.resolve(new JavaType(Animal.class), lookup, 1); + + // then + assertThat(result.getRawType()).isEqualTo(Mammal.class); + } + + @Test + void zeroDepthReturnsInputUnchanged() { + // given + Function lookup = property -> candidates(Dog.class); + + // when + JvmType result = resolver.resolve(new JavaType(Animal.class), lookup, 0); + + // then + assertThat(result.getRawType()).isEqualTo(Animal.class); + } + + @Test + void emptyCandidatesReturnUnchanged() { + // given + Function lookup = property -> p -> Collections.emptyList(); + + // when + JvmType result = resolver.resolve(new JavaType(Animal.class), lookup, 10); + + // then + assertThat(result.getRawType()).isEqualTo(Animal.class); + } + + @Test + void multipleCandidatesPickOneOfThem() { + // given + Function lookup = property -> + property.getJvmType().getRawType() == Animal.class ? candidates(Dog.class, Cat.class) : null; + + // when + JvmType result = resolver.resolve(new JavaType(Animal.class), lookup, 10); + + // then + assertThat(result.getRawType()).isIn(Dog.class, Cat.class); + } + + private static CandidateConcretePropertyResolver candidates(Class... classes) { + return property -> Arrays.stream(classes) + .map(c -> JvmNodePropertyFactory.fromType(new JavaType(c))) + .collect(Collectors.toList()); + } +} diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ApplyAdapterTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ApplyTest.java similarity index 93% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ApplyAdapterTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ApplyTest.java index b6a2f4116f..bb121193ea 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ApplyAdapterTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ApplyTest.java @@ -16,14 +16,13 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; import java.util.List; -import net.jqwik.api.Property; -import net.jqwik.api.PropertyDefaults; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.ArbitraryBuilder; import com.navercorp.fixturemonkey.FixtureMonkey; @@ -33,15 +32,13 @@ import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.StringListWrapper; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.StringWrapper; -@PropertyDefaults(tries = 10) -class ApplyAdapterTest { +class ApplyTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void apply() { // when String actual = SUT.giveMeBuilder(StringListWrapper.class) @@ -54,7 +51,7 @@ void apply() { then(actual).isEqualTo("applied"); } - @Property + @Test void applyWithoutAnyManipulators() { // when StringWrapper actual = SUT.giveMeBuilder(StringWrapper.class) @@ -67,7 +64,7 @@ void applyWithoutAnyManipulators() { then(actual.getValue()).startsWith("applied-"); } - @Property + @Test void applyWithComplexObject() { // when String actual = SUT.giveMeBuilder(ComplexObject.class) @@ -80,7 +77,7 @@ void applyWithComplexObject() { then(actual).isEqualTo("set"); } - @Property + @Test void applyNotAffectedManipulatorsAfterApply() { String actual = SUT.giveMeBuilder(ComplexObject.class) .set("str", "set") @@ -93,7 +90,7 @@ void applyNotAffectedManipulatorsAfterApply() { then(actual).isEqualTo("set"); } - @Property + @Test void applySetElementNull() { String actual = SUT.giveMeBuilder(ComplexObject.class) .thenApply((obj, builder) -> builder.size("strList", 1).setNull("strList[0]")) @@ -104,7 +101,7 @@ void applySetElementNull() { then(actual).isNull(); } - @Property(tries = 100) + @Test void thenApplySetNullElementShouldAlwaysBeNull() { String actual = SUT.giveMeBuilder(ComplexObject.class) .thenApply((obj, builder) -> builder.size("strList", 1).setNull("strList[0]")) @@ -115,7 +112,7 @@ void thenApplySetNullElementShouldAlwaysBeNull() { then(actual).isNull(); } - @Property + @Test void applySampleTwiceReturnsDiff() { ArbitraryBuilder builder = SUT.giveMeBuilder(SimpleObject.class).thenApply((obj, b) -> { }); @@ -125,7 +122,7 @@ void applySampleTwiceReturnsDiff() { then(actual).isNotEqualTo(expected); } - @Property + @Test void applyFixedSize() { String expectedElement = "test"; @@ -138,7 +135,7 @@ void applyFixedSize() { then(actual).allMatch(expectedElement::equals); } - @Property + @Test void acceptIfAlwaysTrue() { String actual = SUT.giveMeBuilder(ComplexObject.class) .acceptIf(it -> true, builder -> builder.set("str", "set")) @@ -148,7 +145,7 @@ void acceptIfAlwaysTrue() { then(actual).isEqualTo("set"); } - @Property + @Test void acceptIf() { String actual = SUT.giveMeBuilder(ComplexObject.class) .set("str", "set") @@ -160,7 +157,7 @@ void acceptIf() { then(actual).isEqualTo("set"); } - @Property + @Test void giveMeListTypeApply() { SimpleObject actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -172,7 +169,7 @@ void giveMeListTypeApply() { then(actual.getStr()).isEqualTo(actual.getInteger() + ""); } - @Property + @Test void acceptIfSetNull() { // when String actual = SUT.giveMeBuilder(ComplexObject.class) @@ -185,7 +182,7 @@ void acceptIfSetNull() { then(actual).isNull(); } - @Property + @Test void acceptIfSetNotNull() { // when SimpleObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -198,7 +195,7 @@ void acceptIfSetNotNull() { then(actual).isNotNull(); } - @Property + @Test void setNullThenAcceptIfSet() { // when String actual = SUT.giveMeBuilder(ComplexObject.class) @@ -211,7 +208,7 @@ void setNullThenAcceptIfSet() { then(actual).isEqualTo("recovered"); } - @Property + @Test void setNotNullThenAcceptIfSetNull() { // when String actual = SUT.giveMeBuilder(ComplexObject.class) diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/BasicGenerationAdapterTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/BasicGenerationTest.java similarity index 92% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/BasicGenerationAdapterTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/BasicGenerationTest.java index 090fc34433..b91ba4ad42 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/BasicGenerationAdapterTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/BasicGenerationTest.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; import static org.assertj.core.api.BDDAssertions.thenNoException; @@ -25,9 +25,9 @@ import java.util.Map; import java.util.function.Supplier; +import org.junit.jupiter.api.Test; + import net.jqwik.api.Arbitrary; -import net.jqwik.api.Property; -import net.jqwik.api.PropertyDefaults; import com.navercorp.fixturemonkey.ArbitraryBuilder; import com.navercorp.fixturemonkey.FixtureMonkey; @@ -43,15 +43,13 @@ import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.StringWrapper; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.StringWrapperList; -@PropertyDefaults(tries = 10) -class BasicGenerationAdapterTest { +class BasicGenerationTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void sampleStringWrapper() { // when StringWrapper actual = SUT.giveMeBuilder(StringWrapper.class).sample(); @@ -61,7 +59,7 @@ void sampleStringWrapper() { then(actual.getValue()).isNotNull(); } - @Property + @Test void sampleStringListWrapper() { // when StringListWrapper actual = SUT.giveMeBuilder(StringListWrapper.class).sample(); @@ -71,7 +69,7 @@ void sampleStringListWrapper() { then(actual.getValues()).isNotNull(); } - @Property + @Test void sampleStringWrapperList() { // when StringWrapperList actual = SUT.giveMeBuilder(StringWrapperList.class).sample(); @@ -81,7 +79,7 @@ void sampleStringWrapperList() { then(actual.getValues()).isNotNull(); } - @Property + @Test void sampleWithTypeReference() { TypeReference type = new TypeReference() { }; @@ -93,7 +91,7 @@ void sampleWithTypeReference() { then(actual.getValues()).isNotNull(); } - @Property + @Test void sampleListTypeReference() { // when List actual = SUT.giveMeBuilder(new TypeReference>() { @@ -102,7 +100,7 @@ void sampleListTypeReference() { then(actual).isNotNull(); } - @Property + @Test void sampleWithType() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class).sample(); @@ -113,14 +111,14 @@ void sampleWithType() { then(actual.getMapEntry()).isNotNull(); } - @Property + @Test void sampleNotGeneratingStaticField() { FixtureMonkey sut = FixtureMonkey.builder().defaultNotNull(true).build(); thenNoException().isThrownBy(() -> sut.giveMeOne(StaticFieldObject.class)); } - @Property + @Test void generatePrimitiveArray() { // when int[] actual = SUT.giveMeBuilder(ComplexObject.class).fixed().sample().getIntArray(); @@ -128,21 +126,21 @@ void generatePrimitiveArray() { then(actual).isNotNull(); } - @Property + @Test void sampleObjectField() { ObjectWrapper actual = SUT.giveMeOne(ObjectWrapper.class); then(actual).isNotNull(); } - @Property + @Test void sampleChild() { Child actual = SUT.giveMeOne(Child.class); then(actual).isNotNull(); } - @Property + @Test void sampleNullableContainerReturnsNotNull() { // when List values = SUT.giveMeOne(NullableObject.class).getValues(); @@ -150,7 +148,7 @@ void sampleNullableContainerReturnsNotNull() { then(values).isNotNull(); } - @Property + @Test void notFixedSampleReturnsDiff() { ArbitraryBuilder builder = SUT.giveMeBuilder(SimpleObject.class); @@ -159,7 +157,7 @@ void notFixedSampleReturnsDiff() { then(sample1).isNotEqualTo(sample2); } - @Property + @Test void sampleSupplier() { Supplier actual = SUT.giveMeBuilder(new TypeReference>() { }).sample(); @@ -168,7 +166,7 @@ void sampleSupplier() { then(actual.get()).isNotNull(); } - @Property + @Test void sampleNestedStrSupplier() { Supplier> actual = SUT.giveMeBuilder( new TypeReference>>() { @@ -180,7 +178,7 @@ void sampleNestedStrSupplier() { then(actual.get().get()).isNotNull(); } - @Property + @Test void supplierReturnsNew() { // given TypeReference> supplierTypeReference = new TypeReference>() { @@ -196,13 +194,13 @@ void supplierReturnsNew() { then(result1).isNotEqualTo(result2); } - @Property + @Test void sampleWildcard() { thenNoException().isThrownBy(() -> SUT.giveMeOne(new TypeReference>() { })); } - @Property + @Test void sampleMapValueWildcardListString() { thenNoException().isThrownBy(() -> SUT.giveMeOne(new TypeReference>>() { })); @@ -221,12 +219,11 @@ public void setNestedValues(List> nestedValues) { } } - @Property + @Test void nestedStringListWrapperWorks() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); StringWrapperListHolder wrapped = sut.giveMeOne(StringWrapperListHolder.class); @@ -235,12 +232,11 @@ void nestedStringListWrapperWorks() { then(wrapped.getNestedValues()).isNotNull(); } - @Property + @Test void nestedStringListWrapperInnerElementIsNotNull() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); StringWrapperListHolder wrapped = sut.giveMeOne(StringWrapperListHolder.class); diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ContainerAdapterTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ContainerTest.java similarity index 93% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ContainerAdapterTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ContainerTest.java index 713fbf6525..e8c0d4a7b4 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ContainerAdapterTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ContainerTest.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; import static org.assertj.core.api.BDDAssertions.thenNoException; @@ -25,8 +25,7 @@ import java.util.Map; import java.util.Set; -import net.jqwik.api.Property; -import net.jqwik.api.PropertyDefaults; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.type.TypeReference; @@ -38,15 +37,13 @@ import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.SimpleObject; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.TwoEnum; -@PropertyDefaults(tries = 10) -class ContainerAdapterTest { +class ContainerTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void sampleEnumSet() { // when Set actual = SUT.giveMeOne(new TypeReference>() { @@ -55,7 +52,7 @@ void sampleEnumSet() { then(actual).hasSizeLessThanOrEqualTo(2); } - @Property + @Test void sampleEnumMap() { Map values = SUT.giveMeOne(new TypeReference>() { }); @@ -63,7 +60,7 @@ void sampleEnumMap() { then(values).hasSizeLessThanOrEqualTo(2); } - @Property + @Test void sampleEnumSetList() { FixtureMonkey sut = FixtureMonkey.builder().defaultNotNull(true).build(); @@ -73,13 +70,13 @@ void sampleEnumSetList() { ); } - @Property + @Test void sampleEnumMapInMap() { thenNoException().isThrownBy(() -> SUT.giveMeOne(new TypeReference>>() { })); } - @Property + @Test void sampleListWildcardEnum() { // when List actual = SUT.giveMeOne(new TypeReference>() { @@ -88,7 +85,7 @@ void sampleListWildcardEnum() { then(actual).isNotNull(); } - @Property + @Test void sampleUniqueSet() { // when Set actual = SUT.giveMeBuilder(new TypeReference>() { @@ -97,7 +94,7 @@ void sampleUniqueSet() { then(actual).hasSize(200); } - @Property + @Test void sampleUniqueMap() { // when Map actual = SUT.giveMeBuilder(new TypeReference>() { @@ -108,7 +105,7 @@ void sampleUniqueMap() { then(actual).hasSize(200); } - @Property + @Test void sampleStandaloneMapEntrySimple() { // when Map.Entry actual = SUT.giveMeBuilder( @@ -122,7 +119,7 @@ void sampleStandaloneMapEntrySimple() { then(actual.getValue()).isNotNull(); } - @Property + @Test void sampleStandaloneMapEntryComplex() { // when Map.Entry actual = SUT.giveMeBuilder( @@ -136,7 +133,7 @@ void sampleStandaloneMapEntryComplex() { then(actual.getValue()).isNotNull(); } - @Property + @Test void sampleMapEntryWrapper() { // when MapEntryWrapper actual = SUT.giveMeBuilder(MapEntryWrapper.class).sample(); @@ -151,7 +148,7 @@ void sampleMapEntryWrapper() { then(actual.getComplexEntry().getValue()).isNotNull(); } - @Property + @Test void sampleNestedListList() { // when ListListStringObject actual = SUT.giveMeBuilder(ListListStringObject.class) @@ -169,7 +166,7 @@ void sampleNestedListList() { } } - @Property + @Test void sampleMapWithListValue() { // when MapStringListObject actual = SUT.giveMeBuilder(MapStringListObject.class) @@ -184,7 +181,7 @@ void sampleMapWithListValue() { } } - @Property + @Test void sampleOptionalWithList() { // when OptionalListStringObject actual = SUT.giveMeBuilder(OptionalListStringObject.class) diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/CustomizationAdapterTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/CustomizationTest.java similarity index 95% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/CustomizationAdapterTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/CustomizationTest.java index ecd66bc28c..f155b1adac 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/CustomizationAdapterTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/CustomizationTest.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static com.navercorp.fixturemonkey.customizer.Values.NOT_NULL; import static org.assertj.core.api.BDDAssertions.then; @@ -43,9 +43,9 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.junit.jupiter.api.Test; + import net.jqwik.api.Arbitraries; -import net.jqwik.api.Property; -import net.jqwik.api.PropertyDefaults; import com.navercorp.fixturemonkey.ArbitraryBuilder; import com.navercorp.fixturemonkey.FixtureMonkey; @@ -62,15 +62,13 @@ import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.StringWrapper; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.StringWrapperList; -@PropertyDefaults(tries = 10) -class CustomizationAdapterTest { +class CustomizationTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void set() { // when StringWrapper actual = SUT.giveMeBuilder(StringWrapper.class).set("value", "str").sample(); @@ -79,7 +77,7 @@ void set() { then(actual.getValue()).isEqualTo("str"); } - @Property + @Test void setDecomposedList() { // given List expected = java.util.Arrays.asList("a", "b", "c", "d", "e"); @@ -90,7 +88,7 @@ void setDecomposedList() { then(actual).isEqualTo(expected); } - @Property + @Test void setNotNullString() { // when String actual = SUT.giveMeBuilder(StringWrapper.class).setNotNull("value").sample().getValue(); @@ -99,7 +97,7 @@ void setNotNullString() { then(actual).isNotNull(); } - @Property + @Test void setNotNullList() { // when List actual = SUT.giveMeBuilder(StringListWrapper.class).setNotNull("values").sample().getValues(); @@ -108,7 +106,7 @@ void setNotNullList() { then(actual).isNotNull(); } - @Property + @Test void setListElement() { String expected = "test"; @@ -122,7 +120,7 @@ void setListElement() { then(actual).isEqualTo(expected); } - @Property + @Test void setAndSetNull() { // when String actual = SUT.giveMeBuilder(StringWrapper.class) @@ -134,7 +132,7 @@ void setAndSetNull() { then(actual).isNull(); } - @Property + @Test void setRootJavaType() { // given String expected = "test"; @@ -145,7 +143,7 @@ void setRootJavaType() { then(actual).isEqualTo(expected); } - @Property + @Test void setStringWrapperListElement() { String expected = "nested-test"; @@ -160,7 +158,7 @@ void setStringWrapperListElement() { then(actual.getValues().get(0).getValue()).isEqualTo(expected); } - @Property + @Test void setComplexObjectField() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class).set("str", "test-str").sample(); @@ -169,7 +167,7 @@ void setComplexObjectField() { then(actual.getStr()).isEqualTo("test-str"); } - @Property + @Test void setDecomposedMap() { // given Map expected = new java.util.HashMap<>(); @@ -185,7 +183,7 @@ void setDecomposedMap() { then(actual).isEqualTo(expected); } - @Property + @Test void setDecomposedValue() { // given SimpleObject expected = new SimpleObject(); @@ -205,7 +203,7 @@ void setDecomposedValue() { then(actual.getStr()).isEqualTo("str"); } - @Property + @Test void setArbitrary() { // given SimpleObject expected = new SimpleObject(); @@ -225,7 +223,7 @@ void setArbitrary() { then(actual.getStr()).isEqualTo("str"); } - @Property + @Test void setOptional() { // given Optional optional = Optional.of("test"); @@ -240,7 +238,7 @@ void setOptional() { then(actual).isEqualTo(optional); } - @Property + @Test void setDecomposedSet() { // given Set expected = new HashSet<>(); @@ -257,7 +255,7 @@ void setDecomposedSet() { then(actual).isEqualTo(expected); } - @Property + @Test void setDecomposedMapEntry() { // given Map.Entry expected = new SimpleEntry<>("a", new SimpleObject()); @@ -271,7 +269,7 @@ void setDecomposedMapEntry() { then(actual).isEqualTo(expected); } - @Property + @Test void setDecomposedOptional() { // given Optional expected = Optional.of("test"); @@ -285,7 +283,7 @@ void setDecomposedOptional() { then(actual).isEqualTo(expected); } - @Property + @Test void setDecomposedOptionalEmpty() { // given Optional expected = Optional.empty(); @@ -299,7 +297,7 @@ void setDecomposedOptionalEmpty() { then(actual).isEqualTo(expected); } - @Property + @Test void setDecomposedOptionalInt() { // given OptionalInt expected = OptionalInt.of(0); @@ -313,7 +311,7 @@ void setDecomposedOptionalInt() { then(actual).isEqualTo(expected); } - @Property + @Test void setDecomposedOptionalLong() { // given OptionalLong expected = OptionalLong.of(0L); @@ -327,7 +325,7 @@ void setDecomposedOptionalLong() { then(actual).isEqualTo(expected); } - @Property + @Test void setDecomposedOptionalDouble() { // given OptionalDouble expected = OptionalDouble.of(0.d); @@ -341,7 +339,7 @@ void setDecomposedOptionalDouble() { then(actual).isEqualTo(expected); } - @Property + @Test void setDecomposedSupplier() { // given Supplier expected = () -> "test"; @@ -355,7 +353,7 @@ void setDecomposedSupplier() { then(actual.get()).isEqualTo(expected.get()); } - @Property + @Test void setDecomposedNestedStrSupplier() { // given Supplier> expected = () -> () -> "test"; @@ -369,7 +367,7 @@ void setDecomposedNestedStrSupplier() { then(actual.get()).isEqualTo(expected.get()); } - @Property + @Test void setAllFields() { // when StringPair actual = SUT.giveMeBuilder(StringPair.class).set("*", "str").sample(); @@ -378,7 +376,7 @@ void setAllFields() { then(actual.getValue2()).isEqualTo("str"); } - @Property + @Test void setWithLimit() { // when List actual = SUT.giveMeBuilder(ComplexObject.class) @@ -392,7 +390,7 @@ void setWithLimit() { then(actual).anyMatch(it -> !"test".equals(it)); } - @Property + @Test void setRootComplexType() { ComplexObject expected = new ComplexObject(); expected.setStr("test"); @@ -403,7 +401,7 @@ void setRootComplexType() { then(actual).isEqualTo(expected); } - @Property + @Test void setNullMap() { // when Map actual = SUT.giveMeBuilder(ComplexObject.class).setNull("map").sample().getMap(); @@ -412,7 +410,7 @@ void setNullMap() { then(actual).isNull(); } - @Property + @Test void setNullMapEntry() { // when Map.Entry actual = SUT.giveMeBuilder(ComplexObject.class) @@ -424,7 +422,7 @@ void setNullMapEntry() { then(actual).isNull(); } - @Property + @Test void setNullSupplier() { // when Supplier actual = SUT.giveMeBuilder(ComplexObject.class) @@ -436,7 +434,7 @@ void setNullSupplier() { then(actual).isNull(); } - @Property + @Test void setNotNullMap() { // when Map actual = SUT.giveMeBuilder(ComplexObject.class).setNotNull("map").sample().getMap(); @@ -445,7 +443,7 @@ void setNotNullMap() { then(actual).isNotNull(); } - @Property + @Test void setNotNullMapEntry() { // when Map.Entry actual = SUT.giveMeBuilder(ComplexObject.class) @@ -457,7 +455,7 @@ void setNotNullMapEntry() { then(actual).isNotNull(); } - @Property + @Test void setNotNullSupplier() { // when Supplier actual = SUT.giveMeBuilder(ComplexObject.class) @@ -469,7 +467,7 @@ void setNotNullSupplier() { then(actual).isNotNull(); } - @Property + @Test void setPrimitiveToReference() { // when int integer = SUT.giveMeBuilder(SimpleObject.class) @@ -480,7 +478,7 @@ void setPrimitiveToReference() { then(integer).isEqualTo(1234); } - @Property + @Test void setReferenceToPrimitive() { // when int integer = SUT.giveMeBuilder(SimpleObject.class).set("wrapperInteger", 1234).sample().getWrapperInteger(); @@ -488,7 +486,7 @@ void setReferenceToPrimitive() { then(integer).isEqualTo(1234); } - @Property + @Test void setFieldWhichObjectIsFixedNull() { String expected = "test"; @@ -502,7 +500,7 @@ void setFieldWhichObjectIsFixedNull() { then(actual).isEqualTo(expected); } - @Property + @Test void setFieldWhichRootIsFixedNull() { String expected = "test"; @@ -515,7 +513,7 @@ void setFieldWhichRootIsFixedNull() { then(actual).isEqualTo(expected); } - @Property + @Test void setIterable() { String expected = "test"; @@ -527,7 +525,7 @@ void setIterable() { then(actual.iterator().next()).isEqualTo(expected); } - @Property + @Test void setIterator() { String expected = "test"; @@ -539,7 +537,7 @@ void setIterator() { then(actual.next()).isEqualTo(expected); } - @Property + @Test void setStream() { String expected = "test"; @@ -551,7 +549,7 @@ void setStream() { then(actual.collect(Collectors.toList()).get(0)).isEqualTo(expected); } - @Property + @Test void setInterface() { InterfaceImplementation expected = new InterfaceImplementation(); expected.setValue("test"); @@ -561,7 +559,7 @@ void setInterface() { then(actual).isEqualTo(expected); } - @Property + @Test void setArbitraryBuilder() { String expected = "test"; @@ -573,7 +571,7 @@ void setArbitraryBuilder() { then(actual).isEqualTo(expected); } - @Property + @Test void setLazyValue() { ArbitraryBuilder variable = SUT.giveMeBuilder(String.class); ArbitraryBuilder builder = SUT.giveMeBuilder(String.class).setLazy("$", variable::sample); @@ -584,7 +582,7 @@ void setLazyValue() { then(actual).isEqualTo("test"); } - @Property + @Test void setLazyValueWithLimit() { ArbitraryBuilder variable = SUT.giveMeBuilder(String.class); @@ -600,7 +598,7 @@ void setLazyValueWithLimit() { then(actual).anyMatch(it -> !"test".equals(it)); } - @Property + @Test void setLazyValueSampleReturnsDifferentValue() { // when ArbitraryBuilder builder = SUT.giveMeBuilder(String.class).setLazy("$", () -> @@ -612,7 +610,7 @@ void setLazyValueSampleReturnsDifferentValue() { then(actual).isNotEqualTo(expected); } - @Property + @Test void setJustSubPropertyNotChanged() { String notExpected = "test"; @@ -625,14 +623,14 @@ void setJustSubPropertyNotChanged() { then(actual).isNotEqualTo(notExpected); } - @Property + @Test void setNotNull() { String actual = SUT.giveMeBuilder(SimpleObject.class).set("str", NOT_NULL).sample().getStr(); then(actual).isNotNull(); } - @Property + @Test void setSupplierObjectField() { String actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -644,7 +642,7 @@ void setSupplierObjectField() { then(actual).isEqualTo("expected"); } - @Property + @Test void setNestedSupplierObjectField() { String actual = SUT.giveMeBuilder(new TypeReference>>() { }) @@ -657,7 +655,7 @@ void setNestedSupplierObjectField() { then(actual).isEqualTo("expected"); } - @Property + @Test void setSupplierObjectFieldUsingRootExp() { String actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -669,7 +667,7 @@ void setSupplierObjectFieldUsingRootExp() { then(actual).isEqualTo("expected"); } - @Property + @Test void setOptionalObjectField() { String actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -681,7 +679,7 @@ void setOptionalObjectField() { then(actual).isEqualTo("expected"); } - @Property + @Test void setOptionalObjectFieldUsingRootExp() { String actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -693,7 +691,7 @@ void setOptionalObjectFieldUsingRootExp() { then(actual).isEqualTo("expected"); } - @Property + @Test void setDecomposeContainerTwice() { List strings = new java.util.ArrayList<>(); strings.add("test"); @@ -707,7 +705,7 @@ void setDecomposeContainerTwice() { then(actual).isEmpty(); } - @Property + @Test void setEmptyMap() { Map map = new HashMap<>(); map.put("test", new SimpleObject()); @@ -721,7 +719,7 @@ void setEmptyMap() { then(actual).isEmpty(); } - @Property + @Test void setPostConditionPrimitiveType() { int actual = SUT.giveMeBuilder(SimpleObject.class) .setPostCondition("integer", Integer.class, i -> i > 0) @@ -731,14 +729,14 @@ void setPostConditionPrimitiveType() { then(actual).isGreaterThan(0); } - @Property + @Test void setNotNullZoneId() { ZoneId actual = SUT.giveMeBuilder(SimpleObject.class).setNotNull("zoneId").sample().getZoneId(); then(actual).isNotNull(); } - @Property + @Test void setNull() { // when String actual = SUT.giveMeBuilder(ComplexObject.class).setNull("str").sample().getStr(); @@ -747,7 +745,7 @@ void setNull() { then(actual).isNull(); } - @Property + @Test void setNullFixedAndNotNullReturnsNotNull() { // when SimpleObject actual = SUT.giveMeBuilder(SimpleObject.class).setNull("$").fixed().setNotNull("$").sample(); @@ -755,7 +753,7 @@ void setNullFixedAndNotNullReturnsNotNull() { then(actual).isNotNull(); } - @Property + @Test void setNullList() { // when List actual = SUT.giveMeBuilder(ComplexObject.class).setNull("strList").sample().getStrList(); @@ -764,7 +762,7 @@ void setNullList() { then(actual).isNull(); } - @Property + @Test void setPostCondition() { // when String actual = SUT.giveMeBuilder(ComplexObject.class) @@ -776,7 +774,7 @@ void setPostCondition() { then(actual).hasSizeGreaterThan(5); } - @Property + @Test void setPostConditionRoot() { // when String actual = SUT.giveMeBuilder(ComplexObject.class) @@ -788,7 +786,7 @@ void setPostConditionRoot() { then(actual).hasSizeGreaterThan(5); } - @Property + @Test void setPostConditionWrongTypeThrows() { thenThrownBy(() -> SUT.giveMeBuilder(ComplexObject.class) @@ -799,7 +797,7 @@ void setPostConditionWrongTypeThrows() { .hasMessageContaining("Wrong type filter is applied."); } - @Property + @Test void setNullNestedObject() { // when SimpleObject actual = SUT.giveMeBuilder(ComplexObject.class).setNull("object").sample().getObject(); @@ -808,7 +806,7 @@ void setNullNestedObject() { then(actual).isNull(); } - @Property + @Test void setNullIntArray() { // when int[] actual = SUT.giveMeBuilder(ComplexObject.class).setNull("intArray").sample().getIntArray(); @@ -817,7 +815,7 @@ void setNullIntArray() { then(actual).isNull(); } - @Property + @Test void setNullStringArray() { // when String[] actual = SUT.giveMeBuilder(ComplexObject.class).setNull("strArray").sample().getStrArray(); @@ -826,7 +824,7 @@ void setNullStringArray() { then(actual).isNull(); } - @Property + @Test void setNullRootType() { // when SimpleObject actual = SUT.giveMeBuilder(SimpleObject.class).setNull("$").sample(); @@ -835,7 +833,7 @@ void setNullRootType() { then(actual).isNull(); } - @Property + @Test void setNullOptional() { // when Optional actual = SUT.giveMeBuilder(new TypeReference>() { @@ -845,7 +843,7 @@ void setNullOptional() { then(actual).isNull(); } - @Property + @Test void setNullNestedField() { // when String actual = SUT.giveMeBuilder(ComplexObject.class).setNull("object.str").sample().getObject().getStr(); @@ -854,7 +852,7 @@ void setNullNestedField() { then(actual).isNull(); } - @Property + @Test void setNullListElement() { // given List list = new ArrayList<>(); @@ -872,7 +870,7 @@ void setNullListElement() { then(actual.getStrList().get(1)).isEqualTo("b"); } - @Property + @Test void setNullListAllElements() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class).size("strList", 3).setNull("strList[*]").sample(); @@ -882,7 +880,7 @@ void setNullListAllElements() { then(actual.getStrList()).containsOnlyNulls(); } - @Property + @Test void setNotNullNestedObject() { // when SimpleObject actual = SUT.giveMeBuilder(ComplexObject.class).setNotNull("object").sample().getObject(); @@ -891,7 +889,7 @@ void setNotNullNestedObject() { then(actual).isNotNull(); } - @Property + @Test void setNotNullIntArray() { // when int[] actual = SUT.giveMeBuilder(ComplexObject.class).setNotNull("intArray").sample().getIntArray(); @@ -900,7 +898,7 @@ void setNotNullIntArray() { then(actual).isNotNull(); } - @Property + @Test void setNotNullStringArray() { // when String[] actual = SUT.giveMeBuilder(ComplexObject.class).setNotNull("strArray").sample().getStrArray(); @@ -909,7 +907,7 @@ void setNotNullStringArray() { then(actual).isNotNull(); } - @Property + @Test void setNotNullRootType() { // when SimpleObject actual = SUT.giveMeBuilder(SimpleObject.class).setNotNull("$").sample(); @@ -918,7 +916,7 @@ void setNotNullRootType() { then(actual).isNotNull(); } - @Property + @Test void setNotNullNestedField() { // when String actual = SUT.giveMeBuilder(ComplexObject.class).setNotNull("object.str").sample().getObject().getStr(); @@ -927,7 +925,7 @@ void setNotNullNestedField() { then(actual).isNotNull(); } - @Property + @Test void setNullThenSet() { // when String actual = SUT.giveMeBuilder(ComplexObject.class).setNull("str").set("str", "override").sample().getStr(); @@ -936,7 +934,7 @@ void setNullThenSet() { then(actual).isEqualTo("override"); } - @Property + @Test void setThenSetNullThenSet() { // when String actual = SUT.giveMeBuilder(ComplexObject.class) @@ -950,7 +948,7 @@ void setThenSetNullThenSet() { then(actual).isEqualTo("last"); } - @Property + @Test void setNullAndSetNotNullDifferentFields() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class).setNull("str").setNotNull("object").sample(); @@ -960,7 +958,7 @@ void setNullAndSetNotNullDifferentFields() { then(actual.getObject()).isNotNull(); } - @Property + @Test void setNullThenSetNotNullSameField() { // when String actual = SUT.giveMeBuilder(ComplexObject.class).setNull("str").setNotNull("str").sample().getStr(); @@ -969,7 +967,7 @@ void setNullThenSetNotNullSameField() { then(actual).isNotNull(); } - @Property + @Test void setNotNullThenSetNullSameField() { // when String actual = SUT.giveMeBuilder(ComplexObject.class).setNotNull("str").setNull("str").sample().getStr(); @@ -978,7 +976,7 @@ void setNotNullThenSetNullSameField() { then(actual).isNull(); } - @Property + @Test void setChildThenSetNullParent() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -990,7 +988,7 @@ void setChildThenSetNullParent() { then(actual.getObject()).isNull(); } - @Property + @Test void setDeepChildThenSetNullAncestor() { // when DeepObject actual = SUT.giveMeBuilder(DeepObject.class) @@ -1002,7 +1000,7 @@ void setDeepChildThenSetNullAncestor() { then(actual.getPolicy()).isNull(); } - @Property + @Test void setNullThenSetLazy() { // when String actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1015,7 +1013,7 @@ void setNullThenSetLazy() { then(actual).isEqualTo("lazy"); } - @Property + @Test void setLazyThenSetNull() { // when String actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1028,7 +1026,7 @@ void setLazyThenSetNull() { then(actual).isNull(); } - @Property + @Test void setNotNullWithPostCondition() { // when String actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1042,7 +1040,7 @@ void setNotNullWithPostCondition() { then(actual).hasSizeGreaterThan(0); } - @Property + @Test void setNotNullThenSet() { // when String actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1055,7 +1053,7 @@ void setNotNullThenSet() { then(actual).isEqualTo("override"); } - @Property + @Test void setThenSetNotNull() { // when String actual = SUT.giveMeBuilder(ComplexObject.class).set("str", "value").setNotNull("str").sample().getStr(); @@ -1064,7 +1062,7 @@ void setThenSetNotNull() { then(actual).isNotNull(); } - @Property + @Test void setNotNullThenSetLazy() { // when String actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1077,7 +1075,7 @@ void setNotNullThenSetLazy() { then(actual).isEqualTo("lazy"); } - @Property + @Test void setLazyThenSetNotNull() { // when String actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1090,7 +1088,7 @@ void setLazyThenSetNotNull() { then(actual).isNotNull(); } - @Property + @Test void setNotNullThenSize() { // when List actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1103,7 +1101,7 @@ void setNotNullThenSize() { then(actual).hasSize(3); } - @Property + @Test void sizeThenSetNotNull() { // when List actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1116,7 +1114,7 @@ void sizeThenSetNotNull() { then(actual).isNotNull(); } - @Property + @Test void sizeThenSetNull() { // when List actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1129,7 +1127,7 @@ void sizeThenSetNull() { then(actual).isNull(); } - @Property + @Test void setNullThenPostCondition() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1141,7 +1139,7 @@ void setNullThenPostCondition() { then(actual.getStr()).isNull(); } - @Property + @Test void postConditionThenSetNotNull() { // when String actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1154,7 +1152,7 @@ void postConditionThenSetNotNull() { then(actual).isNotNull(); } - @Property + @Test void setNullSetThenSize() { // when Set actual = SUT.giveMeBuilder(new TypeReference>() { @@ -1164,7 +1162,7 @@ void setNullSetThenSize() { then(actual).hasSize(3); } - @Property + @Test void setNullArrayThenSize() { // when String[] actual = SUT.giveMeBuilder(new TypeReference() { @@ -1174,7 +1172,7 @@ void setNullArrayThenSize() { then(actual).hasSize(3); } - @Property + @Test void setNullParentThenSetChild() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1187,7 +1185,7 @@ void setNullParentThenSetChild() { then(actual.getObject().getStr()).isEqualTo("child"); } - @Property + @Test void setNotNullParentThenSetChild() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1200,7 +1198,7 @@ void setNotNullParentThenSetChild() { then(actual.getObject().getStr()).isEqualTo("child"); } - @Property + @Test void setChildThenSetNotNullParent() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1212,7 +1210,7 @@ void setChildThenSetNotNullParent() { then(actual.getObject()).isNotNull(); } - @Property + @Test void setNullContainerThenSetNullElement() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1227,7 +1225,7 @@ void setNullContainerThenSetNullElement() { then(actual.getStrList().get(0)).isNull(); } - @Property + @Test void setNullElementThenSetNullContainer() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1240,7 +1238,7 @@ void setNullElementThenSetNullContainer() { then(actual.getStrList()).isNull(); } - @Property + @Test void postConditionThenSetNull() { thenThrownBy(() -> SUT.giveMeBuilder(ComplexObject.class) @@ -1250,7 +1248,7 @@ void postConditionThenSetNull() { ).isExactlyInstanceOf(IllegalArgumentException.class); } - @Property + @Test void setNotNullListElement() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1262,7 +1260,7 @@ void setNotNullListElement() { then(actual.getStrList().get(0)).isNotNull(); } - @Property + @Test void setNotNullListAllElements() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1275,7 +1273,7 @@ void setNotNullListAllElements() { then(actual.getStrList()).allMatch(it -> it != null); } - @Property + @Test void setNotNullTwiceSameField() { // when String actual = SUT.giveMeBuilder(ComplexObject.class).setNotNull("str").setNotNull("str").sample().getStr(); @@ -1284,7 +1282,7 @@ void setNotNullTwiceSameField() { then(actual).isNotNull(); } - @Property + @Test void setNullThenSetNullThenSetNotNull() { // when String actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1298,7 +1296,7 @@ void setNullThenSetNullThenSetNotNull() { then(actual).isNotNull(); } - @Property + @Test void setNullThenSetLazyThenPostCondition() { // when String actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1312,7 +1310,7 @@ void setNullThenSetLazyThenPostCondition() { then(actual).isEqualTo("lazy"); } - @Property + @Test void setLazyThenPostConditionThenSetNull() { thenThrownBy(() -> SUT.giveMeBuilder(ComplexObject.class) @@ -1323,7 +1321,7 @@ void setLazyThenPostConditionThenSetNull() { ).isExactlyInstanceOf(IllegalArgumentException.class); } - @Property + @Test void postConditionThenSetNullThenSetLazy() { // when String actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1337,7 +1335,7 @@ void postConditionThenSetNullThenSetLazy() { then(actual).isEqualTo("lazy"); } - @Property + @Test void setNotNullThenSizeThenPostCondition() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1351,7 +1349,7 @@ void setNotNullThenSizeThenPostCondition() { then(actual.getStrList()).hasSize(2); } - @Property + @Test void setLazyContainerThenSize() { // when StringListWrapper actual = SUT.giveMeBuilder(StringListWrapper.class) @@ -1363,7 +1361,7 @@ void setLazyContainerThenSize() { then(actual.getValues()).hasSize(5); } - @Property + @Test void sizeThenSetLazyElement() { // when StringListWrapper actual = SUT.giveMeBuilder(StringListWrapper.class) @@ -1376,7 +1374,7 @@ void sizeThenSetLazyElement() { then(actual.getValues().get(0)).isEqualTo("LAZY_FIRST"); } - @Property + @Test void setNonPublicJdkListThenApplyOverridesElements() { // given List arraysAsList = Arrays.asList("a", "b"); @@ -1396,7 +1394,7 @@ void setNonPublicJdkListThenApplyOverridesElements() { then(actual.get(1)).isEqualTo("b"); } - @Property + @Test void setCollectionsSingletonListThenApplyOverridesElements() { // given List singletonList = Collections.singletonList("original"); @@ -1415,7 +1413,7 @@ void setCollectionsSingletonListThenApplyOverridesElements() { then(actual.get(0)).isEqualTo("override"); } - @Property + @Test void setIterableWithArraysAsListThenApplyOverridesElements() { // given List arraysAsList = Arrays.asList("a", "b"); diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/DoubleThenApplyAdapterTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/DoubleThenApplyTest.java similarity index 94% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/DoubleThenApplyAdapterTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/DoubleThenApplyTest.java index 9729d1ab58..2c8a0cdf9b 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/DoubleThenApplyAdapterTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/DoubleThenApplyTest.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; @@ -24,8 +24,7 @@ import java.util.Arrays; import java.util.List; -import net.jqwik.api.Property; -import net.jqwik.api.PropertyDefaults; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.ArbitraryBuilder; import com.navercorp.fixturemonkey.FixtureMonkey; @@ -39,15 +38,13 @@ import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.ThreeLevelMid; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.ThreeLevelObject; -@PropertyDefaults(tries = 10) -class DoubleThenApplyAdapterTest { +class DoubleThenApplyTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void directDoubleThenApplyMultiSampleShouldApplyBoth() { ArbitraryBuilder builder = SUT.giveMeBuilder(StringIntComposite.class) .thenApply((obj, b) -> b.set("value1.value", "fromFirst")) @@ -61,11 +58,10 @@ void directDoubleThenApplyMultiSampleShouldApplyBoth() { } } - @Property + @Test void registerThenApplyWithDirectDoubleThenApplyMultiSample() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringWrapper.class, fixture -> fixture.giveMeBuilder(StringWrapper.class) .thenApply((obj, builder) -> builder.set("value", "registered")) @@ -85,11 +81,10 @@ void registerThenApplyWithDirectDoubleThenApplyMultiSample() { } } - @Property + @Test void registerDoubleThenApplyWithDirectDoubleThenApplyMultiSample() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringWrapper.class, fixture -> fixture .giveMeBuilder(StringWrapper.class) @@ -111,11 +106,10 @@ void registerDoubleThenApplyWithDirectDoubleThenApplyMultiSample() { } } - @Property + @Test void nestedRegisteredThenApplyWithDirectDoubleThenApplyMultiSample() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(SimpleObject.class, fixture -> fixture.giveMeBuilder(SimpleObject.class).thenApply((obj, builder) -> builder.set("str", "regStr")) ) @@ -141,11 +135,10 @@ void nestedRegisteredThenApplyWithDirectDoubleThenApplyMultiSample() { } } - @Property + @Test void doubleThenApplySecondSampleShouldApplyOverride() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); ArbitraryBuilder builder = sut @@ -166,11 +159,10 @@ void doubleThenApplySecondSampleShouldApplyOverride() { } } - @Property + @Test void doubleThenApplyWithRegisteredChildSecondSampleShouldApplyOverride() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringWrapper.class, fixture -> fixture.giveMeBuilder(StringWrapper.class) .thenApply((obj, builder) -> builder.set("value", "registered")) @@ -196,11 +188,10 @@ void doubleThenApplyWithRegisteredChildSecondSampleShouldApplyOverride() { } } - @Property + @Test void doubleThenApplyWithComplexObjectMultiSample() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(SimpleObject.class, fixture -> fixture.giveMeBuilder(SimpleObject.class).thenApply((obj, builder) -> builder.set("str", "regStr")) ) @@ -225,11 +216,10 @@ void doubleThenApplyWithComplexObjectMultiSample() { } } - @Property + @Test void tripleThenApplySecondSampleShouldApplyAll() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); ArbitraryBuilder builder = sut @@ -252,11 +242,10 @@ void tripleThenApplySecondSampleShouldApplyAll() { } } - @Property + @Test void doubleThenApplyWithSharedLazyAndRegisteredBuildersMultiSample() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(SimpleObject.class, fixture -> fixture.giveMeBuilder(SimpleObject.class).thenApply((obj, builder) -> builder.set("str", "regStr")) ) @@ -276,7 +265,6 @@ void doubleThenApplyWithSharedLazyAndRegisteredBuildersMultiSample() { }); for (int i = 0; i < 3; i++) { - System.err.println("\n\n====== OUTER SAMPLE #" + i + " ======\n"); ComplexObject actual = builder.sample(); then(actual.getInteger()).as("sample #%d: integer should be 42", i).isEqualTo(42); @@ -286,11 +274,10 @@ void doubleThenApplyWithSharedLazyAndRegisteredBuildersMultiSample() { } } - @Property + @Test void compositePatternRegisterMidFirst() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ThreeLevelMid.class, fixture -> fixture.giveMeBuilder(ThreeLevelMid.class).thenApply((obj, builder) -> builder.set("code", "123456")) ) @@ -321,11 +308,10 @@ void compositePatternRegisterMidFirst() { } } - @Property + @Test void compositePatternRegisterObjectFirst() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ThreeLevelObject.class, fixture -> fixture .giveMeBuilder(ThreeLevelObject.class) @@ -356,11 +342,10 @@ void compositePatternRegisterObjectFirst() { } } - @Property + @Test void compositePatternWithCompositeObjectRegistered() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ThreeLevelMid.class, fixture -> fixture.giveMeBuilder(ThreeLevelMid.class).thenApply((obj, builder) -> builder.set("code", "123456")) ) @@ -392,11 +377,10 @@ void compositePatternWithCompositeObjectRegistered() { } } - @Property + @Test void compositePatternRegisteredBuilderMultiSample() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ThreeLevelMid.class, fixture -> fixture.giveMeBuilder(ThreeLevelMid.class).thenApply((obj, builder) -> builder.set("code", "123456")) ) @@ -429,11 +413,10 @@ void compositePatternRegisteredBuilderMultiSample() { } } - @Property + @Test void registerWithDoubleThenApplyBothShouldApply() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringIntComposite.class, fixture -> fixture .giveMeBuilder(StringIntComposite.class) @@ -449,12 +432,11 @@ void registerWithDoubleThenApplyBothShouldApply() { then(actual.getValue2().getValue()).isEqualTo(42); } - @Property + @Test void directDoubleThenApply_builderSampleTwice() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); ArbitraryBuilder builder = sut @@ -477,12 +459,11 @@ void directDoubleThenApply_builderSampleTwice() { then(second.getLeft().getStockQuantity()).isEqualTo(20L); } - @Property + @Test void directDoubleThenApply_giveMeOneTwice() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); // when @@ -513,12 +494,11 @@ void directDoubleThenApply_giveMeOneTwice() { then(second.getLeft().getStockQuantity()).isEqualTo(20L); } - @Property + @Test void directDoubleThenApply_sampleList() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); // when @@ -539,12 +519,11 @@ void directDoubleThenApply_sampleList() { } } - @Property + @Test void registeredChildSetOnly_directDoubleThenApply_builderSampleTwice() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ThreeLevelMid.class, fixture -> fixture.giveMeBuilder(ThreeLevelMid.class).set("code", "REGISTERED_ITEM") ) @@ -573,12 +552,11 @@ void registeredChildSetOnly_directDoubleThenApply_builderSampleTwice() { then(second.getLeft().getStockQuantity()).isEqualTo(20L); } - @Property + @Test void registeredChildThenApply_directDoubleThenApply_builderSampleTwice() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ThreeLevelMid.class, fixture -> fixture .giveMeBuilder(ThreeLevelMid.class) @@ -612,12 +590,11 @@ void registeredChildThenApply_directDoubleThenApply_builderSampleTwice() { then(second.getLeft().getStockQuantity()).isEqualTo(20L); } - @Property + @Test void registeredChildDoubleThenApply_directDoubleThenApply_builderSampleTwice() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ThreeLevelMid.class, fixture -> fixture .giveMeBuilder(ThreeLevelMid.class) @@ -652,12 +629,11 @@ void registeredChildDoubleThenApply_directDoubleThenApply_builderSampleTwice() { then(second.getLeft().getStockQuantity()).isEqualTo(20L); } - @Property + @Test void registeredDoubleThenApply_builderSampleTwice() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ThreeLevelMid.class, fixture -> fixture.giveMeBuilder(ThreeLevelMid.class).set("code", "REG_ITEM") ) @@ -690,12 +666,11 @@ void registeredDoubleThenApply_builderSampleTwice() { then(second.getLeft().getStockQuantity()).isEqualTo(20L); } - @Property + @Test void registeredDoubleThenApply_giveMeBuilderSampleTwice() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ThreeLevelMid.class, fixture -> fixture.giveMeBuilder(ThreeLevelMid.class).set("code", "REG_ITEM") ) @@ -730,12 +705,11 @@ void registeredDoubleThenApply_giveMeBuilderSampleTwice() { then(second.getLeft().getStockQuantity()).isEqualTo(20L); } - @Property + @Test void directDoubleThenApply_externalSampleNoFixed_builderSampleTwice() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ThreeLevelMid.class, fixture -> fixture.giveMeBuilder(ThreeLevelMid.class).set("code", "REG_ITEM") ) @@ -763,12 +737,11 @@ void directDoubleThenApply_externalSampleNoFixed_builderSampleTwice() { then(second.getLeft().getStockQuantity()).isEqualTo(20L); } - @Property + @Test void directDoubleThenApply_externalSampleFixed_builderSampleTwice() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ThreeLevelMid.class, fixture -> fixture.giveMeBuilder(ThreeLevelMid.class).set("code", "REG_ITEM") ) @@ -799,12 +772,11 @@ void directDoubleThenApply_externalSampleFixed_builderSampleTwice() { then(second.getLeft().getStockQuantity()).isEqualTo(20L); } - @Property + @Test void registerOrderItemFirst_directDoubleThenApply_builderSampleTwice() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ThreeLevelMid.class, fixture -> fixture.giveMeBuilder(ThreeLevelMid.class).set("code", "REG_ITEM") ) @@ -838,12 +810,11 @@ void registerOrderItemFirst_directDoubleThenApply_builderSampleTwice() { then(second.getLeft().getStockQuantity()).isEqualTo(20L); } - @Property + @Test void registerOrderProductFirst_directDoubleThenApply_builderSampleTwice() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ThreeLevelObject.class, fixture -> fixture .giveMeBuilder(ThreeLevelObject.class) @@ -877,12 +848,11 @@ void registerOrderProductFirst_directDoubleThenApply_builderSampleTwice() { then(second.getLeft().getStockQuantity()).isEqualTo(20L); } - @Property + @Test void directTripleThenApply_builderSampleTwice() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ThreeLevelMid.class, fixture -> fixture.giveMeBuilder(ThreeLevelMid.class).set("code", "REG_ITEM") ) @@ -915,12 +885,11 @@ void directTripleThenApply_builderSampleTwice() { then(second.getLeft().getStockQuantity()).isEqualTo(20L); } - @Property + @Test void directDoubleThenApply_outerFixed_sampleTwice() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ThreeLevelMid.class, fixture -> fixture.giveMeBuilder(ThreeLevelMid.class).set("code", "REG_ITEM") ) @@ -949,12 +918,11 @@ void directDoubleThenApply_outerFixed_sampleTwice() { then(second.getLeft().getStockQuantity()).isEqualTo(20L); } - @Property + @Test void directDoubleThenApply_interleavedOtherTypeSampling() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ThreeLevelMid.class, fixture -> fixture.giveMeBuilder(ThreeLevelMid.class).set("code", "REG_ITEM") ) @@ -986,12 +954,11 @@ void directDoubleThenApply_interleavedOtherTypeSampling() { then(second.getLeft().getStockQuantity()).isEqualTo(20L); } - @Property + @Test void directDoubleThenApply_withContainerSize_builderSampleTwice() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ThreeLevelMid.class, fixture -> fixture.giveMeBuilder(ThreeLevelMid.class).set("code", "REG_ITEM") ) @@ -1023,12 +990,11 @@ void directDoubleThenApply_withContainerSize_builderSampleTwice() { then(second.getLeft().getEntries()).hasSize(2); } - @Property + @Test void registeredDoubleThenApply_directAdditionalThenApply_builderSampleTwice() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ThreeLevelMid.class, fixture -> fixture.giveMeBuilder(ThreeLevelMid.class).set("code", "REG_ITEM") ) @@ -1066,12 +1032,11 @@ void registeredDoubleThenApply_directAdditionalThenApply_builderSampleTwice() { then(second.getLeft().getStockQuantity()).isEqualTo(20L); } - @Property + @Test void complexObject_directDoubleThenApply_builderSampleTwice() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(SimpleObject.class, fixture -> fixture.giveMeBuilder(SimpleObject.class).set("str", "REGISTERED")) .build(); @@ -1094,12 +1059,11 @@ void complexObject_directDoubleThenApply_builderSampleTwice() { then(second.getStrList()).containsExactly("a", "b", "c"); } - @Property + @Test void directDoubleThenApply_setBothFieldsInFirst_builderSampleTwice() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ThreeLevelMid.class, fixture -> fixture.giveMeBuilder(ThreeLevelMid.class).set("code", "REG_ITEM") ) @@ -1135,12 +1099,11 @@ void directDoubleThenApply_setBothFieldsInFirst_builderSampleTwice() { then(second.getRight().getPrice()).isEqualTo(648L); } - @Property + @Test void directDoubleThenApply_manySamples() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ThreeLevelMid.class, fixture -> fixture.giveMeBuilder(ThreeLevelMid.class).set("code", "REG_ITEM") ) @@ -1171,12 +1134,11 @@ void directDoubleThenApply_manySamples() { } } - @Property + @Test void registeredWithSize_directDoubleThenApply_builderSampleTwice() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ThreeLevelMid.class, fixture -> fixture.giveMeBuilder(ThreeLevelMid.class).set("code", "REG_ITEM").size("leaves", 2) ) @@ -1206,12 +1168,11 @@ void registeredWithSize_directDoubleThenApply_builderSampleTwice() { then(second.getRight().getMids()).hasSize(3); } - @Property + @Test void directThenApplyThenAcceptIf_builderSampleTwice() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); ArbitraryBuilder builder = sut @@ -1236,12 +1197,11 @@ void directThenApplyThenAcceptIf_builderSampleTwice() { then(second.getLeft().getStockQuantity()).isEqualTo(20L); } - @Property + @Test void directDoubleThenApply_sharedFixtureMonkey_builderSampleTwice() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(NestedListObject.class, fixture -> fixture.giveMeBuilder(NestedListObject.class).set("id", 12345L).size("entries", 2).size("items", 1) ) @@ -1278,12 +1238,11 @@ void directDoubleThenApply_sharedFixtureMonkey_builderSampleTwice() { then(second.getLeft().getId()).isEqualTo(12345L); } - @Property + @Test void registeredBuilderSamplesOtherRegisteredBuilder_doubleThenApply() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(NestedListObject.class, fixture -> fixture.giveMeBuilder(NestedListObject.class).set("id", 12345L).size("entries", 2).size("items", 1) ) @@ -1325,12 +1284,11 @@ void registeredBuilderSamplesOtherRegisteredBuilder_doubleThenApply() { then(second.getLeft().getId()).isEqualTo(12345L); } - @Property + @Test void registeredDoubleThenApply_builderFromGiveMeBuilder_sampleTwice() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(NestedListObject.class, fixture -> fixture.giveMeBuilder(NestedListObject.class).set("id", 12345L) ) @@ -1374,12 +1332,11 @@ void registeredDoubleThenApply_builderFromGiveMeBuilder_sampleTwice() { then(third.getLeft().getStockQuantity()).isEqualTo(20L); } - @Property + @Test void registeredDoubleThenApply_directSetOverride_builderSampleTwice() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ThreeLevelMid.class, fixture -> fixture .giveMeBuilder(ThreeLevelMid.class) @@ -1417,12 +1374,11 @@ void registeredDoubleThenApply_directSetOverride_builderSampleTwice() { then(second.getLeft().getStockQuantity()).isEqualTo(20L); } - @Property + @Test void setObjectInThenApply_nestedContainerSizePreserved_builderSampleTwice() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); ArbitraryBuilder builder = sut @@ -1445,12 +1401,11 @@ void setObjectInThenApply_nestedContainerSizePreserved_builderSampleTwice() { then(second.getLeft().getEntries()).hasSize(3); } - @Property + @Test void registeredDoubleThenApply_nestedContainerSizePreserved_builderSampleTwice() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ThreeLevelMid.class, fixture -> fixture .giveMeBuilder(ThreeLevelMid.class) @@ -1493,12 +1448,11 @@ void registeredDoubleThenApply_nestedContainerSizePreserved_builderSampleTwice() then(second.getLeft().getEntries()).hasSize(3); } - @Property + @Test void registeredDoubleThenApply_childAndWildcardSet_consistentAcrossSamples() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(CompositeObject.class, fixture -> fixture .giveMeBuilder(CompositeObject.class) diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/FixedSampleAdapterTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/FixedSampleTest.java similarity index 92% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/FixedSampleAdapterTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/FixedSampleTest.java index c9066ac2b3..640ffe7965 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/FixedSampleAdapterTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/FixedSampleTest.java @@ -16,15 +16,15 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; import java.util.List; +import org.junit.jupiter.api.Test; + import net.jqwik.api.Arbitraries; -import net.jqwik.api.Property; -import net.jqwik.api.PropertyDefaults; import com.navercorp.fixturemonkey.ArbitraryBuilder; import com.navercorp.fixturemonkey.FixtureMonkey; @@ -32,15 +32,13 @@ import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.SimpleObject; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.StringListWrapper; -@PropertyDefaults(tries = 10) -class FixedSampleAdapterTest { +class FixedSampleTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void fixedSampleReturnsSame() { ArbitraryBuilder fixedBuilder = SUT.giveMeBuilder(SimpleObject.class).fixed(); @@ -49,7 +47,7 @@ void fixedSampleReturnsSame() { then(sample1.getStr()).isEqualTo(sample2.getStr()); } - @Property + @Test void arbitraryFixedSampleReturnsSame() { ArbitraryBuilder fixedBuilder = SUT.giveMeBuilder(SimpleObject.class) .set("str", Arbitraries.of("value1", "value2")) @@ -60,14 +58,14 @@ void arbitraryFixedSampleReturnsSame() { then(sample1.getStr()).isEqualTo(sample2.getStr()); } - @Property + @Test void setNullFixedReturnsNull() { SimpleObject actual = SUT.giveMeBuilder(SimpleObject.class).setNull("$").fixed().sample(); then(actual).isNull(); } - @Property + @Test void fixedRangedSizeReturnsSameSize() { ArbitraryBuilder fixedBuilder = SUT.giveMeBuilder(StringListWrapper.class) .size("values", 1, 5) @@ -78,7 +76,7 @@ void fixedRangedSizeReturnsSameSize() { then(actual).isEqualTo(expected); } - @Property + @Test void setNullFixed() { String expected = "test"; @@ -93,7 +91,7 @@ void setNullFixed() { then(actual).isEqualTo(expected); } - @Property + @Test void fixedOnDifferentBuilderCopiesProducesSameContainerSize() { // given ArbitraryBuilder base = SUT.giveMeBuilder(StringListWrapper.class).fixed(); @@ -110,7 +108,7 @@ void fixedOnDifferentBuilderCopiesProducesSameContainerSize() { then(size2).isEqualTo(size3); } - @Property + @Test void fixedOnDifferentBuilderCopiesProducesSameNestedContainerSize() { // given ArbitraryBuilder base = SUT.giveMeBuilder(ComplexObject.class).fixed(); diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyOptionsAdditionalTestSpecs.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyOptionsAdditionalTestSpecs.java index de3e6e6f40..8ee5de52b5 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyOptionsAdditionalTestSpecs.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyOptionsAdditionalTestSpecs.java @@ -19,7 +19,6 @@ package com.navercorp.fixturemonkey.test; import java.beans.ConstructorProperties; -import java.lang.reflect.AnnotatedType; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -50,7 +49,6 @@ import com.navercorp.fixturemonkey.api.property.ElementProperty; import com.navercorp.fixturemonkey.api.property.Property; import com.navercorp.fixturemonkey.api.type.TypeReference; -import com.navercorp.fixturemonkey.api.type.Types; import com.navercorp.fixturemonkey.buildergroup.ArbitraryBuilderGroup; import com.navercorp.fixturemonkey.customizer.InnerSpec; import com.navercorp.fixturemonkey.resolver.ArbitraryBuilderCandidateFactory; @@ -178,19 +176,20 @@ public static class PairContainerPropertyGenerator implements ContainerPropertyG public ContainerProperty generate(ContainerPropertyGeneratorContext context) { com.navercorp.fixturemonkey.api.property.Property property = context.getProperty(); - List elementTypes = Types.getGenericsTypes(property.getAnnotatedType()); + List elementTypes = + property.getJvmType().getTypeVariables(); if (elementTypes.size() != 2) { throw new IllegalArgumentException( "Pair elementsTypes must be have 1 generics type for element. " + "propertyType: " - + property.getType() + + property.getJvmType().getRawType() + ", elementTypes: " + elementTypes ); } - AnnotatedType firstElementType = elementTypes.get(0); - AnnotatedType secondElementType = elementTypes.get(1); + com.navercorp.objectfarm.api.type.JvmType firstElementType = elementTypes.get(0); + com.navercorp.objectfarm.api.type.JvmType secondElementType = elementTypes.get(1); List elementProperties = new ArrayList<>(); elementProperties.add(new ElementProperty(property, firstElementType, 0, 0)); elementProperties.add(new ElementProperty(property, secondElementType, 1, 1)); diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyOptionsTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyOptionsTest.java index 3a041d55d4..5c3cce1738 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyOptionsTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyOptionsTest.java @@ -24,7 +24,6 @@ import static org.assertj.core.api.BDDAssertions.thenNoException; import static org.assertj.core.api.BDDAssertions.thenThrownBy; -import java.lang.reflect.AnnotatedType; import java.sql.Timestamp; import java.time.Instant; import java.util.ArrayList; @@ -38,9 +37,10 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; +import org.junit.jupiter.api.Test; + import net.jqwik.api.Arbitraries; import net.jqwik.api.Arbitrary; -import net.jqwik.api.Example; import net.jqwik.api.arbitraries.StringArbitrary; import net.jqwik.time.api.DateTimes; import net.jqwik.time.api.arbitraries.InstantArbitrary; @@ -69,7 +69,6 @@ import com.navercorp.fixturemonkey.api.matcher.MatcherOperator; import com.navercorp.fixturemonkey.api.plugin.InterfacePlugin; import com.navercorp.fixturemonkey.api.type.TypeReference; -import com.navercorp.fixturemonkey.api.type.Types; import com.navercorp.fixturemonkey.test.FixtureMonkeyOptionsAdditionalTestSpecs.AbstractNoneConcreteIntValue; import com.navercorp.fixturemonkey.test.FixtureMonkeyOptionsAdditionalTestSpecs.AbstractNoneConcreteStringValue; import com.navercorp.fixturemonkey.test.FixtureMonkeyOptionsAdditionalTestSpecs.AbstractNoneValue; @@ -113,7 +112,7 @@ import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.TwoEnum; class FixtureMonkeyOptionsTest { - @Example + @Test void strictModeSetWrongExpressionThrows() { FixtureMonkey sut = FixtureMonkey.builder().useExpressionStrictMode().build(); @@ -125,7 +124,7 @@ void strictModeSetWrongExpressionThrows() { .hasMessageContaining("No matching results for given NodeResolvers."); } - @Example + @Test void strictModeSizeWrongExpressionThrows() { FixtureMonkey sut = FixtureMonkey.builder().useExpressionStrictMode().build(); @@ -137,7 +136,7 @@ void strictModeSizeWrongExpressionThrows() { .hasMessageContaining("No matching results for given container expression."); } - @Example + @Test void strictModeSizeNestedWrongExpressionThrows() { FixtureMonkey sut = FixtureMonkey.builder().useExpressionStrictMode().build(); @@ -149,7 +148,7 @@ void strictModeSizeNestedWrongExpressionThrows() { .hasMessageContaining("No matching results for given container expression."); } - @Example + @Test void strictModeSetWrongExpressionAfterPushAssignableTypePropertyNameResolverThrows() { FixtureMonkey sut = FixtureMonkey.builder() .useExpressionStrictMode() @@ -164,7 +163,7 @@ void strictModeSetWrongExpressionAfterPushAssignableTypePropertyNameResolverThro .hasMessageContaining("No matching results for given NodeResolvers."); } - @Example + @Test void strictModeSizeWrongExpressionAfterPushAssignableTypePropertyNameResolverThrows() { FixtureMonkey sut = FixtureMonkey.builder() .useExpressionStrictMode() @@ -179,7 +178,7 @@ void strictModeSizeWrongExpressionAfterPushAssignableTypePropertyNameResolverThr .hasMessageContaining("No matching results for given container expression."); } - @Example + @Test void strictModeSetWrongExpressionAfterDefaultPropertyNameResolverThrows() { FixtureMonkey sut = FixtureMonkey.builder() .useExpressionStrictMode() @@ -194,7 +193,7 @@ void strictModeSetWrongExpressionAfterDefaultPropertyNameResolverThrows() { .hasMessageContaining("No matching results for given NodeResolvers."); } - @Example + @Test void strictModeSizeWrongExpressionAfterDefaultPropertyNameResolverThrows() { FixtureMonkey sut = FixtureMonkey.builder() .useExpressionStrictMode() @@ -209,7 +208,7 @@ void strictModeSizeWrongExpressionAfterDefaultPropertyNameResolverThrows() { .hasMessageContaining("No matching results for given container expression."); } - @Example + @Test void notStrictModeSetWrongExpressionDoesNotThrows() { FixtureMonkey sut = FixtureMonkey.builder().build(); @@ -219,7 +218,7 @@ void notStrictModeSetWrongExpressionDoesNotThrows() { .sample()); } - @Example + @Test void notStrictModeSizeWrongExpressionDoesNotThrows() { FixtureMonkey sut = FixtureMonkey.builder().build(); @@ -229,7 +228,7 @@ void notStrictModeSizeWrongExpressionDoesNotThrows() { .sample()); } - @Example + @Test void strictModeMultiOperationValidExpression() { FixtureMonkey sut = FixtureMonkey.builder().useExpressionStrictMode().build(); @@ -246,7 +245,7 @@ void strictModeMultiOperationValidExpression() { then(actual).isEqualTo("expected"); } - @Example + @Test void pushAssignableTypeNullInjectGenerator() { FixtureMonkey sut = FixtureMonkey.builder() .pushAssignableTypeNullInjectGenerator( @@ -260,7 +259,7 @@ void pushAssignableTypeNullInjectGenerator() { then(actual).isNull(); } - @Example + @Test void pushExactTypeNullInjectGenerator() { FixtureMonkey sut = FixtureMonkey.builder() .pushExactTypeNullInjectGenerator( @@ -274,7 +273,7 @@ void pushExactTypeNullInjectGenerator() { then(actual).isNull(); } - @Example + @Test void pushNullInjectGenerator() { FixtureMonkey sut = FixtureMonkey.builder() .pushNullInjectGenerator( @@ -287,7 +286,7 @@ void pushNullInjectGenerator() { then(actual).isNull(); } - @Example + @Test void defaultNullInjectGenerator() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNullInjectGenerator((context) -> 1.0d) @@ -298,7 +297,7 @@ void defaultNullInjectGenerator() { then(actual).isNull(); } - @Example + @Test void pushExactTypePropertyNameResolver() { FixtureMonkey sut = FixtureMonkey.builder() .pushExactTypePropertyNameResolver(String.class, (property) -> "string") @@ -313,7 +312,7 @@ void pushExactTypePropertyNameResolver() { then(actual).isEqualTo(expected); } - @Example + @Test void pushAssignableTypePropertyNameResolver() { FixtureMonkey sut = FixtureMonkey.builder() .pushAssignableTypePropertyNameResolver(Interface.class, (property) -> "interface") @@ -329,7 +328,7 @@ void pushAssignableTypePropertyNameResolver() { then(actual).isEqualTo(expected); } - @Example + @Test void pushPropertyNameResolver() { FixtureMonkey sut = FixtureMonkey.builder() .pushPropertyNameResolver(MatcherOperator.exactTypeMatchOperator(String.class, (property) -> "string")) @@ -344,7 +343,7 @@ void pushPropertyNameResolver() { then(actual).isEqualTo(expected); } - @Example + @Test void defaultPropertyNameResolver() { FixtureMonkey sut = FixtureMonkey.builder() .defaultPropertyNameResolver((property) -> "'" + property.getName() + "'") @@ -359,7 +358,7 @@ void defaultPropertyNameResolver() { then(actual).isEqualTo(expected); } - @Example + @Test void pushAssignableTypeArbitraryIntrospector() { FixtureMonkey sut = FixtureMonkey.builder() .pushAssignableTypeArbitraryIntrospector( @@ -375,7 +374,7 @@ void pushAssignableTypeArbitraryIntrospector() { then(actual).isNull(); } - @Example + @Test void pushExactTypeArbitraryIntrospector() { FixtureMonkey sut = FixtureMonkey.builder() .pushExactTypeArbitraryIntrospector( @@ -391,7 +390,7 @@ void pushExactTypeArbitraryIntrospector() { then(actual).isNull(); } - @Example + @Test void pushArbitraryIntrospector() { FixtureMonkey sut = FixtureMonkey.builder() .pushArbitraryIntrospector( @@ -409,7 +408,7 @@ void pushArbitraryIntrospector() { then(actual).isNull(); } - @Example + @Test void objectIntrospector() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector( @@ -426,19 +425,20 @@ void objectIntrospector() { then(complexObject).isNull(); } - @Example + @Test void pushArbitraryContainerInfoGenerator() { FixtureMonkey sut = FixtureMonkey.builder() .pushArbitraryContainerInfoGenerator( new MatcherOperator<>( (property) -> { - if (Types.getActualType(property.getType()).isArray() - || Types.getGenericsTypes(property.getAnnotatedType()).isEmpty()) { + if (property.getJvmType().getRawType().isArray() + || property.getJvmType().getTypeVariables().isEmpty()) { return false; } - AnnotatedType elementType = Types.getGenericsTypes(property.getAnnotatedType()).get(0); - Class type = Types.getActualType(elementType); + com.navercorp.objectfarm.api.type.JvmType elementType = + property.getJvmType().getTypeVariables().get(0); + Class type = elementType.getRawType(); return type.isAssignableFrom(String.class); }, (context) -> new ArbitraryContainerInfo(5, 5) @@ -452,19 +452,20 @@ void pushArbitraryContainerInfoGenerator() { then(actual).hasSize(5); } - @Example + @Test void pushArbitraryContainerInfoGeneratorNotMatching() { FixtureMonkey sut = FixtureMonkey.builder() .pushArbitraryContainerInfoGenerator( new MatcherOperator<>( (property) -> { - if (Types.getActualType(property.getType()).isArray() - || Types.getGenericsTypes(property.getAnnotatedType()).isEmpty()) { + if (property.getJvmType().getRawType().isArray() + || property.getJvmType().getTypeVariables().isEmpty()) { return false; } - AnnotatedType elementType = Types.getGenericsTypes(property.getAnnotatedType()).get(0); - Class type = Types.getActualType(elementType); + com.navercorp.objectfarm.api.type.JvmType elementType = + property.getJvmType().getTypeVariables().get(0); + Class type = elementType.getRawType(); return type.isAssignableFrom(String.class); }, (context) -> new ArbitraryContainerInfo(5, 5) @@ -478,7 +479,7 @@ void pushArbitraryContainerInfoGeneratorNotMatching() { then(actual).hasSizeBetween(0, 3); } - @Example + @Test void defaultArbitraryContainerMaxSize() { FixtureMonkey sut = FixtureMonkey.builder() .defaultArbitraryContainerInfoGenerator(context -> new ArbitraryContainerInfo(0, 1)) @@ -490,7 +491,7 @@ void defaultArbitraryContainerMaxSize() { then(actual).hasSizeLessThanOrEqualTo(1); } - @Example + @Test void defaultArbitraryContainerInfo() { FixtureMonkey sut = FixtureMonkey.builder() .defaultArbitraryContainerInfoGenerator(context -> new ArbitraryContainerInfo(3, 3)) @@ -502,7 +503,7 @@ void defaultArbitraryContainerInfo() { then(actual).hasSize(3); } - @Example + @Test void javaTypeArbitraryGenerator() { FixtureMonkey sut = FixtureMonkey.builder() .plugin( @@ -521,7 +522,7 @@ public StringArbitrary strings() { then(actual).matches(Pattern.compile("\\d*")); } - @Example + @Test void javaTypeArbitraryGeneratorAffectsField() { FixtureMonkey sut = FixtureMonkey.builder() .plugin( @@ -541,7 +542,7 @@ public StringArbitrary strings() { then(actual).matches(it -> it == null || Pattern.compile("\\d*").matcher(it).matches()); } - @Example + @Test void javaArbitraryResolver() { FixtureMonkey sut = FixtureMonkey.builder() .plugin( @@ -561,7 +562,7 @@ public Arbitrary strings(StringArbitrary stringArbitrary, then(actual).isEqualTo("test"); } - @Example + @Test void javaArbitraryResolverAffectsField() { FixtureMonkey sut = FixtureMonkey.builder() .plugin( @@ -582,7 +583,7 @@ public Arbitrary strings(StringArbitrary stringArbitrary, then(actual).isIn("test", null); } - @Example + @Test void javaTimeTypeArbitraryGenerator() { Instant expected = Instant.now(); FixtureMonkey sut = FixtureMonkey.builder() @@ -602,7 +603,7 @@ public InstantArbitrary instants() { then(actual).isEqualTo(expected); } - @Example + @Test void javaTimeTypeArbitraryGeneratorAffectsField() { Instant expected = Instant.now(); FixtureMonkey sut = FixtureMonkey.builder() @@ -623,7 +624,7 @@ public InstantArbitrary instants() { then(actual).isIn(null, expected); } - @Example + @Test void javaTimeArbitraryResolver() { Instant expected = Instant.now(); FixtureMonkey sut = FixtureMonkey.builder() @@ -646,7 +647,7 @@ public Arbitrary instants( then(actual).isEqualTo(expected); } - @Example + @Test void javaTimeArbitraryResolverAffectsField() { Instant expected = Instant.now(); FixtureMonkey sut = FixtureMonkey.builder() @@ -670,7 +671,7 @@ public Arbitrary instants( then(actual).isIn(expected, null); } - @Example + @Test void alterArbitraryValidator() { FixtureMonkey sut = FixtureMonkey.builder() .arbitraryValidator(obj -> { @@ -682,7 +683,7 @@ void alterArbitraryValidator() { .isExactlyInstanceOf(IllegalArgumentException.class); } - @Example + @Test void defaultNotNull() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) @@ -694,7 +695,7 @@ void defaultNotNull() { then(actual).isNotNull(); } - @Example + @Test void defaultNotNullNotWorksWhenSetDefaultNullInjectGenerator() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNullInjectGenerator( @@ -716,7 +717,7 @@ void defaultNotNullNotWorksWhenSetDefaultNullInjectGenerator() { then(actual).isNull(); } - @Example + @Test void pushExceptGenerateType() { FixtureMonkey sut = FixtureMonkey.builder() .pushExceptGenerateType(new ExactTypeMatcher(String.class)) @@ -727,7 +728,7 @@ void pushExceptGenerateType() { then(actual).isNull(); } - @Example + @Test void addExceptGenerateClass() { FixtureMonkey sut = FixtureMonkey.builder() .addExceptGenerateClass(Timestamp.class) @@ -738,7 +739,7 @@ void addExceptGenerateClass() { then(actual).isNull(); } - @Example + @Test void addExceptGenerateClassNotGenerateField() { FixtureMonkey sut = FixtureMonkey.builder() .addExceptGenerateClass(String.class) @@ -750,7 +751,7 @@ void addExceptGenerateClassNotGenerateField() { then(actual).isNull(); } - @Example + @Test void addExceptGeneratePackage() { FixtureMonkey sut = FixtureMonkey.builder() .addExceptGeneratePackage("java.lang") @@ -761,7 +762,7 @@ void addExceptGeneratePackage() { then(actual).isNull(); } - @Example + @Test void addExceptGeneratePackageNotGenerateField() { FixtureMonkey sut = FixtureMonkey.builder() .addExceptGeneratePackage("java.lang") @@ -773,7 +774,7 @@ void addExceptGeneratePackageNotGenerateField() { then(actual).isNull(); } - @Example + @Test void registerInstance() { FixtureMonkey sut = FixtureMonkey.builder() .register(String.class, monkey -> monkey.giveMeBuilder("test")) @@ -784,7 +785,7 @@ void registerInstance() { then(actual).isEqualTo("test"); } - @Example + @Test void registerField() { FixtureMonkey sut = FixtureMonkey.builder() .register(String.class, monkey -> monkey.giveMeBuilder("test")) @@ -796,7 +797,7 @@ void registerField() { then(actual).isEqualTo("test"); } - @Example + @Test void registerGroup() { FixtureMonkey sut = FixtureMonkey.builder() .registerGroup(RegisterGroup.class) @@ -813,7 +814,7 @@ void registerGroup() { then(actual3.getIntValue()).isEqualTo(RegisterGroup.FIXED_INT_VALUE.getIntValue()); } - @Example + @Test void registerBuilderGroup() { FixtureMonkey sut = FixtureMonkey.builder() .registerGroup(new ChildBuilderGroup()) @@ -830,7 +831,7 @@ void registerBuilderGroup() { then(actual3.getIntValue()).isEqualTo(ChildBuilderGroup.FIXED_INT_VALUE.getIntValue()); } - @Example + @Test void registerSetFirst() { String expected = "test2"; FixtureMonkey sut = FixtureMonkey.builder() @@ -844,7 +845,7 @@ void registerSetFirst() { then(actual).isEqualTo(expected); } - @Example + @Test void registerWithPriority() { FixtureMonkey sut = FixtureMonkey.builder() .register(String.class, monkey -> monkey.giveMeBuilder("test2"), 2) @@ -857,8 +858,7 @@ void registerWithPriority() { then(actual).isEqualTo("test"); } - - @Example + @Test void nullableElement() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNullInjectGenerator( @@ -879,7 +879,7 @@ void nullableElement() { then(actual).allMatch(Objects::isNull); } - @Example + @Test void generateNewContainer() { FixtureMonkey sut = FixtureMonkey.builder() .pushAssignableTypeContainerPropertyGenerator(Pair.class, new PairContainerPropertyGenerator()) @@ -893,7 +893,7 @@ void generateNewContainer() { then(pair).isNotNull(); } - @Example + @Test void decomposeNewContainer() { FixtureMonkey sut = FixtureMonkey.builder() .pushAssignableTypeContainerPropertyGenerator(Pair.class, new PairContainerPropertyGenerator()) @@ -923,7 +923,7 @@ void decomposeNewContainer() { then(actual1).isEqualTo(actual2); } - @Example + @Test void decomposeNewContainerByAddContainerType() { FixtureMonkey sut = FixtureMonkey.builder() .addContainerType( @@ -949,7 +949,7 @@ void decomposeNewContainerByAddContainerType() { then(actual1).isEqualTo(actual2); } - @Example + @Test void decomposeNewContainerByAddContainerTypeInterface() { FixtureMonkey sut = FixtureMonkey.builder() .addContainerType( @@ -973,7 +973,7 @@ void decomposeNewContainerByAddContainerTypeInterface() { }))); } - @Example + @Test void plugin() { FixtureMonkey sut = FixtureMonkey.builder() .plugin((optionsBuilder) -> optionsBuilder.insertFirstNullInjectGenerators(String.class, (context) -> 1.0d)) @@ -986,7 +986,7 @@ void plugin() { then(actual).isEqualTo(null); } - @Example + @Test void registerMultipleTimesWithHierarchyReturnsCorrectOrder() { String expected = "test"; FixtureMonkey sut = FixtureMonkey.builder() @@ -1002,7 +1002,7 @@ void registerMultipleTimesWithHierarchyReturnsCorrectOrder() { then(actual).isEqualTo(expected); } - @Example + @Test void generateWithBuilderArbitraryIntrospector() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -1015,7 +1015,7 @@ void generateWithBuilderArbitraryIntrospector() { then(actual.getValue()).isBetween(Integer.MIN_VALUE, Integer.MAX_VALUE); } - @Example + @Test void generateWithBuilderArbitraryIntrospectorDefaultBuilderMethod() { // given BuilderArbitraryIntrospector builderArbitraryIntrospector = new BuilderArbitraryIntrospector(); @@ -1031,7 +1031,7 @@ void generateWithBuilderArbitraryIntrospectorDefaultBuilderMethod() { then(actual.getValue()).isBetween(Integer.MIN_VALUE, Integer.MAX_VALUE); } - @Example + @Test void generateWithBuilderArbitraryIntrospectorDefaultBuildMethod() { // given BuilderArbitraryIntrospector builderArbitraryIntrospector = new BuilderArbitraryIntrospector(); @@ -1047,7 +1047,7 @@ void generateWithBuilderArbitraryIntrospectorDefaultBuildMethod() { then(actual.getValue()).isBetween(Integer.MIN_VALUE, Integer.MAX_VALUE); } - @Example + @Test void registerRootAndChildElementGeneratingRoot() { // given String expected = "test"; @@ -1067,7 +1067,7 @@ void registerRootAndChildElementGeneratingRoot() { then(actual).allMatch(expected::equals); } - @Example + @Test void registerSize() { FixtureMonkey sut = FixtureMonkey.builder() .register(ComplexObject.class, fixture -> fixture.giveMeBuilder(ComplexObject.class).size("strList", 1)) @@ -1079,7 +1079,7 @@ void registerSize() { then(actual).hasSize(1); } - @Example + @Test void registerFieldSet() { FixtureMonkey sut = FixtureMonkey.builder() .register(StringWrapper.class, fixture -> fixture.giveMeBuilder(StringWrapper.class).set("value", "test")) @@ -1091,7 +1091,7 @@ void registerFieldSet() { then(actual).allMatch(it -> "test".equals(it.getValue())); } - @Example + @Test void registerFieldSize() { FixtureMonkey sut = FixtureMonkey.builder() .register( @@ -1106,7 +1106,7 @@ void registerFieldSize() { then(actual).allMatch(it -> it.getValues().size() == 1); } - @Example + @Test void sizeRegisteredElement() { String expected = "test"; FixtureMonkey sut = FixtureMonkey.builder() @@ -1121,7 +1121,7 @@ void sizeRegisteredElement() { then(actual).allMatch(expected::equals); } - @Example + @Test void sizeBiggerThanRegisterSized() { FixtureMonkey sut = FixtureMonkey.builder() .register(ComplexObject.class, fixture -> fixture.giveMeBuilder(ComplexObject.class).size("strList", 3)) @@ -1135,7 +1135,7 @@ void sizeBiggerThanRegisterSized() { then(actual).hasSize(10); } - @Example + @Test void registerObjectNotFixed() { FixtureMonkey sut = FixtureMonkey.builder() .register(String.class, it -> it.giveMeBuilder(String.class).set("$", Arbitraries.strings().ofLength(10))) @@ -1150,7 +1150,7 @@ void registerObjectNotFixed() { then(actual).hasSizeGreaterThan(1); } - @Example + @Test void registerParentSetNullChildAndChildRegistered() { FixtureMonkey sut = FixtureMonkey.builder() .register(SimpleObject.class, fixture -> fixture.giveMeBuilder(SimpleObject.class).set("str", "test")) @@ -1167,7 +1167,7 @@ void registerParentSetNullChildAndChildRegistered() { then(actual).isNull(); } - @Example + @Test void sampleNullableContainerWhenOptionNullableContainerIsSetReturnsNull() { DefaultNullInjectGenerator nullInjectGenerator = new DefaultNullInjectGenerator( ALWAYS_NULL_INJECT, @@ -1187,7 +1187,7 @@ void sampleNullableContainerWhenOptionNullableContainerIsSetReturnsNull() { then(values).isNull(); } - @Example + @Test void applySizeWhenRegisteredWithSize() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -1206,7 +1206,7 @@ void applySizeWhenRegisteredWithSize() { then(actual).hasSize(10); } - @Example + @Test void sizeWhenRegisterSizeInApply() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -1226,7 +1226,7 @@ void sizeWhenRegisterSizeInApply() { then(actual).hasSize(2); } - @Example + @Test void sizeWhenRegisterApply() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -1248,7 +1248,7 @@ void sizeWhenRegisterApply() { then(actual).hasSize(2); } - @Example + @Test void sampleEnumMapWithEnumSizeIsLessThanContainerInfoMaxSize() { FixtureMonkey sut = FixtureMonkey.builder() .defaultArbitraryContainerInfoGenerator(context -> new ArbitraryContainerInfo(0, 5)) @@ -1260,7 +1260,7 @@ void sampleEnumMapWithEnumSizeIsLessThanContainerInfoMaxSize() { then(values).hasSizeLessThanOrEqualTo(2); } - @Example + @Test void sampleEnumMapWithEnumSizeIsLessThanContainerInfoMinSize() { FixtureMonkey sut = FixtureMonkey.builder() .defaultArbitraryContainerInfoGenerator(context -> new ArbitraryContainerInfo(3, 5)) @@ -1272,7 +1272,7 @@ void sampleEnumMapWithEnumSizeIsLessThanContainerInfoMinSize() { then(values).hasSizeLessThanOrEqualTo(2); } - @Example + @Test void sampleEnumSetWithEnumSizeIsLessThanContainerInfoMinSize() { FixtureMonkey sut = FixtureMonkey.builder() .defaultArbitraryContainerInfoGenerator(context -> new ArbitraryContainerInfo(3, 5)) @@ -1284,7 +1284,7 @@ void sampleEnumSetWithEnumSizeIsLessThanContainerInfoMinSize() { then(values).hasSizeLessThanOrEqualTo(2); } - @Example + @Test void interfaceImplements() { // given List> implementations = new ArrayList<>(); @@ -1304,7 +1304,7 @@ void interfaceImplements() { then(actual).isIn(1, "fixed"); } - @Example + @Test void sampleGenericInterface() { // given List> implementations = new ArrayList<>(); @@ -1329,7 +1329,7 @@ void sampleGenericInterface() { then(actual).isIn(1, "fixed"); } - @Example + @Test void sampleGenericInterfaceReturnsDiff() { // given List> implementations = new ArrayList<>(); @@ -1356,7 +1356,7 @@ void sampleGenericInterfaceReturnsDiff() { then(actual).hasSize(2); } - @Example + @Test void sampleInterfaceChildWhenOptionHasHierarchy() { // given List> implementations = new ArrayList<>(); @@ -1382,7 +1382,7 @@ void sampleInterfaceChildWhenOptionHasHierarchy() { then(actual).isEqualTo(2); } - @Example + @Test void sampleConcreteWhenHasSameNameProperty() { FixtureMonkey sut = FixtureMonkey.builder() .plugin( @@ -1400,7 +1400,7 @@ void sampleConcreteWhenHasSameNameProperty() { then(actual).isNotNull(); } - @Example + @Test void setConcreteListWithNoParentValue() { // given List> implementations = new ArrayList<>(); @@ -1431,7 +1431,7 @@ void setConcreteListWithNoParentValue() { then(actual).isEqualTo(expected); } - @Example + @Test void setConcreteClassWhenHasParentValue() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -1453,7 +1453,7 @@ void setConcreteClassWhenHasParentValue() { then(actual).isEqualTo(expected); } - @Example + @Test void setConcreteClassWhenHasNoParentValue() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -1478,7 +1478,7 @@ void setConcreteClassWhenHasNoParentValue() { then(actual).isEqualTo(expected); } - @Example + @Test void setConcreteList() { // given List> implementations = new ArrayList<>(); @@ -1511,7 +1511,7 @@ void setConcreteList() { then(actual).isEqualTo(expected); } - @Example + @Test void sampleSelfRecursiveAbstract() { FixtureMonkey sut = FixtureMonkey.builder() .plugin( @@ -1529,7 +1529,7 @@ void sampleSelfRecursiveAbstract() { then(actual).isNotNull(); } - @Example + @Test void sizeElementWhenRegisteredSize() { FixtureMonkey sut = FixtureMonkey.builder() .register( @@ -1548,7 +1548,7 @@ void sizeElementWhenRegisteredSize() { then(actual).allMatch(it -> it.getValues().size() >= 3 && it.getValues().size() <= 5); } - @Example + @Test void samePropertyDiffImplementations() { FixtureMonkey sut = FixtureMonkey.builder() .plugin( @@ -1571,7 +1571,7 @@ void samePropertyDiffImplementations() { then(actual).isEqualTo("expected"); } - @Example + @Test void sampleWithMonkeyStringArbitrary() { FixtureMonkey sut = FixtureMonkey.builder() .plugin( @@ -1592,7 +1592,7 @@ public StringArbitrary strings() { then(actual).isNotNull(); } - @Example + @Test void filterWithMonkeyStringArbitrary() { FixtureMonkey sut = FixtureMonkey.builder() .plugin( @@ -1611,7 +1611,7 @@ public StringArbitrary strings() { then(actual).isUpperCase(); } - @Example + @Test void filterIsoControlCharacterWithMonkeyStringArbitrary() { FixtureMonkey sut = FixtureMonkey.builder().build(); @@ -1627,7 +1627,7 @@ void filterIsoControlCharacterWithMonkeyStringArbitrary() { }); } - @Example + @Test void multipleFiltersWithMonkeyStringArbitrary() { FixtureMonkey sut = FixtureMonkey.builder() .plugin( @@ -1656,7 +1656,7 @@ public MonkeyStringArbitrary monkeyStrings() { }); } - @Example + @Test void alterDefaultArbitraryGenerator() { FixtureMonkey sut = FixtureMonkey.builder() .defaultArbitraryGenerator(generator -> new MatchArbitraryGenerator( @@ -1674,7 +1674,7 @@ void alterDefaultArbitraryGenerator() { then(actual).isNull(); } - @Example + @Test void skipArbitraryGenerator() { FixtureMonkey sut = FixtureMonkey.builder() .defaultArbitraryGenerator(generator -> new CompositeArbitraryGenerator( @@ -1691,7 +1691,7 @@ void skipArbitraryGenerator() { then(actual).isNotNull(); } - @Example + @Test void uniqueArbitraryGenerator() { FixtureMonkey sut = FixtureMonkey.builder() .defaultArbitraryGenerator(UniqueArbitraryGenerator::new) @@ -1703,7 +1703,7 @@ void uniqueArbitraryGenerator() { then(actual).hasSameSizeAs(expected); } - @Example + @Test void allArbitraryGeneratorSkipReturnsNull() { FixtureMonkey sut = FixtureMonkey.builder() .defaultArbitraryGenerator(generator -> ( @@ -1721,7 +1721,7 @@ void allArbitraryGeneratorSkipReturnsNull() { then(actual).isNull(); } - @Example + @Test void setConcrete() { // given List> implementations = new ArrayList<>(); diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyTest.java index 7418182d3d..b30bf49fae 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyTest.java @@ -43,9 +43,10 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.junit.jupiter.api.Test; + import net.jqwik.api.Arbitraries; import net.jqwik.api.Arbitrary; -import net.jqwik.api.Example; import com.navercorp.fixturemonkey.ArbitraryBuilder; import com.navercorp.fixturemonkey.ArbitraryBuilders; @@ -85,7 +86,7 @@ class FixtureMonkeyTest { private static final FixtureMonkey SUT = FixtureMonkey.create(); - @Example + @Test void sampleWithType() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class).sample(); @@ -96,7 +97,7 @@ void sampleWithType() { then(actual.getMapEntry()).isNotNull(); } - @Example + @Test void sampleWithTypeReference() { TypeReference type = new TypeReference() { }; @@ -110,7 +111,7 @@ void sampleWithTypeReference() { then(actual.getMapEntry()).isNotNull(); } - @Example + @Test void set() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class).set("str", "str").sample(); @@ -119,7 +120,7 @@ void set() { then(actual.getStr()).isEqualTo("str"); } - @Example + @Test void setDecomposedValue() { // given SimpleObject expected = new SimpleObject(); @@ -139,7 +140,7 @@ void setDecomposedValue() { then(actual.getStr()).isEqualTo("str"); } - @Example + @Test void setArbitrary() { // given SimpleObject expected = new SimpleObject(); @@ -159,7 +160,7 @@ void setArbitrary() { then(actual.getStr()).isEqualTo("str"); } - @Example + @Test void setOptional() { // given Optional optional = Optional.of("test"); @@ -174,7 +175,7 @@ void setOptional() { then(actual).isEqualTo(optional); } - @Example + @Test void setDecomposedList() { // given List expected = new ArrayList<>(); @@ -190,7 +191,7 @@ void setDecomposedList() { then(actual).isEqualTo(expected); } - @Example + @Test void setDecomposedSet() { // given Set expected = new HashSet<>(); @@ -207,7 +208,7 @@ void setDecomposedSet() { then(actual).isEqualTo(expected); } - @Example + @Test void setDecomposedMap() { // given Map expected = new HashMap<>(); @@ -226,7 +227,7 @@ void setDecomposedMap() { then(actual).isEqualTo(expected); } - @Example + @Test void setDecomposedMapEntry() { // given Map.Entry expected = new SimpleEntry<>("a", new SimpleObject()); @@ -240,7 +241,7 @@ void setDecomposedMapEntry() { then(actual).isEqualTo(expected); } - @Example + @Test void setDecomposedOptional() { // given Optional expected = Optional.of("test"); @@ -254,7 +255,7 @@ void setDecomposedOptional() { then(actual).isEqualTo(expected); } - @Example + @Test void setDecomposedOptionalEmpty() { // given Optional expected = Optional.empty(); @@ -268,7 +269,7 @@ void setDecomposedOptionalEmpty() { then(actual).isEqualTo(expected); } - @Example + @Test void setDecomposedOptionalInt() { // given OptionalInt expected = OptionalInt.of(0); @@ -282,7 +283,7 @@ void setDecomposedOptionalInt() { then(actual).isEqualTo(expected); } - @Example + @Test void setDecomposedOptionalLong() { // given OptionalLong expected = OptionalLong.of(0L); @@ -296,7 +297,7 @@ void setDecomposedOptionalLong() { then(actual).isEqualTo(expected); } - @Example + @Test void setDecomposedOptionalDouble() { // given OptionalDouble expected = OptionalDouble.of(0.d); @@ -310,7 +311,7 @@ void setDecomposedOptionalDouble() { then(actual).isEqualTo(expected); } - @Example + @Test void setDecomposedSupplier() { // given Supplier expected = () -> "test"; @@ -324,7 +325,7 @@ void setDecomposedSupplier() { then(actual.get()).isEqualTo(expected.get()); } - @Example + @Test void setDecomposedNestedStrSupplier() { // given Supplier> expected = () -> () -> "test"; @@ -338,7 +339,7 @@ void setDecomposedNestedStrSupplier() { then(actual.get()).isEqualTo(expected.get()); } - @Example + @Test void setAllFields() { // when StringPair actual = SUT.giveMeBuilder(StringPair.class).set("*", "str").sample(); @@ -347,7 +348,7 @@ void setAllFields() { then(actual.getValue2()).isEqualTo("str"); } - @Example + @Test void sizeZero() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class).size("strList", 0).sample(); @@ -356,7 +357,7 @@ void sizeZero() { then(actual.getStrList()).hasSize(0); } - @Example + @Test void size() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class).size("strList", 10).sample(); @@ -365,7 +366,7 @@ void size() { then(actual.getStrList()).hasSize(10); } - @Example + @Test void sizeArray() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class).size("strArray", 10).sample(); @@ -374,7 +375,7 @@ void sizeArray() { then(actual.getStrArray()).hasSize(10); } - @Example + @Test void sizeMinMax() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class).size("strList", 3, 8).sample(); @@ -383,7 +384,7 @@ void sizeMinMax() { then(actual.getStrList()).hasSizeBetween(3, 8); } - @Example + @Test void sizeMinIsBiggerThanMax() { // when thenThrownBy(() -> SUT.giveMeBuilder(ComplexObject.class).size("strList", 5, 1).sample()) @@ -391,7 +392,7 @@ void sizeMinIsBiggerThanMax() { .hasMessageContaining("should be min <= max"); } - @Example + @Test void minSize() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class).minSize("strList", 10).sample(); @@ -400,7 +401,7 @@ void minSize() { then(actual.getStrList()).hasSizeGreaterThanOrEqualTo(10); } - @Example + @Test void maxSize() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class).maxSize("strList", 10).sample(); @@ -409,7 +410,7 @@ void maxSize() { then(actual.getStrList()).hasSizeLessThanOrEqualTo(10); } - @Example + @Test void maxSizeZero() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class).maxSize("strList", 0).sample(); @@ -418,7 +419,7 @@ void maxSizeZero() { then(actual.getStrList()).hasSizeLessThanOrEqualTo(0); } - @Example + @Test void notFixedSampleReturnsDiff() { // when ArbitraryBuilder fixedArbitraryBuilder = SUT.giveMeBuilder(ComplexObject.class); @@ -429,7 +430,7 @@ void notFixedSampleReturnsDiff() { then(sample1).isNotEqualTo(sample2); } - @Example + @Test void fixedSampleReturnsSame() { // when ArbitraryBuilder fixedArbitraryBuilder = SUT.giveMeBuilder(ComplexObject.class).fixed(); @@ -440,7 +441,7 @@ void fixedSampleReturnsSame() { then(sample1).isEqualTo(sample2); } - @Example + @Test void arbitraryFixedSampleReturnsSame() { // when ArbitraryBuilder fixedArbitraryBuilder = SUT.giveMeBuilder(ComplexObject.class) @@ -453,7 +454,7 @@ void arbitraryFixedSampleReturnsSame() { then(sample1).isEqualTo(sample2); } - @Example + @Test void apply() { // when String actual = SUT.giveMeBuilder(ComplexObject.class) @@ -466,7 +467,7 @@ void apply() { then(actual).isEqualTo("set"); } - @Example + @Test void applyWithoutAnyManipulators() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -480,7 +481,7 @@ void applyWithoutAnyManipulators() { then(actualStrList.get(0)).isEqualTo(actualStr); } - @Example + @Test void applyNotAffectedManipulatorsAfterApply() { // when String actual = SUT.giveMeBuilder(ComplexObject.class) @@ -494,7 +495,7 @@ void applyNotAffectedManipulatorsAfterApply() { then(actual).isEqualTo("set"); } - @Example + @Test void acceptIfAlwaysTrue() { // when String actual = SUT.giveMeBuilder(ComplexObject.class) @@ -505,7 +506,7 @@ void acceptIfAlwaysTrue() { then(actual).isEqualTo("set"); } - @Example + @Test void acceptIf() { // when String actual = SUT.giveMeBuilder(ComplexObject.class) @@ -518,7 +519,7 @@ void acceptIf() { then(actual).isEqualTo("set"); } - @Example + @Test void setRootJavaType() { // given String expected = "test"; @@ -529,7 +530,7 @@ void setRootJavaType() { then(actual).isEqualTo(expected); } - @Example + @Test void setRootComplexType() { ComplexObject expected = new ComplexObject(); expected.setStr("test"); @@ -540,7 +541,7 @@ void setRootComplexType() { then(actual).isEqualTo(expected); } - @Example + @Test void setWithLimit() { // when List actual = SUT.giveMeBuilder(ComplexObject.class) @@ -554,7 +555,44 @@ void setWithLimit() { then(actual).anyMatch(it -> !"test".equals(it)); } - @Example + @Test + void setWithLimitAlwaysAppliesExactlyTheLimit() { + ArbitraryBuilder builder = SUT.giveMeBuilder(ComplexObject.class) + .size("strList", 3) + .set("strList[*]", "test", 1); + + for (int i = 0; i < 100; i++) { + List actual = builder.sample().getStrList(); + + then(actual).hasSize(3); + long testCount = actual.stream().filter("test"::equals).count(); + then(testCount).isEqualTo(1L); + } + } + + @Test + void setWithLimitMatchedWildcardSiblingsAreNotNullInjected() { + // All paths default to null injection. The wildcard pattern $.values[*] + // is set with limit 1, so element [0] resolves to "test". Elements [1] and [2] + // match the same wildcard, so they must NOT be null-injected — they should be + // generated as random non-null strings. + FixtureMonkey sut = FixtureMonkey.builder() + .defaultNullInjectGenerator(context -> 1.0d) + .build(); + + List actual = sut.giveMeBuilder(FixtureMonkeyTestSpecs.StringListWrapper.class) + .setNotNull("values") + .size("values", 3) + .set("values[*]", "test", 1) + .sample() + .getValues(); + + then(actual).hasSize(3); + then(actual).doesNotContainNull(); + then(actual.stream().filter("test"::equals).count()).isEqualTo(1L); + } + + @Test void setNull() { // when String actual = SUT.giveMeBuilder(ComplexObject.class).setNull("str").sample().getStr(); @@ -563,7 +601,7 @@ void setNull() { then(actual).isNull(); } - @Example + @Test void setNullList() { // when List actual = SUT.giveMeBuilder(ComplexObject.class).setNull("strList").sample().getStrList(); @@ -572,7 +610,7 @@ void setNullList() { then(actual).isNull(); } - @Example + @Test void setNullMap() { // when Map actual = SUT.giveMeBuilder(ComplexObject.class).setNull("map").sample().getMap(); @@ -581,7 +619,7 @@ void setNullMap() { then(actual).isNull(); } - @Example + @Test void setNullMapEntry() { // when Map.Entry actual = SUT.giveMeBuilder(ComplexObject.class) @@ -593,7 +631,7 @@ void setNullMapEntry() { then(actual).isNull(); } - @Example + @Test void setNullSupplier() { // when Supplier actual = SUT.giveMeBuilder(ComplexObject.class) @@ -605,7 +643,7 @@ void setNullSupplier() { then(actual).isNull(); } - @Example + @Test void setNotNullString() { // when String actual = SUT.giveMeBuilder(ComplexObject.class).setNotNull("str").sample().getStr(); @@ -614,7 +652,7 @@ void setNotNullString() { then(actual).isNotNull(); } - @Example + @Test void setNotNullList() { // when List actual = SUT.giveMeBuilder(ComplexObject.class).setNotNull("strList").sample().getStrList(); @@ -623,7 +661,7 @@ void setNotNullList() { then(actual).isNotNull(); } - @Example + @Test void setNotNullMap() { // when Map actual = SUT.giveMeBuilder(ComplexObject.class).setNotNull("map").sample().getMap(); @@ -632,7 +670,7 @@ void setNotNullMap() { then(actual).isNotNull(); } - @Example + @Test void setNotNullMapEntry() { // when Map.Entry actual = SUT.giveMeBuilder(ComplexObject.class) @@ -644,7 +682,7 @@ void setNotNullMapEntry() { then(actual).isNotNull(); } - @Example + @Test void setNotNullSupplier() { // when Supplier actual = SUT.giveMeBuilder(ComplexObject.class) @@ -656,7 +694,7 @@ void setNotNullSupplier() { then(actual).isNotNull(); } - @Example + @Test void setPostCondition() { // when String actual = SUT.giveMeBuilder(ComplexObject.class) @@ -668,7 +706,7 @@ void setPostCondition() { then(actual).hasSizeGreaterThan(5); } - @Example + @Test void setPostConditionRoot() { // when String actual = SUT.giveMeBuilder(ComplexObject.class) @@ -680,7 +718,7 @@ void setPostConditionRoot() { then(actual).hasSizeGreaterThan(5); } - @Example + @Test void setPostConditionWrongTypeThrows() { thenThrownBy(() -> SUT.giveMeBuilder(ComplexObject.class) @@ -691,7 +729,7 @@ void setPostConditionWrongTypeThrows() { .hasMessageContaining("Wrong type filter is applied."); } - @Example + @Test void mapWhenNull() { // when String actual = SUT.giveMeBuilder(ComplexObject.class).setNull("str").map(ComplexObject::getStr).sample(); @@ -699,7 +737,7 @@ void mapWhenNull() { then(actual).isNull(); } - @Example + @Test void mapWhenNotNull() { // when String actual = SUT.giveMeBuilder(ComplexObject.class).setNotNull("str").map(ComplexObject::getStr).sample(); @@ -707,7 +745,7 @@ void mapWhenNotNull() { then(actual).isNotNull(); } - @Example + @Test void mapToFixedValue() { // when String actual = SUT.giveMeBuilder(ComplexObject.class) @@ -717,7 +755,7 @@ void mapToFixedValue() { then(actual).isEqualTo("test"); } - @Example + @Test void mapKeyIsNotNull() { // when Set actual = SUT.giveMeBuilder(new TypeReference>() { @@ -726,7 +764,7 @@ void mapKeyIsNotNull() { then(actual).allMatch(Objects::nonNull); } - @Example + @Test void sampleAfterMapTwiceReturnsDiff() { ArbitraryBuilder arbitraryBuilder = SUT.giveMeBuilder(ComplexObject.class) .set( @@ -745,7 +783,7 @@ void sampleAfterMapTwiceReturnsDiff() { then(actual).isNotEqualTo(notExpected); } - @Example + @Test void giveMeBuilderWithValue() { SimpleObject expected = new SimpleObject(); expected.setStr("test"); @@ -756,7 +794,7 @@ void giveMeBuilderWithValue() { then(actual).isEqualTo(expected); } - @Example + @Test void zipList() { // given List> list = new ArrayList<>(); @@ -775,7 +813,7 @@ void zipList() { then(actual.getValue2()).isNotNull(); } - @Example + @Test void zipEmptyListThrows() { // given List> list = new ArrayList<>(); @@ -785,7 +823,7 @@ void zipEmptyListThrows() { .hasMessageContaining("zip should be used in more than two ArbitraryBuilders, given size"); } - @Example + @Test void zipThree() { // given ArbitraryBuilder s1 = SUT.giveMeBuilder(StringWrapper.class).set("value", "s1"); @@ -810,7 +848,7 @@ void zipThree() { then(actual.getValues().get(2).getValue()).isEqualTo("s3"); } - @Example + @Test void zipWithThree() { // given ArbitraryBuilder s1 = SUT.giveMeBuilder(StringWrapper.class).set("value", "s1"); @@ -837,7 +875,7 @@ void zipWithThree() { then(actual.getValues().get(2).getValue()).isEqualTo("s3"); } - @Example + @Test void zipFour() { // given ArbitraryBuilder s1 = SUT.giveMeBuilder(StringWrapper.class).set("value", "s1"); @@ -865,7 +903,7 @@ void zipFour() { then(actual.getValues().get(3).getValue()).isEqualTo("s4"); } - @Example + @Test void zipWithFour() { // given ArbitraryBuilder s1 = SUT.giveMeBuilder(StringWrapper.class).set("value", "s1"); @@ -895,7 +933,7 @@ void zipWithFour() { then(actual.getValues().get(3).getValue()).isEqualTo("s4"); } - @Example + @Test void zipWith() { // given ArbitraryBuilder stringArbitraryBuilder = SUT.giveMeBuilder(String.class); @@ -908,7 +946,7 @@ void zipWith() { then(actual).isNotNull(); } - @Example + @Test void zipTwo() { // given ArbitraryBuilder stringArbitraryBuilder = SUT.giveMeBuilder(String.class); @@ -924,7 +962,7 @@ void zipTwo() { then(actual).isNotNull(); } - @Example + @Test void zipReturnsNew() { // given ArbitraryBuilder stringArbitraryBuilder = SUT.giveMeBuilder(String.class); @@ -943,7 +981,7 @@ void zipReturnsNew() { then(result1).isNotEqualTo(result2); } - @Example + @Test void supplierReturnsNew() { // given TypeReference> supplierTypeReference = new TypeReference>() { @@ -959,7 +997,7 @@ void supplierReturnsNew() { then(result1).isNotEqualTo(result2); } - @Example + @Test void setNullFixedReturnsNull() { // when SimpleObject actual = SUT.giveMeBuilder(SimpleObject.class).setNull("$").fixed().sample(); @@ -967,7 +1005,7 @@ void setNullFixedReturnsNull() { then(actual).isNull(); } - @Example + @Test void setNullFixedAndNotNullReturnsNotNull() { // when SimpleObject actual = SUT.giveMeBuilder(SimpleObject.class).setNull("$").fixed().setNotNull("$").sample(); @@ -975,7 +1013,7 @@ void setNullFixedAndNotNullReturnsNotNull() { then(actual).isNotNull(); } - @Example + @Test void setListElement() { String expected = "test"; @@ -989,7 +1027,7 @@ void setListElement() { then(actual).isEqualTo(expected); } - @Example + @Test void sizeSmallerRemains() { String expected = "test"; @@ -1005,7 +1043,7 @@ void sizeSmallerRemains() { then(actual.get(0)).isEqualTo(expected); } - @Example + @Test void applySetElementNull() { String actual = SUT.giveMeBuilder(ComplexObject.class) .thenApply((obj, builder) -> builder.size("strList", 1).setNull("strList[0]")) @@ -1016,7 +1054,7 @@ void applySetElementNull() { then(actual).isNull(); } - @Example + @Test void setAndSetNull() { // when String actual = SUT.giveMeBuilder(SimpleObject.class).set("str", "test").setNull("str").sample().getStr(); @@ -1024,7 +1062,7 @@ void setAndSetNull() { then(actual).isNull(); } - @Example + @Test void setAfterBuildNotAffected() { // given ArbitraryBuilder builder = SUT.giveMeBuilder(SimpleObject.class); @@ -1040,7 +1078,7 @@ void setAfterBuildNotAffected() { then(actualSample.getStr()).isEqualTo("set"); } - @Example + @Test void applySampleTwiceReturnsDiff() { ArbitraryBuilder builder = SUT.giveMeBuilder(SimpleObject.class).thenApply((obj, b) -> { }); @@ -1051,7 +1089,7 @@ void applySampleTwiceReturnsDiff() { then(actual).isNotEqualTo(expected); } - @Example + @Test void setPrimitiveToReference() { // when int integer = SUT.giveMeBuilder(SimpleObject.class) @@ -1062,7 +1100,7 @@ void setPrimitiveToReference() { then(integer).isEqualTo(1234); } - @Example + @Test void setReferenceToPrimitive() { // when int integer = SUT.giveMeBuilder(SimpleObject.class).set("wrapperInteger", 1234).sample().getWrapperInteger(); @@ -1070,14 +1108,14 @@ void setReferenceToPrimitive() { then(integer).isEqualTo(1234); } - @Example + @Test void copyValidOnly() { thenNoException().isThrownBy(() -> SUT.giveMeBuilder(StringListWrapper.class).size("values", 0).validOnly(false).copy().sample() ); } - @Example + @Test void generatePrimitiveArray() { // when int[] actual = SUT.giveMeBuilder(ComplexObject.class).fixed().sample().getIntArray(); @@ -1085,7 +1123,7 @@ void generatePrimitiveArray() { then(actual).isNotNull(); } - @Example + @Test void setFieldWhichObjectIsFixedNull() { String expected = "test"; @@ -1099,7 +1137,7 @@ void setFieldWhichObjectIsFixedNull() { then(actual).isEqualTo(expected); } - @Example + @Test void setFieldWhichRootIsFixedNull() { String expected = "test"; @@ -1112,7 +1150,7 @@ void setFieldWhichRootIsFixedNull() { then(actual).isEqualTo(expected); } - @Example + @Test void setLazyValue() { ArbitraryBuilder variable = SUT.giveMeBuilder(String.class); ArbitraryBuilder builder = SUT.giveMeBuilder(String.class).setLazy("$", variable::sample); @@ -1123,7 +1161,7 @@ void setLazyValue() { then(actual).isEqualTo("test"); } - @Example + @Test void setLazyValueWithLimit() { ArbitraryBuilder variable = SUT.giveMeBuilder(String.class); @@ -1139,7 +1177,7 @@ void setLazyValueWithLimit() { then(actual).anyMatch(it -> !"test".equals(it)); } - @Example + @Test void setLazyValueSampleReturnsDifferentValue() { // when ArbitraryBuilder builder = SUT.giveMeBuilder(String.class).setLazy("$", () -> @@ -1151,7 +1189,7 @@ void setLazyValueSampleReturnsDifferentValue() { then(actual).isNotEqualTo(expected); } - @Example + @Test void setArbitraryBuilder() { String expected = "test"; @@ -1163,7 +1201,7 @@ void setArbitraryBuilder() { then(actual).isEqualTo(expected); } - @Example + @Test void giveMeListTypeApply() { // when SimpleObject actual = SUT.giveMeBuilder(new TypeReference>() { @@ -1176,7 +1214,7 @@ void giveMeListTypeApply() { then(actual.getStr()).isEqualTo(actual.getInteger() + ""); } - @Example + @Test void setIterable() { String expected = "test"; @@ -1188,7 +1226,7 @@ void setIterable() { then(actual.iterator().next()).isEqualTo(expected); } - @Example + @Test void setIterator() { String expected = "test"; @@ -1200,7 +1238,7 @@ void setIterator() { then(actual.next()).isEqualTo(expected); } - @Example + @Test void setStream() { String expected = "test"; @@ -1212,7 +1250,7 @@ void setStream() { then(actual.collect(Collectors.toList()).get(0)).isEqualTo(expected); } - @Example + @Test void sampleListWildcardEnum() { // when List actual = SUT.giveMeOne(new TypeReference>() { @@ -1221,7 +1259,7 @@ void sampleListWildcardEnum() { then(actual).isNotNull(); } - @Example + @Test void fixedRangedSizeReturnsSameSize() { ArbitraryBuilder fixedArbitraryBuilder = SUT.giveMeBuilder(ComplexObject.class) .size("strList", 1, 5) @@ -1233,7 +1271,7 @@ void fixedRangedSizeReturnsSameSize() { then(actual).isEqualTo(expected); } - @Example + @Test void giveMeManipulatedObjectRemainsManipulator() { StringListWrapper expected = SUT.giveMeBuilder(StringListWrapper.class).size("values", 2, 2).sample(); @@ -1242,13 +1280,13 @@ void giveMeManipulatedObjectRemainsManipulator() { then(actual.getValues().get(1)).isEqualTo("test"); } - @Example + @Test void sampleNotGeneratingStaticField() { // when, then thenNoException().isThrownBy(() -> SUT.giveMeOne(StaticFieldObject.class)); } - @Example + @Test void setDecomposeContainerTwice() { List strings = new ArrayList<>(); strings.add("test"); @@ -1262,7 +1300,7 @@ void setDecomposeContainerTwice() { then(actual).isEmpty(); } - @Example + @Test void setEmptyMap() { Map map = new HashMap<>(); map.put("test", new SimpleObject()); @@ -1276,7 +1314,7 @@ void setEmptyMap() { then(actual).isEmpty(); } - @Example + @Test void sampleEnumSet() { // when Set actual = SUT.giveMeOne(new TypeReference>() { @@ -1285,7 +1323,7 @@ void sampleEnumSet() { then(actual).hasSizeLessThanOrEqualTo(2); } - @Example + @Test void setNullFixed() { String expected = "test"; @@ -1300,7 +1338,7 @@ void setNullFixed() { then(actual).isEqualTo(expected); } - @Example + @Test void applyFixedSize() { String expectedElement = "test"; @@ -1313,7 +1351,7 @@ void applyFixedSize() { then(actual).allMatch(expectedElement::equals); } - @Example + @Test void sizeNotSetEmptyList() { // when List actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1325,7 +1363,7 @@ void sizeNotSetEmptyList() { then(actual).isEmpty(); } - @Example + @Test void sampleNullableContainerReturnsNotNull() { // when List values = SUT.giveMeOne(NullableObject.class).getValues(); @@ -1333,7 +1371,7 @@ void sampleNullableContainerReturnsNotNull() { then(values).isNotNull(); } - @Example + @Test void sampleUniqueSet() { // when Set actual = SUT.giveMeBuilder(new TypeReference>() { @@ -1342,7 +1380,7 @@ void sampleUniqueSet() { then(actual).hasSize(200); } - @Example + @Test void sampleUniqueMap() { // when Map actual = SUT.giveMeBuilder(new TypeReference>() { @@ -1353,7 +1391,7 @@ void sampleUniqueMap() { then(actual).hasSize(200); } - @Example + @Test void sampleEnumMap() { Map values = SUT.giveMeOne(new TypeReference>() { }); @@ -1361,7 +1399,7 @@ void sampleEnumMap() { then(values).hasSizeLessThanOrEqualTo(2); } - @Example + @Test void sizeEnumSetGreaterThanEnumSizeNotThrows() { Set actual = SUT.giveMeBuilder(new TypeReference>() { }).size("$", 3).sample(); @@ -1369,7 +1407,7 @@ void sizeEnumSetGreaterThanEnumSizeNotThrows() { then(actual).hasSize(2); } - @Example + @Test void sizeEnumMapGreaterThanEnumSizeNotThrows() { Map actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -1379,13 +1417,13 @@ void sizeEnumMapGreaterThanEnumSizeNotThrows() { then(actual).hasSize(2); } - @Example + @Test void sampleEnumMapInMap() { thenNoException().isThrownBy(() -> SUT.giveMeOne(new TypeReference>>() { })); } - @Example + @Test void setInterface() { InterfaceImplementation expected = new InterfaceImplementation(); expected.setValue("test"); @@ -1395,7 +1433,7 @@ void setInterface() { then(actual).isEqualTo(expected); } - @Example + @Test void sampleEnumSetList() { thenNoException().isThrownBy(() -> SUT.giveMeBuilder(new TypeReference>>() { @@ -1403,7 +1441,7 @@ void sampleEnumSetList() { ); } - @Example + @Test void sampleSupplier() { Supplier actual = SUT.giveMeBuilder(new TypeReference>() { }).sample(); @@ -1412,7 +1450,7 @@ void sampleSupplier() { then(actual.get()).isNotNull(); } - @Example + @Test void sampleNestedStrSupplier() { Supplier> actual = SUT.giveMeBuilder( new TypeReference>>() { @@ -1424,7 +1462,7 @@ void sampleNestedStrSupplier() { then(actual.get().get()).isNotNull(); } - @Example + @Test void sampleSelfRecursiveObject() { FixtureMonkey sut = FixtureMonkey.builder().defaultNotNull(true).build(); @@ -1435,7 +1473,7 @@ void sampleSelfRecursiveObject() { then(actual.getRecursive().getValue()).isNotNull(); } - @Example + @Test void sampleSelfRecursiveList() { FixtureMonkey sut = FixtureMonkey.builder().defaultNotNull(true).build(); @@ -1445,7 +1483,7 @@ void sampleSelfRecursiveList() { then(actual.getRecursives()).isNotNull(); } - @Example + @Test void sampleRecursiveSupplier() { FixtureMonkey sut = FixtureMonkey.builder().defaultNotNull(true).build(); @@ -1456,7 +1494,7 @@ void sampleRecursiveSupplier() { then(actual.getRecursive().get()).isNotNull(); } - @Example + @Test void sampleRecursiveObject() { FixtureMonkey sut = FixtureMonkey.builder().defaultNotNull(true).build(); @@ -1467,7 +1505,7 @@ void sampleRecursiveObject() { then(actual.getRecursive().getValue()).isNotNull(); } - @Example + @Test void sampleGeneric() { String actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -1478,7 +1516,7 @@ void sampleGeneric() { then(actual).isNotNull(); } - @Example + @Test void sampleGenericWildcardExtends() { String actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -1489,14 +1527,14 @@ void sampleGenericWildcardExtends() { then(actual).isNotNull(); } - @Example + @Test void sampleStringGenericField() { GenericStringWrapper actual = SUT.giveMeOne(GenericStringWrapper.class); then(actual).isNotNull(); } - @Example + @Test void sampleGenericField() { GenericWrapper actual = SUT.giveMeOne(new TypeReference>() { }); @@ -1504,41 +1542,41 @@ void sampleGenericField() { then(actual).isNotNull(); } - @Example + @Test void sampleGenericChild() { GenericStringChild actual = SUT.giveMeOne(GenericStringChild.class); then(actual).isNotNull(); } - @Example + @Test void sampleTwoGenericChild() { GenericStringIntChild actual = SUT.giveMeOne(GenericStringIntChild.class); then(actual).isNotNull(); } - @Example + @Test void sampleObjectField() { ObjectWrapper actual = SUT.giveMeOne(ObjectWrapper.class); then(actual).isNotNull(); } - @Example + @Test void sampleChild() { Child actual = SUT.giveMeOne(Child.class); then(actual).isNotNull(); } - @Example + @Test void sampleWildcard() { thenNoException().isThrownBy(() -> SUT.giveMeOne(new TypeReference>() { })); } - @Example + @Test void nestedSize() { // when List> actual = SUT.giveMeBuilder(new TypeReference>>() { @@ -1552,19 +1590,19 @@ void nestedSize() { then(actual.get(0)).hasSize(10); } - @Example + @Test void sampleMapValueWildcardListString() { thenNoException().isThrownBy(() -> SUT.giveMeOne(new TypeReference>>() { })); } - @Example + @Test void sampleGenericSimpleChild() { thenNoException().isThrownBy(() -> SUT.giveMeOne(new TypeReference() { })); } - @Example + @Test void sizeThirdNestedNested() { List actual = SUT.giveMeBuilder(DoubleNestedStringListWrapper.class) .size("values", 1) @@ -1580,7 +1618,7 @@ void sizeThirdNestedNested() { then(actual).hasSize(1); } - @Example + @Test void sizeAfterSetReturnsSet() { List actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -1591,7 +1629,7 @@ void sizeAfterSetReturnsSet() { then(actual).isEmpty(); } - @Example + @Test void sizeAfterSetEmptyListReturnsSized() { List actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -1602,7 +1640,7 @@ void sizeAfterSetEmptyListReturnsSized() { then(actual).hasSize(3); } - @Example + @Test void greaterSizeAfterSetReturnsSizeRemainsSet() { List set = new ArrayList<>(); set.add("1"); @@ -1617,7 +1655,7 @@ void greaterSizeAfterSetReturnsSizeRemainsSet() { then(actual.get(0)).isEqualTo("1"); } - @Example + @Test void smallerSizeAfterSetReturnsSizeRemainsSet() { List set = new ArrayList<>(); set.add("1"); @@ -1638,21 +1676,40 @@ void smallerSizeAfterSetReturnsSizeRemainsSet() { then(actual.get(2)).isEqualTo("3"); } - @Example + @Test void setNotNull() { String actual = SUT.giveMeBuilder(SimpleObject.class).set("str", NOT_NULL).sample().getStr(); then(actual).isNotNull(); } - @Example + @Test void setNotNullZoneId() { - ZoneId actual = SUT.giveMeBuilder(SimpleObject.class).setNotNull("zoneId").sample().getZoneId(); + FixtureMonkey sut = FixtureMonkey.builder() + .defaultNullInjectGenerator(context -> 1.0d) + .build(); + + ZoneId actual = sut.giveMeBuilder(SimpleObject.class).setNotNull("zoneId").sample().getZoneId(); then(actual).isNotNull(); } - @Example + @Test + void primitiveArrayElementNotInjectNullWhenNullInjectProbabilityIsOne() { + FixtureMonkey sut = FixtureMonkey.builder() + .defaultNullInjectGenerator(context -> 1.0d) + .build(); + + int[] actual = sut.giveMeBuilder(new TypeReference() { + }) + .setNotNull("$") + .size("$", 3) + .sample(); + + then(actual).hasSize(3); + } + + @Test void setJustSubPropertyNotChanged() { String notExpected = "test"; @@ -1665,7 +1722,7 @@ void setJustSubPropertyNotChanged() { then(actual).isNotEqualTo(notExpected); } - @Example + @Test void setPostConditionPrimitiveType() { int actual = SUT.giveMeBuilder(SimpleObject.class) .setPostCondition("integer", Integer.class, i -> i > 0) @@ -1675,7 +1732,7 @@ void setPostConditionPrimitiveType() { then(actual).isGreaterThan(0); } - @Example + @Test void setSupplierObjectField() { String actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -1687,7 +1744,7 @@ void setSupplierObjectField() { then(actual).isEqualTo("expected"); } - @Example + @Test void setNestedSupplierObjectField() { String actual = SUT.giveMeBuilder(new TypeReference>>() { }) @@ -1700,7 +1757,7 @@ void setNestedSupplierObjectField() { then(actual).isEqualTo("expected"); } - @Example + @Test void setSupplierObjectFieldUsingRootExp() { String actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -1712,7 +1769,7 @@ void setSupplierObjectFieldUsingRootExp() { then(actual).isEqualTo("expected"); } - @Example + @Test void setOptionalObjectField() { String actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -1724,7 +1781,7 @@ void setOptionalObjectField() { then(actual).isEqualTo("expected"); } - @Example + @Test void setOptionalObjectFieldUsingRootExp() { String actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -1736,7 +1793,7 @@ void setOptionalObjectFieldUsingRootExp() { then(actual).isEqualTo("expected"); } - @Example + @Test void nestedThenApply() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1756,7 +1813,7 @@ void nestedThenApply() { then(actual.getStrList().get(0)).isEqualTo("outer"); } - @Example + @Test void nestedThenApplyRandomValuePreserved() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1770,7 +1827,7 @@ void nestedThenApplyRandomValuePreserved() { then(actual.getObject().getStr()).isEqualTo(actual.getStr()); } - @Example + @Test void tripleNestedThenApply() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1792,7 +1849,7 @@ void tripleNestedThenApply() { then(actual.getStrList().get(0)).isEqualTo("level1-level2-level3"); } - @Example + @Test void nestedThenApplyInnerOverwritesOuter() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1806,7 +1863,7 @@ void nestedThenApplyInnerOverwritesOuter() { then(actual.getStr()).isEqualTo("inner"); } - @Example + @Test void nestedThenApplyWithSizeAndElement() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -1825,7 +1882,7 @@ void nestedThenApplyWithSizeAndElement() { then(actual.getStrList().get(1)).isEqualTo("second"); } - @Example + @Test void nestedThenApplySetAfterNestedApply() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/GenericTypeAdapterTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/GenericTypeTest.java similarity index 89% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/GenericTypeAdapterTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/GenericTypeTest.java index cc70104529..e74f64cf96 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/GenericTypeAdapterTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/GenericTypeTest.java @@ -16,13 +16,12 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; import static org.assertj.core.api.BDDAssertions.thenNoException; -import net.jqwik.api.Property; -import net.jqwik.api.PropertyDefaults; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.introspector.FieldReflectionArbitraryIntrospector; @@ -34,15 +33,13 @@ import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.GenericValue; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.GenericWrapper; -@PropertyDefaults(tries = 10) -class GenericTypeAdapterTest { +class GenericTypeTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void sampleGeneric() { String actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -53,7 +50,7 @@ void sampleGeneric() { then(actual).isNotNull(); } - @Property + @Test void sampleGenericWildcardExtends() { String actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -64,14 +61,14 @@ void sampleGenericWildcardExtends() { then(actual).isNotNull(); } - @Property + @Test void sampleStringGenericField() { GenericStringWrapper actual = SUT.giveMeOne(GenericStringWrapper.class); then(actual).isNotNull(); } - @Property + @Test void sampleGenericField() { GenericWrapper actual = SUT.giveMeOne(new TypeReference>() { }); @@ -79,33 +76,32 @@ void sampleGenericField() { then(actual).isNotNull(); } - @Property + @Test void sampleGenericChild() { GenericStringChild actual = SUT.giveMeOne(GenericStringChild.class); then(actual).isNotNull(); } - @Property + @Test void sampleTwoGenericChild() { GenericStringIntChild actual = SUT.giveMeOne(GenericStringIntChild.class); then(actual).isNotNull(); } - @Property + @Test void sampleGenericSimpleChild() { thenNoException().isThrownBy(() -> SUT.giveMeOne(new TypeReference() { })); } - @Property + @Test void genericTypePropertyGeneratorResolvesTypeVariables() { // given FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); // when diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/InnerSpecTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/InnerSpecTest.java index 04f9df0361..f0a7daaf48 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/InnerSpecTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/InnerSpecTest.java @@ -33,8 +33,9 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.junit.jupiter.api.Test; + import net.jqwik.api.Arbitraries; -import net.jqwik.api.Example; import com.navercorp.fixturemonkey.ArbitraryBuilder; import com.navercorp.fixturemonkey.FixtureMonkey; @@ -55,7 +56,7 @@ class InnerSpecTest { private static final FixtureMonkey SUT = FixtureMonkey.create(); - @Example + @Test void key() { // when Map actual = SUT.giveMeBuilder(MapObject.class) @@ -69,7 +70,7 @@ void key() { then(actual.keySet()).contains("key"); } - @Example + @Test void value() { // when Map actual = SUT.giveMeBuilder(MapObject.class) @@ -83,7 +84,7 @@ void value() { then(actual.values()).contains("value"); } - @Example + @Test void entry() { // when Map actual = SUT.giveMeBuilder(MapObject.class) @@ -97,7 +98,7 @@ void entry() { then(actual.get("key")).isEqualTo("value"); } - @Example + @Test void keys() { // when Map actual = SUT.giveMeBuilder(MapObject.class) @@ -113,7 +114,7 @@ void keys() { ); } - @Example + @Test void values() { // when Map actual = SUT.giveMeBuilder(MapObject.class) @@ -129,7 +130,7 @@ void values() { ); } - @Example + @Test void entries() { // when Map actual = SUT.giveMeBuilder(MapObject.class) @@ -144,7 +145,7 @@ void entries() { then(actual.get("key2")).isEqualTo("value2"); } - @Example + @Test void entryTwice() { // when MapObject actual = SUT.giveMeBuilder(MapObject.class) @@ -162,7 +163,7 @@ void entryTwice() { then(actual.getStrMap().get("key2")).isEqualTo("value2"); } - @Example + @Test void valueNull() { // when MapObject actual = SUT.giveMeBuilder(MapObject.class) @@ -175,7 +176,7 @@ void valueNull() { then(actual.getStrMap().containsValue(null)).isTrue(); } - @Example + @Test void keyNullThrows() { thenThrownBy(() -> SUT.giveMeBuilder(MapObject.class) @@ -188,7 +189,7 @@ void keyNullThrows() { .hasMessageContaining("Map key cannot be null."); } - @Example + @Test void keyInKey() { FixtureMonkey sut = FixtureMonkey.builder() .defaultArbitraryContainerInfoGenerator(context -> new ArbitraryContainerInfo(1, 3)) @@ -206,7 +207,7 @@ void keyInKey() { then(keyList).contains("key"); } - @Example + @Test void valueInKey() { FixtureMonkey sut = FixtureMonkey.builder() .defaultArbitraryContainerInfoGenerator(context -> new ArbitraryContainerInfo(1, 3)) @@ -223,7 +224,7 @@ void valueInKey() { then(keyList).contains("value"); } - @Example + @Test void keyInValue() { // when MapObject actual = SUT.giveMeBuilder(MapObject.class) @@ -238,7 +239,7 @@ void keyInValue() { then(valueList).contains("key"); } - @Example + @Test void valueInValue() { // when MapObject actual = SUT.giveMeBuilder(MapObject.class) @@ -253,7 +254,7 @@ void valueInValue() { then(valueList).contains("value"); } - @Example + @Test void sizeInValue() { // when MapObject actual = SUT.giveMeBuilder(MapObject.class) @@ -269,7 +270,7 @@ void sizeInValue() { then(sizeList).contains(10); } - @Example + @Test void listElementInValue() { // when MapObject actual = SUT.giveMeBuilder(MapObject.class) @@ -288,7 +289,7 @@ void listElementInValue() { then(elementList).contains("test"); } - @Example + @Test void propertyInValue() { // when MapObject actual = SUT.giveMeBuilder(MapObject.class) @@ -305,7 +306,7 @@ void propertyInValue() { then(fieldList).contains("test"); } - @Example + @Test void entryInEntryValue() { // when MapObject actual = SUT.giveMeBuilder(MapObject.class) @@ -322,7 +323,7 @@ void entryInEntryValue() { } @SuppressWarnings("OptionalGetWithoutIsPresent") - @Example + @Test void entryInEntryKey() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -349,7 +350,7 @@ void entryInEntryKey() { then(expected.get("key")).isEqualTo("value2"); } - @Example + @Test void entryValueSetNull() { // when MapObject actual = SUT.giveMeBuilder(MapObject.class) @@ -364,7 +365,7 @@ void entryValueSetNull() { then(actual.getStrMap().get("key")).isNull(); } - @Example + @Test void listElementInListElement() { // when NestedListStringObject actual = SUT.giveMeBuilder(NestedListStringObject.class) @@ -384,7 +385,7 @@ void listElementInListElement() { then(actual.getValues().get(0).get(0)).isEqualTo("test"); } - @Example + @Test void propertyInProperty() { // when ComplexObjectObject actual = SUT.giveMeBuilder(ComplexObjectObject.class) @@ -399,7 +400,7 @@ void propertyInProperty() { then(actual.getValue().getValue().getStr()).isEqualTo("test"); } - @Example + @Test void sizeAndEntry() { // when Map actual = SUT.giveMeBuilder(MapObject.class) @@ -419,7 +420,7 @@ void sizeAndEntry() { then(actual.get("key")).isEqualTo("test"); } - @Example + @Test void entryAndSize() { // when Map actual = SUT.giveMeBuilder(MapObject.class) @@ -439,7 +440,7 @@ void entryAndSize() { then(actual.get("key")).isEqualTo("test"); } - @Example + @Test void sizeTwiceReturnsLatterSize() { // when Map actual = SUT.giveMeBuilder(MapObject.class) @@ -459,7 +460,7 @@ void sizeTwiceReturnsLatterSize() { then(actual).hasSize(0); } - @Example + @Test void keyLazy() { ArbitraryBuilder variable = SUT.giveMeBuilder(String.class); ArbitraryBuilder builder = SUT.giveMeBuilder(MapObject.class) @@ -476,7 +477,7 @@ void keyLazy() { then(actual.getStrMap().containsKey("key")).isTrue(); } - @Example + @Test void valueLazy() { ArbitraryBuilder variable = SUT.giveMeBuilder(String.class); ArbitraryBuilder builder = SUT.giveMeBuilder(MapObject.class) @@ -493,7 +494,7 @@ void valueLazy() { then(actual.getStrMap().containsValue("value")).isTrue(); } - @Example + @Test void entryLazy() { ArbitraryBuilder keyVariable = SUT.giveMeBuilder(String.class); ArbitraryBuilder valueVariable = SUT.giveMeBuilder(String.class); @@ -512,7 +513,7 @@ void entryLazy() { then(actual.getStrMap().get("key")).isEqualTo("value"); } - @Example + @Test void keyLazyNullThrows() { thenThrownBy(() -> SUT.giveMeBuilder(MapObject.class) @@ -527,7 +528,7 @@ void keyLazyNullThrows() { .hasMessageContaining("Map key cannot be null."); } - @Example + @Test void allKeyLazy() { IntegerMapObject actual = SUT.giveMeBuilder(IntegerMapObject.class) .setInner( @@ -541,7 +542,7 @@ void allKeyLazy() { then(actual.getIntegerMap().keySet()).allMatch(it -> it >= 0 && it <= 100); } - @Example + @Test void allValueLazy() { IntegerMapObject actual = SUT.giveMeBuilder(IntegerMapObject.class) .setInner( @@ -555,7 +556,7 @@ void allValueLazy() { then(actual.getIntegerMap().values()).allMatch(it -> it >= 0 && it <= 100); } - @Example + @Test void allEntry() { IntegerMapObject actual = SUT.giveMeBuilder(IntegerMapObject.class) .setInner( @@ -573,7 +574,7 @@ void allEntry() { then(actual.getIntegerMap().values()).allMatch(it -> it == 100); } - @Example + @Test void allEntryLazy() { IntegerMapObject actual = SUT.giveMeBuilder(IntegerMapObject.class) .setInner( @@ -591,7 +592,7 @@ void allEntryLazy() { then(actual.getIntegerMap().values()).allMatch(it -> it >= 0 && it <= 100); } - @Example + @Test void allKey() { String expected = "test"; @@ -614,7 +615,7 @@ void allKey() { then(actual).allMatch(expected::equals); } - @Example + @Test void allValue() { String expected = "test"; @@ -632,7 +633,7 @@ void allValue() { then(actual).allMatch(expected::equals); } - @Example + @Test void allValueInner() { String expected = "test"; @@ -655,7 +656,7 @@ void allValueInner() { then(actual).allMatch(expected::equals); } - @Example + @Test void allListElement() { String expected = "test"; @@ -671,7 +672,7 @@ void allListElement() { then(actual).allMatch(expected::equals); } - @Example + @Test void allListElementInnerSpec() { String expected = "test"; @@ -690,7 +691,7 @@ void allListElementInnerSpec() { then(actual).allMatch(expected::equals); } - @Example + @Test void setPostCondition() { SimpleObject actual = SUT.giveMeBuilder(SimpleObject.class) .setInner( @@ -705,7 +706,7 @@ void setPostCondition() { then(actual.getStr()).hasSizeGreaterThan(5); } - @Example + @Test void inner() { InnerSpec innerSpec = new InnerSpec().property("str", "test"); @@ -716,7 +717,7 @@ void inner() { then(actual.getStr()).isEqualTo("test"); } - @Example + @Test void propertyInner() { InnerSpec innerSpec = new InnerSpec().property("str", "test"); @@ -727,7 +728,7 @@ void propertyInner() { then(actual.getValue().getStr()).isEqualTo("test"); } - @Example + @Test void listElementInMaxSize() { String expected = "expected"; @@ -744,7 +745,7 @@ void listElementInMaxSize() { then(actual).allMatch(expected::equals); } - @Example + @Test void setAfterSizeReturnsSet() { List actual = SUT.giveMeBuilder(ListStringObject.class) .setInner( @@ -758,7 +759,7 @@ void setAfterSizeReturnsSet() { then(actual).isEmpty(); } - @Example + @Test void sizeAfterSetReturnsSize() { List actual = SUT.giveMeBuilder(ListStringObject.class) .setInner( @@ -772,7 +773,7 @@ void sizeAfterSetReturnsSize() { then(actual).hasSize(2); } - @Example + @Test void sizeAfterSetWithSeparateInnerSpecReturnsSize() { List actual = SUT.giveMeBuilder(ListStringObject.class) .setInner( @@ -789,7 +790,7 @@ void sizeAfterSetWithSeparateInnerSpecReturnsSize() { then(actual).hasSize(2); } - @Example + @Test void setAfterSetWithSeparateInnerSpecReturnsSet() { List actual = SUT.giveMeBuilder(ListStringObject.class) .setInner( @@ -806,7 +807,7 @@ void setAfterSetWithSeparateInnerSpecReturnsSet() { then(actual).isEmpty(); } - @Example + @Test void innerSpecIncrementsSequence() { List actual = SUT.giveMeBuilder(ListStringObject.class) .setInner( @@ -822,7 +823,7 @@ void innerSpecIncrementsSequence() { then(actual).hasSize(5); } - @Example + @Test void setNotNull() { String actual = SUT.giveMeBuilder(SimpleObject.class) .setInner(new InnerSpec().property("str", NOT_NULL)) @@ -832,7 +833,7 @@ void setNotNull() { then(actual).isNotNull(); } - @Example + @Test void keysForCollection() { List keyList = Arrays.asList("key1", "key2", "key3"); @@ -847,7 +848,7 @@ void keysForCollection() { then(actual.keySet()).containsAll(keyList); } - @Example + @Test void valuesForCollection() { List valueList = Arrays.asList("value1", "value2", "value3"); @@ -862,7 +863,7 @@ void valuesForCollection() { then(actual.values()).containsAll(valueList); } - @Example + @Test void entriesForCollection() { List entries = Arrays.asList("key1", "value1", "key2", "value2"); @@ -878,7 +879,7 @@ void entriesForCollection() { then(actual.get("key2")).isEqualTo("value2"); } - @Example + @Test void supportSupplierWrapping() { String expected = "test"; @@ -896,7 +897,7 @@ void supportSupplierWrapping() { then(actual).isEqualTo(expected); } - @Example + @Test void supportSupplierObjectField() { Supplier expected = () -> "test"; diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/InstantiatorAdapterTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/InstantiatorTest.java similarity index 94% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/InstantiatorAdapterTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/InstantiatorTest.java index d1cf8ae439..a66b642171 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/InstantiatorAdapterTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/InstantiatorTest.java @@ -16,15 +16,14 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; import java.lang.reflect.Modifier; import java.util.List; -import net.jqwik.api.Property; -import net.jqwik.api.PropertyDefaults; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.instantiator.Instantiator; @@ -35,15 +34,13 @@ import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.MutableJavaTypeObject; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.SimpleContainerObject; -@PropertyDefaults(tries = 10) -class InstantiatorAdapterTest { +class InstantiatorTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void instantiateConstructorField() { // when String actual = SUT.giveMeBuilder(MutableJavaTypeObject.class) @@ -55,7 +52,7 @@ void instantiateConstructorField() { then(actual).isNotNull(); } - @Property + @Test void instantiateConstructorJavaBeansProperty() { // when String actual = SUT.giveMeBuilder(MutableJavaTypeObject.class) @@ -67,7 +64,7 @@ void instantiateConstructorJavaBeansProperty() { then(actual).isNotNull(); } - @Property + @Test void instantiateConstructorFieldFilter() { // when MutableJavaTypeObject actual = SUT.giveMeBuilder(MutableJavaTypeObject.class) @@ -81,7 +78,7 @@ void instantiateConstructorFieldFilter() { then(actual.getWrapperBoolean()).isNull(); } - @Property + @Test void instantiateConstructorJavaBeansPropertyFilter() { // when MutableJavaTypeObject actual = SUT.giveMeBuilder(MutableJavaTypeObject.class) @@ -97,7 +94,7 @@ void instantiateConstructorJavaBeansPropertyFilter() { then(actual.getWrapperBoolean()).isNotNull(); } - @Property + @Test void instantiateWithFilteredFieldsUsingCustomGenerator() { // given @@ -112,7 +109,7 @@ void instantiateWithFilteredFieldsUsingCustomGenerator() { then(actual.getWrapperInteger()).isNull(); } - @Property + @Test void instantiateParametersInOrder() { // when String actual = SUT.giveMeBuilder(ConstructorJavaTypeObject.class) @@ -135,7 +132,7 @@ void instantiateParametersInOrder() { then(actual).isEqualTo("first"); } - @Property + @Test void instantiateNoArgsConstructor() { // when String actual = SUT.giveMeBuilder(ConstructorJavaTypeObject.class) @@ -147,7 +144,7 @@ void instantiateNoArgsConstructor() { then(actual).isEqualTo("second"); } - @Property + @Test void instantiateParameterNameHint() { // when String actual = SUT.giveMeBuilder(ConstructorJavaTypeObject.class) @@ -160,7 +157,7 @@ void instantiateParameterNameHint() { then(actual).isEqualTo("third"); } - @Property + @Test void instantiateConstructorContainer() { // when List actual = SUT.giveMeBuilder(SimpleContainerObject.class) @@ -189,7 +186,7 @@ void instantiateConstructorContainer() { then(actual).hasSize(1); } - @Property + @Test void instantiateGenericObjectByConstructor() { // when ConstructorGenericObject actual = SUT.giveMeBuilder( @@ -208,7 +205,7 @@ void instantiateGenericObjectByConstructor() { then(actual.getValue()).isNotNull(); } - @Property + @Test void instantiateTwoGenericObjectByConstructor() { // when ConstructorTwoGenericObject actual = SUT.giveMeBuilder( @@ -228,7 +225,7 @@ void instantiateTwoGenericObjectByConstructor() { then(actual.getUValue()).isNotNull(); } - @Property + @Test void instantiateByFactoryMethod() { // when String actual = SUT.giveMeBuilder(ConstructorJavaTypeObject.class) @@ -240,7 +237,7 @@ void instantiateByFactoryMethod() { then(actual).isEqualTo("factory"); } - @Property + @Test void instantiateByFactoryMethodWithParameter() { // when String actual = SUT.giveMeBuilder(ConstructorJavaTypeObject.class) @@ -252,7 +249,7 @@ void instantiateByFactoryMethodWithParameter() { then(actual).isEqualTo("factory"); } - @Property + @Test void instantiateFactoryMethodAndField() { // when Integer actual = SUT.giveMeBuilder(ConstructorJavaTypeObject.class) diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/InterfaceResolverConverterTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/InterfaceResolverConverterTest.java similarity index 96% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/InterfaceResolverConverterTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/InterfaceResolverConverterTest.java index 0f3ba8a788..168a317e11 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/InterfaceResolverConverterTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/InterfaceResolverConverterTest.java @@ -16,14 +16,14 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.Assertions.assertThat; import java.util.Collections; import java.util.List; -import net.jqwik.api.Property; +import org.junit.jupiter.api.Test; import com.navercorp.objectfarm.api.expression.PathExpression; import com.navercorp.objectfarm.api.input.InterfaceResolverConverter; @@ -54,7 +54,7 @@ public String getName() { } } - @Property + @Test void createsResolverFromValueType() { Dog dog = new Dog(); @@ -73,7 +73,7 @@ void createsResolverFromValueType() { assertThat(resolvedType.getRawType()).isEqualTo(Dog.class); } - @Property + @Test void createsResolverWithSpecificConcreteType() { PathResolver resolver = InterfaceResolverConverter.createResolver("$.animal", Cat.class); @@ -87,7 +87,7 @@ void createsResolverWithSpecificConcreteType() { assertThat(resolvedType.getRawType()).isEqualTo(Cat.class); } - @Property + @Test void returnsNullForNonAssignableTypes() { PathResolver resolver = InterfaceResolverConverter.createResolver("$.animal", Dog.class); @@ -99,14 +99,14 @@ void returnsNullForNonAssignableTypes() { assertThat(resolvedType).isNull(); } - @Property + @Test void nullValueReturnsNullResolver() { PathResolver resolver = InterfaceResolverConverter.fromValue("$.animal", null); assertThat(resolver).isNull(); } - @Property + @Test void createsResolverWithTypeVariables() { List stringList = Collections.singletonList("test"); JvmType stringType = new JavaType(String.class); @@ -128,7 +128,7 @@ void createsResolverWithTypeVariables() { assertThat(resolvedType.getTypeVariables().get(0).getRawType()).isEqualTo(String.class); } - @Property + @Test void pathPatternMatchingWorksCorrectly() { PathResolver resolver = InterfaceResolverConverter.createResolver( "$.items[*].animal", diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/IntrospectorAdapterTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/IntrospectorTest.java similarity index 91% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/IntrospectorAdapterTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/IntrospectorTest.java index 20417d49dd..3d14bfe568 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/IntrospectorAdapterTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/IntrospectorTest.java @@ -16,14 +16,13 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; import java.util.Collections; -import net.jqwik.api.Property; -import net.jqwik.api.PropertyDefaults; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.generator.ArbitraryGeneratorContext; @@ -40,21 +39,18 @@ import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.SimpleObject; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.StringIntComposite; -@PropertyDefaults(tries = 10) -class IntrospectorAdapterTest { +class IntrospectorTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void fieldReflectionIntrospectorGeneratesAllFields() { // given FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); // when @@ -66,13 +62,12 @@ void fieldReflectionIntrospectorGeneratesAllFields() { then(actual.getWrapperInteger()).isNotNull(); } - @Property + @Test void beanIntrospectorGeneratesAllFields() { // given FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(BeanArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); // when @@ -84,13 +79,12 @@ void beanIntrospectorGeneratesAllFields() { then(actual.getWrapperInteger()).isNotNull(); } - @Property + @Test void constructorIntrospectorGeneratesConstructorParams() { // given FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); // when @@ -101,13 +95,12 @@ void constructorIntrospectorGeneratesConstructorParams() { then(actual.getValue()).isNotNull(); } - @Property + @Test void typeSpecificIntrospectorOverridesDefault() { // given FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .pushExactTypeArbitraryIntrospector(SimpleObject.class, BeanArbitraryIntrospector.INSTANCE) .build(); @@ -119,7 +112,7 @@ void typeSpecificIntrospectorOverridesDefault() { then(actual.getStr()).isNotNull(); } - @Property + @Test void instantiateWithConstructorGeneratesParams() { // when ConstructorOnlyObject actual = SUT.giveMeBuilder(ConstructorOnlyObject.class) @@ -131,13 +124,12 @@ void instantiateWithConstructorGeneratesParams() { then(actual.getValue()).isNotNull(); } - @Property + @Test void nestedObjectWithDifferentIntrospectors() { // given FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); // when @@ -150,7 +142,7 @@ void nestedObjectWithDifferentIntrospectors() { then(actual.getMapEntry()).isNotNull(); } - @Property + @Test void fieldFilteredPropertyGeneratorWorks() { // when MutableJavaTypeObject actual = SUT.giveMeBuilder(MutableJavaTypeObject.class) @@ -163,7 +155,7 @@ void fieldFilteredPropertyGeneratorWorks() { then(actual.getString()).isEqualTo("filtered"); } - @Property + @Test void customPropertyGeneratorViaIntrospectorRestrictsFields() { // given ArbitraryIntrospector customIntrospector = new ArbitraryIntrospector() { @@ -193,7 +185,6 @@ public PropertyGenerator getRequiredPropertyGenerator( FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(customIntrospector) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); // when @@ -205,7 +196,7 @@ public PropertyGenerator getRequiredPropertyGenerator( then(actual.getValue2()).isNull(); } - @Property + @Test void pushExactTypePropertyGeneratorRestrictsFields() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -222,7 +213,6 @@ void pushExactTypePropertyGeneratorRestrictsFields() { } }) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); // when diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/MiscAdapterTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/MiscTest.java similarity index 92% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/MiscAdapterTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/MiscTest.java index 9b8837e6b3..2ac37a7ba7 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/MiscAdapterTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/MiscTest.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; @@ -29,12 +29,10 @@ import java.util.Map; import java.util.Set; -import net.jqwik.api.Property; -import net.jqwik.api.PropertyDefaults; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.ArbitraryBuilder; import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.tracing.ResolutionTrace; import com.navercorp.fixturemonkey.api.type.TypeCache; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.ComplexObject; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.DeepNestedListObject; @@ -45,16 +43,15 @@ import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.SimpleObject; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.StringListWrapper; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.StringWrapperPair; +import com.navercorp.fixturemonkey.tracing.ResolutionTrace; -@PropertyDefaults(tries = 10) -class MiscAdapterTest { +class MiscTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void sampleComplexObject() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class).sample(); @@ -65,7 +62,7 @@ void sampleComplexObject() { then(actual.getMapEntry()).isNotNull(); } - @Property + @Test void giveMeManipulatedObjectRemainsManipulator() { StringListWrapper expected = SUT.giveMeBuilder(StringListWrapper.class).size("values", 2, 2).sample(); @@ -74,7 +71,7 @@ void giveMeManipulatedObjectRemainsManipulator() { then(actual.getValues().get(1)).isEqualTo("test"); } - @Property + @Test void thenApplyContainerSizeConsistentAcrossSamples() { // given ArbitraryBuilder builder = SUT.giveMeBuilder(ComplexObject.class).thenApply((obj, b) -> { @@ -95,7 +92,7 @@ void thenApplyContainerSizeConsistentAcrossSamples() { then(listSizes).as("list sizes should be consistent across thenApply samples").hasSize(1); } - @Property + @Test void thenApplyNestedObjectContainerSizeConsistent() { // given ArbitraryBuilder builder = SUT.giveMeBuilder(RichObject.class).thenApply((obj, b) -> { @@ -119,7 +116,7 @@ void thenApplyNestedObjectContainerSizeConsistent() { then(addonSizes).as("addons sizes should be consistent").hasSize(1); } - @Property + @Test void decomposedObjectPreservesContainerSize() { // given List expectedList = new ArrayList<>(java.util.Arrays.asList("a", "b", "c")); @@ -134,7 +131,7 @@ void decomposedObjectPreservesContainerSize() { then(actual.getValues()).containsExactly("a", "b", "c"); } - @Property + @Test void decomposedChildObjectPreservesContainerSize() { // given DeepObject product = SUT.giveMeBuilder(DeepObject.class).size("options", 2).fixed().sample(); @@ -146,7 +143,7 @@ void decomposedChildObjectPreservesContainerSize() { then(actual.getContent().getOptions()).hasSize(2); } - @Property + @Test void decomposedNestedContainerPreservesExplicitSize() { // given ComplexObject sampled = SUT.giveMeBuilder(ComplexObject.class) @@ -163,7 +160,7 @@ void decomposedNestedContainerPreservesExplicitSize() { then(actual.getList()).hasSize(2); } - @Property + @Test void thenApplyWithChildSampleContainerSizeConsistent() { // given ArbitraryBuilder builder = SUT.giveMeBuilder(RichObject.class).thenApply((order, b) -> { @@ -182,26 +179,7 @@ void thenApplyWithChildSampleContainerSizeConsistent() { then(optionSizes).as("options sizes should be 0 from explicit size()").containsExactly(0); } - @Property - void thenApplyWithChildSampleNoExplicitSizeContainerVaries() { - // given - ArbitraryBuilder builder = SUT.giveMeBuilder(RichObject.class).thenApply((order, b) -> { - DeepObject product = SUT.giveMeBuilder(DeepObject.class).sample(); - b.set("content", product); - }); - - // when - Set optionSizes = new HashSet<>(); - for (int i = 0; i < 100; i++) { - RichObject sampled = builder.sample(); - optionSizes.add(sampled.getContent().getOptions().size()); - } - - // then - then(optionSizes).as("without fixed(), option sizes should vary").hasSizeGreaterThan(1); - } - - @Property + @Test void setFieldThenSetRootDecomposed_laterRootOverridesEarlierField() { // given SimpleObject earlierField = new SimpleObject(); @@ -229,7 +207,7 @@ void setFieldThenSetRootDecomposed_laterRootOverridesEarlierField() { then(actual.getObject().getInteger()).isEqualTo(999); } - @Property(tries = 1) + @Test void adapterShouldNotIntrospectJavaStandardLibraryTypes() throws Exception { // given TypeCache.clearCache(); @@ -251,7 +229,7 @@ void adapterShouldNotIntrospectJavaStandardLibraryTypes() throws Exception { .isFalse(); } - @Property + @Test void setFieldOnNonRecursivePojoWithCacheEnabled() { // given StringWrapperPair actual = SUT.giveMeBuilder(StringWrapperPair.class).set("value1.value", "fixed").sample(); @@ -261,7 +239,7 @@ void setFieldOnNonRecursivePojoWithCacheEnabled() { then(actual.getValue2()).isNotNull(); } - @Property + @Test void setFieldOnNonRecursivePojoRepeatedSamplesRetainSetValue() { // given ArbitraryBuilder builder = SUT.giveMeBuilder(StringWrapperPair.class).set( @@ -280,7 +258,7 @@ void setFieldOnNonRecursivePojoRepeatedSamplesRetainSetValue() { then(value2Values.size()).as("non-set fields should vary across samples").isGreaterThan(1); } - @Property + @Test void setDeepRecursiveValueWithCacheEnabled() { // given SelfRecursiveObject actual = SUT.giveMeBuilder(SelfRecursiveObject.class) @@ -294,7 +272,7 @@ void setDeepRecursiveValueWithCacheEnabled() { then(actual.getRecursive().getRecursive().getValue()).as("value").isEqualTo("deep"); } - @Property + @Test void setRecursiveFieldValueWithCacheEnabled() { // given SelfRecursiveObject actual = SUT.giveMeBuilder(SelfRecursiveObject.class) @@ -306,7 +284,7 @@ void setRecursiveFieldValueWithCacheEnabled() { then(actual.getRecursive().getValue()).isEqualTo("test"); } - @Property + @Test void sizeOnContainerWithCacheEnabled() { // given StringListWrapper actual = SUT.giveMeBuilder(StringListWrapper.class).size("values", 3).sample(); @@ -315,7 +293,7 @@ void sizeOnContainerWithCacheEnabled() { then(actual.getValues()).hasSize(3); } - @Property + @Test void nestedSizeWithCacheEnabled() { // given NestedStringListWrapper actual = SUT.giveMeBuilder(NestedStringListWrapper.class) @@ -330,12 +308,11 @@ void nestedSizeWithCacheEnabled() { then(actual.getValues().get(1).getValues()).hasSize(4); } - @Property + @Test void registerTypedContainerSizeWithCacheEnabled() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture.giveMeBuilder(StringListWrapper.class).size("values", 4) ) @@ -350,12 +327,11 @@ void registerTypedContainerSizeWithCacheEnabled() { } } - @Property + @Test void registerPathSpecificSizeWithCacheEnabled() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(NestedStringListWrapper.class, fixture -> fixture .giveMeBuilder(NestedStringListWrapper.class) @@ -374,12 +350,11 @@ void registerPathSpecificSizeWithCacheEnabled() { then(actual.getValues().get(1).getValues()).hasSize(4); } - @Property + @Test void exactPathOverridesTypedSizeWithCacheEnabled() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture.giveMeBuilder(StringListWrapper.class).size("values", 4) ) @@ -398,13 +373,13 @@ void exactPathOverridesTypedSizeWithCacheEnabled() { then(actual.getValues().get(1).getValues()).hasSize(4); } - @Property(tries = 1) + @Test void tracerCapturesSubtreeCacheEvents() { // given List traces = new ArrayList<>(); FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin().tracer(traces::add)) + .tracer(traces::add) .build(); // when @@ -434,7 +409,7 @@ void tracerCapturesSubtreeCacheEvents() { .isTrue(); } - @Property + @Test void giveMeBuilderWithValueThenSetNestedContainerElementField() { // given DeepObject value = SUT.giveMeBuilder(DeepObject.class) @@ -452,7 +427,7 @@ void giveMeBuilderWithValueThenSetNestedContainerElementField() { then(actual.getOptions().get(0).getName()).isEqualTo(expected); } - @Property + @Test void giveMeBuilderWithValueThenSetDeepNestedField() { // given DeepObject value = SUT.giveMeBuilder(DeepObject.class).sample(); @@ -467,7 +442,7 @@ void giveMeBuilderWithValueThenSetDeepNestedField() { then(actual.getPolicy().getThreshold().getLimit()).isEqualTo(expected); } - @Property + @Test void giveMeBuilderWithValueThenSetMultipleNestedFields() { // given DeepObject value = SUT.giveMeBuilder(DeepObject.class) @@ -487,7 +462,7 @@ void giveMeBuilderWithValueThenSetMultipleNestedFields() { then(actual.getPolicy().getMethod()).isEqualTo(expectedMethod); } - @Property + @Test void giveMeBuilderWithValueThenSetWildcardContainerElementField() { // given DeepObject value = SUT.giveMeBuilder(DeepObject.class) @@ -505,7 +480,7 @@ void giveMeBuilderWithValueThenSetWildcardContainerElementField() { then(actual.getOptions().get(1).getName()).isEqualTo("NOTHING"); } - @Property + @Test void giveMeBuilderWithValueThenSetDeepNestedContainerPath() { // given — items[0].detail.spec.category 시나리오 재현 // DeepObject.options[0].name 은 2-depth, policy.threshold.limit 은 3-depth @@ -525,7 +500,7 @@ void giveMeBuilderWithValueThenSetDeepNestedContainerPath() { then(actual.getOptions().get(0).getValues().get(0)).isEqualTo(expected); } - @Property + @Test void giveMeBuilderWithValueThenSetDeep4DepthNestedField() { // given — items[0].detail.spec.category enum 시나리오 DeepNestedListObject value = SUT.giveMeBuilder(DeepNestedListObject.class) @@ -543,7 +518,7 @@ void giveMeBuilderWithValueThenSetDeep4DepthNestedField() { .isEqualTo(expected); } - @Property + @Test void giveMeBuilderWithValueThenSetWildcard4DepthNestedField() { // given — items[*].detail.spec.category 시나리오 재현 DeepNestedListObject value = SUT.giveMeBuilder(DeepNestedListObject.class) @@ -564,7 +539,7 @@ void giveMeBuilderWithValueThenSetWildcard4DepthNestedField() { .isEqualTo(expected); } - @Property + @Test void giveMeBuilderWithValueThenSizeThenSetDeep4DepthNestedField() { // given — giveMeBuilder(value) + size + set indexed element DeepNestedListObject value = SUT.giveMeBuilder(DeepNestedListObject.class) @@ -584,7 +559,7 @@ void giveMeBuilderWithValueThenSizeThenSetDeep4DepthNestedField() { .isEqualTo(expected); } - @Property + @Test void setWildcard4DepthNestedFieldWithoutGiveMeValue() { // given — giveMeBuilder(Class)에서도 와일드카드 4-depth가 실패하는지 확인 DeepNestedListObject.Category expected = DeepNestedListObject.Category.NOTHING; diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/PluginAdapterTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/PluginTest.java similarity index 88% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/PluginAdapterTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/PluginTest.java index 8516be370a..0fd284a2d2 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/PluginAdapterTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/PluginTest.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static com.navercorp.fixturemonkey.api.experimental.TypedExpressionGenerator.typedRoot; import static com.navercorp.fixturemonkey.api.experimental.TypedExpressionGenerator.typedString; @@ -27,8 +27,7 @@ import java.util.List; import java.util.Set; -import net.jqwik.api.Property; -import net.jqwik.api.PropertyDefaults; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary; @@ -36,13 +35,11 @@ import com.navercorp.fixturemonkey.api.type.TypeReference; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.SimpleObject; -@PropertyDefaults(tries = 10) -class PluginAdapterTest { +class PluginTest { - @Property + @Test void plugin() { FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin(optionsBuilder -> optionsBuilder.insertFirstNullInjectGenerators(String.class, context -> 1.0d)) .build(); @@ -51,10 +48,9 @@ void plugin() { then(actual).isEqualTo(null); } - @Property(tries = 1) + @Test void alterArbitraryValidator() { FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .arbitraryValidator(obj -> { throw new ValidationFailedException("thrown by test ArbitraryValidator", new HashSet<>()); }) @@ -63,11 +59,10 @@ void alterArbitraryValidator() { thenThrownBy(() -> sut.giveMeOne(String.class)).isExactlyInstanceOf(IllegalArgumentException.class); } - @Property + @Test void customizePropertyUnique() { // given FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .defaultNotNull(true) .build(); diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/RecursiveTypeAdapterTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/RecursiveTypeTest.java similarity index 90% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/RecursiveTypeAdapterTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/RecursiveTypeTest.java index 8747887eac..5353fe3bda 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/RecursiveTypeAdapterTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/RecursiveTypeTest.java @@ -16,12 +16,11 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; -import net.jqwik.api.Property; -import net.jqwik.api.PropertyDefaults; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.RecursiveLeftObject; @@ -29,15 +28,13 @@ import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.SelfRecursiveObject; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.SelfRecursiveSupplierObject; -@PropertyDefaults(tries = 10) -class RecursiveTypeAdapterTest { +class RecursiveTypeTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void sampleSelfRecursiveObject() { SelfRecursiveObject actual = SUT.giveMeOne(SelfRecursiveObject.class); @@ -46,7 +43,7 @@ void sampleSelfRecursiveObject() { then(actual.getRecursive().getValue()).isNotNull(); } - @Property + @Test void sampleSelfRecursiveList() { SelfRecursiveListObject actual = SUT.giveMeOne(SelfRecursiveListObject.class); @@ -54,7 +51,7 @@ void sampleSelfRecursiveList() { then(actual.getRecursives()).isNotNull(); } - @Property + @Test void sampleRecursiveSupplier() { SelfRecursiveSupplierObject actual = SUT.giveMeOne(SelfRecursiveSupplierObject.class); @@ -63,7 +60,7 @@ void sampleRecursiveSupplier() { then(actual.getRecursive().get()).isNotNull(); } - @Property + @Test void sampleRecursiveObject() { RecursiveLeftObject actual = SUT.giveMeOne(RecursiveLeftObject.class); @@ -72,7 +69,7 @@ void sampleRecursiveObject() { then(actual.getRecursive().getValue()).isNotNull(); } - @Property + @Test void setRecursiveFieldValue() { // given SelfRecursiveObject actual = SUT.giveMeBuilder(SelfRecursiveObject.class) @@ -84,7 +81,7 @@ void setRecursiveFieldValue() { then(actual.getRecursive().getValue()).isEqualTo("test"); } - @Property + @Test void setDeepRecursiveValue() { // given SelfRecursiveObject actual = SUT.giveMeBuilder(SelfRecursiveObject.class) diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/RegisterComplexAdapterTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/RegisterComplexTest.java similarity index 95% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/RegisterComplexAdapterTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/RegisterComplexTest.java index 4567824ae5..bcfe869a5f 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/RegisterComplexAdapterTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/RegisterComplexTest.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; @@ -26,12 +26,11 @@ import java.util.Collections; import java.util.List; +import org.junit.jupiter.api.Test; + import net.jqwik.api.Arbitraries; -import net.jqwik.api.Property; -import net.jqwik.api.PropertyDefaults; import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.tracing.AdapterTracer; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.DeepObject; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.DoubleNestedStringListWrapper; @@ -41,20 +40,19 @@ import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.StringListWrapper; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.StringWrapper; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.WrapperObject; +import com.navercorp.fixturemonkey.tracing.AssemblyTracer; /** * Reproduction tests for complex registered builder scenarios. * Tests various suspicious patterns from fixture-test.txt trace analysis. */ -@PropertyDefaults(tries = 10) -class RegisterComplexAdapterTest { +class RegisterComplexTest { - @Property + @Test void registeredBuilderFieldLevelSetLazyShouldApply() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.class, fixture -> fixture .giveMeBuilder(DeepObject.class) @@ -92,12 +90,11 @@ void registeredBuilderFieldLevelSetLazyShouldApply() { then(actual.getPolicy().getAreaRule().isEnabled()).isTrue(); } - @Property + @Test void exactTracePattern_sixRegisteredBuildersZeroActive() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(Envelope.Body.DeliveryInfo.Range.class, fixture -> fixture .giveMeBuilder(Envelope.Body.DeliveryInfo.Range.class) @@ -156,12 +153,11 @@ void exactTracePattern_sixRegisteredBuildersZeroActive() { then(actual.getDeliveryInfo().getRange().getTo()).isEqualByComparingTo(BigDecimal.valueOf(3000)); } - @Property + @Test void registeredNestedTypeViaWrapperWithSixBuilders() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(Envelope.Body.DeliveryInfo.Range.class, fixture -> fixture .giveMeBuilder(Envelope.Body.DeliveryInfo.Range.class) @@ -214,12 +210,11 @@ void registeredNestedTypeViaWrapperWithSixBuilders() { then(actual.getBody().getDeliveryInfo().getAreaRule().getUnit()).isEqualTo("AREA"); } - @Property + @Test void rootTypeWithBothFieldSetLazyAndThenApply() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(Envelope.Body.class, fixture -> fixture .giveMeBuilder(Envelope.Body.class) @@ -275,12 +270,11 @@ void rootTypeWithBothFieldSetLazyAndThenApply() { then(actual.getDeliveryInfo().getAreaRule().getRate1()).isEqualByComparingTo(BigDecimal.valueOf(3000)); } - @Property + @Test void rootThenApplyConditionalMultiFieldSet() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(Envelope.Body.DeliveryInfo.Range.class, fixture -> fixture .giveMeBuilder(Envelope.Body.DeliveryInfo.Range.class) @@ -359,12 +353,11 @@ void rootThenApplyConditionalMultiFieldSet() { then(actual.getDeliveryInfo().getRange().getTo()).isEqualByComparingTo(BigDecimal.valueOf(600)); } - @Property + @Test void giveMeOneWithZeroActiveAndTwoRegisteredBuilders() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.class, fixture -> fixture .giveMeBuilder(DeepObject.class) @@ -385,12 +378,11 @@ void giveMeOneWithZeroActiveAndTwoRegisteredBuilders() { then(actual.getPolicy().getMethod()).isEqualTo("DELIVERY"); } - @Property + @Test void rootFieldSetLazyWithNestedConditionalThenApply() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.class, fixture -> fixture .giveMeBuilder(DeepObject.class) @@ -441,12 +433,11 @@ void rootFieldSetLazyWithNestedConditionalThenApply() { then(actual.getPolicy().getAreaRule().getUnit()).isEqualTo("ZIP"); } - @Property + @Test void multipleSamplesWithConditionalThenApply() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(Envelope.Body.DeliveryInfo.Range.class, fixture -> fixture .giveMeBuilder(Envelope.Body.DeliveryInfo.Range.class) @@ -504,12 +495,11 @@ void multipleSamplesWithConditionalThenApply() { } } - @Property + @Test void registeredSetWithConditionalThenApply() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(Envelope.Body.DeliveryInfo.Range.class, fixture -> fixture .giveMeBuilder(Envelope.Body.DeliveryInfo.Range.class) @@ -533,12 +523,11 @@ void registeredSetWithConditionalThenApply() { then(actual.getTo()).isEqualByComparingTo(BigDecimal.valueOf(100)); } - @Property + @Test void directSetOverridesRegisteredSetLazy() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(Envelope.Body.class, fixture -> fixture .giveMeBuilder(Envelope.Body.class) @@ -555,12 +544,11 @@ void directSetOverridesRegisteredSetLazy() { then(actual.getTaxType()).isEqualTo("TAX"); } - @Property + @Test void registeredBuilderOnlyOnDeeplyNestedType() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(Envelope.Body.DeliveryInfo.QuantityRule.class, fixture -> fixture .giveMeBuilder(Envelope.Body.DeliveryInfo.QuantityRule.class) @@ -577,12 +565,11 @@ void registeredBuilderOnlyOnDeeplyNestedType() { then(actual.getDeliveryInfo().getQuantityRule().getRepeat()).isEqualTo(7L); } - @Property + @Test void registeredContentViaWrapperObjectWithThenApply() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(WrapperObject.Content.class, fixture -> fixture .giveMeBuilder(WrapperObject.Content.class) @@ -607,12 +594,11 @@ void registeredContentViaWrapperObjectWithThenApply() { then(actual.getContent().getName()).isEqualTo("ACTIVE_FREE"); } - @Property + @Test void parentThenApplyWithRealLogicAndChildRegisteredSetLazy() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.class, fixture -> fixture .giveMeBuilder(DeepObject.class) @@ -644,12 +630,11 @@ void parentThenApplyWithRealLogicAndChildRegisteredSetLazy() { then(actual.getContent().getName()).isEqualTo("P_ON_SALE"); } - @Property + @Test void registeredBuilderContainerSizeWithFieldSetLazy() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.class, fixture -> fixture .giveMeBuilder(DeepObject.class) @@ -670,12 +655,11 @@ void registeredBuilderContainerSizeWithFieldSetLazy() { then(actual.getAddons()).hasSize(2); } - @Property + @Test void registeredBuilderDoubleThenApplyWithConditions() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.class, fixture -> fixture .giveMeBuilder(DeepObject.class) @@ -708,12 +692,11 @@ void registeredBuilderDoubleThenApplyWithConditions() { then(actual.getFlag()).isTrue(); } - @Property + @Test void sameRegisteredTypeAtMultipleTreeLocations() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.class, fixture -> fixture .giveMeBuilder(DeepObject.class) @@ -740,12 +723,11 @@ void sameRegisteredTypeAtMultipleTreeLocations() { then(actual.getContent().getPolicy().getFeeType()).isEqualTo("DELIVERY_FEE"); } - @Property + @Test void registeredBuilderMixedSetAndSetLazyWithThenApply() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(Envelope.Body.class, fixture -> fixture .giveMeBuilder(Envelope.Body.class) @@ -778,12 +760,11 @@ void registeredBuilderMixedSetAndSetLazyWithThenApply() { then(actual.getDeliveryInfo().getGroupId()).isEqualTo("CONDITIONAL_FREE_GRP"); } - @Property + @Test void registeredBuilderContainerSizeThenApplyFieldSetLazy() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(Envelope.Body.class, fixture -> fixture .giveMeBuilder(Envelope.Body.class) @@ -816,12 +797,11 @@ void registeredBuilderContainerSizeThenApplyFieldSetLazy() { then(actual.getDeliveryInfo().getGroupId()).isEqualTo("DELIVERY_CONDITIONAL_FREE"); } - @Property + @Test void registeredThenApplySamplesAnotherRegisteredType() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(RichObject.Metadata.class, fixture -> fixture .giveMeBuilder(RichObject.Metadata.class) @@ -850,12 +830,11 @@ void registeredThenApplySamplesAnotherRegisteredType() { then(actual.getMetadata().isVerified()).isTrue(); } - @Property + @Test void sixRegisteredBuildersWithActiveManipulatorOnRoot() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(Envelope.Body.DeliveryInfo.Range.class, fixture -> fixture .giveMeBuilder(Envelope.Body.DeliveryInfo.Range.class) @@ -908,12 +887,11 @@ void sixRegisteredBuildersWithActiveManipulatorOnRoot() { then(actual.getDeliveryInfo().getGroupId()).isEqualTo("GRP_DELIVERY"); } - @Property + @Test void allRegisteredBuildersFieldSetLazyOnlyNoThenApply() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(Envelope.Body.DeliveryInfo.Range.class, fixture -> fixture.giveMeBuilder(Envelope.Body.DeliveryInfo.Range.class).set("type", "3") ) @@ -955,12 +933,11 @@ void allRegisteredBuildersFieldSetLazyOnlyNoThenApply() { then(actual.getDeliveryInfo().getRange().getType()).isEqualTo("3"); } - @Property + @Test void registeredParentThenApplySamplesRegisteredChild() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.class, fixture -> fixture .giveMeBuilder(DeepObject.class) @@ -1016,12 +993,11 @@ void registeredParentThenApplySamplesRegisteredChild() { then(actual.getMetadata().getTrackingCode()).isEqualTo("TRACK_ACC"); } - @Property + @Test void registeredBuilderSetLazyMixedWithSetNull() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(Envelope.Body.class, fixture -> fixture .giveMeBuilder(Envelope.Body.class) @@ -1040,12 +1016,11 @@ void registeredBuilderSetLazyMixedWithSetNull() { then(actual.getOptionSupport()).isNull(); } - @Property + @Test void largeTreeWithRegisteredValuesOnFewFields() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(Envelope.Body.class, fixture -> fixture .giveMeBuilder(Envelope.Body.class) @@ -1065,12 +1040,11 @@ void largeTreeWithRegisteredValuesOnFewFields() { then(actual.getProductUrl()).isNotNull(); } - @Property + @Test void registeredBuilderRootSetFollowedByConditionalThenApply() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.Policy.QuantityRule.class, fixture -> fixture .giveMeBuilder(DeepObject.Policy.QuantityRule.class) @@ -1095,12 +1069,11 @@ void registeredBuilderRootSetFollowedByConditionalThenApply() { then(actual.getRepeat()).isNull(); } - @Property + @Test void registeredBuilderWithSetAndConditionalThenApply() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(Envelope.Body.class, fixture -> fixture .giveMeBuilder(Envelope.Body.class) @@ -1133,12 +1106,11 @@ void registeredBuilderWithSetAndConditionalThenApply() { then(actual.getDeliveryInfo().getGroupId()).isEqualTo("DELIVERY_CONDITIONAL_FREE"); } - @Property + @Test void shippingPolicyThenApplySetsEntireChildObjectsByMethod() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.class, fixture -> fixture .giveMeBuilder(DeepObject.class) @@ -1192,12 +1164,11 @@ void shippingPolicyThenApplySetsEntireChildObjectsByMethod() { then(actual.getPolicy().getThreshold().getLimit()).isEqualByComparingTo(BigDecimal.valueOf(50000)); } - @Property + @Test void shippingPolicyThenApplySetsChildObjectsViaFixtureSample() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.class, fixture -> fixture .giveMeBuilder(DeepObject.class) @@ -1250,12 +1221,11 @@ void shippingPolicyThenApplySetsChildObjectsViaFixtureSample() { then(actual.getPolicy().getThreshold().getLimit()).isEqualByComparingTo(BigDecimal.valueOf(50000)); } - @Property + @Test void remoteShippingInfoThenApplySetsEntireChildObjectsByMethod() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(Envelope.Body.DeliveryInfo.Range.class, fixture -> fixture .giveMeBuilder(Envelope.Body.DeliveryInfo.Range.class) @@ -1334,12 +1304,11 @@ void remoteShippingInfoThenApplySetsEntireChildObjectsByMethod() { then(actual.getDeliveryInfo().getThreshold().getLimit()).isEqualByComparingTo(BigDecimal.valueOf(50000)); } - @Property + @Test void remoteShippingInfoThenApplySetsChildObjectsViaFixtureSample() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(Envelope.Body.DeliveryInfo.Range.class, fixture -> fixture.giveMeBuilder(Envelope.Body.DeliveryInfo.Range.class).set("type", "3") ) @@ -1404,12 +1373,11 @@ void remoteShippingInfoThenApplySetsChildObjectsViaFixtureSample() { then(actual.getDeliveryInfo().getThreshold().getLimit()).isEqualByComparingTo(BigDecimal.valueOf(50000)); } - @Property + @Test void shippingPolicyThenApplyThreeBranchMethodRouting() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.class, fixture -> fixture .giveMeBuilder(DeepObject.class) @@ -1469,12 +1437,11 @@ void shippingPolicyThenApplyThreeBranchMethodRouting() { then(actual.getPolicy().getThreshold().getLimit()).isEqualByComparingTo(BigDecimal.valueOf(50000)); } - @Property + @Test void shippingPolicyThenApplySetsObjectsViaBuilderChain() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.class, fixture -> fixture .giveMeBuilder(DeepObject.class) @@ -1530,12 +1497,11 @@ void shippingPolicyThenApplySetsObjectsViaBuilderChain() { then(actual.getPolicy().getThreshold().getLimit()).isEqualByComparingTo(BigDecimal.valueOf(30000)); } - @Property + @Test void wrapperSampledNestedPolicyThenApplySetsObjects() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(Envelope.Body.DeliveryInfo.Range.class, fixture -> fixture.giveMeBuilder(Envelope.Body.DeliveryInfo.Range.class).set("type", "3") ) @@ -1605,12 +1571,11 @@ void wrapperSampledNestedPolicyThenApplySetsObjects() { ); } - @Property + @Test void multipleSamplesPolicyThenApplySetsObjects() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.class, fixture -> fixture .giveMeBuilder(DeepObject.class) @@ -1660,12 +1625,12 @@ void multipleSamplesPolicyThenApplySetsObjects() { } } - @Property + @Test void exactRealPattern_thenApplySetsDollarWithSampledObject() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin().tracer(AdapterTracer.console())) + .tracer(AssemblyTracer.console()) .register(Envelope.Body.DeliveryInfo.Range.class, fixture -> fixture .giveMeBuilder(Envelope.Body.DeliveryInfo.Range.class) @@ -1730,12 +1695,12 @@ void exactRealPattern_thenApplySetsDollarWithSampledObject() { then(actual.getTaxType()).isEqualTo("TAX"); } - @Property + @Test void nestedPathSet_shippingPolicyFieldsViaNestedExpression() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin().tracer(AdapterTracer.console())) + .tracer(AssemblyTracer.console()) .register(Envelope.Body.DeliveryInfo.Range.class, fixture -> fixture.giveMeBuilder(Envelope.Body.DeliveryInfo.Range.class).set("type", "3") ) @@ -1792,12 +1757,12 @@ void nestedPathSet_shippingPolicyFieldsViaNestedExpression() { then(actual.getDeliveryInfo().getThreshold().getLimit()).isEqualByComparingTo(BigDecimal.valueOf(50000)); } - @Property + @Test void newObjectSet_shippingPolicyChildObjectsViaNew() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin().tracer(AdapterTracer.console())) + .tracer(AssemblyTracer.console()) .register(Envelope.Body.DeliveryInfo.Range.class, fixture -> fixture.giveMeBuilder(Envelope.Body.DeliveryInfo.Range.class).set("type", "3") ) @@ -1863,14 +1828,14 @@ void newObjectSet_shippingPolicyChildObjectsViaNew() { then(actual.getDeliveryInfo().getThreshold().getLimit()).isEqualByComparingTo(BigDecimal.valueOf(50000)); } - @Property + @Test void registeredSetLazyArbitrariesOf_methodFieldRandomSelection() { // given List validMethods = Arrays.asList("DELIVERY", "VISIT", "DIRECT"); FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin().tracer(AdapterTracer.console())) + .tracer(AssemblyTracer.console()) .register(Envelope.Body.DeliveryInfo.Range.class, fixture -> fixture.giveMeBuilder(Envelope.Body.DeliveryInfo.Range.class).set("type", "3") ) @@ -1948,12 +1913,11 @@ void registeredSetLazyArbitrariesOf_methodFieldRandomSelection() { } } - @Property + @Test void registeredSetLazyBeforeAndAfterThenApply_allFieldsAppliedInNestedType() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.Policy.class, fixture -> fixture .giveMeBuilder(DeepObject.Policy.class) @@ -1979,12 +1943,11 @@ void registeredSetLazyBeforeAndAfterThenApply_allFieldsAppliedInNestedType() { } } - @Property + @Test void registeredFieldLevelSetLazy_allFieldsShouldResolveOnDirectSample() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(Envelope.Body.DeliveryInfo.Range.class, fixture -> fixture.giveMeBuilder(Envelope.Body.DeliveryInfo.Range.class).set("type", "3") ) @@ -2023,7 +1986,7 @@ void registeredFieldLevelSetLazy_allFieldsShouldResolveOnDirectSample() { } } - @Property + @Test void registerSizeThenApply_directSetDecomposed() { // given List decomposed = new ArrayList<>(); @@ -2033,7 +1996,6 @@ void registerSizeThenApply_directSetDecomposed() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture .giveMeBuilder(StringListWrapper.class) @@ -2052,7 +2014,7 @@ void registerSizeThenApply_directSetDecomposed() { then(actual.get(2)).isEqualTo("c"); } - @Property + @Test void registerSetDecomposed_directThenApplyWildcardSize() { // given List innerList = new ArrayList<>(); @@ -2062,7 +2024,6 @@ void registerSetDecomposed_directThenApplyWildcardSize() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(NestedStringListWrapper.class, fixture -> fixture.giveMeBuilder(NestedStringListWrapper.class) .set("values[0].values", innerList) @@ -2084,7 +2045,7 @@ void registerSetDecomposed_directThenApplyWildcardSize() { then(actual.get(1).getValues()).hasSize(2); } - @Property + @Test void registerThenApplyWildcardSize_directSetDecomposed() { // given List innerList = new ArrayList<>(); @@ -2094,7 +2055,6 @@ void registerThenApplyWildcardSize_directSetDecomposed() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(NestedStringListWrapper.class, fixture -> fixture .giveMeBuilder(NestedStringListWrapper.class) @@ -2118,12 +2078,11 @@ void registerThenApplyWildcardSize_directSetDecomposed() { then(actual.get(1).getValues()).hasSize(2); } - @Property + @Test void registerThenApplyWildcardSet_directSize() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture .giveMeBuilder(StringListWrapper.class) @@ -2138,12 +2097,11 @@ void registerThenApplyWildcardSet_directSize() { then(actual).hasSize(5); } - @Property + @Test void registerThenApply_directThenApplyWildcardSize_conflict() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(NestedStringListWrapper.class, fixture -> fixture .giveMeBuilder(NestedStringListWrapper.class) @@ -2165,7 +2123,7 @@ void registerThenApply_directThenApplyWildcardSize_conflict() { then(actual.get(2).getValues()).hasSize(2); } - @Property + @Test void nestedRegister_parentThenApplySetsChildContainer_childRegisterSize() { // given List innerList = new ArrayList<>(); @@ -2174,7 +2132,6 @@ void nestedRegister_parentThenApplySetsChildContainer_childRegisterSize() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture.giveMeBuilder(StringListWrapper.class).size("values", 4) ) @@ -2197,12 +2154,11 @@ void nestedRegister_parentThenApplySetsChildContainer_childRegisterSize() { then(actual.get(1).getValues()).hasSize(4); } - @Property + @Test void exactPathSizeOverridesTypedBasedRegisterSize() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture.giveMeBuilder(StringListWrapper.class).size("values", 4) ) @@ -2215,12 +2171,11 @@ void exactPathSizeOverridesTypedBasedRegisterSize() { then(actual.getValues()).hasSize(2); } - @Property + @Test void typeBasedRegisterSizeOverridesWildcardSize() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture.giveMeBuilder(StringListWrapper.class).size("values", 4) ) @@ -2239,12 +2194,11 @@ void typeBasedRegisterSizeOverridesWildcardSize() { then(actual.getValues().get(1).getValues()).hasSize(4); } - @Property + @Test void nestedRegisterSize_withoutThenApply() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture.giveMeBuilder(StringListWrapper.class).size("values", 4) ) @@ -2262,12 +2216,11 @@ void nestedRegisterSize_withoutThenApply() { then(actual.getValues().get(1).getValues()).hasSize(4); } - @Property + @Test void tripleNestedRegisterSize() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture.giveMeBuilder(StringListWrapper.class).size("values", 3) ) @@ -2289,12 +2242,11 @@ void tripleNestedRegisterSize() { then(actual.getValues().get(0).getValues().get(1).getValues()).hasSize(3); } - @Property + @Test void exactPathPartiallyOverridesTypeBasedSize() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture.giveMeBuilder(StringListWrapper.class).size("values", 4) ) @@ -2313,7 +2265,7 @@ void exactPathPartiallyOverridesTypeBasedSize() { then(actual.getValues().get(1).getValues()).hasSize(4); } - @Property + @Test void registerRootSetLazy_directDecomposed_directFieldSetNull() { // given DeepObject.Policy.AreaRule registeredAreaRule = new DeepObject.Policy.AreaRule(); @@ -2324,7 +2276,6 @@ void registerRootSetLazy_directDecomposed_directFieldSetNull() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.Policy.AreaRule.class, fixture -> fixture.giveMeBuilder(DeepObject.Policy.AreaRule.class).setLazy("$", () -> registeredAreaRule) ) @@ -2345,7 +2296,7 @@ void registerRootSetLazy_directDecomposed_directFieldSetNull() { then(actual.getRate2()).isNull(); } - @Property + @Test void registerRootSetLazy_directDecomposed_directFieldSetLazy() { // given DeepObject.Policy.AreaRule registeredAreaRule = new DeepObject.Policy.AreaRule(); @@ -2356,7 +2307,6 @@ void registerRootSetLazy_directDecomposed_directFieldSetLazy() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.Policy.AreaRule.class, fixture -> fixture.giveMeBuilder(DeepObject.Policy.AreaRule.class).setLazy("$", () -> registeredAreaRule) ) @@ -2376,7 +2326,7 @@ void registerRootSetLazy_directDecomposed_directFieldSetLazy() { then(actual.getRate2()).isEqualByComparingTo(BigDecimal.valueOf(5000)); } - @Property + @Test void registerRootSetLazy_directDecomposed_directRootSetLazy() { // given DeepObject.Policy.AreaRule decomposedAreaRule = new DeepObject.Policy.AreaRule(); @@ -2393,7 +2343,6 @@ void registerRootSetLazy_directDecomposed_directRootSetLazy() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.Policy.AreaRule.class, fixture -> fixture .giveMeBuilder(DeepObject.Policy.AreaRule.class) @@ -2416,7 +2365,7 @@ void registerRootSetLazy_directDecomposed_directRootSetLazy() { then(actual.getRate2()).isEqualByComparingTo(BigDecimal.valueOf(8000)); } - @Property + @Test void directDecomposedChildOverridesRegisteredBuilder() { // given DeepObject.Policy.AreaRule customAreaRule = new DeepObject.Policy.AreaRule(); @@ -2427,7 +2376,6 @@ void directDecomposedChildOverridesRegisteredBuilder() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.Policy.AreaRule.class, fixture -> fixture .giveMeBuilder(DeepObject.Policy.AreaRule.class) @@ -2455,12 +2403,11 @@ void directDecomposedChildOverridesRegisteredBuilder() { then(actual.getAreaRule().getRate2()).isEqualByComparingTo(BigDecimal.valueOf(8888)); } - @Property + @Test void registerSetLazy_directAcceptIf() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.Policy.AreaRule.class, fixture -> fixture .giveMeBuilder(DeepObject.Policy.AreaRule.class) @@ -2483,12 +2430,11 @@ void registerSetLazy_directAcceptIf() { then(actual.getRate1()).isEqualByComparingTo(BigDecimal.valueOf(1000)); } - @Property + @Test void registerThenApply_directSetNull() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.Policy.AreaRule.class, fixture -> fixture .giveMeBuilder(DeepObject.Policy.AreaRule.class) @@ -2512,12 +2458,11 @@ void registerThenApply_directSetNull() { then(actual.getRate1()).isEqualByComparingTo(BigDecimal.valueOf(2000)); } - @Property + @Test void registerThenApply_directSetNotNull() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.Policy.AreaRule.class, fixture -> fixture .giveMeBuilder(DeepObject.Policy.AreaRule.class) @@ -2540,12 +2485,11 @@ void registerThenApply_directSetNotNull() { then(actual.getRate1()).isEqualByComparingTo(BigDecimal.valueOf(3000)); } - @Property + @Test void registerFieldSetLazy_directSetNotNull() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.Policy.AreaRule.class, fixture -> fixture .giveMeBuilder(DeepObject.Policy.AreaRule.class) @@ -2565,12 +2509,11 @@ void registerFieldSetLazy_directSetNotNull() { then(actual.getUnit()).isNotNull(); } - @Property + @Test void registerFieldSetLazy_directSetLazySameField() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.Policy.AreaRule.class, fixture -> fixture .giveMeBuilder(DeepObject.Policy.AreaRule.class) @@ -2590,12 +2533,11 @@ void registerFieldSetLazy_directSetLazySameField() { then(actual.getUnit()).isEqualTo("DIRECT_LAZY"); } - @Property + @Test void setChildFieldWhereChildHasRegister() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.Policy.AreaRule.class, fixture -> fixture .giveMeBuilder(DeepObject.Policy.AreaRule.class) @@ -2618,12 +2560,11 @@ void setChildFieldWhereChildHasRegister() { then(actual.getAreaRule().getRate2()).isEqualByComparingTo(BigDecimal.valueOf(5000)); } - @Property + @Test void registerSize_directSetElement() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture.giveMeBuilder(StringListWrapper.class).size("values", 3) ) @@ -2639,12 +2580,11 @@ void registerSize_directSetElement() { then(actual.getValues().get(0)).isEqualTo("EXPLICIT_FIRST"); } - @Property + @Test void registerSize_directSetNullWildcard() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture.giveMeBuilder(StringListWrapper.class).size("values", 3) ) @@ -2658,12 +2598,11 @@ void registerSize_directSetNullWildcard() { then(actual.getValues()).allMatch(v -> v == null); } - @Property + @Test void registerDuplicateSetSameField_lastSetWins() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringWrapper.class, fixture -> fixture.giveMeBuilder(StringWrapper.class).set("value", "FIRST").set("value", "SECOND") ) @@ -2675,12 +2614,11 @@ void registerDuplicateSetSameField_lastSetWins() { then(actual.getValue()).isEqualTo("SECOND"); } - @Property + @Test void registerSetField_directWildcardSetNull() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DeepObject.Policy.AreaRule.class, fixture -> fixture .giveMeBuilder(DeepObject.Policy.AreaRule.class) @@ -2697,7 +2635,7 @@ void registerSetField_directWildcardSetNull() { then(actual.getRate2()).isNull(); } - @Property + @Test void registerContainerSetOnly_sizeInferredFromValue() { // given StringWrapper registeredElement = new StringWrapper(); @@ -2705,7 +2643,6 @@ void registerContainerSetOnly_sizeInferredFromValue() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(FixtureMonkeyTestSpecs.StringWrapperList.class, fixture -> fixture .giveMeBuilder(FixtureMonkeyTestSpecs.StringWrapperList.class) @@ -2724,7 +2661,7 @@ void registerContainerSetOnly_sizeInferredFromValue() { then(actual.getValues().get(0).getValue()).isEqualTo("DIRECT"); } - @Property + @Test void registerContainerSet_directElementOverride_fieldShouldUseExplicitElement() { // given StringWrapper registeredElement = new StringWrapper(); @@ -2738,7 +2675,6 @@ void registerContainerSet_directElementOverride_fieldShouldUseExplicitElement() FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(FixtureMonkeyTestSpecs.StringWrapperList.class, fixture -> fixture .giveMeBuilder(FixtureMonkeyTestSpecs.StringWrapperList.class) diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/RegisterAdapterTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/RegisterTest.java similarity index 89% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/RegisterAdapterTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/RegisterTest.java index 1292f5f874..3135ac3e61 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/RegisterAdapterTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/RegisterTest.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; @@ -26,9 +26,9 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.junit.jupiter.api.Test; + import net.jqwik.api.Arbitraries; -import net.jqwik.api.Property; -import net.jqwik.api.PropertyDefaults; import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.type.TypeReference; @@ -46,15 +46,13 @@ import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.StringWrapperList; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.StringWrapperPair; -@PropertyDefaults(tries = 10) -class RegisterAdapterTest { +class RegisterTest { - @Property + @Test void registerInstance() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(String.class, monkey -> monkey.giveMeBuilder("test")) .build(); @@ -65,16 +63,16 @@ void registerInstance() { then(actual).isEqualTo("test"); } - @Property + @Test void registerSizeLessThanThree() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register( new com.navercorp.fixturemonkey.api.matcher.MatcherOperator<>( - it -> it.getType().equals(new TypeReference>() { - }.getType()), + it -> it.getJvmType().getRawType().equals(List.class) + && it.getJvmType().getTypeVariables().size() == 1 + && it.getJvmType().getTypeVariables().get(0).getRawType().equals(String.class), fixture -> fixture.giveMeBuilder(new TypeReference>() { }).maxSize("$", 2) ) @@ -89,12 +87,11 @@ void registerSizeLessThanThree() { then(actual).hasSizeLessThan(3); } - @Property + @Test void registerFieldSize() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture.giveMeBuilder(StringListWrapper.class).size("values", 1) ) @@ -107,12 +104,11 @@ void registerFieldSize() { then(actual).allMatch(it -> it.getValues().size() == 1); } - @Property + @Test void registerNestedListSize() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture.giveMeBuilder(StringListWrapper.class).size("values", 2) ) @@ -125,12 +121,11 @@ void registerNestedListSize() { then(actual).allMatch(it -> it.getValues().size() == 2); } - @Property + @Test void registerThirdNestedListSize() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture.giveMeBuilder(StringListWrapper.class).size("values", 1) ) @@ -147,12 +142,11 @@ void registerThirdNestedListSize() { } } - @Property + @Test void registerRecursiveTypeSize() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(SelfRecursiveListObject.class, fixture -> fixture.giveMeBuilder(SelfRecursiveListObject.class).size("recursives", 1) ) @@ -165,12 +159,11 @@ void registerRecursiveTypeSize() { then(actual.getRecursives()).hasSize(1); } - @Property + @Test void registerMultipleFieldSizes() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ComplexObject.class, fixture -> fixture.giveMeBuilder(ComplexObject.class).size("strList", 2).size("list", 3) ) @@ -184,12 +177,11 @@ void registerMultipleFieldSizes() { then(actual.getList()).hasSize(3); } - @Property + @Test void builderSizeOverridesRegisterSize() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture.giveMeBuilder(StringListWrapper.class).size("values", 1) ) @@ -202,12 +194,11 @@ void builderSizeOverridesRegisterSize() { then(actual.getValues()).hasSize(5); } - @Property + @Test void registerTypeAffectsNestedPaths() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture.giveMeBuilder(StringListWrapper.class).size("values", 2) ) @@ -220,12 +211,11 @@ void registerTypeAffectsNestedPaths() { then(actual.getValues()).allMatch(it -> it.getValues().size() == 2); } - @Property + @Test void registerWithSizeRange() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture.giveMeBuilder(StringListWrapper.class).minSize("values", 2).maxSize("values", 4) ) @@ -245,12 +235,11 @@ void registerWithSizeRange() { }); } - @Property + @Test void registerNestedFieldPathSize() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(NestedStringListWrapper.class, fixture -> fixture.giveMeBuilder(NestedStringListWrapper.class).size("values[*].values", 2) ) @@ -263,12 +252,11 @@ void registerNestedFieldPathSize() { then(actual.getValues()).allMatch(it -> it.getValues().size() == 2); } - @Property + @Test void registerObjectFieldSize() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(NestedStringListWrapper.class, fixture -> fixture .giveMeBuilder(NestedStringListWrapper.class) @@ -287,12 +275,11 @@ void registerObjectFieldSize() { then(actual.getValues().get(1).getValues()).hasSize(4); } - @Property + @Test void registerTypeSizeAndPathSizeCombined() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture.giveMeBuilder(StringListWrapper.class).size("values", 1) ) @@ -312,12 +299,11 @@ void registerTypeSizeAndPathSizeCombined() { } } - @Property + @Test void registerDeepNestedPathSize() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(DoubleNestedStringListWrapper.class, fixture -> fixture .giveMeBuilder(DoubleNestedStringListWrapper.class) @@ -336,12 +322,11 @@ void registerDeepNestedPathSize() { then(actual.getValues().get(0).getValues().get(0).getValues()).hasSize(2); } - @Property + @Test void registerOverlappingTypesInnerTypeHasPriority() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(NestedStringListWrapper.class, fixture -> fixture.giveMeBuilder(NestedStringListWrapper.class).size("values[*].values", 3) ) @@ -357,12 +342,11 @@ void registerOverlappingTypesInnerTypeHasPriority() { then(actual.getValues()).allMatch(it -> it.getValues().size() == 5); } - @Property + @Test void registerOverlappingTypesInnerTypeHasPriorityRegardlessOfOrder() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture.giveMeBuilder(StringListWrapper.class).size("values", 5) ) @@ -378,12 +362,11 @@ void registerOverlappingTypesInnerTypeHasPriorityRegardlessOfOrder() { then(actual.getValues()).allMatch(it -> it.getValues().size() == 5); } - @Property + @Test void registerTypeSetValue() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture.giveMeBuilder(StringListWrapper.class).size("values", 1).set("values[0]", "registered") ) @@ -396,12 +379,11 @@ void registerTypeSetValue() { then(actual.getValues().get(0)).isEqualTo("registered"); } - @Property + @Test void registerOverlappingTypesSetInnerTypeHasPriority() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(NestedStringListWrapper.class, fixture -> fixture .giveMeBuilder(NestedStringListWrapper.class) @@ -420,12 +402,11 @@ void registerOverlappingTypesSetInnerTypeHasPriority() { then(actual.getValues()).allMatch(it -> it.getValues().get(0).equals("fromInner")); } - @Property + @Test void registerOverlappingTypesSetInnerTypeHasPriorityRegardlessOfOrder() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture.giveMeBuilder(StringListWrapper.class).size("values", 1).set("values[0]", "fromInner") ) @@ -444,12 +425,11 @@ void registerOverlappingTypesSetInnerTypeHasPriorityRegardlessOfOrder() { then(actual.getValues()).allMatch(it -> it.getValues().get(0).equals("fromInner")); } - @Property + @Test void registerField() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(String.class, monkey -> monkey.giveMeBuilder("test")) .build(); @@ -460,12 +440,11 @@ void registerField() { then(actual).isEqualTo("test"); } - @Property + @Test void registerGroup() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .registerGroup(RegisterGroup.class) .build(); @@ -481,12 +460,11 @@ void registerGroup() { then(actual3.getIntValue()).isEqualTo(RegisterGroup.FIXED_INT_VALUE.getIntValue()); } - @Property + @Test void registerBuilderGroup() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .registerGroup(new ChildBuilderGroup()) .build(); @@ -502,13 +480,12 @@ void registerBuilderGroup() { then(actual3.getIntValue()).isEqualTo(ChildBuilderGroup.FIXED_INT_VALUE.getIntValue()); } - @Property + @Test void registerSetFirst() { // given String expected = "test2"; FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(String.class, monkey -> monkey.giveMeBuilder("test")) .build(); @@ -519,12 +496,11 @@ void registerSetFirst() { then(actual).isEqualTo(expected); } - @Property + @Test void registerWithPriority() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(String.class, monkey -> monkey.giveMeBuilder("test2"), 2) .register(String.class, monkey -> monkey.giveMeBuilder("test"), 1) .build(); @@ -536,13 +512,12 @@ void registerWithPriority() { then(actual).isEqualTo("test"); } - @Property + @Test void registerMultipleTimesWithHierarchyReturnsCorrectOrder() { // given String expected = "test"; FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(String.class, fixture -> fixture.giveMeBuilder(String.class).set(expected)) .register(SimpleObject.class, fixture -> fixture.giveMeBuilder(SimpleObject.class).set("integer", 1)) .build(); @@ -554,13 +529,12 @@ void registerMultipleTimesWithHierarchyReturnsCorrectOrder() { then(actual).isEqualTo(expected); } - @Property + @Test void registerRootAndChildElementGeneratingRoot() { // given String expected = "test"; FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ComplexObject.class, fixture -> fixture.giveMeBuilder(ComplexObject.class)) .register(String.class, fixture -> fixture.giveMeBuilder(String.class).set(expected)) .build(); @@ -579,12 +553,11 @@ void registerRootAndChildElementGeneratingRoot() { then(actual).allMatch(expected::equals); } - @Property + @Test void registerSize() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ComplexObject.class, fixture -> fixture.giveMeBuilder(ComplexObject.class).size("strList", 1)) .build(); @@ -595,12 +568,11 @@ void registerSize() { then(actual).hasSize(1); } - @Property + @Test void registerFieldSet() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringWrapper.class, fixture -> fixture.giveMeBuilder(StringWrapper.class).set("value", "test")) .build(); @@ -611,12 +583,11 @@ void registerFieldSet() { then(actual).allMatch(it -> "test".equals(it.getValue())); } - @Property + @Test void sizeBiggerThanRegisterSized() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ComplexObject.class, fixture -> fixture.giveMeBuilder(ComplexObject.class).size("strList", 3)) .build(); @@ -627,12 +598,11 @@ void sizeBiggerThanRegisterSized() { then(actual).hasSize(10); } - @Property + @Test void registerObjectNotFixed() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(String.class, it -> it.giveMeBuilder(String.class).set("$", Arbitraries.strings().ofLength(10))) .build(); @@ -646,12 +616,11 @@ void registerObjectNotFixed() { then(actual).hasSizeGreaterThan(1); } - @Property + @Test void registerParentSetNullChildAndChildRegistered() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(SimpleObject.class, fixture -> fixture.giveMeBuilder(SimpleObject.class).set("str", "test")) .register(ComplexObject.class, fixture -> fixture.giveMeBuilder(ComplexObject.class).setNull("object")) .build(); @@ -669,12 +638,11 @@ void registerParentSetNullChildAndChildRegistered() { then(actual).isNull(); } - @Property + @Test void registerAffectsAllSameTypeFields() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(String.class, monkey -> monkey.giveMeBuilder("registered")) .build(); @@ -686,12 +654,11 @@ void registerAffectsAllSameTypeFields() { then(actual.getValue2()).isEqualTo("registered"); } - @Property + @Test void registerSameTypeFieldWithBuilderOverride() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(String.class, monkey -> monkey.giveMeBuilder("registered")) .build(); @@ -703,12 +670,11 @@ void registerSameTypeFieldWithBuilderOverride() { then(actual.getValue2()).isEqualTo("registered"); } - @Property + @Test void registerComplexTypeAffectsAllSameTypeFields() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringWrapper.class, monkey -> monkey.giveMeBuilder(StringWrapper.class).set("value", "registered")) .build(); @@ -721,12 +687,11 @@ void registerComplexTypeAffectsAllSameTypeFields() { then(actual.getValue2().getValue()).isEqualTo("registered"); } - @Property + @Test void registerSameTypeFieldWithThenApply() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringWrapper.class, monkey -> monkey.giveMeBuilder(StringWrapper.class).thenApply((it, builder) -> builder.set("value", "applied")) ) @@ -740,12 +705,11 @@ void registerSameTypeFieldWithThenApply() { then(actual.getValue2().getValue()).isEqualTo("applied"); } - @Property + @Test void applySizeWhenRegisteredWithSize() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture.giveMeBuilder(StringListWrapper.class).size("values", 5) ) @@ -762,12 +726,11 @@ void applySizeWhenRegisteredWithSize() { then(actual).hasSize(10); } - @Property + @Test void sizeWhenRegisterSizeInApply() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture.giveMeBuilder(StringListWrapper.class).thenApply((it, builder) -> builder.size("values", 1)) ) @@ -780,12 +743,11 @@ void sizeWhenRegisterSizeInApply() { then(actual).hasSize(2); } - @Property + @Test void sizeWhenRegisterApply() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringListWrapper.class, fixture -> fixture .giveMeBuilder(StringListWrapper.class) @@ -802,12 +764,11 @@ void sizeWhenRegisterApply() { then(actual).hasSize(2); } - @Property + @Test void sizeElementWhenRegisteredSize() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(NestedStringListWrapper.class, fixture -> fixture.giveMeBuilder(new TypeReference() { }).size("values", 5) @@ -825,11 +786,10 @@ void sizeElementWhenRegisteredSize() { then(actual).allMatch(it -> it.getValues().size() >= 3 && it.getValues().size() <= 5); } - @Property + @Test void sizeRegisteredElement() { String expected = "test"; FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .register(String.class, fixture -> fixture.giveMeBuilder(String.class).set(expected)) .build(); @@ -838,12 +798,11 @@ void sizeRegisteredElement() { then(actual).allMatch(expected::equals); } - @Property + @Test void registerSetThenSetNull() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(SimpleObject.class, fixture -> fixture.giveMeBuilder(SimpleObject.class).set("str", "registered")) .build(); @@ -857,12 +816,11 @@ void registerSetThenSetNull() { then(actual).isNull(); } - @Property + @Test void registerSetThenSetNotNull() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(SimpleObject.class, fixture -> fixture.giveMeBuilder(SimpleObject.class).set("str", "registered")) .build(); @@ -876,12 +834,11 @@ void registerSetThenSetNotNull() { then(actual).isNotNull(); } - @Property + @Test void registerSetNullThenDirectSet() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(SimpleObject.class, fixture -> fixture.giveMeBuilder(SimpleObject.class).setNull("str")) .build(); @@ -895,12 +852,11 @@ void registerSetNullThenDirectSet() { then(actual).isEqualTo("direct"); } - @Property + @Test void registerSetNullThenDirectSetNotNull() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(SimpleObject.class, fixture -> fixture.giveMeBuilder(SimpleObject.class).setNull("str")) .build(); @@ -914,12 +870,11 @@ void registerSetNullThenDirectSetNotNull() { then(actual).isNotNull(); } - @Property + @Test void registerContainerSizeThenSetNull() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(ComplexObject.class, fixture -> fixture.giveMeBuilder(ComplexObject.class).size("strList", 3)) .build(); @@ -933,12 +888,11 @@ void registerContainerSizeThenSetNull() { then(actual).isNull(); } - @Property + @Test void registerSetNotNullThenDirectSetNull() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(SimpleObject.class, fixture -> fixture.giveMeBuilder(SimpleObject.class).setNotNull("str")) .build(); diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/SizeAdapterTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/SizeTest.java similarity index 95% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/SizeAdapterTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/SizeTest.java index 8529fa84d0..36d9caa84c 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/SizeAdapterTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/SizeTest.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; @@ -27,8 +27,7 @@ import java.util.Map; import java.util.Set; -import net.jqwik.api.Property; -import net.jqwik.api.PropertyDefaults; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.type.TypeReference; @@ -39,15 +38,13 @@ import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.StringWrapperList; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.TwoEnum; -@PropertyDefaults(tries = 10) -class SizeAdapterTest { +class SizeTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void sizeZero() { // when StringListWrapper actual = SUT.giveMeBuilder(StringListWrapper.class).size("values", 0).sample(); @@ -56,7 +53,7 @@ void sizeZero() { then(actual.getValues()).hasSize(0); } - @Property + @Test void size() { // when StringListWrapper actual = SUT.giveMeBuilder(StringListWrapper.class).size("values", 10).sample(); @@ -65,7 +62,7 @@ void size() { then(actual.getValues()).hasSize(10); } - @Property + @Test void sizeMinMax() { // when StringListWrapper actual = SUT.giveMeBuilder(StringListWrapper.class).size("values", 3, 8).sample(); @@ -74,7 +71,7 @@ void sizeMinMax() { then(actual.getValues()).hasSizeBetween(3, 8); } - @Property + @Test void minSize() { // when StringListWrapper actual = SUT.giveMeBuilder(StringListWrapper.class).minSize("values", 10).sample(); @@ -83,7 +80,7 @@ void minSize() { then(actual.getValues()).hasSizeGreaterThanOrEqualTo(10); } - @Property + @Test void maxSize() { // when StringListWrapper actual = SUT.giveMeBuilder(StringListWrapper.class).maxSize("values", 10).sample(); @@ -92,7 +89,7 @@ void maxSize() { then(actual.getValues()).hasSizeLessThanOrEqualTo(10); } - @Property + @Test void maxSizeZero() { // when StringListWrapper actual = SUT.giveMeBuilder(StringListWrapper.class).maxSize("values", 0).sample(); @@ -101,7 +98,7 @@ void maxSizeZero() { then(actual.getValues()).hasSizeLessThanOrEqualTo(0); } - @Property + @Test void sizeComplexObjectList() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class).size("list", 5).sample(); @@ -110,7 +107,7 @@ void sizeComplexObjectList() { then(actual.getList()).hasSize(5); } - @Property + @Test void sizeComplexObjectMap() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class).size("map", 3).sample(); @@ -119,7 +116,7 @@ void sizeComplexObjectMap() { then(actual.getMap()).hasSize(3); } - @Property + @Test void sizeAndSetElement() { String expected = "test"; @@ -135,7 +132,7 @@ void sizeAndSetElement() { then(actual.get(1)).isEqualTo(expected); } - @Property + @Test void sizeSmallerRemains() { String expected = "test"; @@ -151,7 +148,7 @@ void sizeSmallerRemains() { then(actual.get(0)).isEqualTo(expected); } - @Property + @Test void greaterSizeAfterSetReturnsSizeRemainsSet() { List set = new ArrayList<>(); set.add("1"); @@ -166,7 +163,7 @@ void greaterSizeAfterSetReturnsSizeRemainsSet() { then(actual.get(0)).isEqualTo("1"); } - @Property + @Test void smallerSizeAfterSetReturnsSizeRemainsSet() { List set = new ArrayList<>(); set.add("1"); @@ -187,7 +184,7 @@ void smallerSizeAfterSetReturnsSizeRemainsSet() { then(actual.get(2)).isEqualTo("3"); } - @Property + @Test void sizeAfterSetEmptyListReturnsSized() { List actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -198,7 +195,7 @@ void sizeAfterSetEmptyListReturnsSized() { then(actual).hasSize(3); } - @Property + @Test void sizeThirdNestedNested() { List actual = SUT.giveMeBuilder(DoubleNestedStringListWrapper.class) .size("values", 1) @@ -214,7 +211,7 @@ void sizeThirdNestedNested() { then(actual).hasSize(1); } - @Property + @Test void sampleStringWrapperListWithSize() { // when StringWrapperList actual = SUT.giveMeBuilder(StringWrapperList.class).size("values", 3).sample(); @@ -223,7 +220,7 @@ void sampleStringWrapperListWithSize() { then(actual.getValues()).hasSize(3); } - @Property + @Test void sizeEnumSetGreaterThanEnumSizeNotThrows() { Set actual = SUT.giveMeBuilder(new TypeReference>() { }).size("$", 3).sample(); @@ -231,7 +228,7 @@ void sizeEnumSetGreaterThanEnumSizeNotThrows() { then(actual).hasSize(2); } - @Property + @Test void sizeEnumMapGreaterThanEnumSizeNotThrows() { Map actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -241,7 +238,7 @@ void sizeEnumMapGreaterThanEnumSizeNotThrows() { then(actual).hasSize(2); } - @Property + @Test void setDecomposedMapThenGreaterSize() { // given Map set = new HashMap<>(); @@ -261,7 +258,7 @@ void setDecomposedMapThenGreaterSize() { then(actual).containsEntry("b", "2"); } - @Property + @Test void setDecomposedMapThenSmallerSize() { // given Map set = new HashMap<>(); @@ -280,7 +277,7 @@ void setDecomposedMapThenSmallerSize() { then(actual).hasSize(2); } - @Property + @Test void sizeThenSetDecomposedMap() { // given Map set = new HashMap<>(); @@ -300,7 +297,7 @@ void sizeThenSetDecomposedMap() { then(actual).containsEntry("b", "2"); } - @Property + @Test void setDecomposedMapFieldThenGreaterSize() { // given Map set = new HashMap<>(); @@ -318,7 +315,7 @@ void setDecomposedMapFieldThenGreaterSize() { then(actual).hasSize(4); } - @Property + @Test void setEmptyMapThenSize() { // when Map actual = SUT.giveMeBuilder(new TypeReference>() { @@ -331,7 +328,7 @@ void setEmptyMapThenSize() { then(actual).hasSize(3); } - @Property + @Test void setDecomposedMapThenSizeZero() { // given Map set = new HashMap<>(); @@ -349,7 +346,7 @@ void setDecomposedMapThenSizeZero() { then(actual).hasSize(0); } - @Property + @Test void setDecomposedSetThenGreaterSize() { // given Set set = new HashSet<>(); @@ -365,7 +362,7 @@ void setDecomposedSetThenGreaterSize() { then(actual).contains("a", "b"); } - @Property + @Test void setDecomposedSetThenSmallerSize() { // given Set set = new HashSet<>(); @@ -381,7 +378,7 @@ void setDecomposedSetThenSmallerSize() { then(actual).hasSize(2); } - @Property + @Test void sizeThenSetDecomposedSet() { // given Set set = new HashSet<>(); @@ -397,7 +394,7 @@ void sizeThenSetDecomposedSet() { then(actual).contains("a", "b"); } - @Property + @Test void setEmptySetThenSize() { // when Set actual = SUT.giveMeBuilder(new TypeReference>() { @@ -410,7 +407,7 @@ void setEmptySetThenSize() { then(actual).hasSize(3); } - @Property + @Test void setDecomposedSetThenSizeZero() { // given Set set = new HashSet<>(); @@ -425,7 +422,7 @@ void setDecomposedSetThenSizeZero() { then(actual).hasSize(0); } - @Property + @Test void setDecomposedArrayThenGreaterSize() { // given String[] set = {"a", "b"}; @@ -443,7 +440,7 @@ void setDecomposedArrayThenGreaterSize() { then(actual[1]).isEqualTo("b"); } - @Property + @Test void setDecomposedArrayThenSmallerSize() { // given String[] set = {"a", "b", "c", "d", "e"}; @@ -462,7 +459,7 @@ void setDecomposedArrayThenSmallerSize() { then(actual[2]).isEqualTo("c"); } - @Property + @Test void sizeThenSetDecomposedArray() { // given String[] set = {"a", "b"}; @@ -480,7 +477,7 @@ void sizeThenSetDecomposedArray() { then(actual[1]).isEqualTo("b"); } - @Property + @Test void setEmptyArrayThenSize() { // when String[] actual = SUT.giveMeBuilder(ComplexObject.class) @@ -493,7 +490,7 @@ void setEmptyArrayThenSize() { then(actual).hasSize(3); } - @Property + @Test void setDecomposedArrayThenSizeZero() { // given String[] set = {"a", "b"}; @@ -509,7 +506,7 @@ void setDecomposedArrayThenSizeZero() { then(actual).hasSize(0); } - @Property + @Test void setDecomposedIntArrayThenGreaterSize() { // given int[] set = {1, 2, 3}; @@ -528,7 +525,7 @@ void setDecomposedIntArrayThenGreaterSize() { then(actual[2]).isEqualTo(3); } - @Property + @Test void setDecomposedIntArrayThenSmallerSize() { // given int[] set = {1, 2, 3, 4, 5}; @@ -546,7 +543,7 @@ void setDecomposedIntArrayThenSmallerSize() { then(actual[1]).isEqualTo(2); } - @Property + @Test void setNullListThenSize() { // when List actual = SUT.giveMeBuilder(ComplexObject.class) @@ -559,7 +556,7 @@ void setNullListThenSize() { then(actual).hasSize(3); } - @Property + @Test void setNullMapThenSize() { // when Map actual = SUT.giveMeBuilder(ComplexObject.class) @@ -572,7 +569,7 @@ void setNullMapThenSize() { then(actual).hasSize(3); } - @Property + @Test void setDecomposedListThenSizeZero() { // given List set = new ArrayList<>(); @@ -590,7 +587,7 @@ void setDecomposedListThenSizeZero() { then(actual).hasSize(0); } - @Property + @Test void sizeZeroThenSetDecomposedList() { // given List set = new ArrayList<>(); diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/StrictModeAdapterTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/StrictModeTest.java similarity index 94% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/StrictModeAdapterTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/StrictModeTest.java index c4ac9af423..573ada52b9 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/StrictModeAdapterTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/StrictModeTest.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; import static org.assertj.core.api.BDDAssertions.thenNoException; @@ -24,18 +24,16 @@ import java.util.List; -import net.jqwik.api.Property; -import net.jqwik.api.PropertyDefaults; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.type.TypeReference; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.SimpleObject; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.StringWrapperList; -@PropertyDefaults(tries = 10) -class StrictModeAdapterTest { +class StrictModeTest { - @Property + @Test void strictModeSetWrongExpressionThrows() { // given FixtureMonkey sut = FixtureMonkey.builder().useExpressionStrictMode().build(); @@ -47,7 +45,7 @@ void strictModeSetWrongExpressionThrows() { .hasMessageContaining("No matching results for given NodeResolvers."); } - @Property + @Test void strictModeSizeWrongExpressionThrows() { // given FixtureMonkey sut = FixtureMonkey.builder().useExpressionStrictMode().build(); @@ -59,7 +57,7 @@ void strictModeSizeWrongExpressionThrows() { .hasMessageContaining("No matching results for given"); } - @Property + @Test void strictModeSizeNestedWrongExpressionThrows() { // given FixtureMonkey sut = FixtureMonkey.builder().useExpressionStrictMode().build(); @@ -71,7 +69,7 @@ void strictModeSizeNestedWrongExpressionThrows() { .hasMessageContaining("No matching results for given"); } - @Property + @Test void strictModeSetWrongExpressionAfterPushAssignableTypePropertyNameResolverThrows() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -86,7 +84,7 @@ void strictModeSetWrongExpressionAfterPushAssignableTypePropertyNameResolverThro .hasMessageContaining("No matching results for given NodeResolvers."); } - @Property + @Test void strictModeSizeWrongExpressionAfterPushAssignableTypePropertyNameResolverThrows() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -101,7 +99,7 @@ void strictModeSizeWrongExpressionAfterPushAssignableTypePropertyNameResolverThr .hasMessageContaining("No matching results for given"); } - @Property + @Test void strictModeSetWrongExpressionAfterDefaultPropertyNameResolverThrows() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -116,7 +114,7 @@ void strictModeSetWrongExpressionAfterDefaultPropertyNameResolverThrows() { .hasMessageContaining("No matching results for given NodeResolvers."); } - @Property + @Test void strictModeSizeWrongExpressionAfterDefaultPropertyNameResolverThrows() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -131,7 +129,7 @@ void strictModeSizeWrongExpressionAfterDefaultPropertyNameResolverThrows() { .hasMessageContaining("No matching results for given"); } - @Property + @Test void notStrictModeSetWrongExpressionDoesNotThrows() { // given FixtureMonkey sut = FixtureMonkey.builder().build(); @@ -141,7 +139,7 @@ void notStrictModeSetWrongExpressionDoesNotThrows() { thenNoException().isThrownBy(() -> sut.giveMeBuilder(String.class).set("nonExistentField", 0).sample()); } - @Property + @Test void notStrictModeSizeWrongExpressionDoesNotThrows() { // given FixtureMonkey sut = FixtureMonkey.builder().build(); @@ -153,7 +151,7 @@ void notStrictModeSizeWrongExpressionDoesNotThrows() { ); } - @Property + @Test void strictModeMultiOperationValidExpression() { // given FixtureMonkey sut = FixtureMonkey.builder().useExpressionStrictMode().build(); diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ThenApplyOrderingAdapterTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ThenApplyOrderingTest.java similarity index 95% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ThenApplyOrderingAdapterTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ThenApplyOrderingTest.java index 1602287efb..26876897cf 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ThenApplyOrderingAdapterTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ThenApplyOrderingTest.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; @@ -25,8 +25,7 @@ import java.util.Collections; import java.util.List; -import net.jqwik.api.Property; -import net.jqwik.api.PropertyDefaults; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.ComplexObject; @@ -37,15 +36,13 @@ import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.StringArrayWrapper; import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.StringListWrapper; -@PropertyDefaults(tries = 10) -class ThenApplyOrderingAdapterTest { +class ThenApplyOrderingTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void nestedThenApply() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -65,7 +62,7 @@ void nestedThenApply() { then(actual.getStrList().get(0)).isEqualTo("outer"); } - @Property + @Test void nestedThenApplyRandomValuePreserved() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -79,7 +76,7 @@ void nestedThenApplyRandomValuePreserved() { then(actual.getObject().getStr()).isEqualTo(actual.getStr()); } - @Property + @Test void tripleNestedThenApply() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -101,7 +98,7 @@ void tripleNestedThenApply() { then(actual.getStrList().get(0)).isEqualTo("level1-level2-level3"); } - @Property + @Test void nestedThenApplyInnerOverwritesOuter() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -115,7 +112,7 @@ void nestedThenApplyInnerOverwritesOuter() { then(actual.getStr()).isEqualTo("inner"); } - @Property + @Test void nestedThenApplyWithSizeAndElement() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -134,7 +131,7 @@ void nestedThenApplyWithSizeAndElement() { then(actual.getStrList().get(1)).isEqualTo("second"); } - @Property + @Test void nestedThenApplySetAfterNestedApply() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -149,7 +146,7 @@ void nestedThenApplySetAfterNestedApply() { then(actual.getObject().getStr()).isEqualTo("afterApply"); } - @Property + @Test void multipleThenApplyLaterOverwritesEarlier() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -161,7 +158,7 @@ void multipleThenApplyLaterOverwritesEarlier() { then(actual.getStr()).isEqualTo("second"); } - @Property + @Test void multipleThenApplySizeOrderPreserved() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -173,7 +170,7 @@ void multipleThenApplySizeOrderPreserved() { then(actual.getStrList()).hasSize(1); } - @Property + @Test void setElementThenSize() { // given String expected = "test"; @@ -190,7 +187,7 @@ void setElementThenSize() { then(actual.get(0)).isEqualTo(expected); } - @Property + @Test void setElementAtIndexThenSize() { // given String expected = "test"; @@ -207,7 +204,7 @@ void setElementAtIndexThenSize() { then(actual.get(2)).isEqualTo(expected); } - @Property + @Test void setElementBeyondSizeThenSize() { // given String expected = "test"; @@ -223,7 +220,7 @@ void setElementBeyondSizeThenSize() { then(actual).hasSize(3); } - @Property + @Test void setDecomposedThenSizeGreater() { // given List decomposed = new ArrayList<>(); @@ -245,7 +242,7 @@ void setDecomposedThenSizeGreater() { then(actual.get(2)).isEqualTo("3"); } - @Property + @Test void setDecomposedThenSizeSmaller() { // given List decomposed = new ArrayList<>(); @@ -266,7 +263,7 @@ void setDecomposedThenSizeSmaller() { then(actual.get(1)).isEqualTo("2"); } - @Property + @Test void sizeThenSetDecomposed() { // given List decomposed = new ArrayList<>(); @@ -288,7 +285,7 @@ void sizeThenSetDecomposed() { then(actual.get(2)).isEqualTo("3"); } - @Property + @Test void setWildcardThenSize() { // given String expected = "test"; @@ -307,7 +304,7 @@ void setWildcardThenSize() { then(actual.get(2)).isEqualTo(expected); } - @Property + @Test void setDecomposedNestedThenSize() { // given List decomposed = new ArrayList<>(); @@ -336,7 +333,7 @@ void setDecomposedNestedThenSize() { then(actual.get(1).getValues()).containsExactly("c"); } - @Property + @Test void setNestedElementThenSizes() { // given List innerList = new ArrayList<>(); @@ -360,7 +357,7 @@ void setNestedElementThenSizes() { then(actual.get(1).getValues()).hasSize(2); } - @Property + @Test void setNestedElementThenSizeAtSamePath() { // given List innerList = new ArrayList<>(); @@ -383,7 +380,7 @@ void setNestedElementThenSizeAtSamePath() { then(actual.get(0).getValues().get(1)).isEqualTo("2"); } - @Property + @Test void sizeThenApplySetDecomposed() { // given List decomposed = new ArrayList<>(); @@ -405,7 +402,7 @@ void sizeThenApplySetDecomposed() { then(actual.get(2)).isEqualTo("3"); } - @Property + @Test void setDecomposedThenApplySize() { // given List decomposed = new ArrayList<>(); @@ -427,7 +424,7 @@ void setDecomposedThenApplySize() { then(actual.get(2)).isEqualTo("3"); } - @Property + @Test void thenApplySetDecomposedThenSize() { // given List decomposed = new ArrayList<>(); @@ -449,7 +446,7 @@ void thenApplySetDecomposedThenSize() { then(actual.get(2)).isEqualTo("3"); } - @Property + @Test void thenApplySizeThenSetDecomposed() { // given List decomposed = new ArrayList<>(); @@ -471,7 +468,7 @@ void thenApplySizeThenSetDecomposed() { then(actual.get(2)).isEqualTo("3"); } - @Property + @Test void sizeThenApplySetElement() { // given String expected = "test"; @@ -488,7 +485,7 @@ void sizeThenApplySetElement() { then(actual.get(0)).isEqualTo(expected); } - @Property + @Test void setElementThenApplySize() { // given String expected = "test"; @@ -505,7 +502,7 @@ void setElementThenApplySize() { then(actual.get(0)).isEqualTo(expected); } - @Property + @Test void nestedThenApplySizeThenSetDecomposed() { // given List decomposed = new ArrayList<>(); @@ -528,7 +525,7 @@ void nestedThenApplySizeThenSetDecomposed() { then(actual.get(1)).isEqualTo("2"); } - @Property + @Test void nestedThenApplySetDecomposedThenSize() { // given List decomposed = new ArrayList<>(); @@ -552,7 +549,7 @@ void nestedThenApplySetDecomposedThenSize() { then(actual.get(1)).isEqualTo("2"); } - @Property + @Test void setDecomposedThenApplySizeWithWildcard() { // given List innerList = new ArrayList<>(); @@ -574,7 +571,7 @@ void setDecomposedThenApplySizeWithWildcard() { then(actual.get(1).getValues()).hasSize(2); } - @Property + @Test void setDecomposedThenSizeWithWildcardWithoutThenApply() { // given List innerList = new ArrayList<>(); @@ -597,7 +594,7 @@ void setDecomposedThenSizeWithWildcardWithoutThenApply() { then(actual.get(1).getValues()).hasSize(2); } - @Property + @Test void wildcardSizeInThenApply() { // when List actual = SUT.giveMeBuilder(NestedStringListWrapper.class) @@ -611,7 +608,7 @@ void wildcardSizeInThenApply() { then(actual.get(1).getValues()).isNotNull(); } - @Property + @Test void wildcardSizeOutsideThenApply() { // when List actual = SUT.giveMeBuilder(NestedStringListWrapper.class) @@ -626,7 +623,7 @@ void wildcardSizeOutsideThenApply() { then(actual.get(1).getValues()).hasSize(2); } - @Property + @Test void simpleWildcardSizeInThenApply() { // when List actual = SUT.giveMeBuilder(StringListWrapper.class) @@ -641,7 +638,7 @@ void simpleWildcardSizeInThenApply() { then(actual.get(2)).isEqualTo("test"); } - @Property + @Test void sizeWithIndexInThenApply() { // when List actual = SUT.giveMeBuilder(NestedStringListWrapper.class) @@ -657,7 +654,7 @@ void sizeWithIndexInThenApply() { then(actual.get(1).getValues()).hasSize(2); } - @Property + @Test void thenApplySetDecomposedThenSizeSmaller() { // given List decomposed = new ArrayList<>(); @@ -680,7 +677,7 @@ void thenApplySetDecomposedThenSizeSmaller() { then(actual.get(1)).isEqualTo("2"); } - @Property + @Test void multipleThenApplySetDecomposedThenSize() { // given List decomposed = new ArrayList<>(); @@ -702,7 +699,7 @@ void multipleThenApplySetDecomposedThenSize() { then(actual.get(2)).isEqualTo("3"); } - @Property + @Test void setDecomposedMultipleIndicesThenApplyWildcardSize() { // given List innerList0 = new ArrayList<>(); @@ -734,7 +731,7 @@ void setDecomposedMultipleIndicesThenApplyWildcardSize() { then(actual.get(1).getValues().get(1)).isEqualTo("y"); } - @Property + @Test void setDecomposedThenApplyWildcardSetOverride() { // given List innerList = new ArrayList<>(); @@ -762,7 +759,7 @@ void setDecomposedThenApplyWildcardSetOverride() { then(actual.get(1).getValues().get(1)).isEqualTo("override"); } - @Property + @Test void setDecomposedThenApplyWildcardSizeLarger() { // given List innerList = new ArrayList<>(); @@ -784,7 +781,7 @@ void setDecomposedThenApplyWildcardSizeLarger() { then(actual.get(1).getValues()).hasSize(5); } - @Property + @Test void thirdNestedSetDecomposedThenApplyWildcardSize() { // given List innerList = new ArrayList<>(); @@ -807,7 +804,7 @@ void thirdNestedSetDecomposedThenApplyWildcardSize() { then(actual.getValues().get(0).getValues().get(0).getValues().get(0)).isEqualTo("deep1"); } - @Property + @Test void setDecomposedObjectListThenApplyWildcardSet() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -822,7 +819,7 @@ void setDecomposedObjectListThenApplyWildcardSet() { then(actual.getStrList().get(2)).isEqualTo("wildcard"); } - @Property + @Test void setDecomposedThenApplyIndexSizeAndWildcardSize() { // given List innerList = new ArrayList<>(); @@ -841,12 +838,14 @@ void setDecomposedThenApplyIndexSizeAndWildcardSize() { // then then(actual).hasSize(2); - then(actual.get(0).getValues()).hasSize(1); + then(actual.get(0).getValues()).hasSize(3); then(actual.get(0).getValues().get(0)).isEqualTo("1"); + then(actual.get(0).getValues().get(1)).isEqualTo("2"); + then(actual.get(0).getValues().get(2)).isEqualTo("3"); then(actual.get(1).getValues()).hasSize(3); } - @Property + @Test void multipleThenApplySizeThenSetDecomposed() { // given List decomposed = new ArrayList<>(); @@ -868,7 +867,7 @@ void multipleThenApplySizeThenSetDecomposed() { then(actual.get(2)).isEqualTo("3"); } - @Property + @Test void setNullThenThenApply() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -880,7 +879,7 @@ void setNullThenThenApply() { then(actual.getStr()).isEqualTo("applied"); } - @Property + @Test void thenApplyThenSetNull() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -892,7 +891,7 @@ void thenApplyThenSetNull() { then(actual.getStr()).isNull(); } - @Property + @Test void setNotNullThenThenApply() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -904,7 +903,7 @@ void setNotNullThenThenApply() { then(actual.getStr()).isNull(); } - @Property + @Test void thenApplyThenSetNotNull() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -916,7 +915,7 @@ void thenApplyThenSetNotNull() { then(actual.getStr()).isNotNull(); } - @Property + @Test void thenApplySizeThenSetNullContainer() { // when ComplexObject actual = SUT.giveMeBuilder(ComplexObject.class) @@ -928,7 +927,7 @@ void thenApplySizeThenSetNullContainer() { then(actual.getStrList()).isNull(); } - @Property + @Test void setDecomposedThenApplyWildcardSetOverrideWithoutSizeChange() { // given List innerList = Arrays.asList("1", "2", "3"); @@ -955,7 +954,7 @@ void setDecomposedThenApplyWildcardSetOverrideWithoutSizeChange() { } } - @Property + @Test void setDecomposedArrayThenApplyWildcardSetOverride() { // given StringArrayWrapper wrapper = new StringArrayWrapper(); @@ -982,7 +981,7 @@ void setDecomposedArrayThenApplyWildcardSetOverride() { } } - @Property + @Test void setDecomposedAfterThenApplyWildcardSetOverride() { // given List innerList = Arrays.asList("a", "b"); @@ -1005,7 +1004,7 @@ void setDecomposedAfterThenApplyWildcardSetOverride() { then(actual.get(0).getValues().get(1)).isEqualTo("b"); } - @Property + @Test void setDecomposedObjectThenApplyWildcardSetOverride() { // when StringListWrapper stringListWrapper = new StringListWrapper(); @@ -1030,7 +1029,7 @@ void setDecomposedObjectThenApplyWildcardSetOverride() { then(actual.get(1).getValues().get(1)).isEqualTo("override"); } - @Property + @Test void setDecomposedNestedContainerThenApplyWildcardSetOverride() { // given List> values = Arrays.asList( @@ -1058,7 +1057,7 @@ void setDecomposedNestedContainerThenApplyWildcardSetOverride() { } } - @Property + @Test void listListStringSizeAndSet() { // when List> actual = SUT.giveMeBuilder(ListListStringObject.class) @@ -1077,12 +1076,11 @@ void listListStringSizeAndSet() { } } - @Property + @Test void listListStringSetThenSize() { // given FixtureMonkey fm = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); List> values = Arrays.asList( @@ -1108,4 +1106,36 @@ void listListStringSetThenSize() { } } + @Test + void wildcardSizeAfterExactOverridesExact() { + // when + List> actual = SUT.giveMeBuilder(ListListStringObject.class) + .size("values", 2) + .size("values[0]", 1) + .size("values[*]", 5) + .sample() + .getValues(); + + // then + then(actual).hasSize(2); + then(actual.get(0)).hasSize(5); + then(actual.get(1)).hasSize(5); + } + + @Test + void exactSizeAfterWildcardWinsAtIndex() { + // when + List> actual = SUT.giveMeBuilder(ListListStringObject.class) + .size("values", 2) + .size("values[*]", 5) + .size("values[0]", 1) + .sample() + .getValues(); + + // then + then(actual).hasSize(2); + then(actual.get(0)).hasSize(1); + then(actual.get(1)).hasSize(5); + } + } diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionAssembleSpecs.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionAssembleSpecs.java similarity index 98% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionAssembleSpecs.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionAssembleSpecs.java index d8dc517e61..93b4099c5a 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionAssembleSpecs.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionAssembleSpecs.java @@ -16,10 +16,9 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import java.beans.ConstructorProperties; -import java.lang.reflect.AnnotatedType; import java.time.Instant; import java.util.ArrayList; import java.util.HashSet; @@ -44,7 +43,6 @@ import com.navercorp.fixturemonkey.api.matcher.AssignableTypeMatcher; import com.navercorp.fixturemonkey.api.matcher.Matcher; import com.navercorp.fixturemonkey.api.property.ElementProperty; -import com.navercorp.fixturemonkey.api.type.Types; public class ValueProjectionAssembleSpecs { @@ -1128,19 +1126,20 @@ public static class PairContainerPropertyGenerator implements ContainerPropertyG public ContainerProperty generate(ContainerPropertyGeneratorContext context) { com.navercorp.fixturemonkey.api.property.Property property = context.getProperty(); - List elementTypes = Types.getGenericsTypes(property.getAnnotatedType()); + List elementTypes = + property.getJvmType().getTypeVariables(); if (elementTypes.size() != 2) { throw new IllegalArgumentException( "Pair elementsTypes must be have 1 generics type for element. " + "propertyType: " - + property.getType() + + property.getJvmType().getRawType() + ", elementTypes: " + elementTypes ); } - AnnotatedType firstElementType = elementTypes.get(0); - AnnotatedType secondElementType = elementTypes.get(1); + com.navercorp.objectfarm.api.type.JvmType firstElementType = elementTypes.get(0); + com.navercorp.objectfarm.api.type.JvmType secondElementType = elementTypes.get(1); List elementProperties = new ArrayList<>(); elementProperties.add(new ElementProperty(property, firstElementType, 0, 0)); elementProperties.add(new ElementProperty(property, secondElementType, 1, 1)); diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionBasicGenerationTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionBasicGenerationTest.java similarity index 75% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionBasicGenerationTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionBasicGenerationTest.java index e492629850..b6de1eb129 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionBasicGenerationTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionBasicGenerationTest.java @@ -16,20 +16,20 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; -import net.jqwik.api.Property; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.ChildValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.IntArrayHolder; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.ObjectValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.Order; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.StringListHolder; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.StringValue; import com.navercorp.fixturemonkey.api.introspector.FieldReflectionArbitraryIntrospector; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.ChildValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.IntArrayHolder; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.ObjectValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.Order; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.StringListHolder; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.StringValue; class ValueProjectionBasicGenerationTest { @@ -38,24 +38,23 @@ class ValueProjectionBasicGenerationTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void generateString() { String actual = SUT.giveMeOne(String.class); then(actual).isNotNull(); } - @Property + @Test void generateInteger() { Integer actual = SUT.giveMeOne(Integer.class); then(actual).isNotNull(); } - @Property + @Test void generateSimpleObject() { StringValue actual = SUT.giveMeOne(StringValue.class); @@ -63,7 +62,7 @@ void generateSimpleObject() { then(actual.getValue()).isNotNull(); } - @Property + @Test void generateNestedObject() { Order actual = SUT.giveMeOne(Order.class); @@ -72,7 +71,7 @@ void generateNestedObject() { then(actual.getProduct().getName()).isNotNull(); } - @Property + @Test void generateListObject() { StringListHolder actual = SUT.giveMeOne(StringListHolder.class); @@ -80,21 +79,21 @@ void generateListObject() { then(actual.getValues()).isNotNull(); } - @Property + @Test void generatePrimitiveArray() { int[] actual = SUT.giveMeBuilder(IntArrayHolder.class).fixed().sample().getValues(); then(actual).isNotNull(); } - @Property + @Test void sampleObjectField() { ObjectValue actual = SUT.giveMeOne(ObjectValue.class); then(actual).isNotNull(); } - @Property + @Test void sampleChildValue() { ChildValue actual = SUT.giveMeOne(ChildValue.class); diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionContainerTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionContainerTest.java similarity index 81% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionContainerTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionContainerTest.java index c36d7ed9b5..8619dbef99 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionContainerTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionContainerTest.java @@ -16,16 +16,16 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; -import net.jqwik.api.Property; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.MapHolder; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.NestedListHolder; import com.navercorp.fixturemonkey.api.introspector.FieldReflectionArbitraryIntrospector; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.MapHolder; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.NestedListHolder; class ValueProjectionContainerTest { @@ -34,10 +34,9 @@ class ValueProjectionContainerTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void generateNestedList() { NestedListHolder actual = SUT.giveMeOne(NestedListHolder.class); @@ -45,7 +44,7 @@ void generateNestedList() { then(actual.getNestedValues()).isNotNull(); } - @Property + @Test void generateMapField() { MapHolder actual = SUT.giveMeOne(MapHolder.class); diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionCustomizationTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionCustomizationTest.java similarity index 87% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionCustomizationTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionCustomizationTest.java index c9e86ba289..f01eaed80b 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionCustomizationTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionCustomizationTest.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary.NOT_GENERATED; import static com.navercorp.fixturemonkey.api.generator.DefaultNullInjectGenerator.ALWAYS_NULL_INJECT; @@ -25,7 +25,6 @@ import static org.assertj.core.api.BDDAssertions.thenNoException; import static org.assertj.core.api.BDDAssertions.thenThrownBy; -import java.lang.reflect.AnnotatedType; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Arrays; @@ -38,40 +37,13 @@ import java.util.Optional; import java.util.Set; +import org.junit.jupiter.api.Test; + import net.jqwik.api.Arbitraries; -import net.jqwik.api.Property; import com.navercorp.fixturemonkey.ArbitraryBuilder; import com.navercorp.fixturemonkey.ArbitraryBuilders; import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.ComplexObject; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.IntValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.Interface; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.InterfaceFieldImplementationValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.InterfaceImplementation; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.ListStringObject; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.MapHolder; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.NestedListHolder; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.NestedSimpleObject; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.NestedStringList; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.NestedStringListHolder; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.NullableObject; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.OptionalStringObject; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.Order; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.Pair; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.PairContainerPropertyGenerator; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.PairInterface; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.PairIntrospector; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.SimpleObject; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.SimpleObjectChild; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.SimpleStringObject; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.StringAndInt; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.StringArrayHolder; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.StringListHolder; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.StringMapHolder; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.StringValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.TwoEnum; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.UniqueArbitraryGenerator; import com.navercorp.fixturemonkey.api.container.DecomposableJavaContainer; import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfo; import com.navercorp.fixturemonkey.api.generator.ArbitraryContainerInfoGenerator; @@ -84,7 +56,34 @@ import com.navercorp.fixturemonkey.api.matcher.ExactTypeMatcher; import com.navercorp.fixturemonkey.api.matcher.MatcherOperator; import com.navercorp.fixturemonkey.api.type.TypeReference; -import com.navercorp.fixturemonkey.api.type.Types; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.ComplexObject; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.IntValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.Interface; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.InterfaceFieldImplementationValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.InterfaceImplementation; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.ListStringObject; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.MapHolder; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.NestedListHolder; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.NestedSimpleObject; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.NestedStringList; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.NestedStringListHolder; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.NullableObject; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.OptionalStringObject; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.Order; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.Pair; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.PairContainerPropertyGenerator; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.PairInterface; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.PairIntrospector; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.SimpleObject; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.SimpleObjectChild; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.SimpleStringObject; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.StringAndInt; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.StringArrayHolder; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.StringListHolder; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.StringMapHolder; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.StringValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.TwoEnum; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.UniqueArbitraryGenerator; class ValueProjectionCustomizationTest { @@ -93,10 +92,9 @@ class ValueProjectionCustomizationTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void setSingleField() { String expected = "test-value"; @@ -106,7 +104,7 @@ void setSingleField() { then(actual.getValue()).isEqualTo(expected); } - @Property + @Test void setContainerField() { List expected = java.util.Arrays.asList("a", "b", "c"); @@ -116,7 +114,7 @@ void setContainerField() { then(actual.getValues()).isEqualTo(expected); } - @Property + @Test void setNestedList() { List> expected = java.util.Arrays.asList( java.util.Arrays.asList("a", "b"), @@ -129,7 +127,7 @@ void setNestedList() { then(actual.getNestedValues()).isEqualTo(expected); } - @Property + @Test void setMultipleFields() { Order actual = SUT.giveMeBuilder(Order.class) .set("orderId", "ORD-123") @@ -145,14 +143,14 @@ void setMultipleFields() { then(actual.getProduct().getPrice()).isEqualTo(1000); } - @Property + @Test void sizeFixesListSize() { StringListHolder actual = SUT.giveMeBuilder(StringListHolder.class).size("values", 5).sample(); then(actual.getValues()).hasSize(5); } - @Property + @Test void setListElementWithIndex() { StringListHolder actual = SUT.giveMeBuilder(StringListHolder.class) .size("values", 3) @@ -163,7 +161,7 @@ void setListElementWithIndex() { then(actual.getValues().get(1)).isEqualTo("modified"); } - @Property + @Test void setMapField() { java.util.Map expected = new java.util.HashMap<>(); expected.put("one", 1); @@ -174,28 +172,28 @@ void setMapField() { then(actual.getMapping()).isEqualTo(expected); } - @Property + @Test void sizeMapField() { MapHolder actual = SUT.giveMeBuilder(MapHolder.class).size("mapping", 3).sample(); then(actual.getMapping()).hasSize(3); } - @Property + @Test void setNull() { String actual = SUT.giveMeBuilder(StringValue.class).setNull("value").sample().getValue(); then(actual).isNull(); } - @Property + @Test void setNullList() { List actual = SUT.giveMeBuilder(StringListHolder.class).setNull("values").sample().getValues(); then(actual).isNull(); } - @Property + @Test void setNestedStringListElement() { String expected = "nested-test"; @@ -208,7 +206,7 @@ void setNestedStringListElement() { then(actual.getValues().get(0).getValue()).isEqualTo(expected); } - @Property + @Test void setMultipleNestedStringListElements() { NestedStringListHolder actual = SUT.giveMeBuilder(NestedStringListHolder.class) .size("values", 3) @@ -223,7 +221,7 @@ void setMultipleNestedStringListElements() { then(actual.getValues().get(2).getValue()).isEqualTo("third"); } - @Property + @Test void sizeSmallerRemains() { List actual = SUT.giveMeBuilder(StringListHolder.class) .size("values", 2) @@ -237,7 +235,7 @@ void sizeSmallerRemains() { then(actual.get(0)).isEqualTo("test"); } - @Property + @Test void sizeSmallerRemovesOutOfRangeValues() { StringListHolder actual = SUT.giveMeBuilder(StringListHolder.class) .size("values", 3) @@ -251,12 +249,11 @@ void sizeSmallerRemovesOutOfRangeValues() { then(actual.getValues().get(0)).isEqualTo("keep"); } - @Property + @Test void defaultNotNull() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); String actual = sut.giveMeOne(SimpleObject.class).getStr(); @@ -264,12 +261,11 @@ void defaultNotNull() { then(actual).isNotNull(); } - @Property + @Test void pushExceptGenerateType() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .pushExceptGenerateType(new ExactTypeMatcher(String.class)) .build(); @@ -278,12 +274,11 @@ void pushExceptGenerateType() { then(actual).isNull(); } - @Property + @Test void addExceptGenerateClass() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .addExceptGenerateClass(Timestamp.class) .build(); @@ -292,12 +287,11 @@ void addExceptGenerateClass() { then(actual).isNull(); } - @Property + @Test void addExceptGenerateClassNotGenerateField() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .addExceptGenerateClass(String.class) .build(); @@ -306,12 +300,11 @@ void addExceptGenerateClassNotGenerateField() { then(actual).isNull(); } - @Property + @Test void addExceptGeneratePackage() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .addExceptGeneratePackage("java.lang") .build(); @@ -320,12 +313,11 @@ void addExceptGeneratePackage() { then(actual).isNull(); } - @Property + @Test void addExceptGeneratePackageNotGenerateField() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .addExceptGeneratePackage("java.lang") .build(); @@ -334,12 +326,11 @@ void addExceptGeneratePackageNotGenerateField() { then(actual).isNull(); } - @Property + @Test void pushAssignableTypeNullInjectGenerator() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .pushAssignableTypeNullInjectGenerator(SimpleObject.class, context -> 1.0d) .build(); @@ -348,12 +339,11 @@ void pushAssignableTypeNullInjectGenerator() { then(actual).isNull(); } - @Property + @Test void pushExactTypeNullInjectGenerator() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .pushExactTypeNullInjectGenerator(SimpleObject.class, context -> 1.0d) .build(); @@ -362,12 +352,11 @@ void pushExactTypeNullInjectGenerator() { then(actual).isNull(); } - @Property + @Test void pushNullInjectGenerator() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .pushNullInjectGenerator(MatcherOperator.exactTypeMatchOperator(SimpleObject.class, context -> 1.0d)) .build(); @@ -376,12 +365,11 @@ void pushNullInjectGenerator() { then(actual).isNull(); } - @Property + @Test void defaultNullInjectGenerator() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .defaultNullInjectGenerator(context -> 1.0d) .build(); @@ -390,12 +378,11 @@ void defaultNullInjectGenerator() { then(actual).isNull(); } - @Property + @Test void pushExactTypePropertyNameResolver() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .pushExactTypePropertyNameResolver(String.class, property -> "string") .build(); String expected = "test"; @@ -405,12 +392,11 @@ void pushExactTypePropertyNameResolver() { then(actual).isEqualTo(expected); } - @Property + @Test void pushAssignableTypePropertyNameResolver() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .pushAssignableTypePropertyNameResolver(Interface.class, property -> "interface") .build(); InterfaceImplementation expected = new InterfaceImplementation(); @@ -425,12 +411,11 @@ void pushAssignableTypePropertyNameResolver() { then(actual).isEqualTo(expected); } - @Property + @Test void pushPropertyNameResolver() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .pushPropertyNameResolver(MatcherOperator.exactTypeMatchOperator(String.class, property -> "string")) .build(); String expected = "test"; @@ -440,12 +425,11 @@ void pushPropertyNameResolver() { then(actual).isEqualTo(expected); } - @Property + @Test void defaultPropertyNameResolver() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .defaultPropertyNameResolver(property -> "'" + property.getName() + "'") .build(); String expected = "test"; @@ -455,20 +439,21 @@ void defaultPropertyNameResolver() { then(actual).isEqualTo(expected); } - @Property + @Test void pushArbitraryContainerInfoGenerator() { // given MatcherOperator containerInfoGenerator = new MatcherOperator<>( property -> { if ( - Types.getActualType(property.getType()).isArray() - || Types.getGenericsTypes(property.getAnnotatedType()).isEmpty() + property.getJvmType().getRawType().isArray() + || property.getJvmType().getTypeVariables().isEmpty() ) { return false; } - AnnotatedType elementType = Types.getGenericsTypes(property.getAnnotatedType()).get(0); - Class type = Types.getActualType(elementType); + com.navercorp.objectfarm.api.type.JvmType elementType = + property.getJvmType().getTypeVariables().get(0); + Class type = elementType.getRawType(); return type.isAssignableFrom(String.class); }, context -> new ArbitraryContainerInfo(5, 5) @@ -477,7 +462,6 @@ void pushArbitraryContainerInfoGenerator() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .pushArbitraryContainerInfoGenerator(containerInfoGenerator) .build(); @@ -488,24 +472,24 @@ void pushArbitraryContainerInfoGenerator() { then(actual).hasSize(5); } - @Property + @Test void pushArbitraryContainerInfoGeneratorNotMatching() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .pushArbitraryContainerInfoGenerator( new MatcherOperator<>( property -> { if ( - Types.getActualType(property.getType()).isArray() - || Types.getGenericsTypes(property.getAnnotatedType()).isEmpty() + property.getJvmType().getRawType().isArray() + || property.getJvmType().getTypeVariables().isEmpty() ) { return false; } - AnnotatedType elementType = Types.getGenericsTypes(property.getAnnotatedType()).get(0); - Class type = Types.getActualType(elementType); + com.navercorp.objectfarm.api.type.JvmType elementType = + property.getJvmType().getTypeVariables().get(0); + Class type = elementType.getRawType(); return type.isAssignableFrom(String.class); }, context -> new ArbitraryContainerInfo(5, 5) @@ -518,7 +502,7 @@ void pushArbitraryContainerInfoGeneratorNotMatching() { then(actual).hasSizeBetween(0, 3); } - @Property + @Test void defaultArbitraryContainerMaxSize() { // given ArbitraryContainerInfoGenerator containerInfoGenerator = context -> new ArbitraryContainerInfo(0, 1); @@ -526,7 +510,6 @@ void defaultArbitraryContainerMaxSize() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .defaultArbitraryContainerInfoGenerator(containerInfoGenerator) .build(); @@ -537,7 +520,7 @@ void defaultArbitraryContainerMaxSize() { then(actual).hasSizeLessThanOrEqualTo(1); } - @Property + @Test void defaultArbitraryContainerInfo() { // given ArbitraryContainerInfoGenerator containerInfoGenerator = context -> new ArbitraryContainerInfo(3, 3); @@ -545,7 +528,6 @@ void defaultArbitraryContainerInfo() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .defaultArbitraryContainerInfoGenerator(containerInfoGenerator) .build(); @@ -556,14 +538,13 @@ void defaultArbitraryContainerInfo() { then(actual).hasSize(3); } - @Property + @Test void sampleEnumMapWithEnumSizeIsLessThanContainerInfoMaxSize() { ArbitraryContainerInfoGenerator containerInfoGenerator = context -> new ArbitraryContainerInfo(0, 5); FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .defaultArbitraryContainerInfoGenerator(containerInfoGenerator) .build(); @@ -573,13 +554,12 @@ void sampleEnumMapWithEnumSizeIsLessThanContainerInfoMaxSize() { then(values).hasSizeLessThanOrEqualTo(2); } - @Property + @Test void sampleEnumMapWithEnumSizeIsLessThanContainerInfoMinSize() { // given FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .defaultArbitraryContainerInfoGenerator(context -> new ArbitraryContainerInfo(3, 5)) .build(); @@ -591,13 +571,12 @@ void sampleEnumMapWithEnumSizeIsLessThanContainerInfoMinSize() { then(values).hasSizeLessThanOrEqualTo(2); } - @Property + @Test void sampleEnumSetWithEnumSizeIsLessThanContainerInfoMinSize() { // given FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .defaultArbitraryContainerInfoGenerator(context -> new ArbitraryContainerInfo(3, 5)) .build(); @@ -609,12 +588,11 @@ void sampleEnumSetWithEnumSizeIsLessThanContainerInfoMinSize() { then(values).hasSizeLessThanOrEqualTo(2); } - @Property + @Test void alterDefaultArbitraryGenerator() { // given FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) - .plugin(new JavaNodeTreeAdapterPlugin()) .defaultArbitraryGenerator(generator -> new MatchArbitraryGenerator( Arrays.asList( @@ -632,12 +610,11 @@ void alterDefaultArbitraryGenerator() { then(actual).isNull(); } - @Property + @Test void skipArbitraryGenerator() { // given FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) - .plugin(new JavaNodeTreeAdapterPlugin()) .defaultArbitraryGenerator(generator -> new CompositeArbitraryGenerator(Arrays.asList(context -> NOT_GENERATED, generator)) ) @@ -651,12 +628,11 @@ void skipArbitraryGenerator() { then(actual).isNotNull(); } - @Property + @Test void uniqueArbitraryGenerator() { // given FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) - .plugin(new JavaNodeTreeAdapterPlugin()) .defaultArbitraryGenerator(UniqueArbitraryGenerator::new) .build(); @@ -668,12 +644,11 @@ void uniqueArbitraryGenerator() { then(actual).hasSameSizeAs(expected); } - @Property + @Test void allArbitraryGeneratorSkipReturnsNull() { // given FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) - .plugin(new JavaNodeTreeAdapterPlugin()) .defaultArbitraryGenerator(generator -> (new CompositeArbitraryGenerator(Arrays.asList(context -> NOT_GENERATED, context -> NOT_GENERATED))) ) @@ -686,11 +661,10 @@ void allArbitraryGeneratorSkipReturnsNull() { then(actual).isNull(); } - @Property + @Test void defaultNotNullNotWorksWhenSetDefaultNullInjectGenerator() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) - .plugin(new JavaNodeTreeAdapterPlugin()) .defaultNullInjectGenerator( new DefaultNullInjectGenerator( ALWAYS_NULL_INJECT, @@ -709,12 +683,11 @@ void defaultNotNullNotWorksWhenSetDefaultNullInjectGenerator() { then(actual).isNull(); } - @Property + @Test void nullableElement() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .defaultNullInjectGenerator( new DefaultNullInjectGenerator(1.0d, false, false, true, Collections.emptySet(), Collections.emptySet()) ) @@ -726,7 +699,7 @@ void nullableElement() { then(actual).allMatch(Objects::isNull); } - @Property + @Test void sampleNullableContainerWhenOptionNullableContainerIsSetReturnsNull() { DefaultNullInjectGenerator nullInjectGenerator = new DefaultNullInjectGenerator( ALWAYS_NULL_INJECT, @@ -739,7 +712,6 @@ void sampleNullableContainerWhenOptionNullableContainerIsSetReturnsNull() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .defaultNullInjectGenerator(nullInjectGenerator) .build(); @@ -748,14 +720,14 @@ void sampleNullableContainerWhenOptionNullableContainerIsSetReturnsNull() { then(values).isNull(); } - @Property + @Test void setSimple() { SimpleStringObject actual = SUT.giveMeBuilder(SimpleStringObject.class).set("str", "str").sample(); then(actual.getStr()).isEqualTo("str"); } - @Property + @Test void setDecomposedValue() { SimpleStringObject expected = new SimpleStringObject(); expected.setStr("original"); @@ -769,7 +741,7 @@ void setDecomposedValue() { then(actual.getStr()).isEqualTo("modified"); } - @Property + @Test void setArbitrary() { SimpleStringObject expected = new SimpleStringObject(); expected.setStr("original"); @@ -783,7 +755,7 @@ void setArbitrary() { then(actual.getStr()).isEqualTo("modified"); } - @Property + @Test void setOptional() { Optional optional = Optional.of("test"); @@ -795,7 +767,7 @@ void setOptional() { then(actual).isEqualTo(optional); } - @Property + @Test void setDecomposedList() { List expected = new ArrayList<>(); expected.add("a"); @@ -807,7 +779,7 @@ void setDecomposedList() { then(actual).isEqualTo(expected); } - @Property + @Test void setDecomposedSet() { Set expected = new HashSet<>(); expected.add("a"); @@ -820,7 +792,7 @@ void setDecomposedSet() { then(actual).isEqualTo(expected); } - @Property + @Test void setDecomposedMap() { Map expected = new HashMap<>(); expected.put("a", "1"); @@ -834,7 +806,7 @@ void setDecomposedMap() { then(actual).isEqualTo(expected); } - @Property + @Test void setDecomposedOptional() { Optional expected = Optional.of("test"); @@ -846,7 +818,7 @@ void setDecomposedOptional() { then(actual).isEqualTo(expected); } - @Property + @Test void setDecomposedOptionalEmpty() { Optional expected = Optional.empty(); @@ -858,28 +830,28 @@ void setDecomposedOptionalEmpty() { then(actual).isEqualTo(expected); } - @Property + @Test void setNullMap() { Map actual = SUT.giveMeBuilder(StringMapHolder.class).setNull("mapping").sample().getMapping(); then(actual).isNull(); } - @Property + @Test void setNotNullString() { String actual = SUT.giveMeBuilder(SimpleStringObject.class).setNotNull("str").sample().getStr(); then(actual).isNotNull(); } - @Property + @Test void setNotNullList() { List actual = SUT.giveMeBuilder(StringListHolder.class).setNotNull("values").sample().getValues(); then(actual).isNotNull(); } - @Property + @Test void setNotNullMap() { Map actual = SUT.giveMeBuilder(StringMapHolder.class) .setNotNull("mapping") @@ -889,14 +861,14 @@ void setNotNullMap() { then(actual).isNotNull(); } - @Property + @Test void setNotNullValue() { String actual = SUT.giveMeBuilder(SimpleStringObject.class).set("str", NOT_NULL).sample().getStr(); then(actual).isNotNull(); } - @Property + @Test void setRootJavaType() { String expected = "test"; @@ -905,7 +877,7 @@ void setRootJavaType() { then(actual).isEqualTo(expected); } - @Property + @Test void setRootComplexType() { SimpleStringObject expected = new SimpleStringObject(); expected.setStr("test"); @@ -915,7 +887,7 @@ void setRootComplexType() { then(actual.getStr()).isEqualTo(expected.getStr()); } - @Property + @Test void setListElement() { String expected = "test"; @@ -929,14 +901,14 @@ void setListElement() { then(actual).isEqualTo(expected); } - @Property + @Test void setAndSetNull() { String actual = SUT.giveMeBuilder(SimpleStringObject.class).set("str", "test").setNull("str").sample().getStr(); then(actual).isNull(); } - @Property + @Test void setAfterBuildNotAffected() { ArbitraryBuilder builder = SUT.giveMeBuilder(SimpleStringObject.class); net.jqwik.api.Arbitrary buildArbitrary = builder.build(); @@ -948,7 +920,7 @@ void setAfterBuildNotAffected() { then(actualSample.getStr()).isEqualTo("set"); } - @Property + @Test void setLazyValue() { ArbitraryBuilder variable = SUT.giveMeBuilder(String.class); ArbitraryBuilder builder = SUT.giveMeBuilder(String.class).setLazy("$", variable::sample); @@ -959,7 +931,7 @@ void setLazyValue() { then(actual).isEqualTo("test"); } - @Property + @Test void setArbitraryBuilder() { String expected = "test"; @@ -971,7 +943,7 @@ void setArbitraryBuilder() { then(actual).isEqualTo(expected); } - @Property + @Test void setDecomposeContainerTwice() { List strings = new ArrayList<>(); strings.add("test"); @@ -985,7 +957,7 @@ void setDecomposeContainerTwice() { then(actual).isEmpty(); } - @Property + @Test void setEmptyMap() { Map map = new HashMap<>(); map.put("test", "value"); @@ -999,7 +971,7 @@ void setEmptyMap() { then(actual).isEmpty(); } - @Property + @Test void setFieldWhichObjectIsFixedNull() { String expected = "test"; @@ -1013,7 +985,7 @@ void setFieldWhichObjectIsFixedNull() { then(actual).isEqualTo(expected); } - @Property + @Test void setFieldWhichRootIsFixedNull() { String expected = "test"; @@ -1026,63 +998,63 @@ void setFieldWhichRootIsFixedNull() { then(actual).isEqualTo(expected); } - @Property + @Test void sizeZero() { StringListHolder actual = SUT.giveMeBuilder(StringListHolder.class).size("values", 0).sample(); then(actual.getValues()).hasSize(0); } - @Property + @Test void size() { StringListHolder actual = SUT.giveMeBuilder(StringListHolder.class).size("values", 10).sample(); then(actual.getValues()).hasSize(10); } - @Property + @Test void sizeArray() { StringArrayHolder actual = SUT.giveMeBuilder(StringArrayHolder.class).size("values", 10).sample(); then(actual.getValues()).hasSize(10); } - @Property + @Test void sizeMinMax() { StringListHolder actual = SUT.giveMeBuilder(StringListHolder.class).size("values", 3, 8).sample(); then(actual.getValues()).hasSizeBetween(3, 8); } - @Property + @Test void sizeMinIsBiggerThanMax() { thenThrownBy(() -> SUT.giveMeBuilder(StringListHolder.class).size("values", 5, 1).sample()) .isExactlyInstanceOf(IllegalArgumentException.class) .hasMessageContaining("should be min <= max"); } - @Property + @Test void minSize() { StringListHolder actual = SUT.giveMeBuilder(StringListHolder.class).minSize("values", 10).sample(); then(actual.getValues()).hasSizeGreaterThanOrEqualTo(10); } - @Property + @Test void maxSize() { StringListHolder actual = SUT.giveMeBuilder(StringListHolder.class).maxSize("values", 10).sample(); then(actual.getValues()).hasSizeLessThanOrEqualTo(10); } - @Property + @Test void maxSizeZero() { StringListHolder actual = SUT.giveMeBuilder(StringListHolder.class).maxSize("values", 0).sample(); then(actual.getValues()).hasSizeLessThanOrEqualTo(0); } - @Property + @Test void nestedSize() { List> actual = SUT.giveMeBuilder(new TypeReference>>() { }) @@ -1094,7 +1066,7 @@ void nestedSize() { then(actual.get(0)).hasSize(10); } - @Property + @Test void sizeAfterSetReturnsSet() { List actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -1105,7 +1077,7 @@ void sizeAfterSetReturnsSet() { then(actual).isEmpty(); } - @Property + @Test void sizeNotSetEmptyList() { List actual = SUT.giveMeBuilder(StringListHolder.class) .size("values", 1) @@ -1116,7 +1088,7 @@ void sizeNotSetEmptyList() { then(actual).isEmpty(); } - @Property + @Test void mapWhenNull() { String actual = SUT.giveMeBuilder(SimpleStringObject.class) .setNull("str") @@ -1126,7 +1098,7 @@ void mapWhenNull() { then(actual).isNull(); } - @Property + @Test void mapWhenNotNull() { String actual = SUT.giveMeBuilder(SimpleStringObject.class) .setNotNull("str") @@ -1136,7 +1108,7 @@ void mapWhenNotNull() { then(actual).isNotNull(); } - @Property + @Test void mapToFixedValue() { String actual = SUT.giveMeBuilder(SimpleStringObject.class) .map(it -> "test") @@ -1145,7 +1117,7 @@ void mapToFixedValue() { then(actual).isEqualTo("test"); } - @Property + @Test void mapKeyIsNotNull() { Set actual = SUT.giveMeBuilder(new TypeReference>() { }).sample().keySet(); @@ -1153,7 +1125,7 @@ void mapKeyIsNotNull() { then(actual).allMatch(Objects::nonNull); } - @Property(tries = 1) + @Test void sampleAfterMapTwiceReturnsDiff() { ArbitraryBuilder arbitraryBuilder = SUT.giveMeBuilder(SimpleStringObject.class) .set( @@ -1170,7 +1142,7 @@ void sampleAfterMapTwiceReturnsDiff() { then(actual).isNotEqualTo(notExpected); } - @Property + @Test void zipList() { List> list = new ArrayList<>(); list.add(SUT.giveMeBuilder(StringValue.class)); @@ -1187,7 +1159,7 @@ void zipList() { then(actual.getValue2()).isNotNull(); } - @Property + @Test void zipEmptyListThrows() { List> list = new ArrayList<>(); @@ -1196,7 +1168,7 @@ void zipEmptyListThrows() { .hasMessageContaining("zip should be used in more than two ArbitraryBuilders, given size"); } - @Property + @Test void zipThree() { ArbitraryBuilder s1 = SUT.giveMeBuilder(StringValue.class).set("value", "s1"); ArbitraryBuilder s2 = SUT.giveMeBuilder(StringValue.class).set("value", "s2"); @@ -1219,7 +1191,7 @@ void zipThree() { then(actual.getValues().get(2).getValue()).isEqualTo("s3"); } - @Property + @Test void zipWithThree() { ArbitraryBuilder s1 = SUT.giveMeBuilder(StringValue.class).set("value", "s1"); ArbitraryBuilder s2 = SUT.giveMeBuilder(StringValue.class).set("value", "s2"); @@ -1244,7 +1216,7 @@ void zipWithThree() { then(actual.getValues().get(2).getValue()).isEqualTo("s3"); } - @Property + @Test void zipFour() { ArbitraryBuilder s1 = SUT.giveMeBuilder(StringValue.class).set("value", "s1"); ArbitraryBuilder s2 = SUT.giveMeBuilder(StringValue.class).set("value", "s2"); @@ -1270,7 +1242,7 @@ void zipFour() { then(actual.getValues().get(3).getValue()).isEqualTo("s4"); } - @Property + @Test void zipWithFour() { ArbitraryBuilder s1 = SUT.giveMeBuilder(StringValue.class).set("value", "s1"); ArbitraryBuilder s2 = SUT.giveMeBuilder(StringValue.class).set("value", "s2"); @@ -1298,7 +1270,7 @@ void zipWithFour() { then(actual.getValues().get(3).getValue()).isEqualTo("s4"); } - @Property + @Test void zipWith() { ArbitraryBuilder stringArbitraryBuilder = SUT.giveMeBuilder(String.class); @@ -1309,7 +1281,7 @@ void zipWith() { then(actual).isNotNull(); } - @Property + @Test void zipTwo() { ArbitraryBuilder stringArbitraryBuilder = SUT.giveMeBuilder(String.class); ArbitraryBuilder integerArbitraryBuilder = SUT.giveMeBuilder(Integer.class); @@ -1323,7 +1295,7 @@ void zipTwo() { then(actual).isNotNull(); } - @Property + @Test void zipReturnsNew() { ArbitraryBuilder stringArbitraryBuilder = SUT.giveMeBuilder(String.class); ArbitraryBuilder integerArbitraryBuilder = SUT.giveMeBuilder(Integer.class); @@ -1339,7 +1311,7 @@ void zipReturnsNew() { then(result1).isNotEqualTo(result2); } - @Property(tries = 1) + @Test void notFixedSampleReturnsDiff() { ArbitraryBuilder fixedArbitraryBuilder = SUT.giveMeBuilder(SimpleStringObject.class); @@ -1348,7 +1320,7 @@ void notFixedSampleReturnsDiff() { then(sample1).isNotEqualTo(sample2); } - @Property + @Test void fixedSampleReturnsSame() { ArbitraryBuilder fixedArbitraryBuilder = SUT.giveMeBuilder( SimpleStringObject.class @@ -1359,7 +1331,7 @@ void fixedSampleReturnsSame() { then(sample1.getStr()).isEqualTo(sample2.getStr()); } - @Property + @Test void arbitraryFixedSampleReturnsSame() { ArbitraryBuilder fixedArbitraryBuilder = SUT.giveMeBuilder(SimpleStringObject.class) .set("str", Arbitraries.of("value1", "value2")) @@ -1370,14 +1342,14 @@ void arbitraryFixedSampleReturnsSame() { then(sample1.getStr()).isEqualTo(sample2.getStr()); } - @Property + @Test void setNullFixedReturnsNull() { SimpleStringObject actual = SUT.giveMeBuilder(SimpleStringObject.class).setNull("$").fixed().sample(); then(actual).isNull(); } - @Property + @Test void fixedRangedSizeReturnsSameSize() { ArbitraryBuilder fixedArbitraryBuilder = SUT.giveMeBuilder(StringListHolder.class) .size("values", 1, 5) @@ -1389,7 +1361,7 @@ void fixedRangedSizeReturnsSameSize() { then(actual).isEqualTo(expected); } - @Property + @Test void setNullFixed() { String expected = "test"; @@ -1404,7 +1376,7 @@ void setNullFixed() { then(actual).isEqualTo(expected); } - @Property + @Test void giveMeBuilderWithValue() { SimpleStringObject expected = new SimpleStringObject(); expected.setStr("test"); @@ -1414,20 +1386,19 @@ void giveMeBuilderWithValue() { then(actual.getStr()).isEqualTo(expected.getStr()); } - @Property + @Test void copyValidOnly() { thenNoException().isThrownBy(() -> SUT.giveMeBuilder(ListStringObject.class).size("values", 0).validOnly(false).copy().sample() ); } - @Property + @Test void generateNewContainer() { // given FixtureMonkey sut = FixtureMonkey.builder() .pushAssignableTypeContainerPropertyGenerator(Pair.class, new PairContainerPropertyGenerator()) .pushContainerIntrospector(new PairIntrospector()) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); // when @@ -1438,7 +1409,7 @@ void generateNewContainer() { then(pair).isNotNull(); } - @Property + @Test void decomposeNewContainer() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -1456,7 +1427,6 @@ void decomposeNewContainer() { "given type is not supported container : " + obj.getClass().getTypeName() ); }) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); ArbitraryBuilder> builder = sut .giveMeBuilder(new TypeReference>() { @@ -1471,7 +1441,7 @@ void decomposeNewContainer() { then(actual1).isEqualTo(actual2); } - @Property + @Test void decomposeNewContainerByAddContainerType() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -1482,7 +1452,6 @@ void decomposeNewContainerByAddContainerType() { list.add(pair.getSecond()); return new DecomposableJavaContainer(list, 2); }) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); ArbitraryBuilder> builder = sut .giveMeBuilder(new TypeReference>() { @@ -1497,7 +1466,7 @@ void decomposeNewContainerByAddContainerType() { then(actual1).isEqualTo(actual2); } - @Property + @Test void decomposeNewContainerByAddContainerTypeInterface() { // given FixtureMonkey sut = FixtureMonkey.builder() @@ -1513,7 +1482,6 @@ void decomposeNewContainerByAddContainerTypeInterface() { return new DecomposableJavaContainer(list, 2); } ) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); // when @@ -1527,12 +1495,11 @@ void decomposeNewContainerByAddContainerTypeInterface() { ); } - @Property + @Test void setContainerThenSize_shouldNotLockConcreteType() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); StringValue element = new StringValue(); diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionGenericTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionGenericTest.java similarity index 84% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionGenericTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionGenericTest.java index ef62fc1149..3de3b184d3 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionGenericTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionGenericTest.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; import static org.assertj.core.api.BDDAssertions.thenNoException; @@ -24,18 +24,18 @@ import java.util.List; import java.util.Map; -import net.jqwik.api.Property; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.GenericChildTwoValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.GenericChildValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.GenericStringWrapperValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.GenericValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.GenericWrapper; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.GenericWrapperValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.SimpleStringObject; import com.navercorp.fixturemonkey.api.introspector.FieldReflectionArbitraryIntrospector; import com.navercorp.fixturemonkey.api.type.TypeReference; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.GenericChildTwoValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.GenericChildValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.GenericStringWrapperValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.GenericValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.GenericWrapper; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.GenericWrapperValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.SimpleStringObject; class ValueProjectionGenericTest { @@ -44,10 +44,9 @@ class ValueProjectionGenericTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void generateGenericWrapper() { GenericWrapper actual = SUT.giveMeBuilder( new com.navercorp.fixturemonkey.api.type.TypeReference>() { @@ -58,7 +57,7 @@ void generateGenericWrapper() { then(actual.getValue()).isNotNull(); } - @Property + @Test void setGenericWrapperValue() { GenericWrapper actual = SUT.giveMeBuilder( new com.navercorp.fixturemonkey.api.type.TypeReference>() { @@ -70,7 +69,7 @@ void setGenericWrapperValue() { then(actual.getValue()).isEqualTo("generic-value"); } - @Property + @Test void generateGenericListWrapper() { GenericWrapper> actual = SUT.giveMeBuilder( new com.navercorp.fixturemonkey.api.type.TypeReference>>() { @@ -82,7 +81,7 @@ void generateGenericListWrapper() { then(actual.getValue()).isInstanceOf(java.util.ArrayList.class); } - @Property + @Test void setGenericListWrapperValue() { List expected = java.util.Arrays.asList("a", "b"); @@ -96,7 +95,7 @@ void setGenericListWrapperValue() { then(actual.getValue()).isEqualTo(expected); } - @Property + @Test void generateNestedGeneric() { GenericWrapper> actual = SUT.giveMeBuilder( new com.navercorp.fixturemonkey.api.type.TypeReference>>() { @@ -108,7 +107,7 @@ void generateNestedGeneric() { then(actual.getValue().getValue()).isNotNull(); } - @Property + @Test void setNestedGenericValue() { GenericWrapper> actual = SUT.giveMeBuilder( new com.navercorp.fixturemonkey.api.type.TypeReference>>() { @@ -120,7 +119,7 @@ void setNestedGenericValue() { then(actual.getValue().getValue()).isEqualTo("nested-generic"); } - @Property + @Test void sampleGeneric() { String actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -131,7 +130,7 @@ void sampleGeneric() { then(actual).isNotNull(); } - @Property + @Test void sampleGenericWildcardExtends() { String actual = SUT.giveMeBuilder(new TypeReference>() { }) @@ -142,14 +141,14 @@ void sampleGenericWildcardExtends() { then(actual).isNotNull(); } - @Property + @Test void sampleStringGenericField() { GenericStringWrapperValue actual = SUT.giveMeOne(GenericStringWrapperValue.class); then(actual).isNotNull(); } - @Property + @Test void sampleGenericField() { GenericWrapperValue actual = SUT.giveMeOne(new TypeReference>() { }); @@ -157,33 +156,33 @@ void sampleGenericField() { then(actual).isNotNull(); } - @Property + @Test void sampleGenericChild() { GenericChildValue actual = SUT.giveMeOne(GenericChildValue.class); then(actual).isNotNull(); } - @Property + @Test void sampleTwoGenericChild() { GenericChildTwoValue actual = SUT.giveMeOne(GenericChildTwoValue.class); then(actual).isNotNull(); } - @Property + @Test void sampleWildcard() { thenNoException().isThrownBy(() -> SUT.giveMeOne(new TypeReference>() { })); } - @Property + @Test void sampleMapValueWildcardListString() { thenNoException().isThrownBy(() -> SUT.giveMeOne(new TypeReference>>() { })); } - @Property + @Test void setGenericContainerThenSize_shouldNotLockConcreteType() { // given GenericWrapper> actual = SUT.giveMeBuilder( diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionInstantiatorTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionInstantiatorTest.java similarity index 83% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionInstantiatorTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionInstantiatorTest.java index 08b260b002..f0de874af3 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionInstantiatorTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionInstantiatorTest.java @@ -16,25 +16,25 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; import java.lang.reflect.Method; import java.util.Arrays; -import net.jqwik.api.Property; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.BuilderInteger; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.ConstructorOnlyInteger; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.CustomBuildMethodInteger; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.CustomBuilderMethodInteger; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.FactoryMethodInteger; import com.navercorp.fixturemonkey.api.introspector.BuilderArbitraryIntrospector; import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; import com.navercorp.fixturemonkey.api.introspector.FactoryMethodArbitraryIntrospector; import com.navercorp.fixturemonkey.api.introspector.FieldReflectionArbitraryIntrospector; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.BuilderInteger; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.ConstructorOnlyInteger; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.CustomBuildMethodInteger; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.CustomBuilderMethodInteger; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.FactoryMethodInteger; class ValueProjectionInstantiatorTest { @@ -43,15 +43,13 @@ class ValueProjectionInstantiatorTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void generateWithBuilderArbitraryIntrospector() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .pushExactTypeArbitraryIntrospector(BuilderInteger.class, BuilderArbitraryIntrospector.INSTANCE) .build(); @@ -62,7 +60,7 @@ void generateWithBuilderArbitraryIntrospector() { then(actual.getValue()).isBetween(Integer.MIN_VALUE, Integer.MAX_VALUE); } - @Property + @Test void generateWithBuilderArbitraryIntrospectorDefaultBuilderMethod() { // given BuilderArbitraryIntrospector builderArbitraryIntrospector = new BuilderArbitraryIntrospector(); @@ -70,7 +68,6 @@ void generateWithBuilderArbitraryIntrospectorDefaultBuilderMethod() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .pushExactTypeArbitraryIntrospector(CustomBuilderMethodInteger.class, builderArbitraryIntrospector) .build(); @@ -81,7 +78,7 @@ void generateWithBuilderArbitraryIntrospectorDefaultBuilderMethod() { then(actual.getValue()).isBetween(Integer.MIN_VALUE, Integer.MAX_VALUE); } - @Property + @Test void generateWithBuilderArbitraryIntrospectorDefaultBuildMethod() { // given BuilderArbitraryIntrospector builderArbitraryIntrospector = new BuilderArbitraryIntrospector(); @@ -89,7 +86,6 @@ void generateWithBuilderArbitraryIntrospectorDefaultBuildMethod() { FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .pushExactTypeArbitraryIntrospector(CustomBuildMethodInteger.class, builderArbitraryIntrospector) .build(); @@ -100,12 +96,11 @@ void generateWithBuilderArbitraryIntrospectorDefaultBuildMethod() { then(actual.getValue()).isBetween(Integer.MIN_VALUE, Integer.MAX_VALUE); } - @Property + @Test void generateWithConstructorPropertiesArbitraryIntrospector() { // given FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .pushExactTypeArbitraryIntrospector( ConstructorOnlyInteger.class, ConstructorPropertiesArbitraryIntrospector.INSTANCE @@ -120,7 +115,7 @@ void generateWithConstructorPropertiesArbitraryIntrospector() { then(actual.getValue()).isBetween(Integer.MIN_VALUE, Integer.MAX_VALUE); } - @Property + @Test void generateWithFactoryMethodArbitraryIntrospector() throws NoSuchMethodException { // given Method factoryMethod = FactoryMethodInteger.class.getDeclaredMethod("of", int.class); @@ -128,7 +123,6 @@ void generateWithFactoryMethodArbitraryIntrospector() throws NoSuchMethodExcepti FixtureMonkey sut = FixtureMonkey.builder() .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .pushExactTypeArbitraryIntrospector( FactoryMethodInteger.class, new FactoryMethodArbitraryIntrospector( diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionInterfaceTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionInterfaceTest.java similarity index 76% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionInterfaceTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionInterfaceTest.java index 25f1ebec26..f6a795b713 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionInterfaceTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionInterfaceTest.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; @@ -27,48 +27,48 @@ import java.util.Set; import java.util.stream.Collectors; -import net.jqwik.api.Property; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.AbstractGenericBox; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.AbstractNoneConcreteIntValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.AbstractNoneConcreteStringValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.AbstractNoneValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.AbstractSamePropertyValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.AbstractValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.AbstractWithNestedInterface; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.ConcreteIntValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.ConcreteSamePropertyValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.ConcreteStringBox; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.ConcreteStringValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.ConcreteWithNestedInterface; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.GenericGetFixedValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.GenericHolder; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.GenericHolderContainer; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.GetFixedValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.GetFixedValueChild; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.GetIntegerFixedValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.GetIntegerFixedValueChild; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.GetStringFixedValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.GetterInterface; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.GetterInterfaceImplementation; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.GetterInterfaceImplementation2; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.IntegerGenericHolder; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.Interface; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.InterfaceHolder; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.InterfaceImplementation; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.SelfRecursiveAbstractValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.SelfRecursiveImplementationValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.SelfRecursiveWithFieldAbstractValue; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.SelfRecursiveWithFieldImplementation; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.StringGenericHolder; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.StringValueProvider; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.ValueProvider; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.ValueProviderContainer; import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; import com.navercorp.fixturemonkey.api.introspector.FieldReflectionArbitraryIntrospector; import com.navercorp.fixturemonkey.api.plugin.InterfacePlugin; import com.navercorp.fixturemonkey.api.type.TypeReference; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.AbstractGenericBox; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.AbstractNoneConcreteIntValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.AbstractNoneConcreteStringValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.AbstractNoneValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.AbstractSamePropertyValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.AbstractValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.AbstractWithNestedInterface; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.ConcreteIntValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.ConcreteSamePropertyValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.ConcreteStringBox; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.ConcreteStringValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.ConcreteWithNestedInterface; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.GenericGetFixedValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.GenericHolder; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.GenericHolderContainer; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.GetFixedValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.GetFixedValueChild; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.GetIntegerFixedValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.GetIntegerFixedValueChild; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.GetStringFixedValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.GetterInterface; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.GetterInterfaceImplementation; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.GetterInterfaceImplementation2; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.IntegerGenericHolder; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.Interface; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.InterfaceHolder; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.InterfaceImplementation; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.SelfRecursiveAbstractValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.SelfRecursiveImplementationValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.SelfRecursiveWithFieldAbstractValue; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.SelfRecursiveWithFieldImplementation; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.StringGenericHolder; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.StringValueProvider; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.ValueProvider; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.ValueProviderContainer; class ValueProjectionInterfaceTest { @@ -77,10 +77,9 @@ class ValueProjectionInterfaceTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void generateWithInterfaceField() { InterfaceHolder actual = SUT.giveMeOne(InterfaceHolder.class); @@ -89,7 +88,7 @@ void generateWithInterfaceField() { then(actual.getItems()).isInstanceOf(java.util.ArrayList.class); } - @Property + @Test void setInterfaceField() { List expected = java.util.Arrays.asList("x", "y", "z"); @@ -98,14 +97,14 @@ void setInterfaceField() { then(actual.getItems()).isEqualTo(expected); } - @Property + @Test void sizeInterfaceField() { InterfaceHolder actual = SUT.giveMeBuilder(InterfaceHolder.class).size("items", 4).sample(); then(actual.getItems()).hasSize(4); } - @Property + @Test void interfaceImplements() { // given List> implementations = new ArrayList<>(); @@ -114,7 +113,6 @@ void interfaceImplements() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin(new InterfacePlugin().interfaceImplements(GetFixedValue.class, implementations)) .build(); @@ -126,7 +124,7 @@ void interfaceImplements() { then(actual).isIn(1, "fixed"); } - @Property + @Test void sampleGenericInterface() { // given List> implementations = new ArrayList<>(); @@ -135,7 +133,6 @@ void sampleGenericInterface() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin(new InterfacePlugin().interfaceImplements(GetFixedValue.class, implementations)) .build(); @@ -152,7 +149,7 @@ void sampleGenericInterface() { then(actual).isIn(1, "fixed"); } - @Property(tries = 1) + @Test void sampleGenericInterfaceReturnsDiff() { // given List> implementations = new ArrayList<>(); @@ -161,7 +158,6 @@ void sampleGenericInterfaceReturnsDiff() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin(new InterfacePlugin().interfaceImplements(GetFixedValue.class, implementations)) .build(); @@ -179,7 +175,7 @@ void sampleGenericInterfaceReturnsDiff() { then(actual).hasSize(2); } - @Property + @Test void sampleInterfaceChildWhenOptionHasHierarchy() { // given List> implementations = new ArrayList<>(); @@ -191,7 +187,6 @@ void sampleInterfaceChildWhenOptionHasHierarchy() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin( new InterfacePlugin() .interfaceImplements(GetFixedValueChild.class, childImplementations) @@ -207,11 +202,10 @@ void sampleInterfaceChildWhenOptionHasHierarchy() { then(actual).isEqualTo(2); } - @Property + @Test void sampleConcreteWhenHasSameNameProperty() { // given FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin( new InterfacePlugin().abstractClassExtends( AbstractSamePropertyValue.class, @@ -228,11 +222,10 @@ void sampleConcreteWhenHasSameNameProperty() { then(actual).isNotNull(); } - @Property + @Test void sampleSelfRecursiveAbstract() { // given FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin( new InterfacePlugin().abstractClassExtends( SelfRecursiveAbstractValue.class, @@ -249,11 +242,10 @@ void sampleSelfRecursiveAbstract() { then(actual).isNotNull(); } - @Property + @Test void setConcreteClassWhenHasParentValue() { // given FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin( new InterfacePlugin().abstractClassExtends( AbstractValue.class, @@ -273,11 +265,10 @@ void setConcreteClassWhenHasParentValue() { then(actual).isEqualTo(expected); } - @Property + @Test void setConcreteClassWhenHasNoParentValue() { // given FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin( new InterfacePlugin().abstractClassExtends( AbstractNoneValue.class, @@ -297,7 +288,7 @@ void setConcreteClassWhenHasNoParentValue() { then(actual).isEqualTo(expected); } - @Property + @Test void setConcreteList() { // given List> implementations = new ArrayList<>(); @@ -305,7 +296,6 @@ void setConcreteList() { implementations.add(ConcreteIntValue.class); FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin(new InterfacePlugin().abstractClassExtends(AbstractValue.class, implementations)) .build(); @@ -330,7 +320,7 @@ void setConcreteList() { then(actual).isEqualTo(expected); } - @Property + @Test void setConcreteListWithNoParentValue() { // given List> implementations = new ArrayList<>(); @@ -338,7 +328,6 @@ void setConcreteListWithNoParentValue() { implementations.add(AbstractNoneConcreteIntValue.class); FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin(new InterfacePlugin().abstractClassExtends(AbstractNoneValue.class, implementations)) .build(); @@ -361,7 +350,7 @@ void setConcreteListWithNoParentValue() { then(actual).isEqualTo(expected); } - @Property + @Test void setConcrete() { // given List> implementations = new ArrayList<>(); @@ -369,7 +358,6 @@ void setConcrete() { implementations.add(ConcreteIntValue.class); FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin(new InterfacePlugin().abstractClassExtends(AbstractValue.class, implementations)) .build(); @@ -384,11 +372,10 @@ void setConcrete() { then(actual).isEqualTo(expected); } - @Property + @Test void samePropertyDiffImplementations() { // given FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin( new InterfacePlugin().interfaceImplements( GetterInterface.class, @@ -404,13 +391,12 @@ void samePropertyDiffImplementations() { then(actual).isEqualTo("expected"); } - @Property + @Test void sampleDifferentGenericImplementations() { // given FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin( new InterfacePlugin().interfaceImplements( GenericHolder.class, @@ -428,13 +414,12 @@ void sampleDifferentGenericImplementations() { then(actual.getIntegerHolder()).isNotNull(); } - @Property + @Test void sampleAbstractWithNestedInterface() { // given FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin( new InterfacePlugin() .abstractClassExtends( @@ -455,11 +440,10 @@ void sampleAbstractWithNestedInterface() { then(actual.getNestedInterface()).isInstanceOf(InterfaceImplementation.class); } - @Property + @Test void setSelfRecursiveAbstractField() { // given FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin( new InterfacePlugin().abstractClassExtends( SelfRecursiveWithFieldAbstractValue.class, @@ -480,11 +464,10 @@ void setSelfRecursiveAbstractField() { then(actual.getName()).isEqualTo("root"); } - @Property + @Test void sizeSelfRecursiveAbstractList() { // given FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin( new InterfacePlugin().abstractClassExtends( SelfRecursiveAbstractValue.class, @@ -505,11 +488,10 @@ void sizeSelfRecursiveAbstractList() { then(actual.getRecursives()).hasSize(2); } - @Property + @Test void sampleAbstractGenericBoxResolvesFieldTypes() { // given FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin( new InterfacePlugin().abstractClassExtends( AbstractGenericBox.class, @@ -531,11 +513,10 @@ void sampleAbstractGenericBoxResolvesFieldTypes() { then(actual.getItems()).allSatisfy(item -> then(item).isInstanceOf(String.class)); } - @Property + @Test void sampleInterfaceWithDifferentReturnType() { // given FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin( new InterfacePlugin().interfaceImplements( ValueProvider.class, diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionIntrospectorTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionIntrospectorTest.java similarity index 84% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionIntrospectorTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionIntrospectorTest.java index f86bb97318..04b79cf000 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionIntrospectorTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionIntrospectorTest.java @@ -16,21 +16,22 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; +import org.junit.jupiter.api.Test; + import net.jqwik.api.Arbitraries; -import net.jqwik.api.Property; import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.ComplexObject; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.SimpleObject; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.SimpleObjectChild; import com.navercorp.fixturemonkey.api.introspector.ArbitraryIntrospectorResult; import com.navercorp.fixturemonkey.api.introspector.FieldReflectionArbitraryIntrospector; import com.navercorp.fixturemonkey.api.jqwik.ArbitraryUtils; import com.navercorp.fixturemonkey.api.matcher.MatcherOperator; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.ComplexObject; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.SimpleObject; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.SimpleObjectChild; class ValueProjectionIntrospectorTest { @@ -39,16 +40,14 @@ class ValueProjectionIntrospectorTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void pushExactTypeArbitraryIntrospector() { // given FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .pushExactTypeArbitraryIntrospector(SimpleObjectChild.class, context -> new ArbitraryIntrospectorResult(ArbitraryUtils.toCombinableArbitrary(Arbitraries.just(null))) ) @@ -61,13 +60,12 @@ void pushExactTypeArbitraryIntrospector() { then(actual).isNull(); } - @Property + @Test void pushAssignableTypeArbitraryIntrospector() { // given FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .pushAssignableTypeArbitraryIntrospector(SimpleObject.class, context -> new ArbitraryIntrospectorResult(ArbitraryUtils.toCombinableArbitrary(Arbitraries.just(null))) ) @@ -80,13 +78,12 @@ void pushAssignableTypeArbitraryIntrospector() { then(actual).isNull(); } - @Property + @Test void pushArbitraryIntrospector() { // given FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .pushArbitraryIntrospector( MatcherOperator.exactTypeMatchOperator(SimpleObjectChild.class, context -> new ArbitraryIntrospectorResult(ArbitraryUtils.toCombinableArbitrary(Arbitraries.just(null))) @@ -101,11 +98,10 @@ void pushArbitraryIntrospector() { then(actual).isNull(); } - @Property + @Test void objectIntrospector() { // given FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .objectIntrospector(context -> new ArbitraryIntrospectorResult(ArbitraryUtils.toCombinableArbitrary(Arbitraries.just(null))) ) diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionMiscTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionMiscTest.java similarity index 87% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionMiscTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionMiscTest.java index 9f055589d5..a5023c5ec0 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionMiscTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionMiscTest.java @@ -16,46 +16,45 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; import static org.assertj.core.api.BDDAssertions.thenNoException; -import net.jqwik.api.Property; +import org.junit.jupiter.api.Test; + import net.jqwik.api.arbitraries.StringArbitrary; import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.PreApproval; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.SimpleObject; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.SimplePayMethod; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.StaticFieldObject; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.StringAndInt; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.StringPair; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.StringValue; import com.navercorp.fixturemonkey.api.arbitrary.MonkeyStringArbitrary; import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; import com.navercorp.fixturemonkey.api.introspector.FieldReflectionArbitraryIntrospector; import com.navercorp.fixturemonkey.api.jqwik.JavaTypeArbitraryGenerator; import com.navercorp.fixturemonkey.api.jqwik.JqwikPlugin; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.PreApproval; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.SimpleObject; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.SimplePayMethod; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.StaticFieldObject; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.StringAndInt; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.StringPair; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.StringValue; class ValueProjectionMiscTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void sampleNotGeneratingStaticField() { thenNoException().isThrownBy(() -> SUT.giveMeOne(StaticFieldObject.class)); } - @Property + @Test void sampleWithMonkeyStringArbitrary() { // given FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin( new JqwikPlugin().javaTypeArbitraryGenerator( new JavaTypeArbitraryGenerator() { @@ -75,11 +74,10 @@ public StringArbitrary strings() { then(actual).isNotNull(); } - @Property + @Test void filterWithMonkeyStringArbitrary() { // given FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin( new JqwikPlugin().javaTypeArbitraryGenerator( new JavaTypeArbitraryGenerator() { @@ -99,10 +97,10 @@ public StringArbitrary strings() { then(actual).isUpperCase(); } - @Property + @Test void filterIsoControlCharacterWithMonkeyStringArbitrary() { // given - FixtureMonkey sut = FixtureMonkey.builder().plugin(new JavaNodeTreeAdapterPlugin()).build(); + FixtureMonkey sut = FixtureMonkey.builder().build(); // when String actual = sut.giveMeOne(String.class); @@ -118,13 +116,12 @@ void filterIsoControlCharacterWithMonkeyStringArbitrary() { }); } - @Property + @Test void sampleConstructorBasedTypeWithDefaultNotNull() { // given FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); // when @@ -137,13 +134,12 @@ void sampleConstructorBasedTypeWithDefaultNotNull() { then(actual.getFirstPayMethod().getPayMethodType()).isNotNull(); } - @Property + @Test void sampleNullableConstructorParamWithDefaultNotNull() { // given FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); // when @@ -157,11 +153,10 @@ void sampleNullableConstructorParamWithDefaultNotNull() { } } - @Property + @Test void multipleFiltersWithMonkeyStringArbitrary() { // given FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin( new JqwikPlugin().javaTypeArbitraryGenerator( new JavaTypeArbitraryGenerator() { @@ -190,13 +185,12 @@ public MonkeyStringArbitrary monkeyStrings() { }); } - @Property + @Test void registerLazyShouldPreserveNullFieldsAfterDecompose() { // given FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringAndInt.class, fixture -> fixture.giveMeBuilder(StringAndInt.class) .setLazy("$", () -> { StringAndInt obj = new StringAndInt(); @@ -219,7 +213,7 @@ void registerLazyShouldPreserveNullFieldsAfterDecompose() { } } - @Property + @Test void setRootWithNullFieldShouldPreserveNull() { // given StringAndInt value = new StringAndInt(); @@ -238,7 +232,7 @@ void setRootWithNullFieldShouldPreserveNull() { then(actual.getValue2()).isNull(); } - @Property + @Test void setRootWithAllNullFieldsShouldPreserveNulls() { // given StringAndInt value = new StringAndInt(); @@ -253,7 +247,7 @@ void setRootWithAllNullFieldsShouldPreserveNulls() { then(actual.getValue2()).isNull(); } - @Property + @Test void setRootWithNullFieldAndChildOverrideShouldOverrideOnly() { // given StringAndInt value = new StringAndInt(); @@ -270,13 +264,12 @@ void setRootWithNullFieldAndChildOverrideShouldOverrideOnly() { then(actual.getValue2().getValue()).isEqualTo(42); } - @Property + @Test void registerThenApplyWithFieldLevelSetLazyShouldNotBeBlockedByRecursionGuard() { // given FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringPair.class, fixture -> fixture.giveMeBuilder(StringPair.class) .thenApply((it, builder) -> builder.set("value2", it.getValue1() + "_suffix")) .setLazy("value1", () -> "fixed") @@ -293,13 +286,12 @@ void registerThenApplyWithFieldLevelSetLazyShouldNotBeBlockedByRecursionGuard() } } - @Property + @Test void registerNestedTypeBothWithThenApplyAndFieldSetLazy() { // given FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringAndInt.class, fixture -> fixture.giveMeBuilder(StringAndInt.class) .thenApply((it, builder) -> { if (it.getValue1() != null) { @@ -322,13 +314,12 @@ void registerNestedTypeBothWithThenApplyAndFieldSetLazy() { } } - @Property + @Test void registerFieldSetLazyOnlyNoThenApplyShouldWork() { // given FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringPair.class, fixture -> fixture.giveMeBuilder(StringPair.class) .setLazy("value1", () -> "lazy1") .setLazy("value2", () -> "lazy2") @@ -345,13 +336,12 @@ void registerFieldSetLazyOnlyNoThenApplyShouldWork() { } } - @Property + @Test void registerTwoTypesWithCrossReferenceThenApply() { // given FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .register(StringValue.class, fixture -> fixture.giveMeBuilder(StringValue.class) .setLazy("value", () -> "sv_fixed") ) @@ -376,7 +366,7 @@ void registerTwoTypesWithCrossReferenceThenApply() { } } - @Property + @Test void setNestedObjectWithNullFieldShouldPreserveNull() { // given SimpleObject value = new SimpleObject(); diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionPluginTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionPluginTest.java similarity index 89% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionPluginTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionPluginTest.java index 7647229d75..84bf3d24d7 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionPluginTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionPluginTest.java @@ -16,23 +16,22 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; import java.time.Instant; import java.util.regex.Pattern; +import org.junit.jupiter.api.Test; + import net.jqwik.api.Arbitraries; import net.jqwik.api.Arbitrary; -import net.jqwik.api.Property; import net.jqwik.api.arbitraries.StringArbitrary; import net.jqwik.time.api.DateTimes; import net.jqwik.time.api.arbitraries.InstantArbitrary; import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.InstantObject; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.SimpleObject; import com.navercorp.fixturemonkey.api.generator.ArbitraryGeneratorContext; import com.navercorp.fixturemonkey.api.introspector.FieldReflectionArbitraryIntrospector; import com.navercorp.fixturemonkey.api.jqwik.JavaArbitraryResolver; @@ -40,6 +39,8 @@ import com.navercorp.fixturemonkey.api.jqwik.JavaTimeTypeArbitraryGenerator; import com.navercorp.fixturemonkey.api.jqwik.JavaTypeArbitraryGenerator; import com.navercorp.fixturemonkey.api.jqwik.JqwikPlugin; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.InstantObject; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.SimpleObject; class ValueProjectionPluginTest { @@ -48,14 +49,12 @@ class ValueProjectionPluginTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void javaTypeArbitraryGenerator() { // given FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin( new JqwikPlugin().javaTypeArbitraryGenerator( new JavaTypeArbitraryGenerator() { @@ -75,11 +74,10 @@ public StringArbitrary strings() { then(actual).matches(Pattern.compile("\\d*")); } - @Property + @Test void javaTypeArbitraryGeneratorAffectsField() { // given FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin( new JqwikPlugin().javaTypeArbitraryGenerator( new JavaTypeArbitraryGenerator() { @@ -99,11 +97,10 @@ public StringArbitrary strings() { then(actual).matches(it -> it == null || Pattern.compile("\\d*").matcher(it).matches()); } - @Property + @Test void javaArbitraryResolver() { // given FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin( new JqwikPlugin().javaArbitraryResolver( new JavaArbitraryResolver() { @@ -126,11 +123,10 @@ public Arbitrary strings( then(actual).isEqualTo("test"); } - @Property + @Test void javaArbitraryResolverAffectsField() { // given FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin( new JqwikPlugin().javaArbitraryResolver( new JavaArbitraryResolver() { @@ -153,12 +149,11 @@ public Arbitrary strings( then(actual).isIn("test", null); } - @Property + @Test void javaTimeTypeArbitraryGenerator() { // given Instant expected = Instant.now(); FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin( new JqwikPlugin().javaTimeTypeArbitraryGenerator( new JavaTimeTypeArbitraryGenerator() { @@ -178,12 +173,11 @@ public InstantArbitrary instants() { then(actual).isEqualTo(expected); } - @Property + @Test void javaTimeTypeArbitraryGeneratorAffectsField() { // given Instant expected = Instant.now(); FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin( new JqwikPlugin().javaTimeTypeArbitraryGenerator( new JavaTimeTypeArbitraryGenerator() { @@ -203,12 +197,11 @@ public InstantArbitrary instants() { then(actual).isIn(null, expected); } - @Property + @Test void javaTimeArbitraryResolver() { // given Instant expected = Instant.now(); FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin( new JqwikPlugin().javaTimeArbitraryResolver( new JavaTimeArbitraryResolver() { @@ -231,12 +224,11 @@ public Arbitrary instants( then(actual).isEqualTo(expected); } - @Property + @Test void javaTimeArbitraryResolverAffectsField() { // given Instant expected = Instant.now(); FixtureMonkey sut = FixtureMonkey.builder() - .plugin(new JavaNodeTreeAdapterPlugin()) .plugin( new JqwikPlugin().javaTimeArbitraryResolver( new JavaTimeArbitraryResolver() { diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionPropertySelectorTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionPropertySelectorTest.java similarity index 86% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionPropertySelectorTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionPropertySelectorTest.java index 78ec3f8c2e..86a73a177c 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionPropertySelectorTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionPropertySelectorTest.java @@ -16,19 +16,19 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; import java.util.List; -import net.jqwik.api.Property; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.NestedSimpleObject; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.StringPair; import com.navercorp.fixturemonkey.api.introspector.FieldReflectionArbitraryIntrospector; import com.navercorp.fixturemonkey.api.type.TypeReference; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.NestedSimpleObject; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.StringPair; class ValueProjectionPropertySelectorTest { @@ -37,10 +37,9 @@ class ValueProjectionPropertySelectorTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void setAllFieldsWithWildcard() { StringPair actual = SUT.giveMeBuilder(StringPair.class).set("*", "str").sample(); @@ -48,7 +47,7 @@ void setAllFieldsWithWildcard() { then(actual.getValue2()).isEqualTo("str"); } - @Property + @Test void wildcardDoesNotOverrideExplicitSet() { StringPair actual = SUT.giveMeBuilder(StringPair.class).set("*", "wildcard").set("value1", "explicit").sample(); @@ -56,7 +55,7 @@ void wildcardDoesNotOverrideExplicitSet() { then(actual.getValue2()).isEqualTo("wildcard"); } - @Property + @Test void setNestedWildcard() { NestedSimpleObject actual = SUT.giveMeBuilder(NestedSimpleObject.class) .set("object.*", "nested-wildcard") @@ -65,7 +64,7 @@ void setNestedWildcard() { then(actual.getObject().getStr()).isEqualTo("nested-wildcard"); } - @Property + @Test void wildcardWithContainerElements() { List actual = SUT.giveMeBuilder(new TypeReference>() { }) diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionStrictModeTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionStrictModeTest.java similarity index 84% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionStrictModeTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionStrictModeTest.java index 3d05a3cb06..9606a1dce5 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionStrictModeTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionStrictModeTest.java @@ -16,15 +16,15 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.thenNoException; -import net.jqwik.api.Property; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.NestedStringList; import com.navercorp.fixturemonkey.api.introspector.FieldReflectionArbitraryIntrospector; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.NestedStringList; class ValueProjectionStrictModeTest { @@ -33,26 +33,23 @@ class ValueProjectionStrictModeTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void notStrictModeSetWrongExpressionDoesNotThrows() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); thenNoException().isThrownBy(() -> sut.giveMeBuilder(String.class).set("nonExistentField", 0).sample()); } - @Property + @Test void notStrictModeSizeWrongExpressionDoesNotThrows() { FixtureMonkey sut = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); thenNoException().isThrownBy(() -> diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionThenApplyTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionThenApplyTest.java similarity index 87% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionThenApplyTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionThenApplyTest.java index 868d4bbd9b..b146349a95 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionThenApplyTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionThenApplyTest.java @@ -16,19 +16,19 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; -import net.jqwik.api.Property; +import org.junit.jupiter.api.Test; import com.navercorp.fixturemonkey.ArbitraryBuilder; import com.navercorp.fixturemonkey.FixtureMonkey; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.Order; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.SimpleListObject; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.SimpleStringObject; -import com.navercorp.fixturemonkey.adapter.ValueProjectionAssembleSpecs.StringValue; import com.navercorp.fixturemonkey.api.introspector.FieldReflectionArbitraryIntrospector; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.Order; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.SimpleListObject; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.SimpleStringObject; +import com.navercorp.fixturemonkey.test.ValueProjectionAssembleSpecs.StringValue; class ValueProjectionThenApplyTest { @@ -37,10 +37,9 @@ class ValueProjectionThenApplyTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE) .defaultNotNull(true) - .plugin(new JavaNodeTreeAdapterPlugin()) .build(); - @Property + @Test void thenApplyTransformsValue() { StringValue actual = SUT.giveMeBuilder(StringValue.class) .set("value", "original") @@ -50,7 +49,7 @@ void thenApplyTransformsValue() { then(actual.getValue()).isEqualTo("original-modified"); } - @Property + @Test void thenApplyWithNestedObject() { Order actual = SUT.giveMeBuilder(Order.class) .set("orderId", "ORD-001") @@ -62,7 +61,7 @@ void thenApplyWithNestedObject() { then(actual.getProduct().getName()).isEqualTo("Initial-Updated"); } - @Property + @Test void setNestedAndThenApply() { Order actual = SUT.giveMeBuilder(Order.class) .set("orderId", "ORD-001") @@ -75,7 +74,7 @@ void setNestedAndThenApply() { then(actual.getProduct().getName()).isEqualTo("Product-Q10"); } - @Property + @Test void apply() { String actual = SUT.giveMeBuilder(SimpleListObject.class) .set("str", "set") @@ -87,7 +86,7 @@ void apply() { then(actual).isEqualTo("set"); } - @Property + @Test void applyNotAffectedManipulatorsAfterApply() { String actual = SUT.giveMeBuilder(SimpleListObject.class) .set("str", "set") @@ -100,7 +99,7 @@ void applyNotAffectedManipulatorsAfterApply() { then(actual).isEqualTo("set"); } - @Property + @Test void acceptIfAlwaysTrue() { String actual = SUT.giveMeBuilder(SimpleStringObject.class) .acceptIf(it -> true, builder -> builder.set("str", "set")) @@ -110,7 +109,7 @@ void acceptIfAlwaysTrue() { then(actual).isEqualTo("set"); } - @Property + @Test void acceptIf() { String actual = SUT.giveMeBuilder(SimpleListObject.class) .set("str", "set") @@ -122,7 +121,7 @@ void acceptIf() { then(actual).isEqualTo("set"); } - @Property + @Test void applySetElementNull() { String actual = SUT.giveMeBuilder(SimpleListObject.class) .thenApply((obj, builder) -> builder.size("strList", 1).setNull("strList[0]")) @@ -133,7 +132,7 @@ void applySetElementNull() { then(actual).isNull(); } - @Property(tries = 1) + @Test void applySampleTwiceReturnsDiff() { ArbitraryBuilder builder = SUT.giveMeBuilder(SimpleStringObject.class).thenApply( (obj, b) -> { diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionUnitTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionUnitTest.java similarity index 94% rename from fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionUnitTest.java rename to fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionUnitTest.java index 2ac5dbac11..ecc09967a1 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/adapter/ValueProjectionUnitTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/ValueProjectionUnitTest.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.navercorp.fixturemonkey.adapter; +package com.navercorp.fixturemonkey.test; import static org.assertj.core.api.BDDAssertions.then; @@ -27,9 +27,9 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; -import net.jqwik.api.Property; +import org.junit.jupiter.api.Test; -import com.navercorp.fixturemonkey.adapter.projection.ValueProjection; +import com.navercorp.fixturemonkey.projection.ValueProjection; import com.navercorp.objectfarm.api.expression.PathExpression; import com.navercorp.objectfarm.api.node.ContainerSizeResolver; import com.navercorp.objectfarm.api.node.FixedContainerSizeResolver; @@ -62,7 +62,7 @@ class ValueProjectionUnitTest { .containerSizeResolver(FIXED_SIZE_RESOLVER) .build(); - @Property(tries = 1) + @Test void buildWithPut() { // given JvmNodeTree tree = createTree(new JavaType(SimpleObject.class)); @@ -78,7 +78,7 @@ void buildWithPut() { then(projection.size()).isEqualTo(2); } - @Property(tries = 1) + @Test void buildWithPutByPathExpression() { // given JvmNodeTree tree = createTree(new JavaType(SimpleObject.class)); @@ -96,7 +96,7 @@ void buildWithPutByPathExpression() { then(projection.get(valueNode)).isEqualTo(100); } - @Property(tries = 1) + @Test void buildWithPutByPathString() { // given JvmNodeTree tree = createTree(new JavaType(SimpleObject.class)); @@ -114,7 +114,7 @@ void buildWithPutByPathString() { then(projection.get(valueNode)).isEqualTo(200); } - @Property(tries = 1) + @Test void putByPathWithUnresolvablePathStoresIt() { // given JvmNodeTree tree = createTree(new JavaType(SimpleObject.class)); @@ -128,7 +128,7 @@ void putByPathWithUnresolvablePathStoresIt() { then(projection.getUnresolvedNonWildcardPaths()).containsExactly("$.nonexistent"); } - @Property(tries = 1) + @Test void allowNullValues() { // given JvmNodeTree tree = createTree(new JavaType(SimpleObject.class)); @@ -142,7 +142,7 @@ void allowNullValues() { then(projection.get(nameNode)).isNull(); } - @Property(tries = 1) + @Test void getExistingNode() { // given JvmNodeTree tree = createTree(new JavaType(SimpleObject.class)); @@ -157,7 +157,7 @@ void getExistingNode() { then(value).isEqualTo("Test"); } - @Property(tries = 1) + @Test void getNonExistingNode() { // given JvmNodeTree tree = createTree(new JavaType(SimpleObject.class)); @@ -173,7 +173,7 @@ void getNonExistingNode() { then(value).isNull(); } - @Property(tries = 1) + @Test void getByPathExpression() { // given JvmNodeTree tree = createTree(new JavaType(SimpleObject.class)); @@ -188,7 +188,7 @@ void getByPathExpression() { then(value).isEqualTo("PathTest"); } - @Property(tries = 1) + @Test void getByPathString() { // given JvmNodeTree tree = createTree(new JavaType(SimpleObject.class)); @@ -203,7 +203,7 @@ void getByPathString() { then(value).isEqualTo("StringPathTest"); } - @Property(tries = 1) + @Test void getByInvalidPath() { // given JvmNodeTree tree = createTree(new JavaType(SimpleObject.class)); @@ -218,7 +218,7 @@ void getByInvalidPath() { then(value).isNull(); } - @Property(tries = 1) + @Test void forEachIteratesAll() { // given JvmNodeTree tree = createTree(new JavaType(SimpleObject.class)); @@ -236,7 +236,7 @@ void forEachIteratesAll() { then(count.get()).isEqualTo(2); } - @Property(tries = 1) + @Test void filterByPredicate() { // given JvmNodeTree tree = createTree(new JavaType(SimpleObject.class)); @@ -256,7 +256,7 @@ void filterByPredicate() { then(nonNullNodes).contains(nameNode); } - @Property(tries = 1) + @Test void filterNoMatch() { // given JvmNodeTree tree = createTree(new JavaType(SimpleObject.class)); @@ -271,7 +271,7 @@ void filterNoMatch() { then(result).isEmpty(); } - @Property(tries = 1) + @Test void sizeReturnsCount() { // given JvmNodeTree tree = createTree(new JavaType(SimpleObject.class)); @@ -284,7 +284,7 @@ void sizeReturnsCount() { then(projection.size()).isEqualTo(2); } - @Property(tries = 1) + @Test void isEmptyForEmpty() { // given JvmNodeTree tree = createTree(new JavaType(SimpleObject.class)); @@ -295,7 +295,7 @@ void isEmptyForEmpty() { then(projection.isEmpty()).isTrue(); } - @Property(tries = 1) + @Test void isEmptyForNonEmpty() { // given JvmNodeTree tree = createTree(new JavaType(SimpleObject.class)); @@ -307,7 +307,7 @@ void isEmptyForNonEmpty() { then(projection.isEmpty()).isFalse(); } - @Property(tries = 1) + @Test void containsNodeForExisting() { // given JvmNodeTree tree = createTree(new JavaType(SimpleObject.class)); @@ -319,7 +319,7 @@ void containsNodeForExisting() { then(projection.containsNode(nameNode)).isTrue(); } - @Property(tries = 1) + @Test void containsNodeForNonExisting() { // given JvmNodeTree tree = createTree(new JavaType(SimpleObject.class)); @@ -332,7 +332,7 @@ void containsNodeForNonExisting() { then(projection.containsNode(valueNode)).isFalse(); } - @Property(tries = 1) + @Test void fromStringPathMap() { // given JvmNodeTree tree = createTree(new JavaType(SimpleObject.class)); @@ -351,7 +351,7 @@ void fromStringPathMap() { then(projection.get(valueNode)).isEqualTo(888); } - @Property(tries = 1) + @Test void fromStringPathMapKeepsUnresolvablePaths() { // given JvmNodeTree tree = createTree(new JavaType(SimpleObject.class)); @@ -371,7 +371,7 @@ void fromStringPathMapKeepsUnresolvablePaths() { then(projection.getUnresolvedNonWildcardPaths()).containsExactly("$.invalid"); } - @Property(tries = 1) + @Test void listElementPaths() { // given JvmNodeTree listTree = createTree(new JavaType(ListContainer.class)); diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/util/StringUtils.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/util/StringUtils.java deleted file mode 100644 index 3c962a23b1..0000000000 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/util/StringUtils.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.navercorp.fixturemonkey.util; - -public abstract class StringUtils { - public static boolean isBlank(String str) { - return str == null || str.trim().isEmpty(); - } - - public static boolean isNotBlank(String str) { - return !isBlank(str); - } -} diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/util/StringUtilsTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/util/StringUtilsTest.java deleted file mode 100644 index 47bf84696f..0000000000 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/util/StringUtilsTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.navercorp.fixturemonkey.util; - -import static org.assertj.core.api.BDDAssertions.then; - -import net.jqwik.api.ForAll; -import net.jqwik.api.Property; -import net.jqwik.api.constraints.NotBlank; - -class StringUtilsTest { - @Property(tries = 1) - void isBlank(@ForAll @NotBlank String actual) { - then(StringUtils.isBlank(actual)).isFalse(); - } - - @Property(tries = 1) - void isNotBlank(@ForAll @NotBlank String actual) { - then(StringUtils.isNotBlank(actual)).isTrue(); - } -} diff --git a/object-farm-api/src/main/java/com/navercorp/objectfarm/api/node/SeedState.java b/object-farm-api/src/main/java/com/navercorp/objectfarm/api/node/SeedState.java index e6acc9596e..225540fd68 100644 --- a/object-farm-api/src/main/java/com/navercorp/objectfarm/api/node/SeedState.java +++ b/object-farm-api/src/main/java/com/navercorp/objectfarm/api/node/SeedState.java @@ -47,8 +47,9 @@ * @see SeedSnapshot */ public final class SeedState { - private final long initialSeed; + private volatile long initialSeed; private final AtomicLong counter; + private final AtomicLong containerSizeCounter; /** * Creates a new SeedState with the specified initial seed. @@ -58,6 +59,24 @@ public final class SeedState { public SeedState(long initialSeed) { this.initialSeed = initialSeed; this.counter = new AtomicLong(0); + this.containerSizeCounter = new AtomicLong(0); + } + + /** + * Resets the seed and counters for a new generation cycle. + * + *

    Sets {@code initialSeed} to the given value and resets all sequence + * counters to {@code 0}. Used at the start of a top-level generation call + * (e.g. {@code adapt()}) so that callers (such as a JUnit {@code @Seed} + * extension) that change the global seed between runs see deterministic + * snapshot sequences starting from {@code 0}.

    + * + * @param newSeed the new seed value + */ + public void reset(long newSeed) { + this.initialSeed = newSeed; + this.counter.set(0); + this.containerSizeCounter.set(0); } /** @@ -72,6 +91,20 @@ public SeedSnapshot snapshot() { return new SeedSnapshot(initialSeed, counter.getAndIncrement()); } + /** + * Creates an immutable snapshot from a counter dedicated to container size resolution. + * + *

    This counter is independent from {@link #snapshot()}, so cache hit/miss patterns + * elsewhere in the adapt pipeline do not perturb container sizes. Two FixtureMonkey + * instances created with the same seed see the same sequence on this counter and + * produce identical container sizes for identical call patterns.

    + * + * @return a new immutable SeedSnapshot whose sequence is the next container-size value + */ + public SeedSnapshot containerSizeSnapshot() { + return new SeedSnapshot(initialSeed, containerSizeCounter.getAndIncrement()); + } + /** * Creates an immutable snapshot at a specific sequence number * without incrementing the internal counter. diff --git a/object-farm-api/src/main/java/com/navercorp/objectfarm/api/tree/JvmNodeCandidateTree.java b/object-farm-api/src/main/java/com/navercorp/objectfarm/api/tree/JvmNodeCandidateTree.java index c53243fae7..1c264b27e3 100644 --- a/object-farm-api/src/main/java/com/navercorp/objectfarm/api/tree/JvmNodeCandidateTree.java +++ b/object-farm-api/src/main/java/com/navercorp/objectfarm/api/tree/JvmNodeCandidateTree.java @@ -373,7 +373,15 @@ private boolean isContainerType(JvmType jvmType) { // Only treat standard Java library collections as container types // Custom classes that implement Collection/Map should be treated as regular objects boolean isCollectionOrMap = Collection.class.isAssignableFrom(rawType) || Map.class.isAssignableFrom(rawType); - return isCollectionOrMap && Types.isJavaType(rawType); + if (isCollectionOrMap) { + return Types.isJavaType(rawType); + } + // For non-Collection/Map types, defer to registered JvmContainerNodeGenerators + // (e.g., Pair, Triple). Without this, custom container types' children would be + // generated via PropertyGenerator in the candidate tree, which may produce an + // unordered result for Kotlin reflection. Collection/Map user classes are + // intentionally excluded above so their declared fields are processed normally. + return jvmNodeContext.isContainerType(jvmType); } /** diff --git a/object-farm-api/src/main/java/com/navercorp/objectfarm/api/tree/JvmNodeTreeTransformer.java b/object-farm-api/src/main/java/com/navercorp/objectfarm/api/tree/JvmNodeTreeTransformer.java index cdea374100..25f4315409 100644 --- a/object-farm-api/src/main/java/com/navercorp/objectfarm/api/tree/JvmNodeTreeTransformer.java +++ b/object-farm-api/src/main/java/com/navercorp/objectfarm/api/tree/JvmNodeTreeTransformer.java @@ -320,10 +320,31 @@ private void expandContainerElements( } List resolvedElements = resolveContainerElementTypes(elements, currentPath); - ctx.allNodes.addAll(resolvedElements); - ctx.parentChildMap.put(containerNode, resolvedElements); + // Drop elements whose type would form a cycle (e.g. List nested inside Self). + // Without this, each element becomes an unexpanded recursion-break leaf and the assembler + // later asks the introspector to construct it with no children — Kotlin non-nullable + // constructor parameters reject the resulting null arguments. Truncating the container + // to the elements we can actually build keeps the recursion bounded. + List retainedElements = new ArrayList<>(resolvedElements.size()); for (JvmNode element : resolvedElements) { + Class elementRawType = element.getConcreteType().getRawType(); + boolean wouldCycle = ancestors.contains(elementRawType) + && (expansionContext == null + || !expansionContext.shouldExpandPath(currentPath, elementRawType, ancestors)); + if (!wouldCycle) { + retainedElements.add(element); + } + } + + if (retainedElements.isEmpty()) { + return; + } + + ctx.allNodes.addAll(retainedElements); + ctx.parentChildMap.put(containerNode, retainedElements); + + for (JvmNode element : retainedElements) { ctx.nodeToParent.put(element, containerNode); Integer index = element.getIndex(); PathExpression elementPath = index != null ? currentPath.index(index) : currentPath; diff --git a/object-farm-api/src/main/java/com/navercorp/objectfarm/api/type/GenericType.java b/object-farm-api/src/main/java/com/navercorp/objectfarm/api/type/GenericType.java index 5c5d4364ea..27c4f3597b 100644 --- a/object-farm-api/src/main/java/com/navercorp/objectfarm/api/type/GenericType.java +++ b/object-farm-api/src/main/java/com/navercorp/objectfarm/api/type/GenericType.java @@ -71,7 +71,12 @@ public Type getOwnerType() { @Override public int hashCode() { - return Objects.hash(containerType, ownerType, Arrays.hashCode(typeArguments)); + // Matches the formula used by sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl + // so that this class hashes equal to JDK-supplied ParameterizedTypes representing the + // same type. Required for cache lookups keyed by Type. + return Arrays.hashCode(typeArguments) + ^ Objects.hashCode(ownerType) + ^ Objects.hashCode(containerType); } @Override diff --git a/object-farm-api/src/main/java/com/navercorp/objectfarm/api/type/JavaType.java b/object-farm-api/src/main/java/com/navercorp/objectfarm/api/type/JavaType.java index 55440a0692..7e2e3317f4 100644 --- a/object-farm-api/src/main/java/com/navercorp/objectfarm/api/type/JavaType.java +++ b/object-farm-api/src/main/java/com/navercorp/objectfarm/api/type/JavaType.java @@ -20,6 +20,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedType; +import java.lang.reflect.Array; import java.lang.reflect.GenericArrayType; import java.lang.reflect.Type; import java.util.Arrays; @@ -35,32 +36,40 @@ public final class JavaType implements JvmType { private final List typeVariables; private final List annotations; @Nullable - private final AnnotatedType annotatedType; + private final JvmType componentType; + @Nullable + private final Boolean nullable; private int cachedHashCode; public JavaType(Class rawType) { - this(rawType, Collections.emptyList(), Collections.emptyList(), null); + this(rawType, Collections.emptyList(), Collections.emptyList()); } public JavaType(Class rawType, List typeVariables, List annotations) { - this.rawType = rawType; - this.typeVariables = typeVariables; - this.annotations = annotations; - this.annotatedType = null; + this(rawType, typeVariables, annotations, deriveComponentType(rawType, typeVariables), null); } - // for backward compatibility - @Deprecated public JavaType( Class rawType, - List typeVariables, + List typeVariables, List annotations, - @Nullable AnnotatedType annotatedType + @Nullable Boolean nullable + ) { + this(rawType, typeVariables, annotations, deriveComponentType(rawType, typeVariables), nullable); + } + + public JavaType( + Class rawType, + List typeVariables, + List annotations, + @Nullable JvmType componentType, + @Nullable Boolean nullable ) { this.rawType = rawType; this.typeVariables = typeVariables; this.annotations = annotations; - this.annotatedType = annotatedType; + this.componentType = componentType; + this.nullable = nullable; } public JavaType(ObjectTypeReference typeReference) { @@ -71,11 +80,10 @@ public JavaType(ObjectTypeReference typeReference) { this.typeVariables = Types.getGenericsTypes(resolvedType).stream() .map(annotatedType -> new JavaType(Types.toTypeReference(annotatedType))) .collect(Collectors.toList()); + this.componentType = resolveComponentType(resolvedType, this.rawType); this.annotations = Arrays.stream(resolvedType.getAnnotations()) .collect(Collectors.toList()); - // Don't store the annotatedType if it contains wildcards in type arguments, - // so that JvmNodePropertyAdapter will build a new AnnotatedType from resolved components - this.annotatedType = Types.containsWildcardTypeArguments(resolvedType) ? null : resolvedType; + this.nullable = null; } private static Class resolveRawType(AnnotatedType annotatedType) { @@ -84,11 +92,38 @@ private static Class resolveRawType(AnnotatedType annotatedType) { // For GenericArrayType, we need the array class, not the component class GenericArrayType genericArrayType = (GenericArrayType)type; Class componentClass = Types.getActualType(genericArrayType.getGenericComponentType()); - return java.lang.reflect.Array.newInstance(componentClass, 0).getClass(); + return Array.newInstance(componentClass, 0).getClass(); } return Types.getActualType(annotatedType); } + @Nullable + private static JvmType resolveComponentType(AnnotatedType annotatedType, Class rawType) { + Type type = annotatedType.getType(); + if (type instanceof GenericArrayType) { + Type genericComponentType = ((GenericArrayType)type).getGenericComponentType(); + return new JavaType( + Types.toTypeReference(Types.generateAnnotatedTypeWithoutAnnotation(genericComponentType) + ) + ); + } + if (rawType.isArray()) { + return new JavaType(rawType.getComponentType()); + } + return null; + } + + @Nullable + private static JvmType deriveComponentType(Class rawType, List typeVariables) { + if (!rawType.isArray()) { + return null; + } + Class componentClass = rawType.getComponentType(); + // Preserve the legacy convention: when constructing an array type with typeVariables, + // those typeVariables represent the component type's generics. + return new JavaType(componentClass, typeVariables, Collections.emptyList()); + } + @Override public Class getRawType() { return rawType; @@ -104,26 +139,16 @@ public List getAnnotations() { return annotations; } - /** - * It is for backward compatibility. Recommend to use the {@link #getRawType()} or {@link #getTypeVariables()} - */ - @Deprecated @Override @Nullable - @SuppressWarnings("override.return") - public AnnotatedType getAnnotatedType() { - return annotatedType; + public Boolean getNullable() { + return nullable; } @Override @Nullable public JvmType getComponentType() { - if (!rawType.isArray()) { - return null; - } - Class componentClass = rawType.getComponentType(); - // For array types, typeVariables holds the component type's type variables - return new JavaType(componentClass, typeVariables, Collections.emptyList()); + return componentType; } @Override @@ -134,14 +159,15 @@ public boolean equals(@Nullable Object obj) { JavaType javaType = (JavaType)obj; return Objects.equals(rawType, javaType.rawType) && Objects.equals(typeVariables, javaType.typeVariables) - && Objects.equals(annotations, javaType.annotations); + && Objects.equals(annotations, javaType.annotations) + && Objects.equals(componentType, javaType.componentType); } @Override public int hashCode() { int hash = cachedHashCode; if (hash == 0) { - hash = Objects.hash(rawType, typeVariables, annotations); + hash = Objects.hash(rawType, typeVariables, annotations, componentType); if (hash == 0) { hash = 1; } diff --git a/object-farm-api/src/main/java/com/navercorp/objectfarm/api/type/JvmType.java b/object-farm-api/src/main/java/com/navercorp/objectfarm/api/type/JvmType.java index 8c9f47dd8d..ea15902d0c 100644 --- a/object-farm-api/src/main/java/com/navercorp/objectfarm/api/type/JvmType.java +++ b/object-farm-api/src/main/java/com/navercorp/objectfarm/api/type/JvmType.java @@ -19,7 +19,6 @@ package com.navercorp.objectfarm.api.type; import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedType; import java.util.Collections; import java.util.List; @@ -103,16 +102,4 @@ default Boolean getNullable() { return null; } - /** - * Returns the AnnotatedType representation of this JvmType. - * - * @deprecated This method is deprecated and will be removed in future versions. - * Use {@link #getRawType()} and {@link #getAnnotations()} instead. - * @return the AnnotatedType representation - * @throws UnsupportedOperationException as this method is not supported - */ - @Deprecated - default AnnotatedType getAnnotatedType() { - throw new UnsupportedOperationException("This method is not supported for JvmType"); - } } diff --git a/object-farm-api/src/main/java/com/navercorp/objectfarm/api/type/JvmTypes.java b/object-farm-api/src/main/java/com/navercorp/objectfarm/api/type/JvmTypes.java index 6173503a95..dc1c0e79b8 100644 --- a/object-farm-api/src/main/java/com/navercorp/objectfarm/api/type/JvmTypes.java +++ b/object-farm-api/src/main/java/com/navercorp/objectfarm/api/type/JvmTypes.java @@ -32,11 +32,26 @@ public abstract class JvmTypes { public static JvmType resolveJvmType(JvmType parentType, Type type, List annotations) { if (!Types.isGenericType(type)) { - return new JavaType(Types.getActualType(type)); + return new JavaType(Types.getActualType(type), Collections.emptyList(), annotations); } if (type instanceof TypeVariable) { - return resolveTypeVariable(parentType, (TypeVariable)type); + JvmType resolved = resolveTypeVariable(parentType, (TypeVariable)type); + if (annotations.isEmpty()) { + return resolved; + } + List merged = new ArrayList<>(resolved.getAnnotations()); + for (Annotation annotation : annotations) { + if (!merged.contains(annotation)) { + merged.add(annotation); + } + } + return new JavaType( + resolved.getRawType(), + resolved.getTypeVariables(), + merged, + resolved.getNullable() + ); } List typeArguments = resolveTypeArguments(parentType, type); @@ -50,13 +65,113 @@ public static JvmType resolveJvmType(JvmType parentType, Type type, List + * The TypeVariable is matched by its declaring class' type parameters. If the immediate + * parent has no type variables (e.g., a concrete class extending a generic superclass), + * walks up the superclass chain. */ private static JvmType resolveTypeVariable(JvmType parentType, TypeVariable typeVariable) { + Class declaringClass = null; + java.lang.reflect.GenericDeclaration declaration = typeVariable.getGenericDeclaration(); + if (declaration instanceof Class) { + declaringClass = (Class)declaration; + } + List parentTypeVariables = parentType.getTypeVariables(); - if (parentTypeVariables.isEmpty()) { - return new JavaType(Object.class); + Class parentRawType = parentType.getRawType(); + + // If the parent matches the declaring class directly, look up by index. + if (declaringClass != null && declaringClass == parentRawType && !parentTypeVariables.isEmpty()) { + TypeVariable[] declaredVars = declaringClass.getTypeParameters(); + for (int i = 0; i < declaredVars.length && i < parentTypeVariables.size(); i++) { + if (declaredVars[i].getName().equals(typeVariable.getName())) { + return parentTypeVariables.get(i); + } + } + } + + // Walk up the superclass/interface chain to find a parameterized super that + // declares the TypeVariable and resolves it via the concrete subtype. + if (declaringClass != null && parentRawType != null) { + JvmType resolved = resolveTypeVariableViaSuperType(parentRawType, declaringClass, typeVariable); + if (resolved != null) { + return resolved; + } + } + + // Fallback: return the first parent type variable if any (legacy behavior). + if (!parentTypeVariables.isEmpty()) { + return parentTypeVariables.get(0); + } + return new JavaType(Object.class); + } + + @Nullable + private static JvmType resolveTypeVariableViaSuperType( + Class startType, + Class declaringClass, + TypeVariable typeVariable + ) { + // Walk superclass first, then interfaces. + Type genericSuper = startType.getGenericSuperclass(); + Class rawSuper = startType.getSuperclass(); + if (genericSuper instanceof ParameterizedType && rawSuper != null) { + JvmType result = matchTypeVariableInParameterizedSuper( + (ParameterizedType)genericSuper, rawSuper, declaringClass, typeVariable + ); + if (result != null) { + return result; + } + } + if (rawSuper != null && rawSuper != Object.class) { + JvmType resolved = resolveTypeVariableViaSuperType(rawSuper, declaringClass, typeVariable); + if (resolved != null) { + return resolved; + } + } + Type[] genericInterfaces = startType.getGenericInterfaces(); + Class[] rawInterfaces = startType.getInterfaces(); + for (int i = 0; i < genericInterfaces.length; i++) { + if (genericInterfaces[i] instanceof ParameterizedType) { + JvmType result = matchTypeVariableInParameterizedSuper( + (ParameterizedType)genericInterfaces[i], + rawInterfaces[i], + declaringClass, + typeVariable + ); + if (result != null) { + return result; + } + } + JvmType resolved = resolveTypeVariableViaSuperType(rawInterfaces[i], declaringClass, typeVariable); + if (resolved != null) { + return resolved; + } + } + return null; + } + + @Nullable + private static JvmType matchTypeVariableInParameterizedSuper( + ParameterizedType parameterizedSuper, + Class rawSuper, + Class declaringClass, + TypeVariable typeVariable + ) { + if (rawSuper != declaringClass) { + return null; + } + TypeVariable[] declaredVars = declaringClass.getTypeParameters(); + Type[] actualArgs = parameterizedSuper.getActualTypeArguments(); + for (int i = 0; i < declaredVars.length && i < actualArgs.length; i++) { + if (declaredVars[i].getName().equals(typeVariable.getName())) { + if (actualArgs[i] instanceof Class) { + return new JavaType((Class)actualArgs[i]); + } + return new JavaType(Types.getActualType(actualArgs[i])); + } } - return parentTypeVariables.get(0); + return null; } /** diff --git a/object-farm-api/src/test/java/com/navercorp/objectfarm/api/type/JavaTypeTest.java b/object-farm-api/src/test/java/com/navercorp/objectfarm/api/type/JavaTypeTest.java new file mode 100644 index 0000000000..e73a7568c0 --- /dev/null +++ b/object-farm-api/src/test/java/com/navercorp/objectfarm/api/type/JavaTypeTest.java @@ -0,0 +1,141 @@ +/* + * Fixture Monkey + * + * Copyright (c) 2021-present NAVER Corp. + * + * 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. + */ + +package com.navercorp.objectfarm.api.type; + +import static org.assertj.core.api.BDDAssertions.then; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.Test; + +class JavaTypeTest { + @Test + void componentType_isNullForNonArrayType() { + // given + JvmType type = new JavaType(new ObjectTypeReference>() { + }); + + // then + then(type.getComponentType()).isNull(); + } + + @Test + void componentType_preservesRawComponentForPlainArrayClass() { + // given + JvmType type = new JavaType(String[].class); + + // when + JvmType componentType = type.getComponentType(); + + // then + then(componentType).isNotNull(); + then(componentType.getRawType()).isEqualTo(String.class); + } + + @Test + void componentType_preservesGenericsForGenericArrayType() { + // given + JvmType arrayType = new JavaType(new ObjectTypeReference[]>() { + }); + + // when + JvmType componentType = arrayType.getComponentType(); + + // then + then(arrayType.getRawType()).isEqualTo(List[].class); + then(componentType).isNotNull(); + then(componentType.getRawType()).isEqualTo(List.class); + then(componentType.getTypeVariables()).hasSize(1); + then(componentType.getTypeVariables().get(0).getRawType()).isEqualTo(String.class); + } + + @Test + void componentType_preservesNestedGenericsForGenericArrayType() { + // given + JvmType arrayType = new JavaType(new ObjectTypeReference[]>() { + }); + + // when + JvmType componentType = arrayType.getComponentType(); + + // then + then(arrayType.getRawType()).isEqualTo(Map[].class); + then(componentType).isNotNull(); + then(componentType.getRawType()).isEqualTo(Map.class); + then(componentType.getTypeVariables()).hasSize(2); + then(componentType.getTypeVariables().get(0).getRawType()).isEqualTo(String.class); + then(componentType.getTypeVariables().get(1).getRawType()).isEqualTo(Integer.class); + } + + @Test + void componentType_explicitlyProvided_isStoredAndReturned() { + // given + JvmType explicitComponent = new JavaType( + List.class, + Collections.singletonList(new JavaType(Integer.class)), + Collections.emptyList() + ); + + // when + JvmType arrayType = new JavaType( + List[].class, + Collections.emptyList(), + Collections.emptyList(), + explicitComponent, + null + ); + + // then + then(arrayType.getComponentType()).isSameAs(explicitComponent); + } + + @Test + void equals_considersComponentType() { + // given + JvmType componentA = new JavaType( + List.class, + Collections.singletonList(new JavaType(String.class)), + Collections.emptyList() + ); + JvmType componentB = new JavaType( + List.class, + Collections.singletonList(new JavaType(Integer.class)), + Collections.emptyList() + ); + JvmType arrayA = new JavaType( + List[].class, + Collections.emptyList(), + Collections.emptyList(), + componentA, + null + ); + JvmType arrayB = new JavaType( + List[].class, + Collections.emptyList(), + Collections.emptyList(), + componentB, + null + ); + + // then + then(arrayA).isNotEqualTo(arrayB); + } +}