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)  ### 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); + } +}