/*
* Copyright 2015-2017 Hewlett Packard Enterprise Development Company, L.P.
* Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
*/
package com.hp.autonomy.frontend.find.core.parametricfields;
import com.hp.autonomy.frontend.find.core.fields.FieldComparatorFactory;
import com.hp.autonomy.searchcomponents.core.fields.TagNameFactory;
import com.hp.autonomy.searchcomponents.core.parametricvalues.BucketingParams;
import com.hp.autonomy.searchcomponents.core.parametricvalues.ParametricRequest;
import com.hp.autonomy.searchcomponents.core.parametricvalues.ParametricRequestBuilder;
import com.hp.autonomy.searchcomponents.core.parametricvalues.ParametricValuesService;
import com.hp.autonomy.searchcomponents.core.search.QueryRestrictions;
import com.hp.autonomy.searchcomponents.core.search.QueryRestrictionsBuilder;
import com.hp.autonomy.types.requests.idol.actions.tags.FieldPath;
import com.hp.autonomy.types.requests.idol.actions.tags.QueryTagInfo;
import com.hp.autonomy.types.requests.idol.actions.tags.RangeInfo;
import lombok.Data;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Matchers;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.json.AutoConfigureJsonTesters;
import org.springframework.boot.test.autoconfigure.json.JsonTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.rules.SpringClassRule;
import org.springframework.test.context.junit4.rules.SpringMethodRule;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.hp.autonomy.frontend.find.core.parametricfields.AbstractParametricValuesControllerTest.ParametricRequestMatcher.matchesParametricRequest;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
@SuppressWarnings("SpringJavaAutowiredMembersInspection")
@JsonTest
@AutoConfigureJsonTesters(enabled = false)
public abstract class AbstractParametricValuesControllerTest<
C extends ParametricValuesController<Q, R, S, E>,
PS extends ParametricValuesService<R, Q, E>,
Q extends QueryRestrictions<S>,
QB extends QueryRestrictionsBuilder<Q, S, QB>,
R extends ParametricRequest<Q>,
RB extends ParametricRequestBuilder<R, Q, RB>,
S extends Serializable,
E extends Exception
> {
@ClassRule
public static final SpringClassRule SCR = new SpringClassRule();
@Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();
private final Function<ControllerArguments<PS, R, RB, Q, QB, S, E>, C> constructController;
private final Supplier<PS> mockService;
@MockBean
private FieldComparatorFactory fieldComparatorFactory;
@Autowired
private TagNameFactory tagNameFactory;
@Autowired
private ObjectFactory<RB> parametricRequestBuilderFactory;
@Autowired
private ObjectFactory<QB> queryRestrictionsBuilderFactory;
private PS parametricValuesService;
private C parametricValuesController;
protected AbstractParametricValuesControllerTest(final Function<ControllerArguments<PS, R, RB, Q, QB, S, E>, C> constructController, final Supplier<PS> mockService) {
this.constructController = constructController;
this.mockService = mockService;
}
@Before
public void setUp() {
when(fieldComparatorFactory.parametricFieldAndValuesComparator()).thenReturn(Comparator.comparing(QueryTagInfo::getId));
parametricValuesService = mockService.get();
parametricValuesController = constructController.apply(new ControllerArguments<>(parametricValuesService, queryRestrictionsBuilderFactory, parametricRequestBuilderFactory, fieldComparatorFactory));
}
@Test
public void getParametricValues() throws E {
final List<FieldPath> fieldNames = Stream.of("CATEGORY", "AUTHOR").map(tagNameFactory::getFieldPath).collect(Collectors.toList());
parametricValuesController.getParametricValues(
fieldNames,
1,
10,
null,
"cat",
"MATCH{ANIMAL}:CATEGORY",
Collections.emptyList(),
null,
null,
null,
null
);
verify(parametricValuesService).getParametricValues(argThat(matchesParametricRequest(fieldNames, "cat", "MATCH{ANIMAL}:CATEGORY")));
}
@Test
public void getDependentParametricValues() throws E {
parametricValuesController.getDependentParametricValues(
Collections.singletonList(tagNameFactory.getFieldPath("SomeParametricField")),
"Some query text",
null,
Collections.emptyList(),
null,
null,
0,
null
);
verify(parametricValuesService).getDependentParametricValues(Matchers.any());
}
@Test
public void getValueDetails() throws E {
parametricValuesController.getValueDetails(tagNameFactory.getFieldPath("SomeParametricField"), "Some query text", null, Collections.emptyList(), null, null, 0, null);
verify(parametricValuesService).getValueDetails(Matchers.any());
}
@Test
public void getParametricValuesInBuckets() throws UnsupportedEncodingException, E {
final String fieldName = "birth&death";
final RangeInfo rangeInfo = mock(RangeInfo.class);
final BucketingParams expectedBucketingParams = new BucketingParams(5, -0.5, 0.5);
when(parametricValuesService.getNumericParametricValuesInBuckets(Matchers.any(), Matchers.any())).thenAnswer(invocation -> {
@SuppressWarnings("unchecked")
final Map<FieldPath, BucketingParams> bucketingParamsPerField = invocation.getArgumentAt(1, Map.class);
final BucketingParams bucketingParams = bucketingParamsPerField.get(tagNameFactory.getFieldPath(fieldName));
return expectedBucketingParams.equals(bucketingParams)
? Collections.singletonList(rangeInfo)
: Collections.emptyList();
});
final RangeInfo output = parametricValuesController.getNumericParametricValuesInBucketsForField(
tagNameFactory.getFieldPath(fieldName),
expectedBucketingParams.getTargetNumberOfBuckets(),
expectedBucketingParams.getMin(),
expectedBucketingParams.getMax(),
"*",
"",
Collections.emptyList(),
null,
null,
0
);
assertThat(output, is(rangeInfo));
}
@Data
public static class ControllerArguments<
PS extends ParametricValuesService<R, Q, E>,
R extends ParametricRequest<Q>,
RB extends ParametricRequestBuilder<R, Q, RB>,
Q extends QueryRestrictions<S>,
QB extends QueryRestrictionsBuilder<Q, S, QB>,
S extends Serializable,
E extends Exception
> {
private final PS parametricValuesService;
private final ObjectFactory<QB> queryRestrictionsBuilderFactory;
private final ObjectFactory<RB> parametricRequestBuilderFactory;
private final FieldComparatorFactory fieldComparatorFactory;
}
static class ParametricRequestMatcher<R extends ParametricRequest<?>> extends BaseMatcher<R> {
private final List<FieldPath> expectedFieldNames;
private final String expectedQueryText;
private final String expectedFieldText;
private ParametricRequestMatcher(final List<FieldPath> expectedFieldNames, final String expectedQueryText, final String expectedFieldText) {
this.expectedFieldNames = expectedFieldNames;
this.expectedQueryText = expectedQueryText;
this.expectedFieldText = expectedFieldText;
}
static <R extends ParametricRequest<?>> ParametricRequestMatcher<R> matchesParametricRequest(
final List<FieldPath> expectedFieldNames,
final String expectedQueryText,
final String expectedFieldText
) {
return new ParametricRequestMatcher<>(expectedFieldNames, expectedQueryText, expectedFieldText);
}
@Override
public boolean matches(final Object item) {
if(!(item instanceof ParametricRequest)) {
return false;
}
final ParametricRequest<?> request = (ParametricRequest<?>)item;
return request.getFieldNames().equals(expectedFieldNames)
&& request.getQueryRestrictions().getQueryText().equals(expectedQueryText)
&& request.getQueryRestrictions().getFieldText().equals(expectedFieldText);
}
@Override
public void describeTo(final Description description) {
description.appendText("matchesParametricRequest(" + expectedFieldNames + ", " + expectedQueryText + ", " + expectedFieldText + ')');
}
}
}