diff --git a/hadoop-hdds/managed-rocksdb/src/test/java/org/apache/hadoop/hdds/utils/db/TestRocksDatabaseException.java b/hadoop-hdds/managed-rocksdb/src/test/java/org/apache/hadoop/hdds/utils/db/TestRocksDatabaseException.java new file mode 100644 index 000000000000..7a4bcddf64e0 --- /dev/null +++ b/hadoop-hdds/managed-rocksdb/src/test/java/org/apache/hadoop/hdds/utils/db/TestRocksDatabaseException.java @@ -0,0 +1,63 @@ +/* + * 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.hadoop.hdds.utils.db; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; +import org.junit.jupiter.api.Test; +import org.rocksdb.RocksDBException; + +/** + * Tests for RocksDatabaseException. + */ +public class TestRocksDatabaseException { + + @Test + public void testConstructorWithMessage() { + RocksDatabaseException ex = new RocksDatabaseException("test error"); + assertThat(ex.getMessage()).isEqualTo("test error"); + assertThat(ex.getCause()).isNull(); + assertThat(ex).isInstanceOf(IOException.class); + } + + @Test + public void testDefaultConstructor() { + RocksDatabaseException ex = new RocksDatabaseException(); + assertThat(ex.getMessage()).isNull(); + assertThat(ex.getCause()).isNull(); + } + + @Test + public void testConstructorWithGenericCause() { + Exception cause = new RuntimeException("generic error"); + RocksDatabaseException ex = new RocksDatabaseException( + "wrapped error", cause); + assertThat(ex.getMessage()).isEqualTo("wrapped error"); + assertThat(ex.getCause()).isEqualTo(cause); + } + + @Test + public void testConstructorWithRocksDBException() { + RocksDBException cause = new RocksDBException("rocksdb failure"); + RocksDatabaseException ex = new RocksDatabaseException( + "operation failed", cause); + assertThat(ex.getMessage()).contains("operation failed"); + assertThat(ex.getCause()).isEqualTo(cause); + } +} diff --git a/hadoop-ozone/httpfsgateway/src/test/java/org/apache/ozone/fs/http/server/TestCheckUploadContentTypeFilter.java b/hadoop-ozone/httpfsgateway/src/test/java/org/apache/ozone/fs/http/server/TestCheckUploadContentTypeFilter.java new file mode 100644 index 000000000000..5fa9b0045ca9 --- /dev/null +++ b/hadoop-ozone/httpfsgateway/src/test/java/org/apache/ozone/fs/http/server/TestCheckUploadContentTypeFilter.java @@ -0,0 +1,154 @@ +/* + * 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.ozone.fs.http.server; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.PrintWriter; +import java.io.StringWriter; +import javax.servlet.FilterChain; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.apache.ozone.fs.http.HttpFSConstants; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +/** + * Tests for CheckUploadContentTypeFilter. + */ +public class TestCheckUploadContentTypeFilter { + + private CheckUploadContentTypeFilter filter; + private HttpServletRequest request; + private HttpServletResponse response; + private FilterChain chain; + + @BeforeEach + public void setUp() { + filter = new CheckUploadContentTypeFilter(); + request = mock(HttpServletRequest.class); + response = mock(HttpServletResponse.class); + chain = mock(FilterChain.class); + } + + @Test + public void testGetRequestPassesThrough() throws Exception { + when(request.getMethod()).thenReturn("GET"); + filter.doFilter(request, response, chain); + verify(chain).doFilter(request, response); + } + + @Test + public void testDeleteRequestPassesThrough() throws Exception { + when(request.getMethod()).thenReturn("DELETE"); + filter.doFilter(request, response, chain); + verify(chain).doFilter(request, response); + } + + @Test + public void testPutWithNonUploadOpPassesThrough() throws Exception { + when(request.getMethod()).thenReturn("PUT"); + when(request.getParameter(HttpFSConstants.OP_PARAM)).thenReturn("MKDIRS"); + filter.doFilter(request, response, chain); + verify(chain).doFilter(request, response); + } + + @Test + public void testPutCreateWithDataFalsePassesThrough() throws Exception { + when(request.getMethod()).thenReturn("PUT"); + when(request.getParameter(HttpFSConstants.OP_PARAM)).thenReturn("CREATE"); + when(request.getParameter(HttpFSParametersProvider.DataParam.NAME)).thenReturn("false"); + filter.doFilter(request, response, chain); + verify(chain).doFilter(request, response); + } + + @Test + public void testPutCreateWithDataTrueAndCorrectContentType() throws Exception { + when(request.getMethod()).thenReturn("PUT"); + when(request.getParameter(HttpFSConstants.OP_PARAM)).thenReturn("CREATE"); + when(request.getParameter(HttpFSParametersProvider.DataParam.NAME)).thenReturn("true"); + when(request.getContentType()).thenReturn(HttpFSConstants.UPLOAD_CONTENT_TYPE); + filter.doFilter(request, response, chain); + verify(chain).doFilter(request, response); + } + + @Test + public void testPutCreateWithDataTrueAndWrongContentType() throws Exception { + when(request.getMethod()).thenReturn("PUT"); + when(request.getParameter(HttpFSConstants.OP_PARAM)).thenReturn("CREATE"); + when(request.getParameter(HttpFSParametersProvider.DataParam.NAME)).thenReturn("true"); + when(request.getContentType()).thenReturn("text/plain"); + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + when(response.getWriter()).thenReturn(pw); + + filter.doFilter(request, response, chain); + + verify(chain, never()).doFilter(request, response); + verify(response).setStatus(HttpServletResponse.SC_BAD_REQUEST); + } + + @Test + public void testPostAppendWithDataTrueAndCorrectContentType() throws Exception { + when(request.getMethod()).thenReturn("POST"); + when(request.getParameter(HttpFSConstants.OP_PARAM)).thenReturn("APPEND"); + when(request.getParameter(HttpFSParametersProvider.DataParam.NAME)).thenReturn("true"); + when(request.getContentType()).thenReturn(HttpFSConstants.UPLOAD_CONTENT_TYPE); + filter.doFilter(request, response, chain); + verify(chain).doFilter(request, response); + } + + @Test + public void testPostAppendWithDataTrueAndWrongContentType() throws Exception { + when(request.getMethod()).thenReturn("POST"); + when(request.getParameter(HttpFSConstants.OP_PARAM)).thenReturn("APPEND"); + when(request.getParameter(HttpFSParametersProvider.DataParam.NAME)).thenReturn("true"); + when(request.getContentType()).thenReturn("text/plain"); + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + when(response.getWriter()).thenReturn(pw); + + filter.doFilter(request, response, chain); + + verify(chain, never()).doFilter(request, response); + verify(response).setStatus(HttpServletResponse.SC_BAD_REQUEST); + } + + @Test + public void testPutWithNullOpPassesThrough() throws Exception { + when(request.getMethod()).thenReturn("PUT"); + when(request.getParameter(HttpFSConstants.OP_PARAM)).thenReturn(null); + filter.doFilter(request, response, chain); + verify(chain).doFilter(request, response); + } + + @Test + public void testPutCreateCaseInsensitiveOp() throws Exception { + when(request.getMethod()).thenReturn("PUT"); + when(request.getParameter(HttpFSConstants.OP_PARAM)).thenReturn("create"); + when(request.getParameter(HttpFSParametersProvider.DataParam.NAME)).thenReturn("true"); + when(request.getContentType()).thenReturn(HttpFSConstants.UPLOAD_CONTENT_TYPE); + filter.doFilter(request, response, chain); + verify(chain).doFilter(request, response); + } +} diff --git a/hadoop-ozone/httpfsgateway/src/test/java/org/apache/ozone/fs/http/server/TestHttpFSExceptionProvider.java b/hadoop-ozone/httpfsgateway/src/test/java/org/apache/ozone/fs/http/server/TestHttpFSExceptionProvider.java new file mode 100644 index 000000000000..d565d0935995 --- /dev/null +++ b/hadoop-ozone/httpfsgateway/src/test/java/org/apache/ozone/fs/http/server/TestHttpFSExceptionProvider.java @@ -0,0 +1,111 @@ +/* + * 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.ozone.fs.http.server; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.FileNotFoundException; +import java.io.IOException; +import javax.ws.rs.core.Response; +import org.apache.ozone.lib.service.FileSystemAccessException; +import org.apache.ozone.lib.wsrs.ExceptionProvider; +import org.junit.jupiter.api.Test; + +/** + * Tests for HttpFSExceptionProvider and ExceptionProvider. + */ +public class TestHttpFSExceptionProvider { + + @Test + public void testSecurityException() { + HttpFSExceptionProvider provider = new HttpFSExceptionProvider(); + Response response = provider.toResponse(new SecurityException("denied")); + assertThat(response.getStatus()).isEqualTo(Response.Status.UNAUTHORIZED.getStatusCode()); + } + + @Test + public void testFileNotFoundException() { + HttpFSExceptionProvider provider = new HttpFSExceptionProvider(); + Response response = provider.toResponse(new FileNotFoundException("missing")); + assertThat(response.getStatus()).isEqualTo(Response.Status.NOT_FOUND.getStatusCode()); + } + + @Test + public void testIOException() { + HttpFSExceptionProvider provider = new HttpFSExceptionProvider(); + Response response = provider.toResponse(new IOException("io error")); + assertThat(response.getStatus()).isEqualTo(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); + } + + @Test + public void testUnsupportedOperationException() { + HttpFSExceptionProvider provider = new HttpFSExceptionProvider(); + Response response = provider.toResponse(new UnsupportedOperationException("not supported")); + assertThat(response.getStatus()).isEqualTo(Response.Status.BAD_REQUEST.getStatusCode()); + } + + @Test + public void testIllegalArgumentException() { + HttpFSExceptionProvider provider = new HttpFSExceptionProvider(); + Response response = provider.toResponse(new IllegalArgumentException("bad arg")); + assertThat(response.getStatus()).isEqualTo(Response.Status.BAD_REQUEST.getStatusCode()); + } + + @Test + public void testGenericException() { + HttpFSExceptionProvider provider = new HttpFSExceptionProvider(); + Response response = provider.toResponse(new RuntimeException("unexpected")); + assertThat(response.getStatus()).isEqualTo(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); + } + + @Test + public void testFileSystemAccessExceptionUnwrapsToFileNotFound() { + HttpFSExceptionProvider provider = new HttpFSExceptionProvider(); + FileSystemAccessException fsae = new FileSystemAccessException( + FileSystemAccessException.ERROR.H08, new FileNotFoundException("missing")); + Response response = provider.toResponse(fsae); + assertThat(response.getStatus()).isEqualTo(Response.Status.NOT_FOUND.getStatusCode()); + } + + @Test + public void testBaseExceptionProvider() { + ExceptionProvider provider = new ExceptionProvider(); + Response response = provider.toResponse(new RuntimeException("test")); + assertThat(response.getStatus()).isEqualTo(Response.Status.BAD_REQUEST.getStatusCode()); + } + + @Test + public void testGetOneLineMessage() { + TestableExceptionProvider provider = new TestableExceptionProvider(); + String message = provider.extractOneLineMessage(new RuntimeException("line1\nline2")); + assertThat(message).isEqualTo("line1"); + } + + @Test + public void testGetOneLineMessageNull() { + TestableExceptionProvider provider = new TestableExceptionProvider(); + String message = provider.extractOneLineMessage(new RuntimeException((String) null)); + assertThat(message).isNull(); + } + + private static class TestableExceptionProvider extends ExceptionProvider { + String extractOneLineMessage(Throwable throwable) { + return getOneLineMessage(throwable); + } + } +} diff --git a/hadoop-ozone/httpfsgateway/src/test/java/org/apache/ozone/lib/wsrs/TestParams.java b/hadoop-ozone/httpfsgateway/src/test/java/org/apache/ozone/lib/wsrs/TestParams.java new file mode 100644 index 000000000000..8a724a9cb7bf --- /dev/null +++ b/hadoop-ozone/httpfsgateway/src/test/java/org/apache/ozone/lib/wsrs/TestParams.java @@ -0,0 +1,431 @@ +/* + * 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.ozone.lib.wsrs; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; +import org.junit.jupiter.api.Test; + +/** + * Tests for the Param hierarchy and Parameters container. + */ +public class TestParams { + + // Concrete subclasses for testing abstract param types. + + private static class TestBooleanParam extends BooleanParam { + TestBooleanParam() { + super("testBool", false); + } + } + + private static class TestIntegerParam extends IntegerParam { + TestIntegerParam() { + super("testInt", 0); + } + } + + private static class TestLongParam extends LongParam { + TestLongParam() { + super("testLong", 0L); + } + } + + private static class TestShortParam extends ShortParam { + TestShortParam() { + super("testShort", (short) 0); + } + } + + private static class TestShortOctalParam extends ShortParam { + TestShortOctalParam() { + super("testShortOctal", (short) 0, 8); + } + } + + private enum Color { RED, GREEN, BLUE } + + private static class TestEnumParam extends EnumParam { + TestEnumParam() { + super("testEnum", Color.class, Color.RED); + } + } + + private static class TestEnumSetParam extends EnumSetParam { + TestEnumSetParam() { + super("testEnumSet", Color.class, EnumSet.noneOf(Color.class)); + } + } + + private static class TestStringParam extends StringParam { + TestStringParam() { + super("testStr", null); + } + } + + private static class TestPatternStringParam extends StringParam { + TestPatternStringParam() { + super("testPatternStr", null, Pattern.compile("[a-z]+")); + } + } + + // --- BooleanParam --- + + @Test + public void testBooleanParseTrue() { + TestBooleanParam p = new TestBooleanParam(); + p.parseParam("true"); + assertThat(p.value()).isTrue(); + } + + @Test + public void testBooleanParseTrueCaseInsensitive() { + TestBooleanParam p = new TestBooleanParam(); + p.parseParam("TRUE"); + assertThat(p.value()).isTrue(); + } + + @Test + public void testBooleanParseFalse() { + TestBooleanParam p = new TestBooleanParam(); + p.parseParam("false"); + assertThat(p.value()).isFalse(); + } + + @Test + public void testBooleanParseInvalid() { + TestBooleanParam p = new TestBooleanParam(); + assertThatThrownBy(() -> p.parseParam("notaboolean")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void testBooleanDefault() { + TestBooleanParam p = new TestBooleanParam(); + assertThat(p.value()).isFalse(); + assertThat(p.getName()).isEqualTo("testBool"); + } + + @Test + public void testBooleanDomain() { + TestBooleanParam p = new TestBooleanParam(); + assertThat(p.getDomain()).isEqualTo("a boolean"); + } + + @Test + public void testBooleanParseBlankKeepsDefault() { + TestBooleanParam p = new TestBooleanParam(); + p.parseParam(" "); + assertThat(p.value()).isFalse(); + } + + // --- IntegerParam --- + + @Test + public void testIntegerParse() { + TestIntegerParam p = new TestIntegerParam(); + p.parseParam("42"); + assertThat(p.value()).isEqualTo(42); + } + + @Test + public void testIntegerParseNegative() { + TestIntegerParam p = new TestIntegerParam(); + p.parseParam("-10"); + assertThat(p.value()).isEqualTo(-10); + } + + @Test + public void testIntegerParseInvalid() { + TestIntegerParam p = new TestIntegerParam(); + assertThatThrownBy(() -> p.parseParam("abc")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void testIntegerDomain() { + TestIntegerParam p = new TestIntegerParam(); + assertThat(p.getDomain()).isEqualTo("an integer"); + } + + // --- LongParam --- + + @Test + public void testLongParse() { + TestLongParam p = new TestLongParam(); + p.parseParam("9876543210"); + assertThat(p.value()).isEqualTo(9876543210L); + } + + @Test + public void testLongParseInvalid() { + TestLongParam p = new TestLongParam(); + assertThatThrownBy(() -> p.parseParam("not_a_long")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void testLongDomain() { + TestLongParam p = new TestLongParam(); + assertThat(p.getDomain()).isEqualTo("a long"); + } + + // --- ShortParam --- + + @Test + public void testShortParse() { + TestShortParam p = new TestShortParam(); + p.parseParam("100"); + assertThat(p.value()).isEqualTo((short) 100); + } + + @Test + public void testShortParseOctal() { + TestShortOctalParam p = new TestShortOctalParam(); + p.parseParam("755"); + assertThat(p.value()).isEqualTo(Short.parseShort("755", 8)); + } + + @Test + public void testShortParseInvalid() { + TestShortParam p = new TestShortParam(); + assertThatThrownBy(() -> p.parseParam("xyz")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void testShortDomain() { + TestShortParam p = new TestShortParam(); + assertThat(p.getDomain()).isEqualTo("a short"); + } + + // --- EnumParam --- + + @Test + public void testEnumParse() { + TestEnumParam p = new TestEnumParam(); + p.parseParam("GREEN"); + assertThat(p.value()).isEqualTo(Color.GREEN); + } + + @Test + public void testEnumParseLowercase() { + TestEnumParam p = new TestEnumParam(); + p.parseParam("blue"); + assertThat(p.value()).isEqualTo(Color.BLUE); + } + + @Test + public void testEnumParseInvalid() { + TestEnumParam p = new TestEnumParam(); + assertThatThrownBy(() -> p.parseParam("YELLOW")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void testEnumDefault() { + TestEnumParam p = new TestEnumParam(); + assertThat(p.value()).isEqualTo(Color.RED); + } + + @Test + public void testEnumDomain() { + TestEnumParam p = new TestEnumParam(); + assertThat(p.getDomain()).contains("RED"); + assertThat(p.getDomain()).contains("GREEN"); + assertThat(p.getDomain()).contains("BLUE"); + } + + // --- EnumSetParam --- + + @Test + public void testEnumSetParseSingle() { + TestEnumSetParam p = new TestEnumSetParam(); + p.parseParam("RED"); + assertThat(p.value()).containsExactly(Color.RED); + } + + @Test + public void testEnumSetParseMultiple() { + TestEnumSetParam p = new TestEnumSetParam(); + p.parseParam("RED,BLUE"); + assertThat(p.value()).containsExactlyInAnyOrder(Color.RED, Color.BLUE); + } + + @Test + public void testEnumSetParseWithSpaces() { + TestEnumSetParam p = new TestEnumSetParam(); + p.parseParam("red , green"); + assertThat(p.value()).containsExactlyInAnyOrder(Color.RED, Color.GREEN); + } + + @Test + public void testEnumSetParseInvalid() { + TestEnumSetParam p = new TestEnumSetParam(); + assertThatThrownBy(() -> p.parseParam("YELLOW")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void testEnumSetToString() { + EnumSet set = EnumSet.of(Color.RED, Color.BLUE); + assertThat(EnumSetParam.toString(set)).contains("RED"); + assertThat(EnumSetParam.toString(set)).contains("BLUE"); + } + + @Test + public void testEnumSetToStringEmpty() { + assertThat(EnumSetParam.toString(EnumSet.noneOf(Color.class))).isEmpty(); + assertThat(EnumSetParam.toString(null)).isEmpty(); + } + + @Test + public void testEnumSetDomain() { + TestEnumSetParam p = new TestEnumSetParam(); + assertThat(p.getDomain()).contains("RED"); + assertThat(p.getDomain()).contains("GREEN"); + assertThat(p.getDomain()).contains("BLUE"); + } + + // --- StringParam --- + + @Test + public void testStringParse() { + TestStringParam p = new TestStringParam(); + p.parseParam("hello"); + assertThat(p.value()).isEqualTo("hello"); + } + + @Test + public void testStringParseNull() { + TestStringParam p = new TestStringParam(); + p.parseParam(null); + assertThat(p.value()).isNull(); + } + + @Test + public void testStringParseEmpty() { + TestStringParam p = new TestStringParam(); + p.parseParam(""); + assertThat(p.value()).isNull(); + } + + @Test + public void testStringParseTrimmed() { + TestStringParam p = new TestStringParam(); + p.parseParam(" hello "); + assertThat(p.value()).isEqualTo("hello"); + } + + @Test + public void testStringWithPatternValid() { + TestPatternStringParam p = new TestPatternStringParam(); + p.parseParam("abc"); + assertThat(p.value()).isEqualTo("abc"); + } + + @Test + public void testStringWithPatternInvalid() { + TestPatternStringParam p = new TestPatternStringParam(); + assertThatThrownBy(() -> p.parseParam("ABC123")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void testStringDomain() { + TestStringParam p = new TestStringParam(); + assertThat(p.getDomain()).isEqualTo("a string"); + } + + @Test + public void testStringPatternDomain() { + TestPatternStringParam p = new TestPatternStringParam(); + assertThat(p.getDomain()).isEqualTo("[a-z]+"); + } + + // --- Param.toString --- + + @Test + public void testParamToStringWithValue() { + TestIntegerParam p = new TestIntegerParam(); + p.parseParam("42"); + assertThat(p.toString()).isEqualTo("42"); + } + + @Test + public void testParamToStringNull() { + TestStringParam p = new TestStringParam(); + assertThat(p.toString()).isEqualTo("NULL"); + } + + // --- Parameters --- + + @Test + public void testParametersGet() { + TestIntegerParam intParam = new TestIntegerParam(); + intParam.parseParam("42"); + + Map>> paramMap = new HashMap<>(); + List> paramList = new ArrayList<>(); + paramList.add(intParam); + paramMap.put("testInt", paramList); + + Parameters params = new Parameters(paramMap); + Integer value = params.get("testInt", TestIntegerParam.class); + assertThat(value).isEqualTo(42); + } + + @Test + public void testParametersGetMissing() { + Parameters params = new Parameters(new HashMap<>()); + Integer value = params.get("missing", TestIntegerParam.class); + assertThat(value).isNull(); + } + + @Test + public void testParametersGetValues() { + TestStringParam p1 = new TestStringParam(); + p1.parseParam("a"); + TestStringParam p2 = new TestStringParam(); + p2.parseParam("b"); + + Map>> paramMap = new HashMap<>(); + List> paramList = new ArrayList<>(); + paramList.add(p1); + paramList.add(p2); + paramMap.put("testStr", paramList); + + Parameters params = new Parameters(paramMap); + List values = params.getValues("testStr", TestStringParam.class); + assertThat(values).containsExactly("a", "b"); + } + + @Test + public void testParametersGetValuesEmpty() { + Parameters params = new Parameters(new HashMap<>()); + List values = params.getValues("missing", TestStringParam.class); + assertThat(values).isEmpty(); + } +} diff --git a/hadoop-ozone/insight/src/test/java/org/apache/hadoop/ozone/insight/TestComponent.java b/hadoop-ozone/insight/src/test/java/org/apache/hadoop/ozone/insight/TestComponent.java new file mode 100644 index 000000000000..274e75322848 --- /dev/null +++ b/hadoop-ozone/insight/src/test/java/org/apache/hadoop/ozone/insight/TestComponent.java @@ -0,0 +1,144 @@ +/* + * 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.hadoop.ozone.insight; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.apache.hadoop.ozone.insight.Component.Type; +import org.junit.jupiter.api.Test; + +/** + * Tests for the Component data class. + */ +public class TestComponent { + + @Test + public void testTypeOnlyConstructor() { + Component c = new Component(Type.SCM); + assertThat(c.getName()).isEqualTo(Type.SCM); + assertThat(c.getId()).isNull(); + assertThat(c.getHostname()).isNull(); + assertThat(c.getPort()).isEqualTo(0); + } + + @Test + public void testTypeAndIdConstructor() { + Component c = new Component(Type.OM, "om-1"); + assertThat(c.getName()).isEqualTo(Type.OM); + assertThat(c.getId()).isEqualTo("om-1"); + } + + @Test + public void testTypeIdHostnameConstructor() { + Component c = new Component(Type.DATANODE, "dn-1", "host1.example.com"); + assertThat(c.getName()).isEqualTo(Type.DATANODE); + assertThat(c.getId()).isEqualTo("dn-1"); + assertThat(c.getHostname()).isEqualTo("host1.example.com"); + } + + @Test + public void testFullConstructor() { + Component c = new Component(Type.S3G, "s3g-1", "s3host", 9878); + assertThat(c.getName()).isEqualTo(Type.S3G); + assertThat(c.getId()).isEqualTo("s3g-1"); + assertThat(c.getHostname()).isEqualTo("s3host"); + assertThat(c.getPort()).isEqualTo(9878); + } + + @Test + public void testPrefixWithId() { + Component c = new Component(Type.SCM, "scm-1"); + assertThat(c.prefix()).isEqualTo("SCM-scm-1"); + } + + @Test + public void testPrefixWithoutId() { + Component c = new Component(Type.OM); + assertThat(c.prefix()).isEqualTo("OM"); + } + + @Test + public void testPrefixWithEmptyId() { + Component c = new Component(Type.OM, ""); + assertThat(c.prefix()).isEqualTo("OM"); + } + + @Test + public void testEqualsSameTypeAndId() { + Component c1 = new Component(Type.SCM, "id1"); + Component c2 = new Component(Type.SCM, "id1"); + assertThat(c1).isEqualTo(c2); + } + + @Test + public void testEqualsDifferentId() { + Component c1 = new Component(Type.SCM, "id1"); + Component c2 = new Component(Type.SCM, "id2"); + assertThat(c1).isNotEqualTo(c2); + } + + @Test + public void testEqualsDifferentType() { + Component c1 = new Component(Type.SCM, "id1"); + Component c2 = new Component(Type.OM, "id1"); + assertThat(c1).isNotEqualTo(c2); + } + + @Test + public void testEqualsNullId() { + Component c1 = new Component(Type.SCM); + Component c2 = new Component(Type.SCM); + assertThat(c1).isEqualTo(c2); + } + + @Test + public void testEqualsNull() { + Component c = new Component(Type.SCM); + assertThat(c).isNotEqualTo(null); + } + + @Test + public void testEqualsDifferentClass() { + Component c = new Component(Type.SCM); + assertThat(c).isNotEqualTo("not a component"); + } + + @Test + public void testHashCodeConsistent() { + Component c1 = new Component(Type.SCM, "id1"); + Component c2 = new Component(Type.SCM, "id1"); + assertThat(c1.hashCode()).isEqualTo(c2.hashCode()); + } + + @Test + public void testHashCodeDiffers() { + Component c1 = new Component(Type.SCM, "id1"); + Component c2 = new Component(Type.OM, "id2"); + assertThat(c1.hashCode()).isNotEqualTo(c2.hashCode()); + } + + @Test + public void testAllTypes() { + for (Type type : Type.values()) { + Component c = new Component(type); + assertThat(c.getName()).isEqualTo(type); + } + assertThat(Type.values()).containsExactly( + Type.SCM, Type.OM, Type.DATANODE, Type.S3G, Type.RECON); + } +} diff --git a/hadoop-ozone/insight/src/test/java/org/apache/hadoop/ozone/insight/TestMetricDisplayClasses.java b/hadoop-ozone/insight/src/test/java/org/apache/hadoop/ozone/insight/TestMetricDisplayClasses.java new file mode 100644 index 000000000000..3bfa0ab9a023 --- /dev/null +++ b/hadoop-ozone/insight/src/test/java/org/apache/hadoop/ozone/insight/TestMetricDisplayClasses.java @@ -0,0 +1,117 @@ +/* + * 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.hadoop.ozone.insight; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.HashMap; +import java.util.Map; +import org.apache.hadoop.ozone.insight.Component.Type; +import org.junit.jupiter.api.Test; + +/** + * Tests for MetricDisplay and MetricGroupDisplay. + */ +public class TestMetricDisplayClasses { + + // --- MetricDisplay --- + + @Test + public void testMetricDisplayTwoArgConstructor() { + MetricDisplay md = new MetricDisplay("Bytes received", "rpc_received_bytes"); + assertThat(md.getDescription()).isEqualTo("Bytes received"); + assertThat(md.getId()).isEqualTo("rpc_received_bytes"); + assertThat(md.getFilter()).isEmpty(); + } + + @Test + public void testMetricDisplayWithFilter() { + Map filter = new HashMap<>(); + filter.put("type", "CreateKey"); + MetricDisplay md = new MetricDisplay("Create calls", + "om_counter", filter); + assertThat(md.getDescription()).isEqualTo("Create calls"); + assertThat(md.getId()).isEqualTo("om_counter"); + assertThat(md.getFilter()).containsEntry("type", "CreateKey"); + } + + @Test + public void testMetricDisplayCheckLineReturnsFalse() { + MetricDisplay md = new MetricDisplay("test", "test_metric"); + assertThat(md.checkLine("any line")).isFalse(); + } + + // --- MetricGroupDisplay --- + + @Test + public void testMetricGroupDisplayWithComponent() { + Component component = new Component(Type.SCM, "scm-1"); + MetricGroupDisplay mgd = new MetricGroupDisplay(component, "Node counters"); + assertThat(mgd.getDescription()).isEqualTo("Node counters"); + assertThat(mgd.getComponent()).isEqualTo(component); + assertThat(mgd.getMetrics()).isEmpty(); + } + + @Test + public void testMetricGroupDisplayWithType() { + MetricGroupDisplay mgd = new MetricGroupDisplay(Type.OM, "RPC metrics"); + assertThat(mgd.getDescription()).isEqualTo("RPC metrics"); + assertThat(mgd.getComponent().getName()).isEqualTo(Type.OM); + } + + @Test + public void testMetricGroupDisplayAddMetrics() { + MetricGroupDisplay mgd = new MetricGroupDisplay(Type.SCM, "Connections"); + MetricDisplay md1 = new MetricDisplay("Open", "rpc_open"); + MetricDisplay md2 = new MetricDisplay("Closed", "rpc_closed"); + mgd.addMetrics(md1); + mgd.addMetrics(md2); + assertThat(mgd.getMetrics()).containsExactly(md1, md2); + } + + // --- LoggerSource --- + + @Test + public void testLoggerSourceWithComponent() { + Component comp = new Component(Type.SCM, "scm-1"); + LoggerSource ls = new LoggerSource(comp, "org.example.Logger", + LoggerSource.Level.DEBUG); + assertThat(ls.getComponent()).isEqualTo(comp); + assertThat(ls.getLoggerName()).isEqualTo("org.example.Logger"); + assertThat(ls.getLevel()).isEqualTo(LoggerSource.Level.DEBUG); + } + + @Test + public void testLoggerSourceWithTypeAndClass() { + LoggerSource ls = new LoggerSource(Type.OM, String.class, + LoggerSource.Level.TRACE); + assertThat(ls.getComponent().getName()).isEqualTo(Type.OM); + assertThat(ls.getLoggerName()).isEqualTo("java.lang.String"); + assertThat(ls.getLevel()).isEqualTo(LoggerSource.Level.TRACE); + } + + @Test + public void testLoggerSourceLevelValues() { + assertThat(LoggerSource.Level.values()).containsExactly( + LoggerSource.Level.TRACE, + LoggerSource.Level.DEBUG, + LoggerSource.Level.INFO, + LoggerSource.Level.WARN, + LoggerSource.Level.ERROR); + } +} diff --git a/hadoop-ozone/insight/src/test/java/org/apache/hadoop/ozone/insight/TestNodeManagerInsight.java b/hadoop-ozone/insight/src/test/java/org/apache/hadoop/ozone/insight/TestNodeManagerInsight.java new file mode 100644 index 000000000000..8c5390174d66 --- /dev/null +++ b/hadoop-ozone/insight/src/test/java/org/apache/hadoop/ozone/insight/TestNodeManagerInsight.java @@ -0,0 +1,128 @@ +/* + * 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.hadoop.ozone.insight; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.hadoop.ozone.insight.Component.Type; +import org.apache.hadoop.ozone.insight.scm.NodeManagerInsight; +import org.junit.jupiter.api.Test; + +/** + * Tests for NodeManagerInsight. + */ +public class TestNodeManagerInsight { + + @Test + public void testGetDescription() { + NodeManagerInsight insight = new NodeManagerInsight(); + assertThat(insight.getDescription()) + .isEqualTo("SCM Datanode management related information."); + } + + @Test + public void testGetRelatedLoggers() { + NodeManagerInsight insight = new NodeManagerInsight(); + List loggers = insight.getRelatedLoggers(false, + new HashMap<>()); + assertThat(loggers).hasSize(1); + assertThat(loggers.get(0).getComponent().getName()).isEqualTo(Type.SCM); + assertThat(loggers.get(0).getLevel()) + .isEqualTo(LoggerSource.Level.DEBUG); + } + + @Test + public void testGetRelatedLoggersVerbose() { + NodeManagerInsight insight = new NodeManagerInsight(); + List loggers = insight.getRelatedLoggers(true, + new HashMap<>()); + assertThat(loggers).hasSize(1); + assertThat(loggers.get(0).getLevel()) + .isEqualTo(LoggerSource.Level.TRACE); + } + + @Test + public void testGetMetrics() { + NodeManagerInsight insight = new NodeManagerInsight(); + List metrics = insight.getMetrics(new HashMap<>()); + assertThat(metrics).hasSize(2); + + MetricGroupDisplay nodeCounters = metrics.get(0); + assertThat(nodeCounters.getDescription()).isEqualTo("Node counters"); + assertThat(nodeCounters.getComponent().getName()).isEqualTo(Type.SCM); + assertThat(nodeCounters.getMetrics()).isNotEmpty(); + + MetricGroupDisplay hbStats = metrics.get(1); + assertThat(hbStats.getDescription()).isEqualTo("HB processing stats"); + assertThat(hbStats.getMetrics()).hasSize(2); + } + + @Test + public void testDefaultLevelNonVerbose() { + NodeManagerInsight insight = new NodeManagerInsight(); + assertThat(insight.defaultLevel(false)) + .isEqualTo(LoggerSource.Level.DEBUG); + } + + @Test + public void testDefaultLevelVerbose() { + NodeManagerInsight insight = new NodeManagerInsight(); + assertThat(insight.defaultLevel(true)) + .isEqualTo(LoggerSource.Level.TRACE); + } + + @Test + public void testFilterLogWithNullFilters() { + NodeManagerInsight insight = new NodeManagerInsight(); + assertThat(insight.filterLog(null, "some log line")).isTrue(); + } + + @Test + public void testFilterLogWithEmptyFilters() { + NodeManagerInsight insight = new NodeManagerInsight(); + Map filters = new HashMap<>(); + assertThat(insight.filterLog(filters, "some log line")).isTrue(); + } + + @Test + public void testFilterLogWithMatchingFilter() { + NodeManagerInsight insight = new NodeManagerInsight(); + Map filters = new HashMap<>(); + filters.put("datanode", "dn-1"); + assertThat(insight.filterLog(filters, + "Log message [datanode=dn-1] heartbeat")).isTrue(); + } + + @Test + public void testFilterLogWithNonMatchingFilter() { + NodeManagerInsight insight = new NodeManagerInsight(); + Map filters = new HashMap<>(); + filters.put("datanode", "dn-1"); + assertThat(insight.filterLog(filters, + "Log message [datanode=dn-2] heartbeat")).isFalse(); + } + + @Test + public void testGetConfigurationClassesDefault() { + NodeManagerInsight insight = new NodeManagerInsight(); + assertThat(insight.getConfigurationClasses()).isEmpty(); + } +}