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
12 changes: 12 additions & 0 deletions agents-audit/dest-hdfs/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,18 @@
</dependency>

<!-- Test -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* 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.ranger.audit.destination;

import org.apache.ranger.audit.utils.RangerAuditWriter;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.io.File;
import java.util.Arrays;
import java.util.Collection;
import java.util.Properties;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

/**
* @generated by copilot
* @description Unit Test cases for HDFSAuditDestination
* */
class HDFSAuditDestinationTest {
private HDFSAuditDestination destination;
private RangerAuditWriter mockWriter;

@BeforeEach
void setUp() throws Exception {
mockWriter = mock(RangerAuditWriter.class);

// Subclass to override getWriter()
destination = new HDFSAuditDestination() {
@Override
public RangerAuditWriter getWriter() {
return mockWriter;
}
};
}

@Test
void testInitSetsInitDone() {
Properties props = new Properties();
destination.init(props, "prefix");
assertTrue(getPrivateInitDone(destination));
}

@Test
void testLogJSONSuccess() throws Exception {
destination.init(new Properties(), "prefix");
Collection<String> events = Arrays.asList("{\"event\":1}", "{\"event\":2}");
when(mockWriter.log(events)).thenReturn(true);

boolean result = destination.logJSON(events);

assertTrue(result);
verify(mockWriter, atLeastOnce()).log(events);
}

@Test
void testLogJSONWhenNotInit() throws Exception {
Collection<String> events = Arrays.asList("{\"event\":1}");
boolean result = destination.logJSON(events);
assertFalse(result);
}

@Test
void testLogFileSuccess() throws Exception {
destination.init(new Properties(), "prefix");
File file = mock(File.class);
when(mockWriter.logFile(file)).thenReturn(true);

boolean result = destination.logFile(file);

assertTrue(result);
verify(mockWriter).logFile(file);
}

@Test
void testLogFileWhenNotInit() throws Exception {
File file = mock(File.class);
boolean result = destination.logFile(file);
assertFalse(result);
}

@Test
void testStopCallsWriterStop() throws Exception {
destination.init(new Properties(), "prefix");
destination.stop();
verify(mockWriter).stop();
}

// Helper to access private field
private boolean getPrivateInitDone(HDFSAuditDestination dest) {
try {
java.lang.reflect.Field f = HDFSAuditDestination.class.getDeclaredField("initDone");
f.setAccessible(true);
return f.getBoolean(dest);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
/*
* 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.ranger.audit.provider;

import org.apache.ranger.audit.model.AuditEventBase;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.io.BufferedReader;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.file.Path;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

/**
* @generated by copilot
* @description Unit Test cases for LocalFileLogBuffer
* */
class LocalFileLogBufferTest {
private LocalFileLogBuffer<AuditEventBase> logBuffer;

@Mock
private DebugTracer mockTracer;

@Mock
private LogDestination<AuditEventBase> mockDestination;

@Mock
private AuditEventBase mockAuditEvent;

@TempDir
Path tempDir;

@BeforeEach
void setUp() {
MockitoAnnotations.initMocks(this);
logBuffer = new LocalFileLogBuffer<>(mockTracer);

// Configure the log buffer
logBuffer.setDirectory(tempDir.toString());
logBuffer.setFile("audit_test_%app-type%_%time:yyyyMMdd-HHmm%.log");
logBuffer.setEncoding("UTF-8");
logBuffer.setFlushIntervalSeconds(1); // Set to 1 second for faster testing
logBuffer.setRolloverIntervalSeconds(5); // Set to 5 seconds for faster testing
logBuffer.setArchiveDirectory(tempDir.resolve("archive").toString());
logBuffer.setArchiveFileCount(3);
logBuffer.setIsAppend(true);
logBuffer.setFileBufferSizeBytes(1024);
}

@Test
void testInitialState() {
assertEquals(tempDir.toString(), logBuffer.getDirectory());
assertEquals("audit_test_%app-type%_%time:yyyyMMdd-HHmm%.log", logBuffer.getFile());
assertEquals("UTF-8", logBuffer.getEncoding());
assertEquals(1, logBuffer.getFlushIntervalSeconds());
assertEquals(5, logBuffer.getRolloverIntervalSeconds());
assertEquals(tempDir.resolve("archive").toString(), logBuffer.getArchiveDirectory());
assertEquals(3, logBuffer.getArchiveFileCount());
assertTrue(logBuffer.getIsAppend());
assertEquals(1024, logBuffer.getFileBufferSizeBytes());
}

@Test
void testFileNotAvailable() {
// Set an invalid directory to test file not available scenario
logBuffer.setDirectory("/invalid/directory/path");

// Try to add a log
when(mockAuditEvent.toString()).thenReturn("Test audit event");
boolean added = logBuffer.add(mockAuditEvent);

// Should fail because the directory doesn't exist
assertFalse(added);
assertFalse(logBuffer.isAvailable());
}

@Test
void testDestinationDispatcherThread() throws Exception {
// Configure the mock destination
when(mockDestination.sendStringified(anyString())).thenReturn(true);

// Add a log to create a file
logBuffer.start(mockDestination);
when(mockAuditEvent.toString()).thenReturn("Test dispatch event");
boolean added = logBuffer.add(mockAuditEvent);
assertTrue(added);

// Force close the file to add it to completed files
Field writerField = LocalFileLogBuffer.class.getDeclaredField("mWriter");
writerField.setAccessible(true);

// Remember the filename before closing
Field bufferFilenameField = LocalFileLogBuffer.class.getDeclaredField("mBufferFilename");
bufferFilenameField.setAccessible(true);
String filename = (String) bufferFilenameField.get(logBuffer);

// Close the file to add it to the completed files list
logBuffer.stop();

// Create a new dispatcher thread with the same file buffer and destination
LocalFileLogBuffer.DestinationDispatcherThread<AuditEventBase> dispatcherThread =
new LocalFileLogBuffer.DestinationDispatcherThread<>(logBuffer, mockDestination, mockTracer);

// Add our test file to the completed files
dispatcherThread.addLogfile(filename);

// Start the thread and let it process our file
dispatcherThread.start();
Thread.sleep(500);

// Verify the destination was called to send the log
verify(mockDestination, timeout(1000).atLeastOnce()).sendStringified("Test dispatch event");

// Stop the thread
dispatcherThread.stopThread();
dispatcherThread.join(1000);
assertFalse(dispatcherThread.isAlive());
}

@Test
void testToString() {
String toString = logBuffer.toString();

assertTrue(toString.contains("LocalFileLogBuffer"));
assertTrue(toString.contains(tempDir.toString()));
assertTrue(toString.contains("audit_test_%app-type%_%time:yyyyMMdd-HHmm%.log"));
assertTrue(toString.contains("RolloverIntervaSeconds=5"));
}

@Test
void testAddLogfileAndIsIdle() {
LocalFileLogBuffer.DestinationDispatcherThread<AuditEventBase> dispatcherThread =
new LocalFileLogBuffer.DestinationDispatcherThread<>(logBuffer, mockDestination, mockTracer);

// Initially idle
assertTrue(dispatcherThread.isIdle());

// Add a logfile
dispatcherThread.addLogfile("dummy.log");
assertFalse(dispatcherThread.isIdle());
}

@Test
void testToStringMethod() {
LocalFileLogBuffer.DestinationDispatcherThread<AuditEventBase> dispatcherThread =
new LocalFileLogBuffer.DestinationDispatcherThread<>(logBuffer, mockDestination, mockTracer);

String str = dispatcherThread.toString();
assertTrue(str.contains("DestinationDispatcherThread"));
assertTrue(str.contains("ThreadName="));
}

@Test
void testOpenCurrentFile_FileNotFound() throws Exception {
LocalFileLogBuffer.DestinationDispatcherThread<AuditEventBase> dispatcherThread =
new LocalFileLogBuffer.DestinationDispatcherThread<>(logBuffer, mockDestination, mockTracer);

Field currentLogfileField = dispatcherThread.getClass().getDeclaredField("mCurrentLogfile");
currentLogfileField.setAccessible(true);
currentLogfileField.set(dispatcherThread, "nonexistent-file.log");

Method openCurrentFileMethod = dispatcherThread.getClass().getDeclaredMethod("openCurrentFile");
openCurrentFileMethod.setAccessible(true);
Object result = openCurrentFileMethod.invoke(dispatcherThread);

assertNull(result);
}

@Test
void testCloseCurrentFile_NullReader() throws Exception {
LocalFileLogBuffer.DestinationDispatcherThread<AuditEventBase> dispatcherThread =
new LocalFileLogBuffer.DestinationDispatcherThread<>(logBuffer, mockDestination, mockTracer);

Method closeCurrentFileMethod = dispatcherThread.getClass().getDeclaredMethod("closeCurrentFile", BufferedReader.class);
closeCurrentFileMethod.setAccessible(true);

// Should not throw
closeCurrentFileMethod.invoke(dispatcherThread, new Object[] {null});
}

@Test
void testArchiveCurrentFile_FileDoesNotExist() throws Exception {
LocalFileLogBuffer.DestinationDispatcherThread<AuditEventBase> dispatcherThread =
new LocalFileLogBuffer.DestinationDispatcherThread<>(logBuffer, mockDestination, mockTracer);

Field currentLogfileField = dispatcherThread.getClass().getDeclaredField("mCurrentLogfile");
currentLogfileField.setAccessible(true);
currentLogfileField.set(dispatcherThread, tempDir.resolve("doesnotexist.log").toString());

Method archiveCurrentFileMethod = dispatcherThread.getClass().getDeclaredMethod("archiveCurrentFile");
archiveCurrentFileMethod.setAccessible(true);

// Should not throw
archiveCurrentFileMethod.invoke(dispatcherThread);
}

@Test
void testSendCurrentFile_EmptyFile() throws Exception {
File logFile = tempDir.resolve("empty.log").toFile();
logFile.createNewFile();

LocalFileLogBuffer.DestinationDispatcherThread<AuditEventBase> dispatcherThread =
new LocalFileLogBuffer.DestinationDispatcherThread<>(logBuffer, mockDestination, mockTracer);

Field currentLogfileField = dispatcherThread.getClass().getDeclaredField("mCurrentLogfile");
currentLogfileField.setAccessible(true);
currentLogfileField.set(dispatcherThread, logFile.getAbsolutePath());

Method sendCurrentFileMethod = dispatcherThread.getClass().getDeclaredMethod("sendCurrentFile");
sendCurrentFileMethod.setAccessible(true);

assertTrue((Boolean) sendCurrentFileMethod.invoke(dispatcherThread));
}
}
Loading