/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.cache.query.internal;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.stream.IntStream;

import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.apache.geode.cache.EntryDestroyedException;
import org.apache.geode.cache.query.NameNotFoundException;
import org.apache.geode.cache.query.NameResolutionException;
import org.apache.geode.cache.query.QueryInvocationTargetException;
import org.apache.geode.cache.query.QueryService;
import org.apache.geode.cache.query.security.MethodInvocationAuthorizer;
import org.apache.geode.cache.query.security.RestrictedMethodAuthorizer;
import org.apache.geode.internal.cache.InternalCache;
import org.apache.geode.internal.cache.Token;
import org.apache.geode.pdx.internal.TypeRegistry;
import org.apache.geode.security.NotAuthorizedException;

@RunWith(JUnitParamsRunner.class)
public class AttributeDescriptorTest {
  private static final String PUBLIC_NO_ACCESSORS = "publicAttributeWithoutAccessors";
  private static final String PUBLIC_ACCESSOR_BY_NAME = "publicAttributeWithPublicAccessor";
  private static final String PUBLIC_ACCESSOR_BY_GETTER = "publicAttributeWithPublicGetterMethod";
  private static final String PRIVATE_ACCESSOR_BY_NAME = "nonPublicAttributeWithPublicAccessor";
  private static final String PRIVATE_ACCESSOR_BY_GETTER =
      "nonPublicAttributeWithPublicGetterMethod";

  private TestBean testBean;
  private TypeRegistry typeRegistry;
  private QueryExecutionContext queryExecutionContext;
  private MethodInvocationAuthorizer methodInvocationAuthorizer;

  @Before
  public void setUp() {
    AttributeDescriptor._localCache.clear();
    testBean = new TestBean(PUBLIC_NO_ACCESSORS, PUBLIC_ACCESSOR_BY_NAME, PUBLIC_ACCESSOR_BY_GETTER,
        PRIVATE_ACCESSOR_BY_NAME, PRIVATE_ACCESSOR_BY_GETTER);

    InternalCache mockCache = mock(InternalCache.class);
    typeRegistry = new TypeRegistry(mockCache, true);
    methodInvocationAuthorizer = spy(MethodInvocationAuthorizer.class);

    InternalQueryService mockQueryService = mock(InternalQueryService.class);
    when(mockCache.getQueryService()).thenReturn(mockQueryService);
    when(mockQueryService.getMethodInvocationAuthorizer()).thenReturn(methodInvocationAuthorizer);
    queryExecutionContext = new QueryExecutionContext(null, mockCache);
  }

  @Test
  @Parameters({PUBLIC_NO_ACCESSORS, PUBLIC_ACCESSOR_BY_NAME, PUBLIC_ACCESSOR_BY_GETTER,
      PRIVATE_ACCESSOR_BY_NAME, PRIVATE_ACCESSOR_BY_GETTER})
  public void validateReadTypeShouldReturnTrueWhenMemberCanBeFound(String attributeName) {
    AttributeDescriptor attributeDescriptor = new AttributeDescriptor(typeRegistry, attributeName);
    assertThat(attributeDescriptor.validateReadType(TestBean.class)).isTrue();
  }

  @Test
  public void validateReadTypeShouldReturnFalseWhenMemberCanNotBeFound() {
    AttributeDescriptor attributeDescriptor =
        new AttributeDescriptor(typeRegistry, "nonExistingAttribute");
    assertThat(attributeDescriptor.validateReadType(TestBean.class)).isFalse();
  }

  @Test
  @Parameters({PRIVATE_ACCESSOR_BY_NAME, PRIVATE_ACCESSOR_BY_GETTER})
  public void getReadFieldShouldReturnNullForNonPublicAttributes(String attributeName) {
    AttributeDescriptor attributeDescriptor = new AttributeDescriptor(typeRegistry, attributeName);
    assertThat(attributeDescriptor.getReadField(TestBean.class)).isNull();
  }

  @Test
  @Parameters({PUBLIC_NO_ACCESSORS, PUBLIC_ACCESSOR_BY_NAME, PUBLIC_ACCESSOR_BY_GETTER})
  public void getReadFieldShouldReturnRequestedFieldForPublicAttributes(String attributeName)
      throws NoSuchFieldException {
    AttributeDescriptor attributeDescriptor = new AttributeDescriptor(typeRegistry, attributeName);
    assertThat(attributeDescriptor.getReadField(TestBean.class))
        .isEqualTo(TestBean.class.getField(attributeName));
  }

  @Test
  @Parameters({PUBLIC_ACCESSOR_BY_GETTER, PRIVATE_ACCESSOR_BY_GETTER})
  public void getReadMethodShouldReturnRequestedMethodForAttributesWithGetters(String attributeName)
      throws NoSuchMethodException {
    AttributeDescriptor attributeDescriptor = new AttributeDescriptor(typeRegistry, attributeName);
    String getterName = "get" + attributeName.substring(0, 1).toUpperCase()
        + attributeName.substring(1);
    assertThat(attributeDescriptor.getReadMethod(TestBean.class))
        .isEqualTo(TestBean.class.getMethod(getterName));
  }

  @Test
  @Parameters({PUBLIC_ACCESSOR_BY_NAME, PRIVATE_ACCESSOR_BY_NAME})
  public void getReadMethodShouldReturnRequestedMethodForAttributesWithAccessors(
      String attributeName) throws NoSuchMethodException {
    AttributeDescriptor attributeDescriptor = new AttributeDescriptor(typeRegistry, attributeName);
    assertThat(attributeDescriptor.getReadMethod(TestBean.class, attributeName))
        .isEqualTo(TestBean.class.getMethod(attributeName));
  }

  @Test
  public void getReadMethodShouldReturnNullAndUpdateCachedClassToMethodsMapWhenMethodCanNotBeFound() {
    DefaultQuery.getPdxClasstoMethodsmap().clear();
    AttributeDescriptor attributeDescriptor =
        new AttributeDescriptor(typeRegistry, "nonExistingAttribute");
    assertThat(attributeDescriptor.getReadMethod(TestBean.class)).isNull();
    assertThat(DefaultQuery.getPdxClasstoMethodsmap().isEmpty()).isFalse();
    assertThat(DefaultQuery.getPdxClasstoMethodsmap()
        .containsKey(TestBean.class.getCanonicalName())).isTrue();
    assertThat(DefaultQuery.getPdxClasstoMethodsmap().get(TestBean.class.getCanonicalName())
        .contains("nonExistingAttribute")).isTrue();
  }

  @Test
  @Parameters({PUBLIC_NO_ACCESSORS, PUBLIC_ACCESSOR_BY_NAME, PUBLIC_ACCESSOR_BY_GETTER})
  public void getReadMemberShouldReturnFieldWhenAttributeIsPublicAndUseInternalCache(
      String attributeName) throws NameNotFoundException {
    AttributeDescriptor attributeDescriptor =
        spy(new AttributeDescriptor(typeRegistry, attributeName));
    assertThat(attributeDescriptor.getReadMember(TestBean.class)).isInstanceOf(Field.class);
    assertThat(attributeDescriptor.getReadMember(TestBean.class)).isInstanceOf(Field.class);

    // Second time the field should be obtained from the local cache.
    verify(attributeDescriptor, times(1)).getReadField(TestBean.class);
  }

  @Test
  @Parameters({PRIVATE_ACCESSOR_BY_NAME, PRIVATE_ACCESSOR_BY_GETTER})
  public void getReadMemberShouldReturnMethodWhenAttributeIsNotPublicAndUseInternalCache(
      String attributeName) throws NameNotFoundException {
    AttributeDescriptor attributeDescriptor =
        spy(new AttributeDescriptor(typeRegistry, attributeName));
    assertThat(attributeDescriptor.getReadMember(TestBean.class)).isInstanceOf(Method.class);
    assertThat(attributeDescriptor.getReadMember(TestBean.class)).isInstanceOf(Method.class);

    // Second time the field should be obtained from the local cache.
    verify(attributeDescriptor, times(1)).getReadMethod(TestBean.class);
  }

  @Test
  public void getReadMemberShouldThrowExceptionWhenMethodCanNotBeFound() {
    AttributeDescriptor attributeDescriptor =
        new AttributeDescriptor(typeRegistry, "nonExistingAttribute");
    assertThatThrownBy(() -> attributeDescriptor.getReadMember(TestBean.class))
        .isInstanceOf(NameNotFoundException.class)
        .hasMessageContaining(
            "No public attribute named ' nonExistingAttribute ' was found in class "
                + TestBean.class.getName());
  }

  @Test
  public void readReflectionShouldReturnUndefinedWhenTargetObjectIsAnInternalToken()
      throws NameNotFoundException, QueryInvocationTargetException {
    AttributeDescriptor attributeDescriptor =
        new AttributeDescriptor(typeRegistry, "nonExistingAttribute");
    assertThat(attributeDescriptor.readReflection(mock(Token.class), queryExecutionContext))
        .isEqualTo(QueryService.UNDEFINED);
  }

  @Test
  public void readReflectionShouldThrowExceptionWhenMemberCanNotBeFound() {
    AttributeDescriptor attributeDescriptor =
        new AttributeDescriptor(typeRegistry, "nonExistingAttribute");
    assertThatThrownBy(
        () -> attributeDescriptor.readReflection(TestBean.class, queryExecutionContext))
            .isInstanceOf(NameNotFoundException.class);
  }

  @Test
  public void readReflectionShouldReturnUndefinedWhenEntryDestroyedExceptionIsThrown()
      throws NameNotFoundException, QueryInvocationTargetException {
    doReturn(true).when(methodInvocationAuthorizer).authorize(any(), any());
    AttributeDescriptor attributeDescriptor =
        spy(new AttributeDescriptor(typeRegistry, "throwEntryDestroyedExceptionMethod"));
    assertThat(attributeDescriptor.readReflection(testBean, queryExecutionContext))
        .isEqualTo(QueryService.UNDEFINED);
  }

  @Test
  @Parameters({PUBLIC_NO_ACCESSORS, PUBLIC_ACCESSOR_BY_NAME, PUBLIC_ACCESSOR_BY_GETTER})
  public void readReflectionForPublicAttributeShouldNotInvokeAuthorizer(String attributeName)
      throws NameResolutionException, QueryInvocationTargetException {
    AttributeDescriptor attributeDescriptor = new AttributeDescriptor(typeRegistry, attributeName);

    Object result = attributeDescriptor.readReflection(testBean, queryExecutionContext);
    assertThat(result).isInstanceOf(String.class);
    assertThat(result).isEqualTo(attributeName);
    verify(methodInvocationAuthorizer, never()).authorize(any(), any());
  }

  @Test
  @Parameters({PRIVATE_ACCESSOR_BY_NAME, PRIVATE_ACCESSOR_BY_GETTER})
  public void readReflectionForImplicitMethodInvocationShouldReturnCorrectlyWhenMethodIsAuthorized(
      String attributeName) throws NameResolutionException, QueryInvocationTargetException {
    doReturn(true).when(methodInvocationAuthorizer).authorize(any(), any());
    AttributeDescriptor attributeDescriptor = new AttributeDescriptor(typeRegistry, attributeName);

    Object result = attributeDescriptor.readReflection(testBean, queryExecutionContext);
    assertThat(result).isInstanceOf(String.class);
    assertThat(result).isEqualTo(attributeName);
  }

  @Test
  @Parameters({
      "nonPublicAttributeWithPublicAccessor, nonPublicAttributeWithPublicAccessor",
      "nonPublicAttributeWithPublicGetterMethod, getNonPublicAttributeWithPublicGetterMethod"})
  public void readReflectionForImplicitMethodInvocationShouldReturnCorrectlyWhenMethodIsAuthorizedAndCacheResult(
      String attributeName, String methodName) throws Exception {
    doReturn(true).when(methodInvocationAuthorizer).authorize(any(), any());
    AttributeDescriptor attributeDescriptor = new AttributeDescriptor(typeRegistry, attributeName);
    attributeDescriptor.readReflection(testBean, queryExecutionContext);

    String cacheKey = TestBean.class.getCanonicalName() + "." + methodName;
    assertThat(queryExecutionContext.cacheGet(cacheKey)).isEqualTo(true);
  }

  @Test
  public void readReflectionForImplicitMethodInvocationShouldUseCachedAuthorizerResultWhenMethodIsAuthorizedAndQueryContextIsTheSame() {
    doReturn(true).when(methodInvocationAuthorizer).authorize(any(), any());
    AttributeDescriptor nonPublicAttributeWithPublicAccessor =
        new AttributeDescriptor(typeRegistry, PRIVATE_ACCESSOR_BY_NAME);
    AttributeDescriptor nonPublicAttributeWithPublicGetterMethod =
        new AttributeDescriptor(typeRegistry, PRIVATE_ACCESSOR_BY_GETTER);

    // Same QueryExecutionContext -> Use cache.
    IntStream.range(0, 10).forEach(element -> {
      try {
        assertThat(
            nonPublicAttributeWithPublicAccessor.readReflection(testBean, queryExecutionContext))
                .isInstanceOf(String.class).isEqualTo(PRIVATE_ACCESSOR_BY_NAME);
        assertThat(nonPublicAttributeWithPublicGetterMethod.readReflection(testBean,
            queryExecutionContext)).isInstanceOf(String.class)
                .isEqualTo(PRIVATE_ACCESSOR_BY_GETTER);
      } catch (NameNotFoundException | QueryInvocationTargetException exception) {
        throw new RuntimeException(exception);
      }
    });
    verify(methodInvocationAuthorizer, times(2)).authorize(any(), any());
  }

  @Test
  public void readReflectionForImplicitMethodInvocationShouldNotUseCachedAuthorizerResultWhenMethodIsAuthorizedAndQueryContextIsNotTheSame() {
    doReturn(true).when(methodInvocationAuthorizer).authorize(any(), any());
    AttributeDescriptor nonPublicAttributeWithPublicAccessor =
        new AttributeDescriptor(typeRegistry, PRIVATE_ACCESSOR_BY_NAME);
    AttributeDescriptor nonPublicAttributeWithPublicGetterMethod =
        new AttributeDescriptor(typeRegistry, PRIVATE_ACCESSOR_BY_GETTER);

    // New QueryExecutionContext every time -> Do not use cache.
    IntStream.range(0, 10).forEach(element -> {
      try {
        QueryExecutionContext mockContext = mock(QueryExecutionContext.class);
        when(mockContext.getMethodInvocationAuthorizer()).thenReturn(methodInvocationAuthorizer);

        assertThat(nonPublicAttributeWithPublicAccessor.readReflection(testBean, mockContext))
            .isInstanceOf(String.class).isEqualTo(PRIVATE_ACCESSOR_BY_NAME);
        assertThat(nonPublicAttributeWithPublicGetterMethod.readReflection(testBean, mockContext))
            .isInstanceOf(String.class).isEqualTo(PRIVATE_ACCESSOR_BY_GETTER);
      } catch (NameNotFoundException | QueryInvocationTargetException exception) {
        throw new RuntimeException(exception);
      }
    });
    verify(methodInvocationAuthorizer, times(20)).authorize(any(), any());
  }

  @Test
  @Parameters({PRIVATE_ACCESSOR_BY_NAME, PRIVATE_ACCESSOR_BY_GETTER})
  public void readReflectionForImplicitMethodInvocationShouldThrowExceptionWhenMethodIsNotAuthorized(
      String attributeName) {
    doReturn(false).when(methodInvocationAuthorizer).authorize(any(), any());
    AttributeDescriptor attributeDescriptor = new AttributeDescriptor(typeRegistry, attributeName);

    assertThatThrownBy(() -> attributeDescriptor.readReflection(testBean, queryExecutionContext))
        .isInstanceOf(NotAuthorizedException.class)
        .hasMessageStartingWith(RestrictedMethodAuthorizer.UNAUTHORIZED_STRING);
  }

  @Test
  @Parameters({
      "nonPublicAttributeWithPublicAccessor, nonPublicAttributeWithPublicAccessor",
      "nonPublicAttributeWithPublicGetterMethod, getNonPublicAttributeWithPublicGetterMethod"})
  public void readReflectionForImplicitMethodInvocationShouldShouldThrowExceptionWhenMethodIsNotAuthorizedAndCacheResult(
      String attributeName, String methodName) {
    doReturn(false).when(methodInvocationAuthorizer).authorize(any(), any());
    AttributeDescriptor attributeDescriptor = new AttributeDescriptor(typeRegistry, attributeName);

    assertThatThrownBy(() -> attributeDescriptor.readReflection(testBean, queryExecutionContext))
        .isInstanceOf(NotAuthorizedException.class)
        .hasMessageStartingWith(RestrictedMethodAuthorizer.UNAUTHORIZED_STRING);

    String cacheKey = TestBean.class.getCanonicalName() + "." + methodName;
    assertThat(queryExecutionContext.cacheGet(cacheKey)).isEqualTo(false);
  }

  @Test
  public void readReflectionForImplicitMethodInvocationShouldUseCachedAuthorizerResultWhenMethodIsForbiddenAndQueryContextIsTheSame() {
    doReturn(false).when(methodInvocationAuthorizer).authorize(any(), any());
    AttributeDescriptor nonPublicAttributeWithPublicAccessor =
        new AttributeDescriptor(typeRegistry, PRIVATE_ACCESSOR_BY_NAME);
    AttributeDescriptor nonPublicAttributeWithPublicGetterMethod =
        new AttributeDescriptor(typeRegistry, PRIVATE_ACCESSOR_BY_GETTER);

    // Same QueryExecutionContext -> Use cache.
    IntStream.range(0, 10).forEach(element -> {
      assertThatThrownBy(() -> nonPublicAttributeWithPublicAccessor.readReflection(testBean,
          queryExecutionContext)).isInstanceOf(NotAuthorizedException.class)
              .hasMessageStartingWith(RestrictedMethodAuthorizer.UNAUTHORIZED_STRING);
      assertThatThrownBy(() -> nonPublicAttributeWithPublicGetterMethod.readReflection(testBean,
          queryExecutionContext)).isInstanceOf(NotAuthorizedException.class)
              .hasMessageStartingWith(RestrictedMethodAuthorizer.UNAUTHORIZED_STRING);
    });
    verify(methodInvocationAuthorizer, times(2)).authorize(any(), any());
  }

  @Test
  public void readReflectionForImplicitMethodInvocationShouldNotUseCachedAuthorizerResultWhenMethodIsForbiddenAndQueryContextIsNotTheSame() {
    doReturn(false).when(methodInvocationAuthorizer).authorize(any(), any());
    AttributeDescriptor nonPublicAttributeWithPublicAccessor =
        new AttributeDescriptor(typeRegistry, PRIVATE_ACCESSOR_BY_NAME);
    AttributeDescriptor nonPublicAttributeWithPublicGetterMethod =
        new AttributeDescriptor(typeRegistry, PRIVATE_ACCESSOR_BY_GETTER);

    // New QueryExecutionContext every time -> Do not use cache.
    IntStream.range(0, 10).forEach(element -> {
      QueryExecutionContext mockContext = mock(QueryExecutionContext.class);
      when(mockContext.getMethodInvocationAuthorizer()).thenReturn(methodInvocationAuthorizer);

      assertThatThrownBy(
          () -> nonPublicAttributeWithPublicAccessor.readReflection(testBean, mockContext))
              .isInstanceOf(NotAuthorizedException.class)
              .hasMessageStartingWith(RestrictedMethodAuthorizer.UNAUTHORIZED_STRING);
      assertThatThrownBy(
          () -> nonPublicAttributeWithPublicGetterMethod.readReflection(testBean, mockContext))
              .isInstanceOf(NotAuthorizedException.class)
              .hasMessageStartingWith(RestrictedMethodAuthorizer.UNAUTHORIZED_STRING);
    });
    verify(methodInvocationAuthorizer, times(20)).authorize(any(), any());
  }

  @Test
  public void readShouldReturnUndefinedForNullOrUndefinedTargetObject()
      throws NameNotFoundException, QueryInvocationTargetException {
    AttributeDescriptor attributeDescriptor = new AttributeDescriptor(typeRegistry, "whatever");
    assertThat(attributeDescriptor.read(null, queryExecutionContext))
        .isEqualTo(QueryService.UNDEFINED);
    assertThat(attributeDescriptor.read(QueryService.UNDEFINED, queryExecutionContext))
        .isEqualTo(QueryService.UNDEFINED);
  }

  @Test
  @Parameters({PUBLIC_NO_ACCESSORS, PUBLIC_ACCESSOR_BY_NAME, PUBLIC_ACCESSOR_BY_GETTER,
      PRIVATE_ACCESSOR_BY_NAME, PRIVATE_ACCESSOR_BY_GETTER})
  public void readShouldReturnCorrectlyForAccessibleAuthorizedNonPdxMembers(String attributeName)
      throws NameNotFoundException, QueryInvocationTargetException {
    doReturn(true).when(methodInvocationAuthorizer).authorize(any(), any());
    AttributeDescriptor attributeDescriptor = new AttributeDescriptor(typeRegistry, attributeName);

    Object result = attributeDescriptor.read(testBean, queryExecutionContext);
    assertThat(result).isInstanceOf(String.class);
    assertThat(result).isEqualTo(attributeName);
  }

  @SuppressWarnings("unused")
  private static class TestBean {
    public final String publicAttributeWithoutAccessors;
    public final String publicAttributeWithPublicAccessor;
    public final String publicAttributeWithPublicGetterMethod;
    private final String nonPublicAttributeWithPublicAccessor;
    private final String nonPublicAttributeWithPublicGetterMethod;

    public String publicAttributeWithPublicAccessor() {
      return publicAttributeWithPublicAccessor;
    }

    public String getPublicAttributeWithPublicGetterMethod() {
      return publicAttributeWithPublicGetterMethod;
    }

    public String nonPublicAttributeWithPublicAccessor() {
      return nonPublicAttributeWithPublicAccessor;
    }

    public String getNonPublicAttributeWithPublicGetterMethod() {
      return nonPublicAttributeWithPublicGetterMethod;
    }

    public void throwEntryDestroyedExceptionMethod() {
      throw new EntryDestroyedException();
    }

    TestBean(String publicAttributeWithoutAccessors,
        String publicAttributeWithPublicAccessor,
        String publicAttributeWithPublicGetterMethod,
        String nonPublicAttributeWithPublicAccessor,
        String nonPublicAttributeWithPublicGetterMethod) {
      this.publicAttributeWithoutAccessors = publicAttributeWithoutAccessors;
      this.publicAttributeWithPublicAccessor = publicAttributeWithPublicAccessor;
      this.publicAttributeWithPublicGetterMethod = publicAttributeWithPublicGetterMethod;
      this.nonPublicAttributeWithPublicAccessor = nonPublicAttributeWithPublicAccessor;
      this.nonPublicAttributeWithPublicGetterMethod = nonPublicAttributeWithPublicGetterMethod;
    }
  }
}
