This is an automated email from the ASF dual-hosted git repository.
hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git
The following commit(s) were added to refs/heads/main by this push:
new 351be5dde1 [SONAR] some coverage improvements and fixes (#6993)
351be5dde1 is described below
commit 351be5dde1d48c94c780d5f0436fa63f62d41209
Author: Hans Van Akelyen <[email protected]>
AuthorDate: Mon Apr 13 19:47:36 2026 +0200
[SONAR] some coverage improvements and fixes (#6993)
---
.../config/DescribedVariablesConfigFileTest.java | 36 ++++
.../core/exception/HopConversionExceptionTest.java | 54 +++++
.../hop/core/exception/HopExceptionTest.java | 58 ++++++
.../hop/core/exception/HopFileExceptionTest.java | 44 ++++
.../apache/hop/core/gui/PointAndDPointTest.java | 79 ++++++++
.../org/apache/hop/core/gui/RectangleTest.java | 65 ++++++
.../hop/core/injection/DataTypeConverterTest.java | 53 +++++
.../DefaultInjectionTypeConverterTest.java | 147 ++++++++++++++
.../core/injection/InjectionTypeConverterTest.java | 43 ++++
.../core/injection/NullNumberConverterTest.java | 49 +++++
.../apache/hop/core/io/CountingStreamsTest.java | 86 ++++++++
.../java/org/apache/hop/core/json/HopJsonTest.java | 60 ++++++
.../apache/hop/core/search/SearchQueryTest.java | 73 +++++++
.../apache/hop/core/search/SearchResultTest.java | 82 ++++++++
.../hop/version/EnvironmentVariableGetterTest.java | 48 +++++
.../org/apache/hop/version/ManifestGetterTest.java | 47 +++++
.../javascript/ScriptValuesAddedFunctions.java | 7 +-
...ptValuesAddedFunctionsRhinoIntegrationTest.java | 224 +++++++++++++++++++++
.../javascript/ScriptValuesAddedFunctionsTest.java | 20 +-
19 files changed, 1259 insertions(+), 16 deletions(-)
diff --git
a/core/src/test/java/org/apache/hop/core/config/DescribedVariablesConfigFileTest.java
b/core/src/test/java/org/apache/hop/core/config/DescribedVariablesConfigFileTest.java
new file mode 100644
index 0000000000..ee94d989e2
--- /dev/null
+++
b/core/src/test/java/org/apache/hop/core/config/DescribedVariablesConfigFileTest.java
@@ -0,0 +1,36 @@
+/*
+ * 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.hop.core.config;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+
+import org.junit.jupiter.api.Test;
+
+class DescribedVariablesConfigFileTest {
+
+ @Test
+ void filenameAndSerializer() {
+ DescribedVariablesConfigFile file = new
DescribedVariablesConfigFile("/tmp/hop-config.json");
+ assertEquals("/tmp/hop-config.json", file.getConfigFilename());
+ assertInstanceOf(ConfigFileSerializer.class, file.getSerializer());
+
+ file.setConfigFilename("/other/path.json");
+ assertEquals("/other/path.json", file.getConfigFilename());
+ }
+}
diff --git
a/core/src/test/java/org/apache/hop/core/exception/HopConversionExceptionTest.java
b/core/src/test/java/org/apache/hop/core/exception/HopConversionExceptionTest.java
new file mode 100644
index 0000000000..c6c1a4a8c6
--- /dev/null
+++
b/core/src/test/java/org/apache/hop/core/exception/HopConversionExceptionTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.hop.core.exception;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Collections;
+import java.util.List;
+import org.apache.hop.core.row.IValueMeta;
+import org.apache.hop.core.row.value.ValueMetaString;
+import org.junit.jupiter.api.Test;
+
+class HopConversionExceptionTest {
+
+ @Test
+ void constructorStoresCausesFieldsAndRow() {
+ List<Exception> causes = Collections.singletonList(new
NumberFormatException("bad"));
+ List<IValueMeta> fields = Collections.singletonList(new
ValueMetaString("f1"));
+ Object[] row = new Object[] {null, "ok"};
+ HopConversionException ex =
+ new HopConversionException("conversion failed", causes, fields, row);
+ assertEquals("conversion failed", ex.getSuperMessage());
+ assertEquals(causes, ex.getCauses());
+ assertEquals(fields, ex.getFields());
+ assertArrayEquals(row, ex.getRowData());
+ assertTrue(ex.getMessage().contains("conversion failed"));
+ }
+
+ @Test
+ void defaultConstructor() {
+ HopConversionException ex = new HopConversionException();
+ assertNull(ex.getCauses());
+ assertNull(ex.getFields());
+ assertNull(ex.getRowData());
+ }
+}
diff --git
a/core/src/test/java/org/apache/hop/core/exception/HopExceptionTest.java
b/core/src/test/java/org/apache/hop/core/exception/HopExceptionTest.java
new file mode 100644
index 0000000000..78543936ed
--- /dev/null
+++ b/core/src/test/java/org/apache/hop/core/exception/HopExceptionTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.hop.core.exception;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.hop.core.Const;
+import org.junit.jupiter.api.Test;
+
+class HopExceptionTest {
+
+ @Test
+ void getSuperMessageReturnsRawMessageWithoutFormatting() {
+ HopException ex = new HopException("hello");
+ assertEquals("hello", ex.getSuperMessage());
+ }
+
+ @Test
+ void getMessageAppendsCauseMessage() {
+ Throwable cause = new RuntimeException("root");
+ HopException ex = new HopException("top", cause);
+ String msg = ex.getMessage();
+ assertTrue(msg.contains(Const.CR));
+ assertTrue(msg.contains("top"));
+ assertTrue(msg.contains("root"));
+ }
+
+ @Test
+ void noArgConstructor() {
+ HopException ex = new HopException();
+ assertNull(ex.getSuperMessage());
+ }
+
+ @Test
+ void causeOnlyConstructor() {
+ Throwable inner = new IllegalStateException("state");
+ HopException ex = new HopException(inner);
+ assertEquals(inner, ex.getCause());
+ assertTrue(ex.getMessage().contains("state"));
+ }
+}
diff --git
a/core/src/test/java/org/apache/hop/core/exception/HopFileExceptionTest.java
b/core/src/test/java/org/apache/hop/core/exception/HopFileExceptionTest.java
new file mode 100644
index 0000000000..82b1b3d722
--- /dev/null
+++ b/core/src/test/java/org/apache/hop/core/exception/HopFileExceptionTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.hop.core.exception;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.hop.core.Const;
+import org.junit.jupiter.api.Test;
+
+class HopFileExceptionTest {
+
+ @Test
+ void messageAndCauseFormattedLikeHopException() {
+ Throwable cause = new RuntimeException("io failed");
+ HopFileException ex = new HopFileException("read error", cause);
+ String msg = ex.getMessage();
+ assertTrue(msg.contains(Const.CR));
+ assertTrue(msg.contains("read error"));
+ assertTrue(msg.contains("io failed"));
+ assertEquals(cause, ex.getCause());
+ }
+
+ @Test
+ void messageOnly() {
+ HopFileException ex = new HopFileException("eof");
+ assertTrue(ex.getMessage().contains("eof"));
+ }
+}
diff --git a/core/src/test/java/org/apache/hop/core/gui/PointAndDPointTest.java
b/core/src/test/java/org/apache/hop/core/gui/PointAndDPointTest.java
new file mode 100644
index 0000000000..ef9c4d8d08
--- /dev/null
+++ b/core/src/test/java/org/apache/hop/core/gui/PointAndDPointTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.hop.core.gui;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+import org.junit.jupiter.api.Test;
+
+class PointAndDPointTest {
+
+ @Test
+ void pointMultiplyRounds() {
+ Point p = new Point(10, 11);
+ p.multiply(1.5f);
+ assertEquals(15, p.getX());
+ assertEquals(17, p.getY());
+ }
+
+ @Test
+ void pointToDoubleAndDPointToPoint() {
+ Point p = new Point(3, 7);
+ DPoint d = p.toDouble();
+ assertEquals(3.0, d.getX());
+ assertEquals(7.0, d.getY());
+ Point back = d.toPoint();
+ assertEquals(3, back.getX());
+ assertEquals(7, back.getY());
+ }
+
+ @Test
+ void dPointMultiplyAndCopyConstructors() {
+ DPoint a = new DPoint(2.0, 4.0);
+ DPoint b = new DPoint(a);
+ b.multiply(0.5);
+ assertEquals(1.0, b.getX());
+ assertEquals(2.0, b.getY());
+ assertEquals(2.0, a.getX());
+
+ DPoint fromInt = new DPoint(new Point(1, 2));
+ assertEquals(1.0, fromInt.getX());
+ assertEquals(2.0, fromInt.getY());
+ }
+
+ @Test
+ void dPointEqualsHashCodeToString() {
+ DPoint p1 = new DPoint(1.25, 2.5);
+ DPoint p2 = new DPoint(1.25, 2.5);
+ DPoint p3 = new DPoint(1.0, 2.0);
+ assertEquals(p1, p2);
+ assertEquals(p1.hashCode(), p2.hashCode());
+ assertNotEquals(p1, p3);
+ assertEquals("DPoint(1.25,2.5)", p1.toString());
+ }
+
+ @Test
+ void pointEqualsAndToString() {
+ Point p1 = new Point(4, 5);
+ Point p2 = new Point(4, 5);
+ assertEquals(p1, p2);
+ assertEquals(p1.hashCode(), p2.hashCode());
+ assertEquals("Point(4,5)", p1.toString());
+ }
+}
diff --git a/core/src/test/java/org/apache/hop/core/gui/RectangleTest.java
b/core/src/test/java/org/apache/hop/core/gui/RectangleTest.java
new file mode 100644
index 0000000000..a175b857bc
--- /dev/null
+++ b/core/src/test/java/org/apache/hop/core/gui/RectangleTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.hop.core.gui;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+class RectangleTest {
+
+ @Test
+ void copyConstructorCopiesFields() {
+ Rectangle a = new Rectangle(1, 2, 3, 4);
+ Rectangle b = new Rectangle(a);
+ assertEquals(a.x, b.x);
+ assertEquals(a.y, b.y);
+ assertEquals(a.width, b.width);
+ assertEquals(a.height, b.height);
+ }
+
+ @Test
+ void containsPointInsideAndEdges() {
+ Rectangle r = new Rectangle(10, 20, 5, 6);
+ assertTrue(r.contains(10, 20));
+ assertTrue(r.contains(15, 26));
+ assertTrue(r.contains(new Point(12, 22)));
+ assertFalse(r.contains(9, 25));
+ assertFalse(r.contains(16, 25));
+ }
+
+ @Test
+ void centreAndDistance() {
+ Rectangle r1 = new Rectangle(0, 0, 10, 10);
+ Rectangle r2 = new Rectangle(10, 0, 10, 10);
+ assertEquals(5, r1.getCentreX());
+ assertEquals(5, r1.getCentreY());
+ assertEquals(15, r2.getCentreX());
+ assertEquals(5, r2.getCentreY());
+ assertEquals(10.0, r1.distance(r2), 1e-9);
+ }
+
+ @Test
+ void isEmptyAndToString() {
+ assertTrue(new Rectangle(0, 0, 0, 0).isEmpty());
+ assertFalse(new Rectangle(0, 0, 1, 0).isEmpty());
+ assertEquals("Rectangle(2,3-4x5)", new Rectangle(2, 3, 4, 5).toString());
+ }
+}
diff --git
a/core/src/test/java/org/apache/hop/core/injection/DataTypeConverterTest.java
b/core/src/test/java/org/apache/hop/core/injection/DataTypeConverterTest.java
new file mode 100644
index 0000000000..056e3e26c0
--- /dev/null
+++
b/core/src/test/java/org/apache/hop/core/injection/DataTypeConverterTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.hop.core.injection;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.apache.hop.core.HopClientEnvironment;
+import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.exception.HopValueException;
+import org.apache.hop.core.row.IValueMeta;
+import org.apache.hop.core.row.value.ValueMetaFactory;
+import org.apache.hop.junit.rules.RestoreHopEnvironmentExtension;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(RestoreHopEnvironmentExtension.class)
+class DataTypeConverterTest {
+
+ @BeforeAll
+ static void initHop() throws HopException {
+ HopClientEnvironment.init();
+ }
+
+ @Test
+ void string2intPrimitiveMapsValueMetaNameToPluginId() throws
HopValueException {
+ DataTypeConverter c = new DataTypeConverter();
+ int stringId = ValueMetaFactory.getIdForValueMeta("String");
+ assertEquals(stringId, c.string2intPrimitive("String"));
+ assertEquals(stringId, c.string2intPrimitive("string"));
+ }
+
+ @Test
+ void unknownTypeNameReturnsTypeNone() throws HopValueException {
+ DataTypeConverter c = new DataTypeConverter();
+ assertEquals(IValueMeta.TYPE_NONE,
c.string2intPrimitive("__not_a_registered_type__"));
+ }
+}
diff --git
a/core/src/test/java/org/apache/hop/core/injection/DefaultInjectionTypeConverterTest.java
b/core/src/test/java/org/apache/hop/core/injection/DefaultInjectionTypeConverterTest.java
new file mode 100644
index 0000000000..7b01018853
--- /dev/null
+++
b/core/src/test/java/org/apache/hop/core/injection/DefaultInjectionTypeConverterTest.java
@@ -0,0 +1,147 @@
+/*
+ * 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.hop.core.injection;
+
+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.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.hop.core.exception.HopValueException;
+import org.apache.hop.metadata.api.IEnumHasCodeAndDescription;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class DefaultInjectionTypeConverterTest {
+
+ private DefaultInjectionTypeConverter c;
+
+ @BeforeEach
+ void setUp() {
+ c = new DefaultInjectionTypeConverter();
+ }
+
+ @Test
+ void stringConversions() throws HopValueException {
+ assertEquals("hi", c.string2string("hi"));
+ assertEquals(42, c.string2intPrimitive("42"));
+ assertNull(c.string2integer(null));
+ assertEquals(7, c.string2integer("7"));
+ assertEquals(9L, c.string2longPrimitive("9"));
+ assertNull(c.string2long(null));
+ assertEquals(3L, c.string2long("3"));
+ }
+
+ @Test
+ void stringToBooleanVariants() throws HopValueException {
+ assertTrue(c.string2booleanPrimitive("Y"));
+ assertTrue(c.string2booleanPrimitive("yes"));
+ assertTrue(c.string2booleanPrimitive("True"));
+ assertTrue(c.string2booleanPrimitive("1"));
+ assertFalse(c.string2booleanPrimitive("N"));
+ assertFalse(c.string2booleanPrimitive("0"));
+ assertNull(c.string2boolean(null));
+ assertFalse(c.string2boolean("no"));
+ }
+
+ @Test
+ void stringToEnumByNameCodeAndDescriptionStyle() throws HopValueException {
+ assertEquals(Plain.A, c.string2enum(Plain.class, "A"));
+ assertNull(c.string2enum(Plain.class, null));
+ assertEquals(Coded.ONE, c.string2enum(Coded.class, "ONE"));
+ assertEquals(Coded.ONE, c.string2enum(Coded.class, "cd1"));
+ assertEquals(Coded.TWO, c.string2enum(Coded.class, "CD2"));
+ HopValueException ex =
+ assertThrows(HopValueException.class, () -> c.string2enum(Plain.class,
"Z"));
+ assertTrue(ex.getMessage().contains("Unknown value"));
+ }
+
+ @Test
+ void booleanConversions() throws HopValueException {
+ assertNull(c.boolean2string(null));
+ assertEquals("Y", c.boolean2string(true));
+ assertEquals("N", c.boolean2string(false));
+ assertEquals(1, c.boolean2intPrimitive(true));
+ assertEquals(0, c.boolean2intPrimitive(false));
+ assertEquals(0, c.boolean2intPrimitive(null));
+ assertNull(c.boolean2integer(null));
+ assertEquals(1L, c.boolean2longPrimitive(true));
+ assertNull(c.boolean2long(null));
+ assertTrue(c.boolean2booleanPrimitive(true));
+ assertFalse(c.boolean2booleanPrimitive(false));
+ assertTrue(c.boolean2boolean(true));
+ assertNull(c.boolean2boolean(null));
+ }
+
+ @Test
+ void integerConversions() throws HopValueException {
+ assertNull(c.integer2string(null));
+ assertEquals("100", c.integer2string(100L));
+ assertEquals(5, c.integer2intPrimitive(5L));
+ assertNull(c.integer2integer(null));
+ assertEquals(9, c.integer2integer(9L));
+ assertEquals(12L, c.integer2longPrimitive(12L));
+ assertNull(c.integer2long(null));
+ assertFalse(c.integer2booleanPrimitive(0L));
+ assertTrue(c.integer2booleanPrimitive(2L));
+ assertNull(c.integer2boolean(null));
+ }
+
+ @Test
+ void numberConversions() throws HopValueException {
+ assertNull(c.number2string(null));
+ assertEquals("3.25", c.number2string(3.25));
+ assertEquals(2, c.number2intPrimitive(1.6));
+ assertEquals(0, c.number2intPrimitive(0.4));
+ assertNull(c.number2integer(null));
+ assertEquals(4L, c.number2longPrimitive(3.7));
+ assertNull(c.number2long(null));
+ assertFalse(c.number2booleanPrimitive(0.0));
+ assertTrue(c.number2booleanPrimitive(1.2));
+ assertNull(c.number2boolean(null));
+ }
+
+ private enum Plain {
+ A,
+ B
+ }
+
+ private enum Coded implements IEnumHasCodeAndDescription {
+ ONE("cd1", "First"),
+ TWO("CD2", "Second");
+
+ private final String code;
+ private final String description;
+
+ Coded(String code, String description) {
+ this.code = code;
+ this.description = description;
+ }
+
+ @Override
+ public String getCode() {
+ return code;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+ }
+}
diff --git
a/core/src/test/java/org/apache/hop/core/injection/InjectionTypeConverterTest.java
b/core/src/test/java/org/apache/hop/core/injection/InjectionTypeConverterTest.java
new file mode 100644
index 0000000000..24203d2e80
--- /dev/null
+++
b/core/src/test/java/org/apache/hop/core/injection/InjectionTypeConverterTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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.hop.core.injection;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.apache.hop.core.exception.HopRuntimeException;
+import org.junit.jupiter.api.Test;
+
+class InjectionTypeConverterTest {
+
+ @Test
+ void defaultImplementationRejectsConversions() {
+ InjectionTypeConverter c = new InjectionTypeConverter();
+ assertThrows(HopRuntimeException.class, () -> c.string2string("x"));
+ assertThrows(HopRuntimeException.class, () -> c.string2intPrimitive("1"));
+ assertThrows(HopRuntimeException.class, () -> c.string2integer("1"));
+ assertThrows(HopRuntimeException.class, () ->
c.string2booleanPrimitive("Y"));
+ assertThrows(HopRuntimeException.class, () ->
c.string2enum(SampleEnum.class, "A"));
+ assertThrows(HopRuntimeException.class, () -> c.boolean2string(true));
+ assertThrows(HopRuntimeException.class, () -> c.integer2string(1L));
+ assertThrows(HopRuntimeException.class, () -> c.number2string(1.0));
+ }
+
+ private enum SampleEnum {
+ A
+ }
+}
diff --git
a/core/src/test/java/org/apache/hop/core/injection/NullNumberConverterTest.java
b/core/src/test/java/org/apache/hop/core/injection/NullNumberConverterTest.java
new file mode 100644
index 0000000000..811af305f0
--- /dev/null
+++
b/core/src/test/java/org/apache/hop/core/injection/NullNumberConverterTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.hop.core.injection;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class NullNumberConverterTest {
+
+ private NullNumberConverter c;
+
+ @BeforeEach
+ void setUp() {
+ c = new NullNumberConverter();
+ }
+
+ @Test
+ void blankStringYieldsMinusOneForIntPrimitive() {
+ assertEquals(-1, c.string2intPrimitive(null));
+ assertEquals(-1, c.string2intPrimitive(""));
+ assertEquals(-1, c.string2intPrimitive(" "));
+ assertEquals(5, c.string2intPrimitive("5"));
+ }
+
+ @Test
+ void nullBoxedNumbersYieldMinusOneForIntPrimitive() {
+ assertEquals(-1, c.integer2intPrimitive(null));
+ assertEquals(-1, c.number2intPrimitive(null));
+ assertEquals(3, c.integer2intPrimitive(3L));
+ assertEquals(2, c.number2intPrimitive(1.7));
+ }
+}
diff --git a/core/src/test/java/org/apache/hop/core/io/CountingStreamsTest.java
b/core/src/test/java/org/apache/hop/core/io/CountingStreamsTest.java
new file mode 100644
index 0000000000..c1a3b34333
--- /dev/null
+++ b/core/src/test/java/org/apache/hop/core/io/CountingStreamsTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.hop.core.io;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import org.junit.jupiter.api.Test;
+
+class CountingStreamsTest {
+
+ @Test
+ void countingInputStreamSingleByteRead() throws IOException {
+ byte[] data = {1, 2, 3};
+ try (CountingInputStream in = new CountingInputStream(new
ByteArrayInputStream(data))) {
+ assertEquals(1, in.read());
+ assertEquals(2, in.read());
+ assertEquals(3, in.read());
+ assertEquals(-1, in.read());
+ assertEquals(3, in.getCount());
+ }
+ }
+
+ @Test
+ void countingInputStreamBulkRead() throws IOException {
+ byte[] data = {9, 8, 7, 6};
+ try (CountingInputStream in = new CountingInputStream(new
ByteArrayInputStream(data))) {
+ byte[] buf = new byte[4];
+ int n = in.read(buf, 0, 4);
+ assertEquals(4, n);
+ assertArrayEquals(data, buf);
+ assertEquals(4, in.getCount());
+ assertEquals(-1, in.read(buf, 0, 1));
+ assertEquals(4, in.getCount());
+ }
+ }
+
+ @Test
+ void countingOutputStreamWrites() throws IOException {
+ ByteArrayOutputStream raw = new ByteArrayOutputStream();
+ try (CountingOutputStream out = new CountingOutputStream(raw)) {
+ out.write(42);
+ out.write(new byte[] {1, 2, 3}, 1, 2);
+ assertEquals(3, out.getCount());
+ }
+ assertArrayEquals(new byte[] {42, 2, 3}, raw.toByteArray());
+ }
+
+ @Test
+ void countingInputStreamEofDoesNotIncrementCount() throws IOException {
+ try (CountingInputStream in = new CountingInputStream(new
ByteArrayInputStream(new byte[0]))) {
+ assertEquals(-1, in.read());
+ assertEquals(0, in.getCount());
+ }
+ }
+
+ @Test
+ void countingInputStreamZeroLengthReadDoesNotIncrement() throws IOException {
+ try (CountingInputStream in =
+ new CountingInputStream(new ByteArrayInputStream(new byte[] {1}))) {
+ byte[] buf = new byte[1];
+ assertEquals(0, in.read(buf, 0, 0));
+ assertEquals(0, in.getCount());
+ assertEquals(1, in.read(buf, 0, 1));
+ assertEquals(1, in.getCount());
+ }
+ }
+}
diff --git a/core/src/test/java/org/apache/hop/core/json/HopJsonTest.java
b/core/src/test/java/org/apache/hop/core/json/HopJsonTest.java
new file mode 100644
index 0000000000..25bd1fcd0c
--- /dev/null
+++ b/core/src/test/java/org/apache/hop/core/json/HopJsonTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.hop.core.json;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import org.junit.jupiter.api.Test;
+
+class HopJsonTest {
+
+ @Test
+ void newMapperDisablesUnknownPropertyFailureAndIndent() {
+ ObjectMapper mapper = HopJson.newMapper();
+ assertFalse(
+ mapper
+ .getDeserializationConfig()
+ .isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES));
+
assertFalse(mapper.getSerializationConfig().isEnabled(SerializationFeature.INDENT_OUTPUT));
+ }
+
+ @Test
+ void newMapperIgnoresUnknownJsonProperties() throws Exception {
+ ObjectMapper mapper = HopJson.newMapper();
+ Simple bean = mapper.readValue("{\"a\":1,\"extra\":true}", Simple.class);
+ assertEquals(1, bean.a);
+ }
+
+ @Test
+ void newMapperWritesCompactJson() throws Exception {
+ ObjectMapper mapper = HopJson.newMapper();
+ Simple bean = new Simple();
+ bean.a = 42;
+ String json = mapper.writeValueAsString(bean);
+ assertFalse(json.contains("\n"));
+ assertEquals("{\"a\":42}", json);
+ }
+
+ public static class Simple {
+ public int a;
+ }
+}
diff --git a/core/src/test/java/org/apache/hop/core/search/SearchQueryTest.java
b/core/src/test/java/org/apache/hop/core/search/SearchQueryTest.java
new file mode 100644
index 0000000000..4373766f0c
--- /dev/null
+++ b/core/src/test/java/org/apache/hop/core/search/SearchQueryTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.hop.core.search;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+class SearchQueryTest {
+
+ @Test
+ void emptySearchStringMatchesNonEmptyTargetOnly() {
+ SearchQuery q = new SearchQuery("", false, false);
+ assertTrue(q.matches("anything"));
+ assertFalse(q.matches(""));
+ }
+
+ @Test
+ void substringCaseInsensitive() {
+ SearchQuery q = new SearchQuery("Foo", false, false);
+ assertTrue(q.matches("barfooBaz"));
+ assertFalse(q.matches("barf00Baz"));
+ }
+
+ @Test
+ void substringCaseSensitive() {
+ SearchQuery q = new SearchQuery("Foo", true, false);
+ assertTrue(q.matches("xFooy"));
+ assertFalse(q.matches("xfooy"));
+ }
+
+ @Test
+ void regExCaseInsensitive() {
+ SearchQuery q = new SearchQuery("^a.c$", false, true);
+ assertTrue(q.matches("AbC"));
+ assertFalse(q.matches("axxc"));
+ }
+
+ @Test
+ void regExCaseSensitive() {
+ SearchQuery q = new SearchQuery("^ABC$", true, true);
+ assertTrue(q.matches("ABC"));
+ assertFalse(q.matches("abc"));
+ }
+
+ @Test
+ void gettersSetters() {
+ SearchQuery q = new SearchQuery();
+ q.setSearchString("x");
+ q.setCaseSensitive(true);
+ q.setRegEx(true);
+ assertEquals("x", q.getSearchString());
+ assertTrue(q.isCaseSensitive());
+ assertTrue(q.isRegEx());
+ }
+}
diff --git
a/core/src/test/java/org/apache/hop/core/search/SearchResultTest.java
b/core/src/test/java/org/apache/hop/core/search/SearchResultTest.java
new file mode 100644
index 0000000000..5022cbac03
--- /dev/null
+++ b/core/src/test/java/org/apache/hop/core/search/SearchResultTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.hop.core.search;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import org.junit.jupiter.api.Test;
+
+class SearchResultTest {
+
+ private static final class DummySearchable implements ISearchable<String> {
+ @Override
+ public String getLocation() {
+ return "loc";
+ }
+
+ @Override
+ public String getName() {
+ return "n";
+ }
+
+ @Override
+ public String getType() {
+ return "t";
+ }
+
+ @Override
+ public String getFilename() {
+ return "f.hpl";
+ }
+
+ @Override
+ public String getSearchableObject() {
+ return "obj";
+ }
+
+ @Override
+ public ISearchableCallback getSearchCallback() {
+ return null;
+ }
+ }
+
+ @Test
+ void accessorsAndMutators() {
+ DummySearchable searchable = new DummySearchable();
+ SearchResult r = new SearchResult(searchable, "match", "desc",
"transform", "value");
+
+ assertEquals(searchable, r.getMatchingSearchable());
+ assertEquals("match", r.getMatchingString());
+ assertEquals("desc", r.getDescription());
+ assertEquals("transform", r.getComponent());
+ assertEquals("value", r.getValue());
+
+ r.setMatchingString("m2");
+ r.setDescription("d2");
+ r.setComponent("c2");
+ r.setValue("v2");
+ r.setMatchingSearchable(null);
+
+ assertEquals("m2", r.getMatchingString());
+ assertEquals("d2", r.getDescription());
+ assertEquals("c2", r.getComponent());
+ assertEquals("v2", r.getValue());
+ assertNull(r.getMatchingSearchable());
+ }
+}
diff --git
a/core/src/test/java/org/apache/hop/version/EnvironmentVariableGetterTest.java
b/core/src/test/java/org/apache/hop/version/EnvironmentVariableGetterTest.java
new file mode 100644
index 0000000000..0f05d4075d
--- /dev/null
+++
b/core/src/test/java/org/apache/hop/version/EnvironmentVariableGetterTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.hop.version;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.hop.core.exception.HopRuntimeException;
+import org.junit.jupiter.api.Test;
+
+class EnvironmentVariableGetterTest {
+
+ @Test
+ void getEnvVariable_returnsPathOnTypicalSystems() throws Exception {
+ EnvironmentVariableGetter getter = new EnvironmentVariableGetter();
+ String path = getter.getEnvVarible("PATH");
+ assertNotNull(path);
+ assertFalse(path.isEmpty());
+ }
+
+ @Test
+ void getEnvVariable_throwsWhenUndefined() {
+ EnvironmentVariableGetter getter = new EnvironmentVariableGetter();
+ HopRuntimeException ex =
+ assertThrows(
+ HopRuntimeException.class,
+ () ->
getter.getEnvVarible("HOP_TEST_ENV_VAR_SHOULD_NOT_EXIST_9f3a2c1b"));
+ assertTrue(ex.getMessage().contains("undefined"));
+
assertTrue(ex.getMessage().contains("HOP_TEST_ENV_VAR_SHOULD_NOT_EXIST_9f3a2c1b"));
+ }
+}
diff --git a/core/src/test/java/org/apache/hop/version/ManifestGetterTest.java
b/core/src/test/java/org/apache/hop/version/ManifestGetterTest.java
new file mode 100644
index 0000000000..f39351d482
--- /dev/null
+++ b/core/src/test/java/org/apache/hop/version/ManifestGetterTest.java
@@ -0,0 +1,47 @@
+/*
+ * 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.hop.version;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
+
+import java.net.URL;
+import java.util.jar.Manifest;
+import org.junit.jupiter.api.Test;
+
+/**
+ * {@link ManifestGetter} only supports {@code META-INF/MANIFEST.MF} resolved
from a {@code jar:}
+ * URL. When the first manifest on the classpath comes from a directory
({@code file:}), the call
+ * fails with {@link ClassCastException}; this test is skipped in that case.
+ */
+class ManifestGetterTest {
+
+ @Test
+ void getManifest_readsFromJarUrlWhenApplicable() throws Exception {
+ ManifestGetter getter = new ManifestGetter();
+ URL url = getter.getClass().getResource("/META-INF/MANIFEST.MF");
+ assumeTrue(url != null, "META-INF/MANIFEST.MF not found on classpath");
+ assumeTrue(
+ "jar".equalsIgnoreCase(url.getProtocol()),
+ "ManifestGetter requires a JAR manifest URL, got: " + url);
+
+ Manifest manifest = getter.getManifest();
+ assertNotNull(manifest);
+ assertNotNull(manifest.getMainAttributes());
+ }
+}
diff --git
a/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesAddedFunctions.java
b/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesAddedFunctions.java
index 9aac30cf78..274f6d66e5 100644
---
a/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesAddedFunctions.java
+++
b/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesAddedFunctions.java
@@ -76,6 +76,7 @@ import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.WrappedException;
+@SuppressWarnings({"java:S1172", "java:S100"})
public class ScriptValuesAddedFunctions extends ScriptableObject {
@Serial private static final long serialVersionUID = 1L;
@@ -312,12 +313,11 @@ public class ScriptValuesAddedFunctions extends
ScriptableObject {
Calendar fisOffsetDate = Calendar.getInstance();
startDate.setTime(dIn);
Format dfFormatter = new SimpleDateFormat("dd.MM.yyyy");
- String strOffsetDate =
- Context.toString(argList[1]) +
String.valueOf(startDate.get(Calendar.YEAR));
+ String strOffsetDate = Context.toString(argList[1]) +
startDate.get(Calendar.YEAR);
Date dOffset = (Date) dfFormatter.parseObject(strOffsetDate);
fisOffsetDate.setTime(dOffset);
- String strFisStartDate = "01.01." +
String.valueOf(startDate.get(Calendar.YEAR) + 1);
+ String strFisStartDate = "01.01." + startDate.get(Calendar.YEAR) + 1;
fisStartDate.setTime((Date) dfFormatter.parseObject(strFisStartDate));
int iDaysToAdd =
(int) ((startDate.getTimeInMillis() -
fisOffsetDate.getTimeInMillis()) / 86400000);
@@ -1792,6 +1792,7 @@ public class ScriptValuesAddedFunctions extends
ScriptableObject {
}
// Print
+ @SuppressWarnings("java:S106")
public static void print(
Context actualContext, Scriptable actualObject, Object[] argList,
Function functionContext) {
for (Object o : argList) { // don't worry about "undefined" arguments
diff --git
a/plugins/transforms/javascript/src/test/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesAddedFunctionsRhinoIntegrationTest.java
b/plugins/transforms/javascript/src/test/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesAddedFunctionsRhinoIntegrationTest.java
new file mode 100644
index 0000000000..62a064eb84
--- /dev/null
+++
b/plugins/transforms/javascript/src/test/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesAddedFunctionsRhinoIntegrationTest.java
@@ -0,0 +1,224 @@
+/*
+ * 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.hop.pipeline.transforms.javascript;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Date;
+import org.apache.hop.core.Const;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.EvaluatorException;
+import org.mozilla.javascript.Scriptable;
+
+/**
+ * Exercises {@link ScriptValuesAddedFunctions} through the same Rhino entry
points the JavaScript
+ * transform uses ({@link Context#toString}, {@link Context#toNumber}, {@link
Context#jsToJava}).
+ */
+class ScriptValuesAddedFunctionsRhinoIntegrationTest {
+
+ private Context cx;
+ private Scriptable scope;
+
+ @BeforeEach
+ void enterRhino() {
+ cx = Context.enter();
+ scope = cx.initStandardObjects();
+ }
+
+ @AfterEach
+ void exitRhino() {
+ Context.exit();
+ }
+
+ private Object[] args(Object... o) {
+ return o;
+ }
+
+ @Test
+ void getDigitsOnly_stripsNonDigits() {
+ assertEquals("123", ScriptValuesAddedFunctions.getDigitsOnly(cx, scope,
args("a1b2c3"), null));
+ }
+
+ @Test
+ void getDigitsOnly_requiresOneArgument() {
+ assertThrows(
+ EvaluatorException.class,
+ () -> ScriptValuesAddedFunctions.getDigitsOnly(cx, scope, args(),
null));
+ }
+
+ @Test
+ void luhnCheck_validAndInvalid() {
+ assertTrue(ScriptValuesAddedFunctions.LuhnCheck(cx, scope,
args("79927398713"), null));
+ assertTrue(ScriptValuesAddedFunctions.LuhnCheck(cx, scope, args("0"),
null));
+ assertFalse(ScriptValuesAddedFunctions.LuhnCheck(cx, scope,
args("79927398712"), null));
+ assertFalse(ScriptValuesAddedFunctions.LuhnCheck(cx, scope,
args("not-a-number"), null));
+ }
+
+ @Test
+ void indexOf_twoAndThreeArguments() {
+ assertEquals(2, ScriptValuesAddedFunctions.indexOf(cx, scope,
args("hello", "l"), null));
+ assertEquals(3, ScriptValuesAddedFunctions.indexOf(cx, scope,
args("hello", "l", 3), null));
+ }
+
+ @Test
+ void trim_ltrim_rtrim() {
+ assertEquals("x", ScriptValuesAddedFunctions.trim(cx, scope, args(" x
"), null));
+ assertEquals("x ", ScriptValuesAddedFunctions.ltrim(cx, scope, args(" x
"), null));
+ assertEquals(" x", ScriptValuesAddedFunctions.rtrim(cx, scope, args(" x
"), null));
+ }
+
+ @Test
+ void substr_twoAndThreeArguments() {
+ assertEquals("bcd", ScriptValuesAddedFunctions.substr(cx, scope,
args("abcd", 1), null));
+ assertEquals("bc", ScriptValuesAddedFunctions.substr(cx, scope,
args("abcd", 1, 2), null));
+ }
+
+ @Test
+ void fillString_lpad_rpad() {
+ assertEquals("xxx", ScriptValuesAddedFunctions.fillString(cx, scope,
args("x", 3), null));
+ assertEquals("00ab", ScriptValuesAddedFunctions.lpad(cx, scope, args("ab",
"0", 4), null));
+ assertEquals("ab00", ScriptValuesAddedFunctions.rpad(cx, scope, args("ab",
"0", 4), null));
+ }
+
+ @Test
+ void upper_lower() {
+ assertEquals("AB", ScriptValuesAddedFunctions.upper(cx, scope, args("aB"),
null));
+ assertEquals("ab", ScriptValuesAddedFunctions.lower(cx, scope, args("Ab"),
null));
+ }
+
+ @Test
+ void escapeAndUnescapeHelpers_delegateToConst() {
+ String raw = "<tag>&\"'";
+ assertEquals(
+ Const.escapeXml(raw), ScriptValuesAddedFunctions.escapeXml(cx, scope,
args(raw), null));
+ assertEquals(
+ Const.escapeHtml(raw), ScriptValuesAddedFunctions.escapeHtml(cx,
scope, args(raw), null));
+ String escaped = Const.escapeHtml(raw);
+ assertEquals(
+ Const.unEscapeHtml(escaped),
+ ScriptValuesAddedFunctions.unEscapeHtml(cx, scope, args(escaped),
null));
+ String xmlEsc = Const.escapeXml(raw);
+ assertEquals(
+ Const.unEscapeXml(xmlEsc),
+ ScriptValuesAddedFunctions.unEscapeXml(cx, scope, args(xmlEsc), null));
+ assertEquals(
+ Const.escapeSql("O'Brien"),
+ ScriptValuesAddedFunctions.escapeSql(cx, scope, args("O'Brien"),
null));
+ assertEquals(
+ Const.protectXmlCdata("]]>"),
+ ScriptValuesAddedFunctions.protectXmlCdata(cx, scope, args("]]>"),
null));
+ assertEquals(
+ Const.removeDigits("a1b2"),
+ ScriptValuesAddedFunctions.removeDigits(cx, scope, args("a1b2"),
null));
+ }
+
+ @Test
+ void initCap_removeCRLF_getOcuranceString() {
+ assertNotNull(ScriptValuesAddedFunctions.initCap(cx, scope, args("hello
world"), null));
+ assertEquals("ab", ScriptValuesAddedFunctions.removeCRLF(cx, scope,
args("a\r\nb"), null));
+ assertEquals(
+ Const.getOcuranceString("banana", "a"),
+ ScriptValuesAddedFunctions.getOcuranceString(cx, scope, args("banana",
"a"), null));
+ }
+
+ @Test
+ void trunc_floorsNumber() {
+ Object out = ScriptValuesAddedFunctions.trunc(cx, scope, args(-3.7), null);
+ assertInstanceOf(Double.class, out);
+ assertEquals(-4.0, (Double) out, 1e-9);
+ }
+
+ @Test
+ void abs_ceil_floor() {
+ assertEquals(2.5, (Double) ScriptValuesAddedFunctions.abs(cx, scope,
args(-2.5), null), 1e-9);
+ assertEquals(3.0, (Double) ScriptValuesAddedFunctions.ceil(cx, scope,
args(2.1), null), 1e-9);
+ assertEquals(2.0, (Double) ScriptValuesAddedFunctions.floor(cx, scope,
args(2.9), null), 1e-9);
+ }
+
+ @Test
+ void num2str_and_str2num_roundTripInteger() {
+ String s = ScriptValuesAddedFunctions.num2str(cx, scope, args(42.0), null);
+ assertNotNull(s);
+ Object n = ScriptValuesAddedFunctions.str2num(cx, scope, args(s), null);
+ assertInstanceOf(Double.class, n);
+ assertEquals(42.0, (Double) n, 1e-9);
+ }
+
+ @Test
+ void isNum_isDate() {
+ assertEquals(Boolean.TRUE, ScriptValuesAddedFunctions.isNum(cx, scope,
args(1.0), null));
+ assertEquals(Boolean.FALSE, ScriptValuesAddedFunctions.isNum(cx, scope,
args("x"), null));
+ Object jsDate = Context.javaToJS(new Date(), scope);
+ assertEquals(Boolean.TRUE, ScriptValuesAddedFunctions.isDate(cx, scope,
args(jsDate), null));
+ assertEquals(Boolean.FALSE, ScriptValuesAddedFunctions.isDate(cx, scope,
args("nope"), null));
+ }
+
+ @Test
+ void decode_and_replace() {
+ assertEquals(
+ "yes", ScriptValuesAddedFunctions.decode(cx, scope, args("k1", "k1",
"yes", "no"), null));
+ assertEquals("d", ScriptValuesAddedFunctions.decode(cx, scope, args("a",
"b", "c", "d"), null));
+ assertEquals(
+ "xby", ScriptValuesAddedFunctions.replace(cx, scope, args("aby", "ab",
"xb"), null));
+ }
+
+ @Test
+ void isEmpty_and_isMailValid() {
+ assertEquals(Boolean.TRUE, ScriptValuesAddedFunctions.isEmpty(cx, scope,
args(""), null));
+ assertEquals(Boolean.FALSE, ScriptValuesAddedFunctions.isMailValid(cx,
scope, args(""), null));
+ assertEquals(
+ Boolean.FALSE,
+ ScriptValuesAddedFunctions.isMailValid(cx, scope,
args("not-an-email"), null));
+ assertEquals(
+ Boolean.TRUE, ScriptValuesAddedFunctions.isMailValid(cx, scope,
args("[email protected]"), null));
+ }
+
+ @Test
+ void isCodepage_utf8_ascii() {
+ Object ok = ScriptValuesAddedFunctions.isCodepage(cx, scope, args("abc",
"UTF-8"), null);
+ assertEquals(Boolean.TRUE, ok);
+ }
+
+ @Test
+ void year_month_fromDate() {
+ Date d = new Date(124, 5, 15);
+ Object y = ScriptValuesAddedFunctions.year(cx, scope,
args(Context.javaToJS(d, scope)), null);
+ Object m = ScriptValuesAddedFunctions.month(cx, scope,
args(Context.javaToJS(d, scope)), null);
+ assertInstanceOf(Double.class, y);
+ assertInstanceOf(Double.class, m);
+ assertEquals(2024.0, (Double) y, 1e-9);
+ // Calendar.MONTH is 0-based (June -> 5), matching
ScriptValuesAddedFunctions.month().
+ assertEquals(5.0, (Double) m, 1e-9);
+ }
+
+ @Test
+ void getDayNumber_weekMonth() {
+ Date d = new Date(124, 5, 15);
+ Object js = Context.javaToJS(d, scope);
+ assertNotNull(ScriptValuesAddedFunctions.getDayNumber(cx, scope, args(js,
"m"), null));
+ assertNotNull(ScriptValuesAddedFunctions.getDayNumber(cx, scope, args(js,
"w"), null));
+ }
+}
diff --git
a/plugins/transforms/javascript/src/test/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesAddedFunctionsTest.java
b/plugins/transforms/javascript/src/test/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesAddedFunctionsTest.java
index 774f91ac63..2f68ceabee 100644
---
a/plugins/transforms/javascript/src/test/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesAddedFunctionsTest.java
+++
b/plugins/transforms/javascript/src/test/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesAddedFunctionsTest.java
@@ -18,7 +18,7 @@
package org.apache.hop.pipeline.transforms.javascript;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.fail;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import java.time.LocalDateTime;
import java.time.ZoneId;
@@ -26,6 +26,7 @@ import java.util.Calendar;
import java.util.Date;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.junit.jupiter.api.Test;
+import org.mozilla.javascript.EvaluatorException;
class ScriptValuesAddedFunctionsTest {
private static final String FORMATTER = "yyyy-MM-dd HH:mm:ss";
@@ -67,17 +68,10 @@ class ScriptValuesAddedFunctionsTest {
assertEquals(0, c2.get(Calendar.MILLISECOND));
assertEquals("2025-02-15 11:11:11", DateFormatUtils.format(rtn,
FORMATTER));
- try {
- ScriptValuesAddedFunctions.truncDate(rtn, 6); // Should throw exception
- fail("Expected exception - passed in level > 5 to truncDate");
- } catch (Exception expected) {
- // Should get here
- }
- try {
- ScriptValuesAddedFunctions.truncDate(rtn, -7); // Should throw exception
- fail("Expected exception - passed in level < 0 to truncDate");
- } catch (Exception expected) {
- // Should get here
- }
+ final Date truncatedToMs = rtn;
+ assertThrows(
+ EvaluatorException.class, () ->
ScriptValuesAddedFunctions.truncDate(truncatedToMs, 6));
+ assertThrows(
+ EvaluatorException.class, () ->
ScriptValuesAddedFunctions.truncDate(truncatedToMs, -7));
}
}