This is an automated email from the ASF dual-hosted git repository.

pdallig pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/zeppelin.git


The following commit(s) were added to refs/heads/master by this push:
     new 8403dcca59 [ZEPPELIN-6201] Add unit tests for utils classes: 
ServerUtils, ExceptionUtils, CommandLineUtils, AnyOfRolesUserAuthorizationFilter
8403dcca59 is described below

commit 8403dcca593fa3efed11bf94d4e60c9a6dd8d101
Author: Gyeongtae Park <67095975+parkgyeong...@users.noreply.github.com>
AuthorDate: Tue Jul 1 02:25:20 2025 +0900

    [ZEPPELIN-6201] Add unit tests for utils classes: ServerUtils, 
ExceptionUtils, CommandLineUtils, AnyOfRolesUserAuthorizationFilter
    
    ### What is this PR for?
    This PR adds missing unit test coverage for several utility classes in the 
`org.apache.zeppelin.utils` package.
    Previously, these classes had no dedicated test cases, which limited 
maintainability and regression detection.
    
    The following classes are now covered with JUnit 5 and Mockito-based tests:
    - `ServerUtils`
    - `ExceptionUtils`
    - `CommandLineUtils`
    - `AnyOfRolesUserAuthorizationFilter`
    
    All tests follow the “Given – When – Then” format for clarity and 
consistency.
    
    ### What type of PR is it?
    Improvement
    
    ### Todos
    * [x] - Add `ServerUtilsTest`
    * [x] - Add `ExceptionUtilsTest`
    * [x] - Add `CommandLineUtilsTest`
    * [x] - Add `AnyOfRolesUserAuthorizationFilterTest`
    
    ### What is the Jira issue?
    * Jira : https://issues.apache.org/jira/browse/ZEPPELIN/ZEPPELIN-6201
    
    ### How should this be tested?
    Run the following command:
    
    ```bash
    ./mvnw -pl zeppelin-server \
    
-Dtest=AnyOfRolesUserAuthorizationFilterTest,CommandLineUtilsTest,ExceptionUtilsTest,ServerUtilsTest
 \
    test
    ```
    
    ### Screenshots (if appropriate)
    
![image](https://github.com/user-attachments/assets/1d5d9b5d-bf0e-4ba5-8cfd-420efbfde9c3)
    
    
    ### Questions:
    * Does the license files need to update? No.
    * Is there breaking changes for older versions? No.
    * Does this needs documentation? No.
    
    
    Closes #4946 from ParkGyeongTae/ZEPPELIN-6201.
    
    Signed-off-by: Philipp Dallig <philipp.dal...@gmail.com>
---
 .../AnyOfRolesUserAuthorizationFilterTest.java     | 121 +++++++++++++++++++++
 .../zeppelin/utils/CommandLineUtilsTest.java       |  91 ++++++++++++++++
 .../apache/zeppelin/utils/ExceptionUtilsTest.java  |  71 ++++++++++++
 .../org/apache/zeppelin/utils/ServerUtilsTest.java |  84 ++++++++++++++
 4 files changed, 367 insertions(+)

diff --git 
a/zeppelin-server/src/test/java/org/apache/zeppelin/utils/AnyOfRolesUserAuthorizationFilterTest.java
 
b/zeppelin-server/src/test/java/org/apache/zeppelin/utils/AnyOfRolesUserAuthorizationFilterTest.java
new file mode 100644
index 0000000000..d658e192ae
--- /dev/null
+++ 
b/zeppelin-server/src/test/java/org/apache/zeppelin/utils/AnyOfRolesUserAuthorizationFilterTest.java
@@ -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.zeppelin.utils;
+
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import org.apache.shiro.subject.Subject;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.anyString;
+
+/**
+ * Unit tests for {@link AnyOfRolesUserAuthorizationFilter}
+ * written in Given-When-Then (GWT) style.
+ */
+class AnyOfRolesUserAuthorizationFilterTest {
+
+    // 
---------------------------------------------------------------------------
+    // Helper: create a filter whose getSubject(...) returns the supplied 
subject
+    // 
---------------------------------------------------------------------------
+    private AnyOfRolesUserAuthorizationFilter filterWith(Subject subject) {
+        return new AnyOfRolesUserAuthorizationFilter() {
+            @Override
+            protected Subject getSubject(ServletRequest request, 
ServletResponse response) {
+                return subject;            // inject mock subject
+            }
+        };
+    }
+
+    @Test
+    @DisplayName("Given no roles mapped, when isAccessAllowed is called, then 
it returns true")
+    void givenNoRoles_whenIsAccessAllowed_thenTrue() {
+        // ----- Given -----
+        Subject subject = mock(Subject.class);
+        AnyOfRolesUserAuthorizationFilter filter = filterWith(subject);
+
+        // ----- When -----
+        boolean allowed = filter.isAccessAllowed(mock(ServletRequest.class),
+                mock(ServletResponse.class),
+                null /* mappedValue */);
+
+        // ----- Then -----
+        assertTrue(allowed);
+    }
+
+    @Test
+    @DisplayName("Given one matching role, when isAccessAllowed is called, 
then it returns true")
+    void givenSubjectHasRole_whenIsAccessAllowed_thenTrue() {
+        // ----- Given -----
+        Subject subject = mock(Subject.class);
+        when(subject.hasRole("admin")).thenReturn(true);
+        AnyOfRolesUserAuthorizationFilter filter = filterWith(subject);
+
+        // ----- When -----
+        boolean allowed = filter.isAccessAllowed(mock(ServletRequest.class),
+                mock(ServletResponse.class),
+                new String[]{"admin", "dev"});
+
+        // ----- Then -----
+        assertTrue(allowed);
+    }
+
+    @Test
+    @DisplayName("Given principal equals one role, when isAccessAllowed is 
called, " +
+            "then it returns true")
+    void givenPrincipalMatchesRole_whenIsAccessAllowed_thenTrue() {
+        // ----- Given -----
+        Subject subject = mock(Subject.class);
+        when(subject.hasRole(anyString())).thenReturn(false);
+        when(subject.getPrincipal()).thenReturn("data_scientist");
+        AnyOfRolesUserAuthorizationFilter filter = filterWith(subject);
+
+        // ----- When -----
+        boolean allowed = filter.isAccessAllowed(mock(ServletRequest.class),
+                mock(ServletResponse.class),
+                new String[]{"guest", "data_scientist"});
+
+        // ----- Then -----
+        assertTrue(allowed);
+    }
+
+    @Test
+    @DisplayName("Given no roles or principal match, when isAccessAllowed is 
called, " +
+            "then it returns false")
+    void givenNoMatch_whenIsAccessAllowed_thenFalse() {
+        // ----- Given -----
+        Subject subject = mock(Subject.class);
+        when(subject.hasRole("qa")).thenReturn(false);
+        when(subject.hasRole("ops")).thenReturn(false);
+        when(subject.getPrincipal()).thenReturn("john_doe");
+        AnyOfRolesUserAuthorizationFilter filter = filterWith(subject);
+
+        // ----- When -----
+        boolean allowed = filter.isAccessAllowed(mock(ServletRequest.class),
+                mock(ServletResponse.class),
+                new String[]{"qa", "ops"});
+
+        // ----- Then -----
+        assertFalse(allowed);
+    }
+}
diff --git 
a/zeppelin-server/src/test/java/org/apache/zeppelin/utils/CommandLineUtilsTest.java
 
b/zeppelin-server/src/test/java/org/apache/zeppelin/utils/CommandLineUtilsTest.java
new file mode 100644
index 0000000000..2c309c2a1d
--- /dev/null
+++ 
b/zeppelin-server/src/test/java/org/apache/zeppelin/utils/CommandLineUtilsTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.zeppelin.utils;
+
+import org.apache.zeppelin.util.Util;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Unit tests for {@link CommandLineUtils} written in Given-When-Then style.
+ */
+class CommandLineUtilsTest {
+
+    /**
+     * Captures standard output during test execution.
+     */
+    private final ByteArrayOutputStream outContent = new 
ByteArrayOutputStream();
+
+    /**
+     * Original System.out kept for restoration.
+     */
+    private final PrintStream originalOut = System.out;
+
+    @AfterEach
+    void restoreStdout() {
+        // Restore the original System.out after each test
+        System.setOut(originalOut);
+    }
+
+    @Test
+    @DisplayName("Given --version flag, when main is executed, then version is 
printed")
+    void givenVersionFlag_whenMain_thenPrintsVersion() {
+        // ----- Given -----
+        System.setOut(new PrintStream(outContent));
+        String expected = Util.getVersion();         // whatever the project 
returns
+
+        // ----- When -----
+        CommandLineUtils.main(new String[]{"--version"});
+
+        // ----- Then -----
+        assertEquals(expected, outContent.toString().trim());
+    }
+
+    @Test
+    @DisplayName("Given -v flag, when main is executed, then version is 
printed")
+    void givenShortVersionFlag_whenMain_thenPrintsVersion() {
+        // ----- Given -----
+        System.setOut(new PrintStream(outContent));
+        String expected = Util.getVersion();
+
+        // ----- When -----
+        CommandLineUtils.main(new String[]{"-v"});
+
+        // ----- Then -----
+        assertEquals(expected, outContent.toString().trim());
+    }
+
+    @Test
+    @DisplayName("Given no arguments, when main is executed, then nothing is 
printed")
+    void givenNoArgs_whenMain_thenPrintsNothing() {
+        // ----- Given -----
+        System.setOut(new PrintStream(outContent));
+
+        // ----- When -----
+        CommandLineUtils.main(new String[]{});
+
+        // ----- Then -----
+        assertEquals("", outContent.toString().trim());
+    }
+}
\ No newline at end of file
diff --git 
a/zeppelin-server/src/test/java/org/apache/zeppelin/utils/ExceptionUtilsTest.java
 
b/zeppelin-server/src/test/java/org/apache/zeppelin/utils/ExceptionUtilsTest.java
new file mode 100644
index 0000000000..bbc0a48c09
--- /dev/null
+++ 
b/zeppelin-server/src/test/java/org/apache/zeppelin/utils/ExceptionUtilsTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.zeppelin.utils;
+
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Unit tests for {@link ExceptionUtils} written in Given-When-Then style.
+ */
+class ExceptionUtilsTest {
+
+    @Test
+    @DisplayName("Given a status, when jsonResponse is called, then the 
response has that status")
+    void givenStatus_whenJsonResponse_thenStatusCodeMatches() {
+        // ----- Given -----
+        Status expectedStatus = Status.BAD_REQUEST;
+
+        // ----- When -----
+        Response response = ExceptionUtils.jsonResponse(expectedStatus);
+
+        // ----- Then -----
+        assertEquals(expectedStatus.getStatusCode(), response.getStatus());
+
+        // entity is a JsonResponse<?>; convert to JSON string via toString()
+        String json = response.getEntity().toString();
+        assertTrue(json.contains("\"status\":\"" + expectedStatus.name() + 
"\""),
+                "JSON should contain the enum name in \"status\"");
+    }
+
+    @Test
+    @DisplayName("Given a status and message, when jsonResponseContent is 
called, " +
+            "then JSON contains both")
+    void givenStatusAndMessage_whenJsonResponseContent_thenJsonContainsBoth() {
+        // ----- Given -----
+        Status expectedStatus = Status.NOT_FOUND;
+        String expectedMessage = "Resource not found";
+
+        // ----- When -----
+        Response response = ExceptionUtils.jsonResponseContent(expectedStatus, 
expectedMessage);
+
+        // ----- Then -----
+        assertEquals(expectedStatus.getStatusCode(), response.getStatus());
+
+        String json = response.getEntity().toString();
+        assertTrue(json.contains("\"status\":\"" + expectedStatus.name() + 
"\""),
+                "JSON should contain the enum name in \"status\"");
+        assertTrue(json.contains(expectedMessage),
+                "JSON should contain the custom message");
+    }
+}
\ No newline at end of file
diff --git 
a/zeppelin-server/src/test/java/org/apache/zeppelin/utils/ServerUtilsTest.java 
b/zeppelin-server/src/test/java/org/apache/zeppelin/utils/ServerUtilsTest.java
new file mode 100644
index 0000000000..8fa35fc707
--- /dev/null
+++ 
b/zeppelin-server/src/test/java/org/apache/zeppelin/utils/ServerUtilsTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.zeppelin.utils;
+
+import jakarta.websocket.Session;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * Unit tests for {@link ServerUtils#getRemoteAddress(Session)} written in
+ * Given-When-Then style.
+ */
+class ServerUtilsTest {
+
+    private static final String KEY = 
"jakarta.websocket.endpoint.remoteAddress";
+
+    @Test
+    @DisplayName("Given a session with remoteAddress, when getRemoteAddress is 
called, " +
+            "then it returns the address")
+    void givenSessionWithAddress_whenGetRemoteAddress_thenReturnAddress() {
+        // ----- Given -----
+        Session session = mock(Session.class);
+        Map<String, Object> props = new HashMap<>();
+        props.put(KEY, "127.0.0.1");
+        when(session.getUserProperties()).thenReturn(props);
+
+        // ----- When -----
+        String actual = ServerUtils.getRemoteAddress(session);
+
+        // ----- Then -----
+        assertEquals("127.0.0.1", actual);
+    }
+
+    @Test
+    @DisplayName("Given a session without remoteAddress, when getRemoteAddress 
is called, " +
+            "then it returns \"null\"")
+    void 
givenSessionWithoutAddress_whenGetRemoteAddress_thenReturnNullString() {
+        // ----- Given -----
+        Session session = mock(Session.class);
+        when(session.getUserProperties()).thenReturn(new HashMap<>());
+
+        // ----- When -----
+        String actual = ServerUtils.getRemoteAddress(session);
+
+        // ----- Then -----
+        assertEquals("null", actual);   // expects the literal string "null"
+    }
+
+    @Test
+    @DisplayName("Given a null session, when getRemoteAddress is called, " +
+            "then it returns \"unknown\"")
+    void givenNullSession_whenGetRemoteAddress_thenReturnUnknown() {
+        // ----- Given -----
+        Session session = null;
+
+        // ----- When -----
+        String actual = ServerUtils.getRemoteAddress(session);
+
+        // ----- Then -----
+        assertEquals("unknown", actual);
+    }
+}

Reply via email to