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

gtchaboussie pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git


The following commit(s) were added to refs/heads/trunk by this push:
     new e3d73ac143 Improved: FlexibleStringExpander tests rewrite (OFBIZ-13336)
e3d73ac143 is described below

commit e3d73ac143e1ec9481f4b89df228eead47aaa879
Author: Gaetan <[email protected]>
AuthorDate: Fri Jan 30 09:41:17 2026 +0100

    Improved: FlexibleStringExpander tests rewrite (OFBIZ-13336)
    
    - Rewrote the FlexibleStringExpander in groovy.
    - Simplified the reading by splitting the tests into two distinct
    classes : Parser, and actual FSE test.
    - Actual tests are now grouped by theme.
    - Small tool classes that were used are now dedicated classes.
    - Also removed the explicit groovy test sources, no longer required,
    with the added useJunit()
    config to allow this behavior
     (#939)
    Thanks Jacques for the review
---
 build.gradle                                       |   4 +-
 .../FlexibleStringExpanderParserTests.groovy       |  87 ++++++
 .../util/string/FlexibleStringExpanderTests.groovy | 246 +++++++++++++++
 .../base/util/string/tool/SpecialNumber.groovy     |  30 ++
 .../base/util/string/tool/TestException.groovy     |  32 ++
 .../ofbiz/base/util/string/tool/TestNpe.groovy     |  31 ++
 .../util/string/FlexibleStringExpanderTests.java   | 342 ---------------------
 7 files changed, 427 insertions(+), 345 deletions(-)

diff --git a/build.gradle b/build.gradle
index 3f7ff5a68c..84aabfc0b1 100644
--- a/build.gradle
+++ b/build.gradle
@@ -305,9 +305,6 @@ sourceSets {
         // If a groovy test is supposed to be tested this way, it can be added 
here.
         groovy {
             srcDirs = getDirectoryInActiveComponentsIfExists('src/test/groovy')
-            include 'org/apache/ofbiz/service/ModelServiceTest.groovy'
-            include 
'org/apache/ofbiz/base/util/string/FlexibleStringExpanderBaseCodeTests.groovy'
-            include 'org/apache/ofbiz/base/util/FileUtilTests.groovy'
         }
         resources {
             srcDirs = 
getDirectoryInActiveComponentsIfExists('src/test/resources')
@@ -374,6 +371,7 @@ eclipse.classpath.file.whenMerged { classpath ->
 tasks.eclipse.dependsOn(cleanEclipse)
 
 test {
+    useJUnit()
     jvmArgs "-javaagent:${classpath.find { it.name.contains('jmockit') 
}.absolutePath}"
 }
 
diff --git 
a/framework/base/src/test/groovy/org/apache/ofbiz/base/util/string/FlexibleStringExpanderParserTests.groovy
 
b/framework/base/src/test/groovy/org/apache/ofbiz/base/util/string/FlexibleStringExpanderParserTests.groovy
new file mode 100644
index 0000000000..e36ae9c613
--- /dev/null
+++ 
b/framework/base/src/test/groovy/org/apache/ofbiz/base/util/string/FlexibleStringExpanderParserTests.groovy
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * 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.ofbiz.base.util.string
+
+import org.junit.Test
+
+/* codenarc-disable GStringExpressionWithinString, 
JUnitTestMethodWithoutAssert */
+
+/**
+ * ./gradlew test --tests '*GroovyFlexibleStringExpander*'
+ */
+class FlexibleStringExpanderParserTests {
+
+    @Test
+    void testSimpleParserIntegrity() {
+        List<String> stringsToTest = [
+                '${\'Hello ${var}\'}!',
+                'Hello ${${groovy:' + FlexibleStringExpanderParserTests + 
'.staticReturnNull()}}World!',
+                '${${throwException.value}}',
+                '${a${}${}',
+                '',
+                '${groovy:}',
+                '\\${}',
+                'a\\${}',
+                '\\${groovy:}',
+                '${',
+                '${a${}',
+                '${a${${}',
+                '\\${',
+                'a\\${',
+                '${?currency(',
+                '${?currency()',
+                '${price?currency(',
+                '${price?currency()',
+                '${?currency(usd',
+                '${?currency(usd)',
+                '${price?currency(usd',
+                '${price?currency(usd)',
+                '${?currency(}',
+                '${?currency()}',
+                '${?currency(usd}',
+                '${?currency(usd)}',
+                '${price?currency(}',
+                '${price?currency()}',
+                '${price?currency(usd}',
+                '${price?currency(usd)}',
+                'a${price?currency(usd)}b']
+        for (String stringToTest in stringsToTest) {
+            doParserIntegrityTest(stringToTest)
+        }
+    }
+
+    @Test
+    void testParserIntegrityWithNullInput() {
+        doParserIntegrityTest(null, '')
+    }
+
+    @Test
+    void testParserIntegrityWithSingleCharInput() {
+        doParserIntegrityTest('a', 'a', false)
+    }
+
+    private static void doParserIntegrityTest(String input, String toString = 
input, boolean checkCache = true) {
+        assert toString == FlexibleStringExpander.getInstance(input, 
false).toString()
+        assert toString == FlexibleStringExpander.getInstance(input, 
true).toString()
+        if (checkCache) {
+            assert FlexibleStringExpander.getInstance(input, true) === 
FlexibleStringExpander.getInstance(input, true)
+        }
+    }
+
+}
diff --git 
a/framework/base/src/test/groovy/org/apache/ofbiz/base/util/string/FlexibleStringExpanderTests.groovy
 
b/framework/base/src/test/groovy/org/apache/ofbiz/base/util/string/FlexibleStringExpanderTests.groovy
new file mode 100644
index 0000000000..4dc83ad0a0
--- /dev/null
+++ 
b/framework/base/src/test/groovy/org/apache/ofbiz/base/util/string/FlexibleStringExpanderTests.groovy
@@ -0,0 +1,246 @@
+/*******************************************************************************
+ * 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.ofbiz.base.util.string
+
+import junit.framework.TestCase
+import org.apache.ofbiz.base.util.string.tool.SpecialNumber
+import org.apache.ofbiz.base.util.string.tool.TestNpe
+import org.apache.ofbiz.base.util.string.tool.TestException
+import org.junit.Test
+
+/* codenarc-disable GStringExpressionWithinString, 
JUnitTestMethodWithoutAssert, UnnecessaryBigDecimalInstantiation */
+
+/**
+ * Test Class for FlexibleStringExpander object
+ */
+class FlexibleStringExpanderTests extends TestCase {
+
+    private static final Locale LOCALE_TO_TEST = new Locale('en', 'US')
+    private static final Locale OTHER_LOCALE = new Locale('fr')
+    private static final TimeZone TIME_ZONE_TO_TEST = 
TimeZone.getTimeZone('PST')
+    private static final TimeZone OTHER_TIME_ZONE = TimeZone.getTimeZone('GMT')
+
+    // Required to avoid ambiguous method calls. And makes tests easier to 
read as a bonus.
+    private static final Map NULL_CONTEXT = null
+    private static final Locale NULL_LOCALE = null
+    private static final TimeZone NULL_TIMEZONE = null
+    private static final Object NULL_OBJECT = null
+
+    @Test
+    void testEmptyFSE() {
+        doEmptyFseTest(null, NULL_CONTEXT, NULL_TIMEZONE, NULL_LOCALE, '')
+        doEmptyFseTest(null, [foo: 'bar'], NULL_TIMEZONE, NULL_LOCALE, '')
+        doEmptyFseTest(null, [foo: 'bar'], TIME_ZONE_TO_TEST, LOCALE_TO_TEST, 
'')
+        doEmptyFseTest('', [foo: 'bar'], null, null, '')
+    }
+
+    @Test
+    void testFSECommonCases() {
+        doFseTest('Hello World!', NULL_CONTEXT, NULL_TIMEZONE, NULL_LOCALE, 
'Hello World!', NULL_OBJECT)
+        doFseTest('Hello World!', [foo: 'bar'], 'Hello World!')
+        doFseTest('Hello ${var}!', [var: 'World'], 'Hello World!')
+        doFseTest('${\'Hello ${var}\'}!', [var: 'World'], 'Hello World!')
+        doFseTest('${\'Hel${blank}lo ${var}\'}!', [var: 'World', blank: ''], 
'Hello World!')
+    }
+
+    @Test
+    void testFSEUelExceptionIntegration() {
+        Map baseCtx = [exception: new TestException()]
+        doFseTest('${exception.value}', [*: baseCtx], NULL_TIMEZONE, 
NULL_LOCALE, '', NULL_OBJECT)
+        doFseEmptyExpandTest('${${exception.value}}', [*: baseCtx])
+        doFseEmptyExpandTest('${excep${var}.value}', [*: baseCtx, var: 'tion'])
+        doFseEmptyExpandTest('${exception${var}.value}', [*: baseCtx, var: ''])
+        doFseTest('${npe.value}', [npe: new TestNpe()], NULL_TIMEZONE, 
NULL_LOCALE, '', NULL_OBJECT)
+        doFseTest('The total is ${exception.value?currency(${usd})}.', [*: 
baseCtx], 'The total is .')
+    }
+
+    @Test
+    void testFSEUelIntegrationOnNullOrEmpty() {
+        Map baseCtx = [nullVar: null]
+        doFseEmptyExpandTest('${${nu${nullVar}ll}}', [*: baseCtx])
+        doFseEmptyExpandTest('${${nullVar.noProp}}', [*: baseCtx])
+        doFseEmptyExpandTest('${${unknonL${nullVar}ist[0]}}', [nullVar: null])
+        doFseTest('${null}', [:], NULL_TIMEZONE, NULL_LOCALE, '', NULL_OBJECT)
+        doFseTest('${nullVar.noProp}', [*: baseCtx], NULL_TIMEZONE, 
NULL_LOCALE, '', NULL_OBJECT)
+        doFseTest('${noList[0]}', [:], NULL_TIMEZONE, NULL_LOCALE, '', 
NULL_OBJECT)
+        doFseTest('The total is ${map.missing?currency(${usd})}.', [map: [:]], 
NULL_TIMEZONE, LOCALE_TO_TEST,
+                'The total is .', 'The total is .')
+        doFseTest('The total is ${noList[0]?currency(${usd})}.', [noList: []], 
NULL_TIMEZONE, LOCALE_TO_TEST,
+                'The total is .', 'The total is .')
+        doFseTest('${${nullVar}}!', [*: baseCtx], '!')
+    }
+
+    @Test
+    void testFSEUelIntegration() {
+        doFseTest('Hello ${testMap.var}!', [testMap: [var: 'World']], 'Hello 
World!')
+        doFseTest('Hello ${testMap.blank}World!', [testMap: [var: '']], 'Hello 
World!')
+        doFseTest('Hello ${testList[0]}!', [testList: ['World']], 'Hello 
World!')
+        doFseTestWithLocaleAndTimezone('${amount}', [amount: new 
BigDecimal('1234567.89')], NULL_TIMEZONE,
+                LOCALE_TO_TEST, '1,234,567.89', new BigDecimal('1234567.89'))
+        doFseTestWithLocaleAndTimezone('${a${\'moun\'}t}', [amount: new 
BigDecimal('1234567.89')], NULL_TIMEZONE,
+                LOCALE_TO_TEST, '1,234,567.89', new BigDecimal('1234567.89'))
+    }
+
+    /* codenarc-disable NoJavaUtilDate */
+
+    @Test
+    void testFSEDate() {
+        Date firstOfbizCommit = new Date(1154466300000)
+        doFseTestWithLocaleAndTimezone('The date is ${date}.', [date: 
firstOfbizCommit], TIME_ZONE_TO_TEST,
+                LOCALE_TO_TEST, 'The date is 2006-08-01 14:05:00.000.', 'The 
date is 2006-08-01 14:05:00.000.')
+    }
+    /* codenarc-enable NoJavaUtilDate */
+
+    @Test
+    void testMisformedFSE() {
+        doFseTest('${foobar', [:], '${foobar')
+        doFseTest('Hello${foobar', [:], 'Hello${foobar')
+        doFseTest('Hello ${var}${foobar', [var: 'World'], 'Hello 
World${foobar')
+    }
+
+    @Test
+    void testCurrencyFSE() {
+        Map baseCtx = [usd: 'USD', amount: new BigDecimal('1234567.89')]
+        doFseTestWithLocaleAndTimezone('${amount?currency(${usd})}', [*: 
baseCtx], NULL_TIMEZONE, LOCALE_TO_TEST,
+                '$1,234,567.89', '$1,234,567.89')
+        doFseTestWithLocaleAndTimezone('The total is 
${amount?currency(${usd})}.', [*: baseCtx], NULL_TIMEZONE,
+                LOCALE_TO_TEST, 'The total is $1,234,567.89.', 'The total is 
$1,234,567.89.')
+    }
+
+    @Test
+    void testGroovyScriptFSE() {
+        Map baseCtx = [var: 'World',
+                       exception: new TestException(),
+                       specialNumber: new SpecialNumber('1.00')]
+        doFseTest('${groovy: return \'Hello \' + var + \'!\'}', [*: baseCtx], 
'Hello World!')
+        doFseTest('${groovy: return null}!', [*: baseCtx], '!')
+        doFseTest('${groovy: return noList[0]}', [*: baseCtx], NULL_OBJECT)
+        doFseTest('${groovy: return exception.value}!', [*: baseCtx], '!')
+        doFseTest('${groovy: return specialNumber}!', [*: baseCtx], '1!')
+        doFseTest('This is a groovy ${groovy: if (true) {return \'bracket\'}} 
expression', [:],
+                'This is a groovy bracket expression')
+        doFseTest('This is a groovy ${groovy: if (true) {if (true) {return 
\'with 2 brackets\'}}} expression',
+                [:], 'This is a groovy with 2 brackets expression')
+        doFseTestWithLocaleAndTimezone('${groovy: return amount}', [amount: 
new BigDecimal('1234567.89')],
+                NULL_TIMEZONE, LOCALE_TO_TEST, '1,234,567.89', new 
BigDecimal('1234567.89'))
+    }
+
+    @Test
+    void testGroovyScriptFSESecurity() {
+        doFseTest('${groovy: java.util.Map.of(\'key\', \'value\')}!', [:], '!')
+        doFseTest('${groovy: \'ls /\'.execute()}!', [:], '!')
+        doFseTest('${groovy: new File(\'/etc/passwd\').getText()}!', [:], '!')
+        doFseTest('${groovy: (new File \'/etc/passwd\') .getText()}!', [:], 
'!')
+        doFseTest('${groovy: Eval.me(\'1\')}!', [:], '!')
+        doFseTest('${groovy: Eval . me(\'1\')}!', [:], '!')
+        doFseTest('${groovy: System.properties[\'ofbiz.home\']}!', [:], '!')
+        doFseTest('${groovy: new 
groovyx.net.http.HTTPBuilder(\'https://XXXX.XXXX.com:443\')}!', [:], '!')
+    }
+
+    @Test
+    void testFSEEscape() {
+        doFseTest('This is an \\${escaped} expression', [:], 'This is an 
${escaped} expression')
+        doFseTest('This is an \\${groovy:escaped} expression', [:], 'This is 
an ${groovy:escaped} expression')
+    }
+
+    private static void doFseBaseTest(String input, Map<String, Object> 
context, TimeZone timeZone, Locale locale,
+                                      String expandedString, Object 
expandedObj, boolean isEmpty) {
+        FlexibleStringExpander fse = FlexibleStringExpander.getInstance(input)
+        assert isEmpty == fse.isEmpty()
+
+        assert (input ?: '') == fse.getOriginal()
+        assert (input ?: '') == fse.toString()
+        expandedString = expandedString ?: ''
+
+        assert expandedString == FlexibleStringExpander.expandString(input, 
context)
+        assert expandedString == FlexibleStringExpander.expandString(input, 
context, locale)
+        assert expandedString == FlexibleStringExpander.expandString(input, 
context, timeZone, locale)
+
+        assert expandedString == fse.expandString(context)
+        assert expandedString == fse.expandString(context as Map, locale as 
Locale)
+        assert expandedString == fse.expandString(context as Map, timeZone as 
TimeZone, locale as Locale)
+
+        assert expandedObj == fse.expand(context)
+        assert expandedObj == fse.expand(context as Map, locale as Locale)
+        assert expandedObj == fse.expand(context as Map, timeZone as TimeZone, 
locale as Locale)
+    }
+
+    private static void doEmptyFseTest(String input, Map<String, Object> 
context, TimeZone timeZone, Locale locale,
+                                       String expandedString, Object 
expandedObj = NULL_OBJECT) {
+        doFseBaseTest(input, context, timeZone, locale, expandedString, 
expandedObj, true)
+    }
+
+    private static void doFseTest(String input, Map<String, Object> context, 
String expandedString) {
+        doFseBaseTest(input, context, NULL_TIMEZONE, NULL_LOCALE, 
expandedString, expandedString, false)
+    }
+
+    private static void doFseEmptyExpandTest(String input, Map<String, Object> 
context) {
+        doFseBaseTest(input, context, NULL_TIMEZONE, NULL_LOCALE, '', '', 
false)
+    }
+
+    private static void doFseTest(String input, Map<String, Object> context, 
TimeZone timeZone, Locale locale,
+                                  String expandedString, Object expandedObj = 
NULL_OBJECT) {
+        doFseBaseTest(input, context, timeZone, locale, expandedString, 
expandedObj, false)
+    }
+
+    /* codenarc-disable LocaleSetDefault */
+
+    private static void doFseTestWithLocaleAndTimezone(String input, 
Map<String, Object> context, TimeZone timeZone,
+                                                       Locale locale, String 
expandedString, Object expandedObj) {
+        // Test with only default locale
+        Locale.setDefault(locale)
+        TimeZone.setDefault(timeZone)
+        doFseBaseTest(input, context, NULL_TIMEZONE, NULL_LOCALE, 
expandedString, expandedObj, false)
+        Locale.setDefault(OTHER_LOCALE)
+        TimeZone.setDefault(OTHER_TIME_ZONE)
+        doFseNotEqualsTest(input, context, expandedString, expandedObj)
+
+        // Test with only autoUserLogin
+        context << [autoUserLogin: [
+                lastLocale: locale ? locale.toString() : null,
+                lastTimeZone: timeZone ? timeZone.getID() : null
+        ]]
+        doFseBaseTest(input, context, NULL_TIMEZONE, NULL_LOCALE, 
expandedString, expandedObj, false)
+        context.autoUserLogin = [
+                lastLocale: OTHER_LOCALE.toString(),
+                lastTimeZone: OTHER_TIME_ZONE.getID()
+        ]
+        doFseNotEqualsTest(input, context, expandedString, expandedObj)
+
+        // Test with only context
+        context.put('locale', locale)
+        context.put('timeZone', timeZone)
+        doFseBaseTest(input, context, timeZone, locale, expandedString, 
expandedObj, false)
+        context.put('locale', OTHER_LOCALE)
+        context.put('timeZone', OTHER_TIME_ZONE)
+        doFseNotEqualsTest(input, context, expandedString, expandedObj)
+    }
+    /* codenarc-enable LocaleSetDefault */
+
+    private static void doFseNotEqualsTest(String input, Map<String, Object> 
context, String expandedString,
+                                           Object expandedObj) {
+        FlexibleStringExpander fse = FlexibleStringExpander.getInstance(input)
+        assert expandedString != FlexibleStringExpander.expandString(input, 
context)
+        assert expandedString != fse.expandString(context)
+        if (expandedObj instanceof String) {
+            assert expandedObj != fse.expand(context)
+        }
+    }
+
+}
diff --git 
a/framework/base/src/test/groovy/org/apache/ofbiz/base/util/string/tool/SpecialNumber.groovy
 
b/framework/base/src/test/groovy/org/apache/ofbiz/base/util/string/tool/SpecialNumber.groovy
new file mode 100644
index 0000000000..f21cdd7f46
--- /dev/null
+++ 
b/framework/base/src/test/groovy/org/apache/ofbiz/base/util/string/tool/SpecialNumber.groovy
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * 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.ofbiz.base.util.string.tool
+
+/**
+ * Class used in testing
+ */
+public class SpecialNumber extends BigDecimal {
+
+    public SpecialNumber(String value) {
+        super(value)
+    }
+
+}
diff --git 
a/framework/base/src/test/groovy/org/apache/ofbiz/base/util/string/tool/TestException.groovy
 
b/framework/base/src/test/groovy/org/apache/ofbiz/base/util/string/tool/TestException.groovy
new file mode 100644
index 0000000000..ceebc60704
--- /dev/null
+++ 
b/framework/base/src/test/groovy/org/apache/ofbiz/base/util/string/tool/TestException.groovy
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * 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.ofbiz.base.util.string.tool
+
+/**
+ * Exception used in testing
+ */
+public class TestException extends Exception {
+
+    /* codenarc-disable ThrowException */
+
+    Object getValue() throws Exception {
+        throw new Exception()
+    }
+
+}
diff --git 
a/framework/base/src/test/groovy/org/apache/ofbiz/base/util/string/tool/TestNpe.groovy
 
b/framework/base/src/test/groovy/org/apache/ofbiz/base/util/string/tool/TestNpe.groovy
new file mode 100644
index 0000000000..b6f06de0dc
--- /dev/null
+++ 
b/framework/base/src/test/groovy/org/apache/ofbiz/base/util/string/tool/TestNpe.groovy
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * 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.ofbiz.base.util.string.tool
+
+/**
+ * Test NPE used in testing
+ */
+public class TestNpe {
+
+    /* codenarc-disable ThrowNullPointerException */
+    Object getValue() throws NullPointerException {
+        throw new NullPointerException()
+    }
+
+}
diff --git 
a/framework/base/src/test/java/org/apache/ofbiz/base/util/string/FlexibleStringExpanderTests.java
 
b/framework/base/src/test/java/org/apache/ofbiz/base/util/string/FlexibleStringExpanderTests.java
deleted file mode 100644
index aa50f1b046..0000000000
--- 
a/framework/base/src/test/java/org/apache/ofbiz/base/util/string/FlexibleStringExpanderTests.java
+++ /dev/null
@@ -1,342 +0,0 @@
-/*******************************************************************************
- * 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.ofbiz.base.util.string;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotSame;
-
-import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.TimeZone;
-
-import org.apache.ofbiz.base.conversion.AbstractConverter;
-import org.apache.ofbiz.base.conversion.ConversionException;
-import org.junit.Test;
-
-public class FlexibleStringExpanderTests {
-    private static final Locale LOCALE_TO_TEST = new Locale("en", "US");
-    private static final Locale BAD_LOCALE = new Locale("fr");
-    private static final TimeZone TIME_ZONE_TO_TEST = 
TimeZone.getTimeZone("PST");
-    private static final TimeZone BAD_TIME_ZONE = TimeZone.getTimeZone("GMT");
-
-    private static void parserTest(String label, String input, boolean 
checkCache, String toString) {
-        FlexibleStringExpander fse = FlexibleStringExpander.getInstance(input, 
false);
-        assertEquals(label + ":toString(no-cache)", toString, fse.toString());
-        fse = FlexibleStringExpander.getInstance(input, true);
-        assertEquals(label + ":toString(cache)", toString, fse.toString());
-        if (checkCache) {
-            assertEquals(label + ":same-cache", fse, 
FlexibleStringExpander.getInstance(input, true));
-        }
-    }
-
-    @Test
-    /**
-     * Test parsing.
-     */
-    public void testParsing() {
-        parserTest("visible nested replacement", "${'Hello ${var}'}!", true, 
"${'Hello ${var}'}!");
-        parserTest("hidden (runtime) nested null callreplacement", "Hello 
${${groovy:" + FlexibleStringExpanderTests.class.getName()
-                + ".staticReturnNull()}}World!", true, "Hello ${${groovy:" + 
FlexibleStringExpanderTests.class.getName()
-                + ".staticReturnNull()}}World!");
-        parserTest("UEL integration(nested): throw Exception", 
"${${throwException.value}}", true, "${${throwException.value}}");
-        parserTest("nested-constant-emptynest-emptynest", "${a${}${}", true, 
"${a${}${}");
-        parserTest("null", null, true, "");
-        parserTest("empty", "", true, "");
-        parserTest("constant-only", "a", false, "a");
-        parserTest("nested-constant-emptynest-emptynest", "${a${}${}", true, 
"${a${}${}");
-        parserTest("groovy", "${groovy:}", true, "${groovy:}");
-
-        parserTest("escaped", "\\${}", true, "\\${}");
-        parserTest("constant-escaped", "a\\${}", true, "a\\${}");
-        parserTest("escaped-groovy", "\\${groovy:}", true, "\\${groovy:}");
-
-        parserTest("missing-}", "${", true, "${");
-        parserTest("nested-constant-missing-}", "${a${}", true, "${a${}");
-        parserTest("nested-constant-nested-nested-missing-}", "${a${${}", 
true, "${a${${}");
-        parserTest("escaped-missing-}", "\\${", true, "\\${");
-        parserTest("constant-escaped-missing-}", "a\\${", true, "a\\${");
-
-        parserTest("currency", "${?currency(", true, "${?currency(");
-        parserTest("currency", "${?currency()", true, "${?currency()");
-        parserTest("currency", "${price?currency(", true, "${price?currency(");
-        parserTest("currency", "${price?currency()", true, 
"${price?currency()");
-        parserTest("currency", "${?currency(usd", true, "${?currency(usd");
-        parserTest("currency", "${?currency(usd)", true, "${?currency(usd)");
-        parserTest("currency", "${price?currency(usd", true, 
"${price?currency(usd");
-        parserTest("currency", "${price?currency(usd)", true, 
"${price?currency(usd)");
-        parserTest("currency", "${?currency(}", true, "${?currency(}");
-        parserTest("currency", "${?currency()}", true, "${?currency()}");
-        parserTest("currency", "${?currency(usd}", true, "${?currency(usd}");
-        parserTest("currency", "${?currency(usd)}", true, "${?currency(usd)}");
-        parserTest("currency", "${price?currency(}", true, 
"${price?currency(}");
-        parserTest("currency", "${price?currency()}", true, 
"${price?currency()}");
-        parserTest("currency", "${price?currency(usd}", true, 
"${price?currency(usd}");
-        parserTest("currency", "${price?currency(usd)}", true, 
"${price?currency(usd)}");
-        parserTest("currency", "a${price?currency(usd)}b", true, 
"a${price?currency(usd)}b");
-    }
-
-    private static void fseTest(String label, String input, Map<String, 
Object> context, String compare, boolean isEmpty) {
-        fseTest(label, input, context, null, null, compare, isEmpty);
-    }
-
-    private static void doFseTest(String label, String input, 
FlexibleStringExpander fse, Map<String, Object> context, TimeZone timeZone,
-                                  Locale locale, String compare, Object 
expand, boolean isEmpty) {
-        assertEquals("isEmpty:" + label, isEmpty, fse.isEmpty());
-        if (input == null) {
-            assertEquals("getOriginal():" + label, "", fse.getOriginal());
-            assertEquals("toString():" + label, "", fse.toString());
-            assertEquals("expandString(null):" + label, "", 
fse.expandString(null));
-            assertEquals("expand(null):" + label, null, fse.expand(null));
-            if (timeZone == null) {
-                assertEquals("expandString(null):" + label, "", 
fse.expandString(null, locale));
-                assertEquals("expand(null):" + label, null, fse.expand(null, 
locale));
-            } else {
-                assertEquals("expandString(null):" + label, "", 
fse.expandString(null, timeZone, locale));
-                assertEquals("expand(null):" + label, null, fse.expand(null, 
timeZone, locale));
-            }
-        } else {
-            assertEquals("getOriginal():" + label, input, fse.getOriginal());
-            assertEquals("toString():" + label, input, fse.toString());
-            assertEquals("expandString(null):" + label, input, 
fse.expandString(null));
-            assertEquals("expand(null):" + label, null, fse.expand(null));
-            if (timeZone == null) {
-                assertEquals("expandString(null):" + label, input, 
fse.expandString(null, locale));
-                assertEquals("expand(null):" + label, null, fse.expand(null, 
locale));
-            } else {
-                assertEquals("expandString(null):" + label, input, 
fse.expandString(null, timeZone, locale));
-                assertEquals("expand(null):" + label, null, fse.expand(null, 
timeZone, locale));
-            }
-        }
-        if (locale == null) {
-            assertEquals(label, compare, fse.expandString(context));
-            assertEquals("expand:" + label, expand, fse.expand(context));
-        } else {
-            Locale defaultLocale = Locale.getDefault();
-            TimeZone defaultTimeZone = TimeZone.getDefault();
-            try {
-                Locale.setDefault(locale);
-                TimeZone.setDefault(timeZone);
-                context.put("locale", locale);
-                context.put("timeZone", timeZone);
-                assertEquals(label, compare, fse.expandString(context, null, 
null));
-                assertEquals(label, expand, fse.expand(context, null, null));
-                Locale.setDefault(BAD_LOCALE);
-                TimeZone.setDefault(BAD_TIME_ZONE);
-                assertNotSame(label, compare, fse.expandString(context, null, 
null));
-                if (input != null) {
-                    assertNotSame(label, expand, fse.expand(context, null, 
null));
-                }
-                Map<String, Object> autoUserLogin = new HashMap<>();
-                autoUserLogin.put("lastLocale", locale.toString());
-                autoUserLogin.put("lastTimeZone", timeZone == null ? null : 
timeZone.getID());
-                context.put("autoUserLogin", autoUserLogin);
-                assertEquals(label, compare, fse.expandString(context, null, 
null));
-                assertEquals(label, expand, fse.expand(context, null, null));
-                autoUserLogin.put("lastLocale", BAD_LOCALE.toString());
-                autoUserLogin.put("lastTimeZone", BAD_TIME_ZONE.getID());
-                assertNotSame(label, compare, fse.expandString(context, null, 
null));
-                if (input != null) {
-                    assertNotSame(label, expand, fse.expand(context, null, 
null));
-                }
-                context.remove("autoUserLogin");
-                assertEquals(label, compare, fse.expandString(context, null, 
null));
-                assertEquals(label, expand, fse.expand(context, null, null));
-                context.put("locale", BAD_LOCALE);
-                context.put("timeZone", BAD_TIME_ZONE);
-                assertNotSame(label, compare, fse.expandString(context, null, 
null));
-                if (input != null) {
-                    assertNotSame(label, expand, fse.expand(context, null, 
null));
-                }
-                context.remove("locale");
-                context.remove("timeZone");
-                assertEquals(label, compare, fse.expandString(context, 
timeZone, locale));
-                assertEquals(label, expand, fse.expand(context, timeZone, 
locale));
-                assertNotSame(label, compare, fse.expandString(context, 
BAD_TIME_ZONE, BAD_LOCALE));
-                if (input != null) {
-                    assertNotSame(label, expand, fse.expand(context, 
BAD_TIME_ZONE, BAD_LOCALE));
-                }
-            } finally {
-                Locale.setDefault(defaultLocale);
-                TimeZone.setDefault(defaultTimeZone);
-            }
-        }
-    }
-
-    private static void fseTest(String label, String input, Map<String, 
Object> context, TimeZone timeZone, Locale locale,
-                                String compare, boolean isEmpty) {
-        fseTest(label, input, context, timeZone, locale, compare, compare, 
isEmpty);
-    }
-
-    private static void fseTest(String label, String input, Map<String, 
Object> context, TimeZone timeZone, Locale locale, String compare,
-                                Object expand, boolean isEmpty) {
-        FlexibleStringExpander fse = FlexibleStringExpander.getInstance(input);
-        doFseTest(label, input, fse, context, timeZone, locale, compare, 
expand, isEmpty);
-        assertEquals("static expandString:" + label, compare, 
FlexibleStringExpander.expandString(input, context, timeZone, locale));
-        if (input == null) {
-            assertEquals("static expandString(null, null):" + label, "", 
FlexibleStringExpander.expandString(input, null));
-            assertEquals("static expandString(null, null):" + label, "", 
FlexibleStringExpander.expandString(input, null, locale));
-        } else {
-            assertEquals("static expandString(input, null):" + label, input, 
FlexibleStringExpander.expandString(input, null));
-            assertEquals("static expandString(input, null):" + label, input, 
FlexibleStringExpander.expandString(input, null, locale));
-        }
-        if (!fse.isEmpty()) {
-            fse = FlexibleStringExpander.getInstance(input, false);
-            doFseTest(label, input, fse, context, timeZone, locale, compare, 
expand, isEmpty);
-        }
-    }
-
-    public static String staticReturnNull() {
-        return null;
-    }
-
-    @SuppressWarnings("serial")
-    public static class ThrowException extends Exception {
-        /**
-         * Gets value.
-         * @return the value
-         * @throws Exception the exception
-         */
-        public Object getValue() throws Exception {
-            throw new Exception();
-        }
-    }
-
-    public static class ThrowNPE {
-        /**
-         * Gets value.
-         * @return the value
-         */
-        public Object getValue() {
-            throw new NullPointerException();
-        }
-    }
-
-    public static class SpecialNumberToString extends 
AbstractConverter<SpecialNumber, String> {
-        public SpecialNumberToString() {
-            super(SpecialNumber.class, String.class);
-        }
-
-        @Override
-        public String convert(SpecialNumber obj) throws ConversionException {
-            throw new NullPointerException();
-        }
-    }
-
-    @SuppressWarnings("serial")
-    public static class SpecialNumber extends BigDecimal {
-        public SpecialNumber(String value) {
-            super(value);
-        }
-
-        @Override
-        public String toString() {
-            return getClass().getName();
-        }
-    }
-
-    @Test
-    public void testEverything() {
-        Map<String, Object> testMap = new HashMap<>();
-        testMap.put("date", new java.util.Date(1234567890));
-        testMap.put("usd", "USD");
-        testMap.put("amount", new BigDecimal("1234567.89"));
-        testMap.put("blank", "");
-        testMap.put("exc", "Exception");
-        testMap.put("nullVar", null);
-        testMap.put("throwException", new ThrowException());
-        testMap.put("throwNPE", new ThrowNPE());
-        testMap.put("var", "World");
-        testMap.put("nested", "Hello ${var}");
-        testMap.put("testMap", testMap);
-        testMap.put("nestedNull", "Hello ${nullVar}${var}");
-        testMap.put("specialNumber", new SpecialNumber("1.00"));
-        List<String> testList = new ArrayList<>();
-        testList.add("World");
-        testMap.put("testList", testList);
-        fseTest("null FlexibleStringExpander, null map", null, null, null, 
null, "", null, true);
-        fseTest("null FlexibleStringExpander", null, testMap, null, null, "", 
null, true);
-        fseTest("null context", "Hello World!", null, null, null, "Hello 
World!", null, false);
-        fseTest("plain string", "Hello World!", testMap, null, null, "Hello 
World!", "Hello World!", false);
-        fseTest("simple replacement", "Hello ${var}!", testMap, "Hello 
World!", false);
-        fseTest("null FlexibleStringExpander with timeZone/locale", null, 
testMap, TIME_ZONE_TO_TEST, LOCALE_TO_TEST, "", null, true);
-        fseTest("empty FlexibleStringExpander", "", testMap, null, null, "", 
null, true);
-        fseTest("UEL integration(nested): throw Exception", 
"${${throwException.value}}", testMap, "", false);
-        fseTest("UEL integration: throw Exception", "${throwException.value}", 
testMap, null, null, "", null, false);
-        fseTest("UEL integration(nested): throw Exception", 
"${throw${exc}.value}", testMap, "", false);
-        fseTest("UEL integration(nested): throw NPE", 
"${throwNPE${blank}.value}", testMap, "", false);
-        fseTest("visible nested replacement", "${'Hello ${var}'}!", testMap, 
"Hello World!", false);
-        fseTest("blank nested replacement", "${'Hel${blank}lo ${var}'}!", 
testMap, "Hello World!", false);
-        fseTest("UEL integration(nested): null", "${${nu${nullVar}ll}}", 
testMap, "", false);
-        fseTest("UEL integration(nested): NPE", "${${nullVar.noProp}}", 
testMap, "", false);
-        fseTest("UEL integration(nested): missing", 
"${${noL${nullVar}ist[0]}}", testMap, "", false);
-        fseTest("date w/ timezone", "The date is ${date}.", testMap, 
TIME_ZONE_TO_TEST, LOCALE_TO_TEST, "The date is 1970-01-14 22:56:07.890.",
-                "The date is 1970-01-14 22:56:07.890.", false);
-        fseTest("just bad", "${foobar", testMap, "${foobar", false);
-        fseTest("constant and bad", "Hello${foobar", testMap, "Hello${foobar", 
false);
-        fseTest("good and bad", "Hello ${var}${foobar", testMap, "Hello 
World${foobar", false);
-        fseTest("plain-currency(USD)", "${amount?currency(${usd})}", testMap, 
null, LOCALE_TO_TEST, "$1,234,567.89", false);
-        fseTest("currency(USD)", "The total is ${amount?currency(${usd})}.", 
testMap, null, LOCALE_TO_TEST, "The total is $1,234,567.89.", false);
-        fseTest("currency(USD): null", "The total is 
${testMap.missing?currency(${usd})}.", testMap, null, LOCALE_TO_TEST, "The 
total is .", false);
-        fseTest("currency(USD): missing", "The total is 
${noList[0]?currency(${usd})}.", testMap, null, LOCALE_TO_TEST, "The total is 
.", false);
-        fseTest("currency(USD): exception", "The total is 
${throwException.value?currency(${usd})}.", testMap, null, LOCALE_TO_TEST,
-                "The total is .", false);
-        fseTest("null nested", "${${nullVar}}!", testMap, "!", false);
-        fseTest("groovy: script", "${groovy:return \"Hello \" + var + 
\"!\";}", testMap, "Hello World!", false);
-        fseTest("groovy: null", "${groovy:return null;}!", testMap, "!", 
false);
-        fseTest("groovy missing property", "${groovy: return noList[0]}", 
testMap, null, null, "", null, false);
-        fseTest("groovy: throw Exception", "${groovy:return 
throwException.value;}!", testMap, "!", false);
-        fseTest("groovy: generate security issue", "${groovy: 
java.util.Map.of('key', 'value')}!", testMap, "!", false);
-        fseTest("groovy: another generate security issue 1", "${groovy: 'ls 
/'.execute()}!", testMap, "!", false);
-        fseTest("groovy: another generate security issue 2", "${groovy: new 
File('/etc/passwd').getText()}!", testMap, "!", false);
-        fseTest("groovy: another generate security issue 3", "${groovy: (new 
File '/etc/passwd') .getText()}!", testMap, "!", false);
-        fseTest("groovy: another generate security issue 4", "${groovy: 
Eval.me('1')}!", testMap, "!", false);
-        fseTest("groovy: another generate security issue 5", "${groovy: Eval . 
me('1')}!", testMap, "!", false);
-        fseTest("groovy: another generate security issue 6", "${groovy: 
System.properties['ofbiz.home']}!", testMap, "!", false);
-        fseTest("groovy: another generate security issue 7", "${groovy: new 
groovyx.net.http.HTTPBuilder('https://XXXX.XXXX.com:443')}!",
-                testMap, "!", false);
-        fseTest("groovy: converter exception", "${groovy:return 
specialNumber;}!", testMap, "1!", false);
-        fseTest("UEL integration: Map", "Hello ${testMap.var}!", testMap, 
"Hello World!", false);
-        fseTest("UEL integration: blank", "Hello ${testMap.blank}World!", 
testMap, "Hello World!", false);
-        fseTest("UEL integration: List", "Hello ${testList[0]}!", testMap, 
"Hello World!", false);
-        fseTest("UEL integration: null", "${null}", testMap, null, null, "", 
null, false);
-        fseTest("UEL integration: null dereference", "${nullVar.noProp}", 
testMap, null, null, "", null, false);
-        fseTest("UEL integration: throw NPE", "${" + 
FlexibleStringExpanderTests.class.getName() + ".ThrowNPE.noProp}", testMap, 
null, null, "",
-                null, false);
-        fseTest("UEL integration: missing", "${noList[0]}", testMap, null, 
null, "", null, false);
-        fseTest("Escaped expression", "This is an \\${escaped} expression", 
testMap, "This is an ${escaped} expression", false);
-        fseTest("Escaped(groovy) expression", "This is an \\${groovy:escaped} 
expression", testMap, "This is an ${groovy:escaped} expression", false);
-        fseTest("Bracket en groovy", "This is a groovy ${groovy: if (true) 
{return 'bracket'}} expression", testMap,
-                "This is a groovy bracket expression", false);
-        fseTest("Bracket en groovy again", "This is a groovy ${groovy: if 
(true) {if (true) {return 'with 2 brackets'}}} expression", testMap,
-                "This is a groovy with 2 brackets expression", false);
-
-        // TODO: Find a better way to setup or handle the big decimal value. 
If new ones are not instantiated in the test
-        // it fails because of the comparison between object pointers..
-        fseTest("nested UEL integration(return BigDecimal)", "${a${'moun'}t}", 
testMap, null, LOCALE_TO_TEST,
-                "1,234,567.89", new BigDecimal("1234567.89"), false);
-        fseTest("UEL integration(return BigDecimal)", "${amount}", testMap, 
null, LOCALE_TO_TEST,
-                "1,234,567.89", new BigDecimal("1234567.89"), false);
-        fseTest("groovy: return BigDecimal", "${groovy: return amount;}", 
testMap, null, LOCALE_TO_TEST,
-                "1,234,567.89", new BigDecimal("1234567.89"), false);
-    }
-}


Reply via email to