You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ss...@apache.org on 2020/04/29 09:54:42 UTC

[sling-org-apache-sling-testing-sling-mock] branch master updated: SLING-9407 sling-mock: Add mock for ResourceBundleProvider and ResourceBundle (i18n)

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

sseifert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-testing-sling-mock.git


The following commit(s) were added to refs/heads/master by this push:
     new 461ac0e  SLING-9407 sling-mock: Add mock for ResourceBundleProvider and ResourceBundle (i18n)
461ac0e is described below

commit 461ac0e0373d0741467d0329c10e29fb2d242464
Author: sseifert <ss...@pro-vision.de>
AuthorDate: Wed Apr 29 11:53:02 2020 +0200

    SLING-9407 sling-mock: Add mock for ResourceBundleProvider and ResourceBundle (i18n)
---
 .../testing/mock/sling/MockResourceBundle.java     |  95 ++++++++++++++++
 .../mock/sling/MockResourceBundleProvider.java     | 126 +++++++++++++++++++++
 .../mock/sling/context/SlingContextImpl.java       |   2 +
 .../sling/testing/mock/sling/package-info.java     |   2 +-
 .../mock/sling/MockResourceBundleProviderTest.java |  82 ++++++++++++++
 .../testing/mock/sling/MockResourceBundleTest.java |  65 +++++++++++
 6 files changed, 371 insertions(+), 1 deletion(-)

diff --git a/core/src/main/java/org/apache/sling/testing/mock/sling/MockResourceBundle.java b/core/src/main/java/org/apache/sling/testing/mock/sling/MockResourceBundle.java
new file mode 100644
index 0000000..8d01887
--- /dev/null
+++ b/core/src/main/java/org/apache/sling/testing/mock/sling/MockResourceBundle.java
@@ -0,0 +1,95 @@
+/*
+ * 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.sling.testing.mock.sling;
+
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.Set;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Mock implementation of an i18n {@link ResourceBundle}.
+ * Contains no translations by default and returns the key itself.
+ * But you can add your own mappings.
+ */
+public final class MockResourceBundle extends ResourceBundle {
+
+    private final String baseName;
+    private final Locale locale;
+    private final Map<String, String> mappings = new HashMap<>();
+
+    /**
+     * @param baseName Base name
+     * @param locale Locale
+     */
+    public MockResourceBundle(String baseName, Locale locale) {
+        this.baseName = baseName;
+        this.locale = locale;
+    }
+
+    @Override
+    public Locale getLocale() {
+        return locale;
+    }
+
+    @Override
+    protected Object handleGetObject(String key) {
+        return mappings.getOrDefault(key,  key);
+    }
+
+    @Override
+    public Set<String> keySet() {
+        return mappings.keySet();
+    }
+
+    @Override
+    public Enumeration<String> getKeys() {
+        return Collections.enumeration(mappings.keySet());
+    }
+
+    /**
+     * @return Base name
+     */
+    public String getBaseName() {
+        return baseName;
+    }    
+
+    /**
+     * Add translation.
+     * @param key Key
+     * @param value Value
+     */
+    public void put(@NotNull String key, @NotNull String value) {
+        mappings.put(key, value);
+    }
+
+    /**
+     * Add translations.
+     * @param map Translation map
+     */
+    public void putAll(@NotNull Map<? extends String, ? extends String> map) {
+        mappings.putAll(map);
+    }
+
+}
diff --git a/core/src/main/java/org/apache/sling/testing/mock/sling/MockResourceBundleProvider.java b/core/src/main/java/org/apache/sling/testing/mock/sling/MockResourceBundleProvider.java
new file mode 100644
index 0000000..8e6418e
--- /dev/null
+++ b/core/src/main/java/org/apache/sling/testing/mock/sling/MockResourceBundleProvider.java
@@ -0,0 +1,126 @@
+/*
+ * 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.sling.testing.mock.sling;
+
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.sling.i18n.ResourceBundleProvider;
+import org.osgi.service.component.annotations.Component;
+
+/**
+ * Mock implementation of @link {@link ResourceBundleProvider} then ensures
+ * resolving i18n keys does not lead to exceptions. By default it contains no
+ * translations, but it's possible to add you own mapping in unit tests.
+ */
+@Component(service = ResourceBundleProvider.class)
+public final class MockResourceBundleProvider implements ResourceBundleProvider {
+
+    private final ConcurrentHashMap<Key, MockResourceBundle> resourceBundleCache = new ConcurrentHashMap<>();
+    private Locale defaultLocale = Locale.US;
+
+    @Override
+    public Locale getDefaultLocale() {
+        return defaultLocale;
+    }
+
+    @Override
+    public ResourceBundle getResourceBundle(final Locale locale) {
+        return getResourceBundle(null, locale);
+    }
+
+    @Override
+    public ResourceBundle getResourceBundle(final String baseName, final Locale locale) {
+        Locale bundleLocale = locale != null ? locale : defaultLocale;
+        Key key = new Key(baseName, bundleLocale);
+        return resourceBundleCache.computeIfAbsent(key, k -> new MockResourceBundle(k.baseName, k.locale));
+    }
+
+    /**
+     * Sets the default locale.
+     * @param defaultLocale Default locale
+     */
+    public void setDefaultLocale(Locale defaultLocale) {
+        this.defaultLocale = defaultLocale;
+    }
+
+    /**
+     * The <code>Key</code> class encapsulates the base name and Locale in a
+     * single object that can be used as the key in a <code>HashMap</code>.
+     */
+    private static final class Key {
+        final String baseName;
+        final Locale locale;
+
+        // precomputed hash code, because this will always be used due to
+        // this instance being used as a key in a HashMap.
+        private final int hashCode;
+
+        Key(final String baseName, final Locale locale) {
+
+            int hc = 0;
+            if (baseName != null) {
+                hc += 17 * baseName.hashCode();
+            }
+            if (locale != null) {
+                hc += 13 * locale.hashCode();
+            }
+
+            this.baseName = baseName;
+            this.locale = locale;
+            this.hashCode = hc;
+        }
+
+        @Override
+        public int hashCode() {
+            return hashCode;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj == this) {
+                return true;
+            } else if (obj instanceof Key) {
+                Key other = (Key) obj;
+                return equals(this.baseName, other.baseName)
+                    && equals(this.locale, other.locale);
+            }
+
+            return false;
+        }
+
+        private static boolean equals(Object o1, Object o2) {
+            if (o1 == null) {
+                if (o2 != null) {
+                    return false;
+                }
+            } else if (!o1.equals(o2)) {
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        public String toString() {
+            return "Key(" + baseName + ", " + locale + ")";
+        }
+    }
+
+}
diff --git a/core/src/main/java/org/apache/sling/testing/mock/sling/context/SlingContextImpl.java b/core/src/main/java/org/apache/sling/testing/mock/sling/context/SlingContextImpl.java
index b6e7ca3..5a90f46 100644
--- a/core/src/main/java/org/apache/sling/testing/mock/sling/context/SlingContextImpl.java
+++ b/core/src/main/java/org/apache/sling/testing/mock/sling/context/SlingContextImpl.java
@@ -47,6 +47,7 @@ import org.apache.sling.scripting.core.impl.BindingsValuesProvidersByContextImpl
 import org.apache.sling.settings.SlingSettingsService;
 import org.apache.sling.testing.mock.osgi.MockOsgi;
 import org.apache.sling.testing.mock.osgi.context.OsgiContextImpl;
+import org.apache.sling.testing.mock.sling.MockResourceBundleProvider;
 import org.apache.sling.testing.mock.sling.MockSling;
 import org.apache.sling.testing.mock.sling.ResourceResolverType;
 import org.apache.sling.testing.mock.sling.builder.ContentBuilder;
@@ -179,6 +180,7 @@ public class SlingContextImpl extends OsgiContextImpl {
         registerService(MimeTypeService.class, new MockMimeTypeService());
         registerInjectActivateService(new ResourceBuilderFactoryService());
         registerInjectActivateService(new JcrObjectsBindingsValuesProvider());
+        registerInjectActivateService(new MockResourceBundleProvider());
         
         // scan for models defined via bundle headers in classpath
         if (registerSlingModelsFromClassPath) {
diff --git a/core/src/main/java/org/apache/sling/testing/mock/sling/package-info.java b/core/src/main/java/org/apache/sling/testing/mock/sling/package-info.java
index 507d918..b5f88a2 100644
--- a/core/src/main/java/org/apache/sling/testing/mock/sling/package-info.java
+++ b/core/src/main/java/org/apache/sling/testing/mock/sling/package-info.java
@@ -19,5 +19,5 @@
 /**
  * Mock implementation of selected Sling APIs.
  */
-@org.osgi.annotation.versioning.Version("3.1.1")
+@org.osgi.annotation.versioning.Version("3.2.0")
 package org.apache.sling.testing.mock.sling;
diff --git a/core/src/test/java/org/apache/sling/testing/mock/sling/MockResourceBundleProviderTest.java b/core/src/test/java/org/apache/sling/testing/mock/sling/MockResourceBundleProviderTest.java
new file mode 100644
index 0000000..c83efba
--- /dev/null
+++ b/core/src/test/java/org/apache/sling/testing/mock/sling/MockResourceBundleProviderTest.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.sling.testing.mock.sling;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import org.apache.sling.i18n.ResourceBundleProvider;
+import org.apache.sling.testing.mock.sling.junit.SlingContext;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class MockResourceBundleProviderTest {
+
+    private static final String MY_NAME = "my-name";
+    
+    @Rule
+    public SlingContext context = new SlingContext();
+
+    @Test
+    public void testGetResourceBundleFromRequest() {
+        ResourceBundle bundle = context.request().getResourceBundle(Locale.CANADA_FRENCH);
+        assertEquals(Locale.CANADA_FRENCH, bundle.getLocale());
+        assertNull(((MockResourceBundle)bundle).getBaseName());
+    }
+
+    @Test
+    public void testGetResourceBundleFromRequestWithBaseName() {
+        ResourceBundle bundle = context.request().getResourceBundle(MY_NAME, Locale.CANADA_FRENCH);
+        assertEquals(Locale.CANADA_FRENCH, bundle.getLocale());
+        assertEquals(MY_NAME, ((MockResourceBundle)bundle).getBaseName());
+    }
+
+    @Test
+    public void testDefaultLocale() {
+        MockResourceBundleProvider bundleProvider = (MockResourceBundleProvider)context.getService(ResourceBundleProvider.class);
+        assertNotNull(bundleProvider);
+        bundleProvider.setDefaultLocale(Locale.KOREA);
+
+        ResourceBundle bundle = context.request().getResourceBundle(null);
+        assertEquals(Locale.KOREA, bundle.getLocale());
+        assertNull(((MockResourceBundle)bundle).getBaseName());
+    }
+
+    @Test
+    public void testCaching() {
+        ResourceBundle bundle = context.request().getResourceBundle(Locale.GERMAN);
+
+        ((MockResourceBundle)bundle).put("key1", "value1");
+        assertEquals("value1", bundle.getString("key1"));
+
+        ResourceBundle bundle_cached = context.request().getResourceBundle(Locale.GERMAN);
+        assertEquals("value1", bundle_cached.getString("key1"));
+
+        ResourceBundle bundle_otherlocale = context.request().getResourceBundle(Locale.FRANCE);
+        assertEquals("key1", bundle_otherlocale.getString("key1"));
+
+        ResourceBundle bundle_otherbasename = context.request().getResourceBundle(MY_NAME, Locale.GERMAN);
+        assertEquals("key1", bundle_otherbasename.getString("key1"));
+    }
+
+}
diff --git a/core/src/test/java/org/apache/sling/testing/mock/sling/MockResourceBundleTest.java b/core/src/test/java/org/apache/sling/testing/mock/sling/MockResourceBundleTest.java
new file mode 100644
index 0000000..8ebd22d
--- /dev/null
+++ b/core/src/test/java/org/apache/sling/testing/mock/sling/MockResourceBundleTest.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.sling.testing.mock.sling;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Locale;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+public class MockResourceBundleTest {
+
+    private static final String MY_NAME = "my-name";
+    private MockResourceBundle underTest;
+
+    @Before
+    public void setUp() {
+        underTest = new MockResourceBundle(MY_NAME, Locale.US);
+        assertEquals(MY_NAME, underTest.getBaseName());
+        assertEquals(Locale.US, underTest.getLocale());
+    }
+
+    @Test
+    public void testEmpty() {
+        assertEquals("unknown", underTest.getString("unknown"));
+        assertEquals(ImmutableSet.of(), underTest.keySet());
+        assertFalse(underTest.getKeys().hasMoreElements());
+    }
+
+    @Test
+    public void testWithMappings() {
+        underTest.put("key1", "value1");
+        underTest.putAll(ImmutableMap.of("key2", "value2", "key3" ,"value3"));
+
+        assertEquals("value1", underTest.getString("key1"));
+        assertEquals("value2", underTest.getString("key2"));
+        assertEquals("value3", underTest.getString("key3"));
+
+        assertEquals(ImmutableSet.of("key1", "key2", "key3"), underTest.keySet());
+        assertTrue(underTest.getKeys().hasMoreElements());
+    }
+
+}