/*
* 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.commons.json.sling;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.when;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import java.util.UUID;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.wrappers.ValueMapDecorator;
import org.apache.sling.commons.json.JSONArray;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class JsonObjectCreatorTest {
@Mock
private Resource resource;
@Mock
private ResourceResolver resourceResolver;
@Mock
private ResourceResolver childResourceResolver;
private Map<String, Object> props;
private static final String RESOURCE_NAME = "testResource";
private static final String PATH = "/" + RESOURCE_NAME;
private static final Object SAME = new Object();
private static final int NCHILDREN = 3;
private static final String ECMA_DATE_FORMAT = "EEE MMM dd yyyy HH:mm:ss 'GMT'Z";
@Before
public void setup() {
props = new HashMap<String, Object>();
props.put("defaultProperty", "defaultValue");
final List<Resource> empty = new ArrayList<Resource>();
when(childResourceResolver.listChildren(any(Resource.class))).thenReturn(empty.iterator());
final List<Resource> children = new ArrayList<Resource>();
for(int i=0; i < NCHILDREN; i++) {
final Map<String, Object> childProps = new HashMap<String, Object>();
final String id = "child" + i;
childProps.put("id", id);
final Resource r = Mockito.mock(Resource.class);
when(r.adaptTo(ValueMap.class)).thenReturn(new ValueMapDecorator(childProps));
when(r.getResourceResolver()).thenReturn(childResourceResolver);
when(r.getPath()).thenReturn(PATH + "/" + id);
children.add(r);
}
when(resourceResolver.listChildren(any(Resource.class))).thenReturn(children.iterator());
when(resource.getResourceResolver()).thenReturn(resourceResolver);
when(resource.getPath()).thenReturn(PATH);
}
private void assertGet(Object data) throws JSONException {
assertGet(data, SAME);
}
private void assertGet(Object data, Object expected) throws JSONException {
final String key = UUID.randomUUID().toString();
props.clear();
props.put(key, data);
when(resource.adaptTo(ValueMap.class)).thenReturn(new ValueMapDecorator(props));
final JSONObject j = JsonObjectCreator.create(resource, 1);
final String getKey = data instanceof InputStream ? ":" + key : key;
final Object toExpect = expected == SAME ? data : expected;
if(toExpect instanceof String) {
assertEquals(toExpect, j.get(getKey).toString());
} else {
assertEquals(toExpect, j.get(getKey));
}
}
@Test
public void testSimpleTypes() throws JSONException {
assertGet("bar");
assertGet(true);
assertGet(123);
assertGet(456.78);
assertGet(System.currentTimeMillis());
}
@Test
public void testStringValue() throws JSONException {
final String value = "the string";
when(resource.adaptTo(String.class)).thenReturn(value);
final JSONObject j = JsonObjectCreator.create(resource, 1);
assertEquals(value, j.get(RESOURCE_NAME));
}
@Test
public void testStringArray() throws JSONException {
final String [] values = { "A", "B" };
when(resource.adaptTo(String[].class)).thenReturn(values);
final JSONObject j = JsonObjectCreator.create(resource, 1);
assertEquals("A", j.getJSONArray(RESOURCE_NAME).get(0));
assertEquals("B", j.getJSONArray(RESOURCE_NAME).get(1));
}
@Test
public void testArray() throws JSONException {
final String [] values = { "C", "D" };
final JSONArray a = new JSONArray().put("C").put("D");
assertGet(values, a.toString());
}
@Test
public void testEmptyArray() throws JSONException {
final Long [] values = {};
assertGet(values, "[]");
}
@Test
public void testCalendar() throws JSONException {
final Calendar nowCalendar = Calendar.getInstance();
final String nowString = new SimpleDateFormat(ECMA_DATE_FORMAT, JsonObjectCreator.DATE_FORMAT_LOCALE).format(nowCalendar.getTime());
assertGet(nowCalendar, nowString);
}
@Test
public void testCalendarTimezones() throws JSONException {
final int[] offsets = { -14400000, -4200000, 14400000, 4300000 };
for (int offset : offsets) {
for (String tzId : TimeZone.getAvailableIDs(offset)) {
final TimeZone tz = TimeZone.getTimeZone(tzId);
final Calendar cal = Calendar.getInstance(tz);
DateFormat fmt = new SimpleDateFormat(ECMA_DATE_FORMAT, Locale.ENGLISH);
fmt.setTimeZone(tz);
final String nowString = fmt.format(cal.getTime());
assertGet(cal, nowString);
}
}
}
@Test
public void testStream() throws JSONException {
final byte [] bytes = "Hello there".getBytes();
final InputStream stream = new ByteArrayInputStream(bytes);
// TODO not sure why we don't get the actual length here
assertGet(stream, -1L);
}
@Test
public void testChildren() throws JSONException {
when(resource.adaptTo(ValueMap.class)).thenReturn(new ValueMapDecorator(props));
final JSONObject j = JsonObjectCreator.create(resource, 2);
for(int i=0 ; i < NCHILDREN; i++) {
final String id = "child" + i;
assertEquals(id, j.getJSONObject(id).get("id"));
}
}
}