Skip to content
Draft
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
@@ -0,0 +1,293 @@
/*
* 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 org.apache.ranger.services.trino;

import org.apache.ranger.plugin.client.HadoopConfigHolder;
import org.apache.ranger.plugin.client.HadoopException;
import org.apache.ranger.plugin.model.RangerPolicy;
import org.apache.ranger.plugin.model.RangerService;
import org.apache.ranger.plugin.model.RangerServiceDef;
import org.apache.ranger.plugin.service.RangerBaseService;
import org.apache.ranger.plugin.service.ResourceLookupContext;
import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
import org.apache.ranger.services.trino.client.TrinoResourceManager;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.MockedStatic;
import org.mockito.junit.jupiter.MockitoExtension;

import java.lang.reflect.Field;
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 static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.never;

/**
* @generated by Cursor
* @description : Unit test cases for RangerServiceTrino.
*/
@ExtendWith(MockitoExtension.class)
@TestMethodOrder(MethodOrderer.MethodName.class)
class TestRangerServiceTrino {
private static final String CREATE_DEFAULT_POLICY_PER_HIERARCHY = "create.default.policy.per.hierarchy";

@Test
void test01_validateConfig_whenConfigsAbsent_returnsEmptyResponse() throws Exception {
RangerServiceTrino svc = initTrino(sampleConfigs());
svc.setConfigs(null);

Map<String, Object> out = svc.validateConfig();

assertNotNull(out);
assertTrue(out.isEmpty());
}

@Test
void test02_validateConfig_whenConfigsAvailable_delegatesToTrinoResourceManager() throws Exception {
RangerServiceTrino svc = initTrino(sampleConfigs());
Map<String, Object> expected = Collections.singletonMap("connectivityStatus", Boolean.TRUE);

try (MockedStatic<TrinoResourceManager> mocked = mockStatic(TrinoResourceManager.class)) {
mocked.when(() -> TrinoResourceManager.connectionTest(eq("trino-svc"), anyMap())).thenReturn(expected);

Map<String, Object> actual = svc.validateConfig();

assertSame(expected, actual);
mocked.verify(() -> TrinoResourceManager.connectionTest(eq("trino-svc"), anyMap()));
}
}

@Test
void test03_validateConfig_whenConnectionTestFails_propagatesHadoopException() throws Exception {
RangerServiceTrino svc = initTrino(sampleConfigs());
HadoopException boom = new HadoopException("failed", new RuntimeException("root"));

try (MockedStatic<TrinoResourceManager> mocked = mockStatic(TrinoResourceManager.class)) {
mocked.when(() -> TrinoResourceManager.connectionTest(eq("trino-svc"), anyMap())).thenThrow(boom);

assertThrows(HadoopException.class, svc::validateConfig);
}
}

@Test
void test04_lookupResource_whenContextIsNull_returnsEmptyList() throws Exception {
RangerServiceTrino svc = initTrinoForLookup(sampleConfigs());

try (MockedStatic<TrinoResourceManager> mocked = mockStatic(TrinoResourceManager.class)) {
List<String> result = svc.lookupResource(null);

assertEquals(Collections.emptyList(), result);

mocked.verify(() -> TrinoResourceManager.getTrinoResources(anyString(), anyString(), anyMap(), any()),
never());
}
}

@Test
void test05_lookupResource_whenContextPresent_delegatesToTrinoResourceManager() throws Exception {
RangerServiceTrino svc = initTrinoForLookup(sampleConfigs());
ResourceLookupContext ctx = sampleLookupContext();
List<String> expected = List.of("/a", "/b");

try (MockedStatic<TrinoResourceManager> mocked = mockStatic(TrinoResourceManager.class)) {
mocked.when(() -> TrinoResourceManager.getTrinoResources(eq("svc-lookup"), eq("trino"), anyMap(), same(ctx)))
.thenReturn(expected);

List<String> result = svc.lookupResource(ctx);

assertSame(expected, result);
}
}

@Test
void test06_lookupResource_whenDelegateThrows_propagatesException() throws Exception {
RangerServiceTrino svc = initTrinoForLookup(sampleConfigs());
ResourceLookupContext ctx = sampleLookupContext();

try (MockedStatic<TrinoResourceManager> mocked = mockStatic(TrinoResourceManager.class)) {
mocked.when(() -> TrinoResourceManager.getTrinoResources(eq("svc-lookup"), eq("trino"), anyMap(), same(ctx)))
.thenThrow(new IllegalStateException("lookup failed"));

assertThrows(IllegalStateException.class, () -> svc.lookupResource(ctx));
}
}

@Test
void test07_getDefaultRangerPolicies_addsOwnerStylePoliciesFromEmbeddedDef() throws Exception {
RangerServiceTrino svc = new RangerServiceTrino();
RangerServiceDef def = EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_TRINO_NAME);

assertNotNull(def);

svc.init(def, buildService("def-svc", "trino", defaultPolicyConfigs()));

List<RangerPolicy> policies = svc.getDefaultRangerPolicies();

assertFalse(policies.isEmpty());

boolean foundAllHierarchyPolicy = policies.stream().anyMatch(p ->
p.getName() != null && p.getName().startsWith("all"));

assertTrue(foundAllHierarchyPolicy);
}

@Test
void test08_getDefaultRangerPolicies_whenLookupUserPresent_addsSelectGrantOnPoliciesContainingAll() throws Exception {
RangerServiceTrino svc = new RangerServiceTrino();

Field lookUpField = RangerBaseService.class.getDeclaredField("lookUpUser");
lookUpField.setAccessible(true);
lookUpField.set(svc, "resolver-user");

RangerServiceDef def = EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_TRINO_NAME);

assertNotNull(def);

svc.init(def, buildService("def-svc-2", "trino", defaultPolicyConfigs()));

List<RangerPolicy> policies = svc.getDefaultRangerPolicies();

Set<String> matchingPolicyNames = new HashSet<>();
for (RangerPolicy p : policies) {
if (p.getName() != null && p.getName().contains("all")) {
boolean hasLookup = p.getPolicyItems().stream().anyMatch(pi ->
pi.getUsers() != null && pi.getUsers().contains("resolver-user"));
boolean hasSelectAccess = p.getPolicyItems().stream().anyMatch(pi ->
pi.getAccesses() != null && pi.getAccesses().stream()
.anyMatch(a -> RangerServiceTrino.ACCESS_TYPE_SELECT.equals(a.getType())));
assertTrue(hasLookup, "expected lookup user on policy " + p.getName());
assertTrue(hasSelectAccess, "expected select access on policy " + p.getName());
matchingPolicyNames.add(p.getName());
}
}

assertFalse(matchingPolicyNames.isEmpty());
}

@Test
void test09_validateConfig_whenRangerLoginPasswordKeyMissing_putsNullPasswordEntry() throws Exception {
RangerServiceTrino svc = initTrino(configsWithoutRangerLoginPassword());

try (MockedStatic<TrinoResourceManager> mocked = mockStatic(TrinoResourceManager.class)) {
mocked.when(() -> TrinoResourceManager.connectionTest(eq("trino-svc"), anyMap()))
.thenReturn(Collections.singletonMap("connectivityStatus", Boolean.TRUE));

svc.validateConfig();

mocked.verify(() -> TrinoResourceManager.connectionTest(eq("trino-svc"), argThat(m ->
m.containsKey(HadoopConfigHolder.RANGER_LOGIN_PASSWORD)
&& m.get(HadoopConfigHolder.RANGER_LOGIN_PASSWORD) == null)));
}
}

@Test
void test10_lookupResource_whenRangerLoginPasswordKeyMissing_putsNullPasswordEntry()
throws Exception {
RangerServiceTrino svc = initTrinoForLookup(configsWithoutRangerLoginPassword());
ResourceLookupContext ctx = sampleLookupContext();

try (MockedStatic<TrinoResourceManager> mocked = mockStatic(TrinoResourceManager.class)) {
mocked.when(() -> TrinoResourceManager.getTrinoResources(
eq("svc-lookup"), eq("trino"), anyMap(), same(ctx)))
.thenReturn(Collections.emptyList());

svc.lookupResource(ctx);

mocked.verify(() -> TrinoResourceManager.getTrinoResources(
eq("svc-lookup"), eq("trino"), argThat(m ->
m.containsKey(HadoopConfigHolder.RANGER_LOGIN_PASSWORD)
&& m.get(HadoopConfigHolder.RANGER_LOGIN_PASSWORD) == null),
same(ctx)));
}
}

private RangerServiceTrino initTrino(Map<String, String> cfg) throws Exception {
RangerServiceTrino svc = new RangerServiceTrino();

RangerServiceDef def = EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_TRINO_NAME);
assertNotNull(def);

svc.init(def, buildService("trino-svc", "trino", cfg));
return svc;
}

private RangerServiceTrino initTrinoForLookup(Map<String, String> cfg) throws Exception {
RangerServiceTrino svc = new RangerServiceTrino();

RangerServiceDef def = EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_TRINO_NAME);
assertNotNull(def);

svc.init(def, buildService("svc-lookup", "trino", cfg));
return svc;
}

private RangerService buildService(String name, String type, Map<String, String> cfg) {
RangerService service = new RangerService();
service.setName(name);
service.setType(type);
service.setConfigs(cfg);
return service;
}

private Map<String, String> sampleConfigs() {
Map<String, String> cfg = new HashMap<>();
cfg.put("username", "u");
cfg.put("password", "p");
cfg.put("jdbc.driverClassName", "io.trino.jdbc.TrinoDriver");
cfg.put("jdbc.url", "jdbc:trino://localhost:8080");
return cfg;
}

/** Config map without {@link HadoopConfigHolder#RANGER_LOGIN_PASSWORD}. */
private Map<String, String> configsWithoutRangerLoginPassword() {
Map<String, String> cfg = new HashMap<>();
cfg.put("username", "u");
cfg.put("jdbc.driverClassName", "io.trino.jdbc.TrinoDriver");
cfg.put("jdbc.url", "jdbc:trino://localhost:8080");
return cfg;
}

private ResourceLookupContext sampleLookupContext() {
ResourceLookupContext ctx = new ResourceLookupContext();
ctx.setUserInput("needle");
ctx.setResourceName("catalog");
return ctx;
}

private Map<String, String> defaultPolicyConfigs() {
Map<String, String> cfg = sampleConfigs();
cfg.put("setup.additional.default.policies", "false");
cfg.put(CREATE_DEFAULT_POLICY_PER_HIERARCHY, Boolean.TRUE.toString());
return cfg;
}
}
Loading