/*
* 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.installer.core.impl;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import org.apache.sling.installer.api.InstallableResource;
import org.apache.sling.installer.api.tasks.RegisteredResource;
import org.apache.sling.installer.api.tasks.ResourceState;
import org.apache.sling.installer.api.tasks.TransformationResult;
import org.junit.Test;
public class RegisteredResourceComparatorTest {
private void assertOrder(final Set<RegisteredResource> toTest, final RegisteredResource[] inOrder) {
assertEquals("Expected sizes to match", toTest.size(), inOrder.length);
int i = 0;
for(final RegisteredResource r : toTest) {
final RegisteredResource ref = inOrder[i];
assertSame("At index " + i + ", expected toTest and ref to match.", ref, r);
i++;
}
}
private RegisteredResourceImpl getConfig(String url, Dictionary<String, Object> data, int priority) throws IOException {
return getConfig(url, data, priority, null);
}
private RegisteredResourceImpl getConfig(String url, Dictionary<String, Object> data, int priority, String digest) throws IOException {
return getConfig(url, data, priority, digest, null);
}
private RegisteredResourceImpl getConfig(String url, Dictionary<String, Object> data, int priority, String digest, ResourceState state) throws IOException {
if (data == null) {
data = new Hashtable<String, Object>();
data.put("foo", "bar");
}
new FileDataStore(new MockBundleContext());
final InstallableResource r = new InstallableResource(url, null, data, digest, null, priority);
final InternalResource internal = InternalResource.create("test", r);
final RegisteredResourceImpl rr = RegisteredResourceImpl.create(internal);
TransformationResult[] tr = new DefaultTransformer().transform(rr);
if ( tr == null ) {
final TransformationResult result = new TransformationResult();
result.setId(url);
result.setResourceType(InstallableResource.TYPE_CONFIG);
tr = new TransformationResult[] {
result
};
}
final RegisteredResourceImpl result = (RegisteredResourceImpl)rr.clone(tr[0]);
if ( state != null ) {
result.setState(state, null);
}
return result;
}
private RegisteredResource untransformedResource(String id, int prio) throws IOException {
final ByteArrayInputStream is = new ByteArrayInputStream(id.getBytes("UTF-8"));
final InstallableResource r = new InstallableResource(id, is, null, id, id, prio);
final InternalResource internal = InternalResource.create("test", r);
return RegisteredResourceImpl.create(internal);
}
private void assertOrder(RegisteredResource[] inOrder) {
final SortedSet<RegisteredResource> toTest = new TreeSet<RegisteredResource>();
for(int i = inOrder.length - 1 ; i >= 0; i--) {
toTest.add(inOrder[i]);
}
assertOrder(toTest, inOrder);
toTest.clear();
for(RegisteredResource r : inOrder) {
toTest.add(r);
}
assertOrder(toTest, inOrder);
}
@Test
public void testBundleName() {
final RegisteredResource [] inOrder = {
new MockBundleResource("a", "1.0", 10),
new MockBundleResource("b", "1.0", 10),
new MockBundleResource("c", "1.0", 10),
new MockBundleResource("d", "1.0", 10),
};
assertOrder(inOrder);
}
@Test
public void testBundleVersion() {
final RegisteredResource [] inOrder = {
new MockBundleResource("a", "1.2.51", 10),
new MockBundleResource("a", "1.2.4", 10),
new MockBundleResource("a", "1.1.0", 10),
new MockBundleResource("a", "1.0.6", 10),
new MockBundleResource("a", "1.0.0", 10),
};
assertOrder(inOrder);
}
@Test
public void testBundlePriority() {
final RegisteredResource [] inOrder = {
new MockBundleResource("a", "1.0.0", 101),
new MockBundleResource("a", "1.0.0", 10),
new MockBundleResource("a", "1.0.0", 0),
new MockBundleResource("a", "1.0.0", -5),
};
assertOrder(inOrder);
}
@Test
public void testComposite() {
final RegisteredResource [] inOrder = {
new MockBundleResource("a", "1.2.0"),
new MockBundleResource("a", "1.0.0"),
new MockBundleResource("b", "1.0.0", 2),
new MockBundleResource("b", "1.0.0", 0),
new MockBundleResource("c", "1.5.0", -5),
new MockBundleResource("c", "1.4.0", 50),
};
assertOrder(inOrder);
}
@Test
public void testBundleDigests() {
final MockBundleResource a = new MockBundleResource("a", "1.2.0", 0, "digestA");
final MockBundleResource b = new MockBundleResource("a", "1.2.0", 0, "digestB");
assertEquals("Digests must not be included in bundles comparison", 0, a.compareTo(b));
final MockBundleResource c = new MockBundleResource("a", "1.2.0.SNAPSHOT", 0, "1000");
final MockBundleResource d = new MockBundleResource("a", "1.2.0.SNAPSHOT", 0, "2000");
assertEquals("Digests should be compared with highest first", 1, c.compareTo(d));
}
@Test
public void testSnapshotSerialNumber() {
// Verify that snapshots with a higher serial number come first
final RegisteredResource [] inOrder = new RegisteredResource [3];
inOrder[0] = new MockBundleResource("a", "1.2.0.SNAPSHOT", 0, "digestC");
inOrder[1] = new MockBundleResource("a", "1.2.0.SNAPSHOT", 0, "digestB");
inOrder[2] = new MockBundleResource("a", "1.2.0.SNAPSHOT", 0, "digestA");
assertOrder(inOrder);
}
@Test
public void testConfigPriority() throws IOException {
final RegisteredResource [] inOrder = new RegisteredResource [3];
inOrder[0] = getConfig("pid", null, 2);
inOrder[1] = getConfig("pid", null, 1);
inOrder[2] = getConfig("pid", null, 0);
assertOrder(inOrder);
}
@Test
public void testConfigDigests() throws IOException {
final Dictionary<String, Object> data = new Hashtable<String, Object>();
data.put("foo", "bar");
final RegisteredResourceImpl a = getConfig("pid", data, 0);
data.put("foo", "changed");
final RegisteredResourceImpl b = getConfig("pid", data, 0);
assertEquals("Entity urls must be the same", a.getEntityId(), b.getEntityId());
assertTrue("Digests must be included in configs comparison", a.compareTo(b) != 0);
final RegisteredResourceImpl a2 = getConfig("pid", data, 0);
final RegisteredResourceImpl b2 = getConfig("pid", data, 0);
assertEquals("Digests must be included in configs comparison", 0, a2.compareTo(b2));
}
@Test
public void testConfigPid() throws IOException {
final RegisteredResource [] inOrder = new RegisteredResource [3];
inOrder[0] = getConfig("pidA", null, 0);
inOrder[1] = getConfig("pidB", null, 0);
inOrder[2] = getConfig("pidC", null, 0);
assertOrder(inOrder);
}
@Test
public void testConfigComposite() throws IOException {
final RegisteredResource [] inOrder = new RegisteredResource [4];
inOrder[0] = getConfig("pidA", null, 10);
inOrder[1] = getConfig("pidA", null, 0);
inOrder[2] = getConfig("pidB", null, 1);
inOrder[3] = getConfig("pidB", null, 0);
assertOrder(inOrder);
}
@Test
public void testConfigState() throws IOException {
final RegisteredResource [] inOrder = new RegisteredResource [2];
inOrder[0] = getConfig("pidA", null, 100, "a", ResourceState.INSTALLED);
inOrder[1] = getConfig("pidA", null, 100, "b", ResourceState.INSTALL);
assertOrder(inOrder);
}
@Test
public void testNullEntityId() throws IOException {
final SortedSet<RegisteredResource> set = new TreeSet<RegisteredResource>();
final RegisteredResource a = untransformedResource("a", 1);
final RegisteredResource b = untransformedResource("b", 1);
set.add(a);
set.add(b);
assertEquals("Expecting a to be first", a, set.first());
}
}