/**
 * 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
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * 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.sentry.hdfs;

import org.apache.hadoop.conf.Configuration;
import org.apache.sentry.core.common.utils.PubSub;
import org.apache.sentry.hdfs.ServiceConstants.ServerConfig;
import org.apache.sentry.hdfs.service.thrift.TAuthzUpdateRequest;
import org.apache.sentry.hdfs.service.thrift.TAuthzUpdateResponse;
import org.apache.sentry.hdfs.service.thrift.TPrivilegePrincipal;
import org.apache.sentry.provider.db.SentryPolicyStorePlugin;
import org.apache.sentry.provider.db.service.model.MSentryPathChange;
import org.apache.sentry.provider.db.service.model.MSentryPermChange;
import org.apache.sentry.provider.db.service.persistent.PermissionsImage;
import org.apache.sentry.provider.db.service.persistent.SentryStore;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.Mockito;

import java.util.*;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

public class TestSentryHDFSServiceProcessor {
  private static SentryHDFSServiceProcessor serviceProcessor;
  private static SentryStore sentryStoreMock;

  @BeforeClass
  public static void setUp() throws SentryPolicyStorePlugin.SentryPluginException {
    serviceProcessor = new SentryHDFSServiceProcessor();
    sentryStoreMock = Mockito.mock(SentryStore.class);
    Configuration conf = new Configuration();
    // enable full update triger via pub-sub mechanism
    conf.set(ServerConfig.SENTRY_SERVICE_FULL_UPDATE_PUBSUB, "true");
    new SentryPlugin().initialize(conf, sentryStoreMock);
  }

  @Test
  @Ignore
  public void testInitialHDFSSyncReturnsAFullImage() throws Exception {
    Mockito.when(sentryStoreMock.getLastProcessedImageID())
        .thenReturn(1L);
    String[]prefixes = {"/"};
    Mockito.when(sentryStoreMock.retrieveFullPathsImageUpdate(prefixes))
        .thenReturn(new PathsUpdate(1, 1, true));

    Mockito.when(sentryStoreMock.getLastProcessedPermChangeID())
        .thenReturn(1L);
    Mockito.when(sentryStoreMock.retrieveFullPermssionsImage())
        .thenReturn(new PermissionsImage(new HashMap<String, List<String>>(), new HashMap<String, Map<TPrivilegePrincipal, String>>(), 1));

    TAuthzUpdateRequest updateRequest = new TAuthzUpdateRequest(1, 1, 0);
    TAuthzUpdateResponse sentryUpdates= serviceProcessor.get_authz_updates(updateRequest);

    assertEquals(1, sentryUpdates.getAuthzPathUpdateSize());
    assertEquals(1, sentryUpdates.getAuthzPathUpdate().get(0).getImgNum());
    assertEquals(1, sentryUpdates.getAuthzPathUpdate().get(0).getSeqNum());
    assertTrue(sentryUpdates.getAuthzPathUpdate().get(0).isHasFullImage());

    assertEquals(1, sentryUpdates.getAuthzPermUpdateSize());
    assertEquals(1, sentryUpdates.getAuthzPermUpdate().get(0).getSeqNum());
    assertTrue(sentryUpdates.getAuthzPermUpdate().get(0).isHasfullImage());
  }

  @Test
  @Ignore
  public void testRequestSyncUpdatesWhenNewImagesArePersistedReturnsANewFullImage() throws Exception {
    Mockito.when(sentryStoreMock.getLastProcessedImageID())
        .thenReturn(2L);
    String[]prefixes = {"/"};
    Mockito.when(sentryStoreMock.retrieveFullPathsImageUpdate(prefixes))
        .thenReturn(new PathsUpdate(3, 2, true));

    Mockito.when(sentryStoreMock.getLastProcessedPermChangeID())
        .thenReturn(3L);
    Mockito.when(sentryStoreMock.retrieveFullPermssionsImage())
        .thenReturn(new PermissionsImage(new HashMap<String, List<String>>(), new HashMap<String, Map<TPrivilegePrincipal, String>>(), 3));

    TAuthzUpdateRequest updateRequest = new TAuthzUpdateRequest(2, 2, 1);
    TAuthzUpdateResponse sentryUpdates= serviceProcessor.get_authz_updates(updateRequest);

    assertEquals(1, sentryUpdates.getAuthzPathUpdateSize());
    assertEquals(2, sentryUpdates.getAuthzPathUpdate().get(0).getImgNum());
    assertEquals(3, sentryUpdates.getAuthzPathUpdate().get(0).getSeqNum());
    assertTrue(sentryUpdates.getAuthzPathUpdate().get(0).isHasFullImage());

    assertEquals(1, sentryUpdates.getAuthzPermUpdateSize());
    assertEquals(3, sentryUpdates.getAuthzPermUpdate().get(0).getSeqNum());
    assertTrue(sentryUpdates.getAuthzPermUpdate().get(0).isHasfullImage());
  }

  @Test
  public void testRequestSyncUpdatesWhenNewDeltasArePersistedReturnsDeltaChanges() throws Exception {
    Mockito.when(sentryStoreMock.getLastProcessedImageID())
        .thenReturn(1L);
    Mockito.when(sentryStoreMock.getLastProcessedPathChangeID())
        .thenReturn(3L);
    Mockito.when(sentryStoreMock.pathChangeExists(2))
        .thenReturn(true);
    Mockito.when(sentryStoreMock.getMSentryPathChanges(2))
        .thenReturn(Arrays.asList(new MSentryPathChange(3, "u3", new PathsUpdate(3, 1, false))));

    Mockito.when(sentryStoreMock.getLastProcessedPermChangeID())
        .thenReturn(3L);
    Mockito.when(sentryStoreMock.permChangeExists(2))
        .thenReturn(true);
    Mockito.when(sentryStoreMock.getMSentryPermChanges(2))
        .thenReturn(Arrays.asList(new MSentryPermChange(3, new PermissionsUpdate(3, false))));

    TAuthzUpdateRequest updateRequest = new TAuthzUpdateRequest(2, 2, 1);
    TAuthzUpdateResponse sentryUpdates= serviceProcessor.get_authz_updates(updateRequest);

    assertEquals(1, sentryUpdates.getAuthzPathUpdateSize());
    assertEquals(1, sentryUpdates.getAuthzPathUpdate().get(0).getImgNum());
    assertEquals(3, sentryUpdates.getAuthzPathUpdate().get(0).getSeqNum());
    assertFalse(sentryUpdates.getAuthzPathUpdate().get(0).isHasFullImage());

    assertEquals(1, sentryUpdates.getAuthzPermUpdateSize());
    assertEquals(3, sentryUpdates.getAuthzPermUpdate().get(0).getSeqNum());
    assertFalse(sentryUpdates.getAuthzPermUpdate().get(0).isHasfullImage());
  }

  /**
   * Verify that publish-subscribe mechanism works for triggering full paths updates
   */
  @Test
  public void testRequestSyncUpdatesWhenPubSubNotifyReturnsFullPathsUpdate() throws Exception {
    // Configure SentryStore mock to return small sequence numbers
    Mockito.when(sentryStoreMock.getLastProcessedImageID())
        .thenReturn(1L);
    Mockito.when(sentryStoreMock.getLastProcessedPathChangeID())
        .thenReturn(2L);
    Mockito.when(sentryStoreMock.getLastProcessedPermChangeID())
        .thenReturn(2L);
    // Also, configure SentryStore mock return full paths update once;
    // throw an exception afterwards.
    Mockito.when(sentryStoreMock.retrieveFullPathsImageUpdate(Mockito.any()))
        .thenReturn(new PathsUpdate(8, 5, true))
        .thenThrow(new RuntimeException("Not supposed to ask for full path update first time"));

    // now ask for larger sequence numbers - supposed to return nothing
    TAuthzUpdateRequest updateRequest = new TAuthzUpdateRequest(3, 3, 1);
    TAuthzUpdateResponse sentryUpdates= serviceProcessor.get_authz_updates(updateRequest);
    // no permissions updates
    assertEquals(0, sentryUpdates.getAuthzPermUpdateSize());
    // no paths updates
    assertEquals(0, sentryUpdates.getAuthzPathUpdateSize());

    // Now set full update trigger ...
    PubSub.getInstance().publish(PubSub.Topic.HDFS_SYNC_NN, "test message");
    // ... then repeat exactly the same update call
    sentryUpdates= serviceProcessor.get_authz_updates(updateRequest);
    // ... still no permissions updates returned
    assertEquals(0, sentryUpdates.getAuthzPermUpdateSize());
    // ... but now we are getting full paths update, as intended by trigger logic
    assertEquals(1, sentryUpdates.getAuthzPathUpdateSize());
    assertEquals(5, sentryUpdates.getAuthzPathUpdate().get(0).getImgNum());
    assertEquals(8, sentryUpdates.getAuthzPathUpdate().get(0).getSeqNum());
    assertTrue(sentryUpdates.getAuthzPathUpdate().get(0).isHasFullImage());
  }

  @Test
  public void testRequestSyncUpdatesWhenNoUpdatesExistReturnsEmptyResults() throws Exception {
    Mockito.when(sentryStoreMock.getLastProcessedImageID())
        .thenReturn(1L);
    Mockito.when(sentryStoreMock.getLastProcessedPathChangeID())
        .thenReturn(2L);
    Mockito.when(sentryStoreMock.getLastProcessedPermChangeID())
        .thenReturn(2L);

    TAuthzUpdateRequest updateRequest = new TAuthzUpdateRequest(3, 3, 1);
    TAuthzUpdateResponse sentryUpdates= serviceProcessor.get_authz_updates(updateRequest);

    assertEquals(0, sentryUpdates.getAuthzPathUpdateSize());
    assertEquals(0, sentryUpdates.getAuthzPermUpdateSize());
  }
}
