Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

package com.navercorp.fixturemonkey.adapter.projection;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
Expand Down Expand Up @@ -297,8 +298,17 @@ private CombinableArbitrary<?> assembleNode(
);
applyDecomposeResult(decomposeResult, state);
if (decomposeResult.hasEarlyReturn()) {
Object earlyValue = decomposeResult.getEarlyReturnValue();

// Apply wildcard overrides to container elements when a wildcard has higher order
if (isCurrentTypeContainer && earlyValue != null && !state.wildcardEntries.isEmpty()) {
earlyValue = applyWildcardOverridesToContainer(
earlyValue, currentPath, parentOrder, state
);
}

return wrapValueWithFiltersAndCustomizers(
decomposeResult.getEarlyReturnValue(),
earlyValue,
currentPath,
currentRawType,
state
Expand Down Expand Up @@ -577,6 +587,7 @@ private CombinableArbitrary<?> assembleNode(
result = options.getDefaultArbitraryGenerator().generate(context);
}


result = applyFilters(result, currentPath, currentRawType, state);
result = applyCustomizers(result, currentPath, state);

Expand Down Expand Up @@ -1970,9 +1981,9 @@ private boolean hasFieldLevelTypeSelectorSiblings(PathExpression rootTypePath, A
return null;
}
if (container.getClass().isArray()) {
int length = java.lang.reflect.Array.getLength(container);
int length = Array.getLength(container);
if (index >= 0 && index < length) {
return java.lang.reflect.Array.get(container, index);
return Array.get(container, index);
}
return null;
}
Expand Down Expand Up @@ -2098,6 +2109,66 @@ private static void applyDecomposeResult(DecomposeResult result, AssemblyState s
}
}

/**
* Applies wildcard overrides to container elements when a wildcard has a higher order
* than the container's own value. This handles the case where a container value is
* returned via earlyReturn (all decomposed elements match), but a wildcard like
* {@code $.values[*].values[*]} should override individual elements.
*/
private Object applyWildcardOverridesToContainer(
Object container,
PathExpression containerPath,
ValueOrder containerOrder,
AssemblyState state
) {
if (container instanceof List) {
List<?> list = (List<?>)container;
List<@Nullable Object> result = null;
for (int i = 0; i < list.size(); i++) {
PathExpression elementPath = containerPath.index(i);
for (Map.Entry<PathExpression, ValueCandidate> entry : state.wildcardEntries) {
if (entry.getKey().matches(elementPath)
&& entry.getValue().order.compareTo(containerOrder) > 0) {
if (result == null) {
result = new ArrayList<>(list);
}
result.set(i, resolveLazyValue(entry.getValue().value, false, state));
break;
}
}
}
return result != null ? result : container;
} else if (container.getClass().isArray()) {
int length = Array.getLength(container);
boolean modified = false;
for (int i = 0; i < length; i++) {
PathExpression elementPath = containerPath.index(i);
for (Map.Entry<PathExpression, ValueCandidate> entry : state.wildcardEntries) {
if (entry.getKey().matches(elementPath)
&& entry.getValue().order.compareTo(containerOrder) > 0) {
if (!modified) {
Class<?> componentType = container.getClass().getComponentType();
if (componentType == null) {
break;
}
Object copy = Array.newInstance(componentType, length);
//noinspection SuspiciousSystemArraycopy
System.arraycopy(container, 0, copy, 0, length);
container = copy;
modified = true;
}
Object resolved = resolveLazyValue(entry.getValue().value, false, state);
if (resolved != null) {
Array.set(container, i, resolved);
}
break;
}
}
}
}
return container;
}

private @Nullable Object resolveLazyValue(@Nullable Object value, boolean isFromRegister, AssemblyState state) {
if (!(value instanceof LazyValueHolder)) {
return value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@
import com.navercorp.fixturemonkey.FixtureMonkey;
import com.navercorp.fixturemonkey.api.type.TypeReference;
import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.EnumObject;
import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.ListListStringObject;
import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.MapEntryWrapper;
import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.MapStringListObject;
import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.OptionalListStringObject;
import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.SimpleObject;
import com.navercorp.fixturemonkey.test.FixtureMonkeyTestSpecs.TwoEnum;

Expand Down Expand Up @@ -148,4 +151,52 @@ void sampleMapEntryWrapper() {
then(actual.getComplexEntry().getValue()).isNotNull();
}

@Property
void sampleNestedListList() {
// when
ListListStringObject actual = SUT.giveMeBuilder(ListListStringObject.class)
.size("values", 2)
.size("values[*]", 2)
.sample();

// then
then(actual.getValues()).hasSize(2);
for (List<String> inner : actual.getValues()) {
then(inner).hasSize(2);
for (String s : inner) {
then(s).isNotNull();
}
}
}

@Property
void sampleMapWithListValue() {
// when
MapStringListObject actual = SUT.giveMeBuilder(MapStringListObject.class)
.size("values", 2)
.sample();

// then
then(actual.getValues()).hasSize(2);
for (Map.Entry<String, List<String>> entry : actual.getValues().entrySet()) {
then(entry.getKey()).isNotNull();
then(entry.getValue()).isNotNull();
}
}

@Property
void sampleOptionalWithList() {
// when
OptionalListStringObject actual = SUT.giveMeBuilder(OptionalListStringObject.class)
.size("value", 2)
.sample();

// then
then(actual.getValue()).isPresent();
then(actual.getValue().get()).hasSize(2);
for (String s : actual.getValue().get()) {
then(s).isNotNull();
}
}

}
Loading
Loading