brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hadr...@apache.org
Subject [07/20] incubator-brooklyn git commit: Package rename to org.apache.brooklyn: usage/camp/
Date Wed, 05 Aug 2015 20:56:11 GMT
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
new file mode 100644
index 0000000..99830c9
--- /dev/null
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
@@ -0,0 +1,262 @@
+/*
+ * 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.brooklyn.camp.brooklyn.catalog;
+
+import static org.testng.Assert.assertTrue;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.basic.BrooklynTypes;
+
+import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
+import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynEntityMatcher;
+import org.apache.brooklyn.catalog.BrooklynCatalog;
+import org.apache.brooklyn.catalog.CatalogItem;
+import org.apache.brooklyn.catalog.CatalogItem.CatalogItemType;
+import brooklyn.catalog.internal.CatalogUtils;
+import brooklyn.entity.Entity;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.location.LocationSpec;
+import brooklyn.management.osgi.OsgiVersionMoreEntityTest;
+import brooklyn.policy.Policy;
+import brooklyn.policy.PolicySpec;
+import org.apache.brooklyn.test.TestResourceUnavailableException;
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.text.Strings;
+
+import com.google.common.collect.Iterables;
+
+/** Many of the same tests as per {@link OsgiVersionMoreEntityTest} but using YAML for catalog and entities, so catalog item ID is set automatically */
+public class CatalogOsgiVersionMoreEntityTest extends AbstractYamlTest {
+    
+    private static final Logger log = LoggerFactory.getLogger(CatalogOsgiVersionMoreEntityTest.class);
+    
+    private static String getLocalResource(String filename) {
+        return ResourceUtils.create(CatalogOsgiVersionMoreEntityTest.class).getResourceAsString(
+            "classpath:/"+CatalogOsgiVersionMoreEntityTest.class.getPackage().getName().replace('.', '/')+"/"+filename);
+    }
+    
+    @Test
+    public void testMoreEntityV1() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar");
+
+        addCatalogItems(getLocalResource("more-entity-v1-osgi-catalog.yaml"));
+        CatalogItem<?, ?> item = CatalogUtils.getCatalogItemOptionalVersion(mgmt(), "more-entity");
+        Assert.assertNotNull(item);
+        Assert.assertEquals(item.getVersion(), "1.0");
+        Assert.assertEquals(item.getCatalogItemType(), CatalogItemType.ENTITY);
+        Assert.assertEquals(item.getLibraries().size(), 1);
+        
+        Entity app = createAndStartApplication("services: [ { type: 'more-entity:1.0' } ]");
+        Entity moreEntity = Iterables.getOnlyElement(app.getChildren());
+        
+        Assert.assertEquals(moreEntity.getCatalogItemId(), "more-entity:1.0");
+        OsgiVersionMoreEntityTest.assertV1EffectorCall(moreEntity);
+        OsgiVersionMoreEntityTest.assertV1MethodCall(moreEntity);
+    }
+
+    /** TODO we get warnings from {@link BrooklynEntityMatcher#extractValidConfigFlagsOrKeys};
+     * if we passed the correct loader at that point we could avoid those warnings. */ 
+    @Test
+    public void testMoreEntityV1WithPolicy() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar");
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-entities.jar");
+
+        addCatalogItems(getLocalResource("simple-policy-osgi-catalog.yaml"));
+        addCatalogItems(getLocalResource("more-entity-v1-with-policy-osgi-catalog.yaml"));
+        Entity app = createAndStartApplication("services: [ { type: 'more-entity:1.0' } ]");
+        Entity moreEntity = Iterables.getOnlyElement(app.getChildren());
+        
+        Assert.assertEquals(moreEntity.getCatalogItemId(), "more-entity:1.0");
+        
+        Assert.assertEquals(moreEntity.getPolicies().size(), 1, "wrong policies: "+moreEntity.getPolicies());
+        Policy policy = Iterables.getOnlyElement(moreEntity.getPolicies());
+        // it was loaded by yaml w ref to catalog, so should have the simple-policy catalog-id
+        Assert.assertEquals(policy.getCatalogItemId(), "simple-policy:1.0");
+    }
+
+    @Test
+    public void testMoreEntityV2() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar");
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-entities.jar");
+
+        addCatalogItems(getLocalResource("more-entity-v2-osgi-catalog.yaml"));
+        Entity app = createAndStartApplication("services: [ { type: 'more-entity:1.0' } ]");
+        Entity moreEntity = Iterables.getOnlyElement(app.getChildren());
+        
+        Assert.assertEquals(moreEntity.getCatalogItemId(), "more-entity:1.0");
+        OsgiVersionMoreEntityTest.assertV2EffectorCall(moreEntity);
+        OsgiVersionMoreEntityTest.assertV2MethodCall(moreEntity);
+        
+        Assert.assertEquals(moreEntity.getPolicies().size(), 1, "wrong policies: "+moreEntity.getPolicies());
+        Policy policy = Iterables.getOnlyElement(moreEntity.getPolicies());
+        // it was loaded from the java so should have the base more-entity catalog id
+        Assert.assertEquals(policy.getCatalogItemId(), "more-entity:1.0");
+    }
+
+    @Test
+    /** TODO this test works if we assume most recent version wins, but semantics TBC */
+    public void testMoreEntityV2ThenV1GivesV1() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar");
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar");
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-entities.jar");
+
+        addCatalogItems(getLocalResource("more-entity-v2-osgi-catalog.yaml"));
+        forceCatalogUpdate();
+        addCatalogItems(getLocalResource("more-entity-v1-osgi-catalog.yaml"));
+        Entity app = createAndStartApplication("services: [ { type: 'more-entity:1.0' } ]");
+        Entity moreEntity = Iterables.getOnlyElement(app.getChildren());
+        
+        OsgiVersionMoreEntityTest.assertV1EffectorCall(moreEntity);
+        OsgiVersionMoreEntityTest.assertV1MethodCall(moreEntity);
+    }
+
+    /** unlike {@link #testMoreEntityV2ThenV1GivesV1()} this test should always work,
+     * because default should probably be either most-recent version or highest version,
+     * in either case this works */
+    @Test
+    public void testMoreEntityV1ThenV2GivesV2() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar");
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar");
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-entities.jar");
+
+        addCatalogItems(getLocalResource("more-entity-v1-osgi-catalog.yaml"));
+        forceCatalogUpdate();
+        addCatalogItems(getLocalResource("more-entity-v2-osgi-catalog.yaml"));
+        Entity app = createAndStartApplication("services: [ { type: 'more-entity:1.0' } ]");
+        Entity moreEntity = Iterables.getOnlyElement(app.getChildren());
+        
+        OsgiVersionMoreEntityTest.assertV2EffectorCall(moreEntity);
+        OsgiVersionMoreEntityTest.assertV2MethodCall(moreEntity);
+    }
+
+    @Test
+    public void testMoreEntityBothV1AndV2() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar");
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar");
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-entities.jar");
+
+        addCatalogItems(getLocalResource("more-entity-v1-called-v1-osgi-catalog.yaml"));
+        addCatalogItems(getLocalResource("more-entity-v2-osgi-catalog.yaml"));
+        Entity v1 = createAndStartApplication("services: [ { type: 'more-entity-v1:1.0' } ]");
+        Entity v2 = createAndStartApplication("services: [ { type: 'more-entity:1.0' } ]");
+        
+        Entity moreEntityV1 = Iterables.getOnlyElement(v1.getChildren());
+        Entity moreEntityV2 = Iterables.getOnlyElement(v2.getChildren());
+        
+        OsgiVersionMoreEntityTest.assertV1EffectorCall(moreEntityV1);
+        OsgiVersionMoreEntityTest.assertV1MethodCall(moreEntityV1);
+        
+        OsgiVersionMoreEntityTest.assertV2EffectorCall(moreEntityV2);
+        OsgiVersionMoreEntityTest.assertV2MethodCall(moreEntityV2);
+    }
+
+    // @Test FIXME: https://issues.apache.org/jira/browse/BROOKLYN-161
+    public void testMoreEntityV2AutoscanWithClasspath() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar");
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-entities.jar");
+        
+        addCatalogItems(getLocalResource("more-entities-osgi-catalog-scan.yaml"));
+        
+        log.info("autoscan for osgi found catalog items: "+Strings.join(mgmt().getCatalog().getCatalogItems(), ", "));
+
+        CatalogItem<?, ?> item = CatalogUtils.getCatalogItemOptionalVersion(mgmt(), "more-entity");
+        Assert.assertNotNull(item);
+        Assert.assertEquals(item.getVersion(), "2.0.test");
+        Assert.assertEquals(item.getCatalogItemType(), CatalogItemType.ENTITY);
+        
+        // this refers to the java item, where the libraries are defined
+        item = CatalogUtils.getCatalogItemOptionalVersion(mgmt(), "brooklyn.osgi.tests.more.MoreEntity");
+        Assert.assertEquals(item.getVersion(), "2.0.test_java");
+        Assert.assertEquals(item.getLibraries().size(), 2);
+        
+        Entity app = createAndStartApplication("services: [ { type: 'more-entity:2.0.test' } ]");
+        Entity moreEntity = Iterables.getOnlyElement(app.getChildren());
+        
+        Assert.assertEquals(moreEntity.getCatalogItemId(), "more-entity:2.0.test");
+        OsgiVersionMoreEntityTest.assertV2EffectorCall(moreEntity);
+        OsgiVersionMoreEntityTest.assertV2MethodCall(moreEntity);
+    }
+
+    // @Test FIXME: https://issues.apache.org/jira/browse/BROOKLYN-161
+    public void testMorePolicyV2AutoscanWithClasspath() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar");
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-entities.jar");
+        
+        addCatalogItems(getLocalResource("more-policies-osgi-catalog-scan.yaml"));
+        
+        log.info("autoscan for osgi found catalog items: "+Strings.join(mgmt().getCatalog().getCatalogItems(), ", "));
+
+        CatalogItem<?, ?> item = CatalogUtils.getCatalogItemOptionalVersion(mgmt(), "more-policy");
+        Assert.assertNotNull(item);
+        Assert.assertEquals(item.getVersion(), "2.0.test");
+        Assert.assertEquals(item.getCatalogItemType(), CatalogItemType.POLICY);
+        
+        // this refers to the java item, where the libraries are defined
+        item = CatalogUtils.getCatalogItemOptionalVersion(mgmt(), "brooklyn.osgi.tests.more.MorePolicy");
+        Assert.assertEquals(item.getVersion(), "2.0.test_java");
+        Assert.assertEquals(item.getLibraries().size(), 2);
+        
+        Entity app = createAndStartApplication(
+                "services: ",
+                "- type: brooklyn.entity.basic.BasicEntity",
+                "  brooklyn.policies:",
+                "  - type: more-policy:2.0.test");
+        Entity basicEntity = Iterables.getOnlyElement(app.getChildren());
+        Policy morePolicy = Iterables.getOnlyElement(basicEntity.getPolicies());
+        
+        Assert.assertEquals(morePolicy.getCatalogItemId(), "more-policy:2.0.test");
+        OsgiVersionMoreEntityTest.assertV2MethodCall(morePolicy);
+    }
+
+    // @Test FIXME: https://issues.apache.org/jira/browse/BROOKLYN-161
+    public void testAutoscanWithClasspathCanCreateSpecs() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar");
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-entities.jar");
+
+        addCatalogItems(getLocalResource("more-entities-osgi-catalog-scan.yaml"));
+
+        log.info("autoscan for osgi found catalog items: "+Strings.join(mgmt().getCatalog().getCatalogItems(), ", "));
+
+        BrooklynCatalog catalog = mgmt().getCatalog();
+        Iterable<CatalogItem<Object, Object>> items = catalog.getCatalogItems();
+        for (CatalogItem<Object, Object> item: items) {
+            Object spec = catalog.createSpec(item);
+            switch (item.getCatalogItemType()) {
+                case TEMPLATE:
+                case ENTITY:
+                    assertTrue(spec instanceof EntitySpec, "Not an EntitySpec: " + spec);
+                    BrooklynTypes.getDefinedEntityType(((EntitySpec<?>)spec).getType());
+                    break;
+                case POLICY:
+                    assertTrue(spec instanceof PolicySpec, "Not a PolicySpec: " + spec);
+                    BrooklynTypes.getDefinedBrooklynType(((PolicySpec<?>)spec).getType());
+                    break;
+                case LOCATION:
+                    assertTrue(spec instanceof LocationSpec, "Not a LocationSpec: " + spec);
+                    BrooklynTypes.getDefinedBrooklynType(((LocationSpec<?>)spec).getType());
+                    break;
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogXmlOsgiTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogXmlOsgiTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogXmlOsgiTest.java
new file mode 100644
index 0000000..fc2c7e5
--- /dev/null
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogXmlOsgiTest.java
@@ -0,0 +1,37 @@
+/*
+ * 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.brooklyn.camp.brooklyn.catalog;
+
+import org.testng.annotations.Test;
+
+public class CatalogXmlOsgiTest extends AbstractCatalogXmlTest {
+
+    public CatalogXmlOsgiTest(String catalogUrl) {
+        super("classpath://osgi-catalog.xml");
+    }
+
+    //OSGi libraries not supported with old-style catalog items
+    //We treat those catalog items just as an alias to the java type they hold.
+    //No loader wrapping their libraries is ever created.
+    @Test(expectedExceptions=IllegalStateException.class)
+    public void testOsgiItem() throws Exception {
+        startApp("OsgiApp");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogXmlVersionTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogXmlVersionTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogXmlVersionTest.java
new file mode 100644
index 0000000..4bed94d
--- /dev/null
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogXmlVersionTest.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.brooklyn.camp.brooklyn.catalog;
+
+import static org.testng.Assert.assertTrue;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.Entity;
+
+public class CatalogXmlVersionTest extends AbstractCatalogXmlTest {
+
+    public CatalogXmlVersionTest(String catalogUrl) {
+        super("classpath://simple-catalog.xml");
+    }
+
+    @DataProvider(name = "types")
+    public Object[][] createTypes() {
+        return new Object[][] {
+                {"brooklyn.entity.basic.BasicApplication"},
+                {"brooklyn.entity.basic.BasicApplication:0.0.0.SNAPSHOT"},
+                {"brooklyn.entity.basic.BasicApplication:2.0"},
+                {"BasicApp"}, // test that items with symbolicName not matching the type work
+                {"BasicApp:0.0.0.SNAPSHOT"},
+                {"BasicApp:2.0"},
+                {"brooklyn.osgi.tests.SimpleApplication"}, //test that classpath is used
+        };
+    }
+
+    @Test(dataProvider = "types")
+    public void testXmlCatalogItem(String type) throws Exception {
+        startApp(type);
+    }
+
+    @Test
+    public void testJavaPrefixDoesNotLoadXMLCatalogItem() throws Exception {
+        Entity entity = startApp("java:org.apache.brooklyn.camp.brooklyn.catalog.TestBasicApp");
+        assertTrue(entity instanceof TestBasicApp, "Entity is not a " + TestBasicApp.class.getName() + ", instead the type is " + entity.getEntityType().getName());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlCombiTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlCombiTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlCombiTest.java
new file mode 100644
index 0000000..e66c185
--- /dev/null
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlCombiTest.java
@@ -0,0 +1,143 @@
+/*
+ * 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.brooklyn.camp.brooklyn.catalog;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
+import org.apache.brooklyn.catalog.CatalogItem;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.BasicEntity;
+import brooklyn.entity.basic.BasicStartable;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.Entities;
+import brooklyn.policy.Policy;
+import brooklyn.policy.ha.ServiceRestarter;
+import brooklyn.util.exceptions.Exceptions;
+
+import com.google.common.collect.Iterables;
+
+
+public class CatalogYamlCombiTest extends AbstractYamlTest {
+
+    private static final Logger log = LoggerFactory.getLogger(CatalogYamlCombiTest.class);
+    
+    @Test
+    public void testBRefEntityA() throws Exception {
+        addCatalogItems(
+            "brooklyn.catalog:",
+            "  version: "+TEST_VERSION,
+            "  items:",
+            "  - item:",
+            "      id: A",
+            "      type: "+BasicEntity.class.getName(),
+            "      brooklyn.config: { a: 1, b: 0 }",
+            "  - item:",
+            "      id: B",
+            "      type: A",
+            "      brooklyn.config: { b: 1 }");
+
+        CatalogItem<?, ?> item = mgmt().getCatalog().getCatalogItem("B", TEST_VERSION);
+        Assert.assertNotNull(item);
+
+        Entity a = launchEntity("A");
+        Assert.assertTrue(BasicEntity.class.isInstance(a), "Wrong type: "+a);
+        Assert.assertEquals(a.config().get(ConfigKeys.newIntegerConfigKey("a")), (Integer)1);
+        Assert.assertEquals(a.config().get(ConfigKeys.newIntegerConfigKey("b")), (Integer)0);
+
+        Entity b = launchEntity("B");
+        Assert.assertTrue(BasicEntity.class.isInstance(b), "Wrong type: "+b);
+        Assert.assertEquals(b.config().get(ConfigKeys.newIntegerConfigKey("a")), (Integer)1);
+        Assert.assertEquals(b.config().get(ConfigKeys.newIntegerConfigKey("b")), (Integer)1);
+
+        deleteCatalogEntity("A");
+        
+        // now loading B makes an error
+        try {
+            launchEntity("B");
+            Assert.fail("B should not be launchable");
+        } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
+            log.info("Got expected error: "+e);
+        }
+        
+        deleteCatalogEntity("B");
+    }
+
+    @Test
+    public void testBRefPolicyALocationZ() throws Exception {
+        addCatalogItems(
+            "brooklyn.catalog:",
+            "  version: "+TEST_VERSION,
+            "  id: Z",
+            "  items:",
+            "  - item: ",
+            "      type: localhost",
+            "      brooklyn.config: { z: 9 }");
+        addCatalogItems(
+            "brooklyn.catalog:",
+            "  version: "+TEST_VERSION,
+            "  items:",
+            "  - item_type: policy", 
+            "    item:",
+            "      id: A",
+            "      type: "+ServiceRestarter.class.getName(),
+            "      brooklyn.config: { a: 99 }",
+            "  - item:",
+            "      id: B",
+            "      type: "+BasicStartable.class.getName(),
+            "      location: Z",
+            "      brooklyn.policies:",
+            "      - type: A");
+
+        CatalogItem<?, ?> item = mgmt().getCatalog().getCatalogItem("A", TEST_VERSION);
+        Assert.assertNotNull(item);
+
+        Entity b = launchEntity("B", false);
+        Assert.assertTrue(BasicStartable.class.isInstance(b), "Wrong type: "+b);
+        Entities.dumpInfo(b);
+        
+        Assert.assertEquals(Iterables.getOnlyElement(b.getLocations()).getConfig(ConfigKeys.newIntegerConfigKey("z")), (Integer)9);
+        
+        Policy p = Iterables.getOnlyElement(b.getPolicies());
+        Assert.assertTrue(ServiceRestarter.class.isInstance(p), "Wrong type: "+p);
+        Assert.assertEquals(p.getConfig(ConfigKeys.newIntegerConfigKey("a")), (Integer)99);
+        
+        deleteCatalogEntity("A");
+        deleteCatalogEntity("B");
+        deleteCatalogEntity("Z");
+    }
+
+    private Entity launchEntity(String symbolicName) throws Exception {
+        return launchEntity(symbolicName, true);
+    }
+    
+    private Entity launchEntity(String symbolicName, boolean includeLocation) throws Exception {
+        String yaml = "name: simple-app-yaml\n" +
+                      (includeLocation ? "location: localhost\n" : "") +
+                      "services: \n" +
+                      "  - type: "+ver(symbolicName);
+        Entity app = createAndStartApplication(yaml);
+        return Iterables.getOnlyElement(app.getChildren());
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
new file mode 100644
index 0000000..5d3dc75
--- /dev/null
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
@@ -0,0 +1,780 @@
+/*
+ * 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.brooklyn.camp.brooklyn.catalog;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.List;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
+import org.apache.brooklyn.catalog.BrooklynCatalog;
+import org.apache.brooklyn.catalog.CatalogItem;
+import brooklyn.catalog.internal.CatalogUtils;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.BasicEntity;
+import brooklyn.management.osgi.OsgiStandaloneTest;
+import brooklyn.management.osgi.OsgiTestResources;
+import org.apache.brooklyn.test.TestResourceUnavailableException;
+import brooklyn.test.entity.TestEntity;
+import brooklyn.test.entity.TestEntityImpl;
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.exceptions.Exceptions;
+
+import com.google.common.collect.Iterables;
+
+
+public class CatalogYamlEntityTest extends AbstractYamlTest {
+    
+    private static final String SIMPLE_ENTITY_TYPE = OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_SIMPLE_ENTITY;
+
+    @Test
+    public void testAddCatalogItemVerySimple() throws Exception {
+        String symbolicName = "my.catalog.app.id.load";
+        addCatalogItems(
+            "brooklyn.catalog:",
+            "  id: " + symbolicName,
+            "  version: " + TEST_VERSION,
+            "  item:",
+            "    type: "+ BasicEntity.class.getName());
+
+        CatalogItem<?, ?> item = mgmt().getCatalog().getCatalogItem(symbolicName, TEST_VERSION);
+        assertTrue(item.getPlanYaml().indexOf("services:")>=0, "expected 'services:' block: "+item+"\n"+item.getPlanYaml());
+
+        deleteCatalogEntity(symbolicName);
+    }
+    @Test
+    public void testAddCatalogItem() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+        String symbolicName = "my.catalog.app.id.load";
+        addCatalogOSGiEntity(symbolicName);
+        CatalogItem<?, ?> item = mgmt().getCatalog().getCatalogItem(symbolicName, TEST_VERSION);
+        assertEquals(item.getSymbolicName(), symbolicName);
+
+        deleteCatalogEntity(symbolicName);
+    }
+
+    @Test
+    public void testAddCatalogItemTypeAsString() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+        String symbolicName = "my.catalog.app.id.load";
+        addCatalogItems(
+            "brooklyn.catalog:",
+            "  id: " + symbolicName,
+            "  name: My Catalog App",
+            "  description: My description",
+            "  icon_url: classpath://path/to/myicon.jpg",
+            "  version: " + TEST_VERSION,
+            "  libraries:",
+            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
+            "  item: " + SIMPLE_ENTITY_TYPE);
+
+        CatalogItem<?, ?> item = mgmt().getCatalog().getCatalogItem(symbolicName, TEST_VERSION);
+        assertEquals(item.getSymbolicName(), symbolicName);
+
+        deleteCatalogEntity(symbolicName);
+    }
+
+    @Test
+    public void testAddCatalogItemTypeExplicitTypeAsString() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+        String symbolicName = "my.catalog.app.id.load";
+        addCatalogItems(
+            "brooklyn.catalog:",
+            "  id: " + symbolicName,
+            "  name: My Catalog App",
+            "  description: My description",
+            "  icon_url: classpath://path/to/myicon.jpg",
+            "  version: " + TEST_VERSION,
+            "  item_type: entity",
+            "  libraries:",
+            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
+            "  item: " + SIMPLE_ENTITY_TYPE);
+
+        CatalogItem<?, ?> item = mgmt().getCatalog().getCatalogItem(symbolicName, TEST_VERSION);
+        assertEquals(item.getSymbolicName(), symbolicName);
+
+        deleteCatalogEntity(symbolicName);
+    }
+
+    @Test
+    public void testAddCatalogItemTopLevelSyntax() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+        String symbolicName = "my.catalog.app.id.load";
+        addCatalogItems(
+            "brooklyn.catalog:",
+            "  id: " + symbolicName,
+            "  name: My Catalog App",
+            "  description: My description",
+            "  icon_url: classpath://path/to/myicon.jpg",
+            "  version: " + TEST_VERSION,
+            "  libraries:",
+            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
+            "",
+            "services:",
+            "- type: " + SIMPLE_ENTITY_TYPE);
+
+        CatalogItem<?, ?> item = mgmt().getCatalog().getCatalogItem(symbolicName, TEST_VERSION);
+        assertEquals(item.getSymbolicName(), symbolicName);
+
+        deleteCatalogEntity(symbolicName);
+    }
+
+    @Test
+    public void testAddCatalogItemWithoutVersion() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+        String id = "unversioned.app";
+        addCatalogItems(
+            "brooklyn.catalog:",
+            "  name: " + id,
+            "  libraries:",
+            "  - " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
+            "  item:",
+            "    type: "+ SIMPLE_ENTITY_TYPE);
+        CatalogItem<?, ?> catalogItem = mgmt().getCatalog().getCatalogItem(id, BrooklynCatalog.DEFAULT_VERSION);
+        assertEquals(catalogItem.getVersion(), "0.0.0.SNAPSHOT");
+        mgmt().getCatalog().deleteCatalogItem(id, "0.0.0.SNAPSHOT");
+    }
+
+    @Test
+    public void testAddCatalogItemWithInlinedVersion() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+        String id = "inline_version.app";
+        addCatalogItems(
+            "brooklyn.catalog:",
+            "  name: " + id+":"+TEST_VERSION,
+            "  libraries:",
+            "  - " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
+            "services:",
+            "- type: " + SIMPLE_ENTITY_TYPE);
+        CatalogItem<?, ?> catalogItem = mgmt().getCatalog().getCatalogItem(id, TEST_VERSION);
+        assertEquals(catalogItem.getVersion(), TEST_VERSION);
+        mgmt().getCatalog().deleteCatalogItem(id, TEST_VERSION);
+    }
+
+    @Test
+    public void testLaunchApplicationReferencingCatalog() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+        String symbolicName = "my.catalog.app.id.launch";
+        registerAndLaunchAndAssertSimpleEntity(symbolicName, SIMPLE_ENTITY_TYPE);
+    }
+
+    @Test
+    public void testLaunchApplicationUnversionedCatalogReference() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+        String symbolicName = "my.catalog.app.id.fail";
+        addCatalogOSGiEntity(symbolicName, SIMPLE_ENTITY_TYPE);
+        try {
+            String yaml = "name: simple-app-yaml\n" +
+                          "location: localhost\n" +
+                          "services: \n" +
+                          "  - serviceType: " + symbolicName;
+            createAndStartApplication(yaml);
+        } finally {
+            deleteCatalogEntity(symbolicName);
+        }
+    }
+
+    @Test
+    public void testLaunchApplicationWithCatalogReferencingOtherCatalog() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+        String referencedSymbolicName = "my.catalog.app.id.referenced";
+        String referrerSymbolicName = "my.catalog.app.id.referring";
+        addCatalogOSGiEntities(referencedSymbolicName, SIMPLE_ENTITY_TYPE, referrerSymbolicName, ver(referencedSymbolicName));
+
+        CatalogItem<?, ?> referrer = mgmt().getCatalog().getCatalogItem(referrerSymbolicName, TEST_VERSION);
+        Assert.assertTrue(referrer.getPlanYaml().indexOf("services")>=0, "expected services in: "+referrer.getPlanYaml());
+        
+        String yaml = "name: simple-app-yaml\n" +
+                      "location: localhost\n" +
+                      "services: \n" +
+                      "  - type: " + ver(referrerSymbolicName);
+        Entity app = createAndStartApplication(yaml);
+
+        Entity simpleEntity = Iterables.getOnlyElement(app.getChildren());
+        assertEquals(simpleEntity.getEntityType().getName(), SIMPLE_ENTITY_TYPE);
+
+        deleteCatalogEntity(referencedSymbolicName);
+        deleteCatalogEntity(referrerSymbolicName);
+    }
+
+    @Test
+    public void testLaunchApplicationWithCatalogReferencingOtherCatalogInTwoSteps() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+        String referencedSymbolicName = "my.catalog.app.id.referenced";
+        String referrerSymbolicName = "my.catalog.app.id.referring";
+        addCatalogOSGiEntity(referencedSymbolicName, SIMPLE_ENTITY_TYPE);
+        addCatalogOSGiEntity(referrerSymbolicName, ver(referencedSymbolicName));
+
+        String yaml = "name: simple-app-yaml\n" +
+                      "location: localhost\n" +
+                      "services: \n" +
+                      "  - serviceType: " + ver(referrerSymbolicName);
+        Entity app = createAndStartApplication(yaml);
+
+        Entity simpleEntity = Iterables.getOnlyElement(app.getChildren());
+        assertEquals(simpleEntity.getEntityType().getName(), SIMPLE_ENTITY_TYPE);
+
+        deleteCatalogEntity(referencedSymbolicName);
+        deleteCatalogEntity(referrerSymbolicName);
+    }
+
+    @Test
+    public void testLaunchApplicationChildWithCatalogReferencingOtherCatalog() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+        String referencedSymbolicName = "my.catalog.app.id.child.referenced";
+        String referrerSymbolicName = "my.catalog.app.id.child.referring";
+        addCatalogOSGiEntity(referencedSymbolicName, SIMPLE_ENTITY_TYPE);
+        addCatalogChildOSGiEntity(referrerSymbolicName, ver(referencedSymbolicName));
+
+        Entity app = createAndStartApplication(
+            "name: simple-app-yaml",
+            "location: localhost",
+            "services:",
+            "- type: "+BasicEntity.class.getName(),
+            "  brooklyn.children:",
+            "  - type: " + ver(referrerSymbolicName));
+
+        Collection<Entity> children = app.getChildren();
+        assertEquals(children.size(), 1);
+        Entity child = Iterables.getOnlyElement(children);
+        assertEquals(child.getEntityType().getName(), BasicEntity.class.getName());
+        Collection<Entity> grandChildren = child.getChildren();
+        assertEquals(grandChildren.size(), 1);
+        Entity grandChild = Iterables.getOnlyElement(grandChildren);
+        assertEquals(grandChild.getEntityType().getName(), BasicEntity.class.getName());
+        Collection<Entity> grandGrandChildren = grandChild.getChildren();
+        assertEquals(grandGrandChildren.size(), 1);
+        Entity grandGrandChild = Iterables.getOnlyElement(grandGrandChildren);
+        assertEquals(grandGrandChild.getEntityType().getName(), SIMPLE_ENTITY_TYPE);
+
+        deleteCatalogEntity(referencedSymbolicName);
+        deleteCatalogEntity(referrerSymbolicName);
+    }
+
+    @Test
+    public void testLaunchApplicationChildWithCatalogReferencingOtherCatalogServicesBlock() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+        String referencedSymbolicName = "my.catalog.app.id.child.referenced";
+        String referrerSymbolicName = "my.catalog.app.id.child.referring";
+        addCatalogOSGiEntity(referencedSymbolicName, SIMPLE_ENTITY_TYPE);
+        addCatalogChildOSGiEntityWithServicesBlock(referrerSymbolicName, ver(referencedSymbolicName));
+
+        Entity app = createAndStartApplication(
+            "name: simple-app-yaml",
+            "location: localhost",
+            "services:",
+            "- serviceType: "+BasicEntity.class.getName(),
+            "  brooklyn.children:",
+            "  - type: " + ver(referrerSymbolicName));
+
+        Collection<Entity> children = app.getChildren();
+        assertEquals(children.size(), 1);
+        Entity child = Iterables.getOnlyElement(children);
+        assertEquals(child.getEntityType().getName(), BasicEntity.class.getName());
+        Collection<Entity> grandChildren = child.getChildren();
+        assertEquals(grandChildren.size(), 1);
+        Entity grandChild = Iterables.getOnlyElement(grandChildren);
+        assertEquals(grandChild.getEntityType().getName(), BasicEntity.class.getName());
+        Collection<Entity> grandGrandChildren = grandChild.getChildren();
+        assertEquals(grandGrandChildren.size(), 1);
+        Entity grandGrandChild = Iterables.getOnlyElement(grandGrandChildren);
+        assertEquals(grandGrandChild.getEntityType().getName(), SIMPLE_ENTITY_TYPE);
+
+        deleteCatalogEntity(referencedSymbolicName);
+        deleteCatalogEntity(referrerSymbolicName);
+    }
+    
+    @Test
+    public void testLaunchApplicationWithTypeUsingJavaColonPrefix() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+        String symbolicName = SIMPLE_ENTITY_TYPE;
+        String serviceName = "java:"+SIMPLE_ENTITY_TYPE;
+        registerAndLaunchAndAssertSimpleEntity(symbolicName, serviceName);
+    }
+
+    @Test
+    public void testLaunchApplicationLoopWithJavaTypeName() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+        String symbolicName = SIMPLE_ENTITY_TYPE;
+        String serviceName = SIMPLE_ENTITY_TYPE;
+        registerAndLaunchAndAssertSimpleEntity(symbolicName, serviceName);
+    }
+
+    @Test
+    public void testLaunchApplicationChildLoopCatalogIdFails() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+        String referrerSymbolicName = "my.catalog.app.id.child.referring";
+        try {
+            // TODO only fails if using 'services', because that forces plan parsing; should fail in all cases
+            addCatalogChildOSGiEntityWithServicesBlock(referrerSymbolicName, ver(referrerSymbolicName));
+            fail("Expected to throw");
+        } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
+            assertTrue(e.getMessage().contains(referrerSymbolicName), "message was: "+e);
+        }
+    }
+
+    @Test
+    public void testReferenceInstalledBundleByName() {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+        String firstItemId = "my.catalog.app.id.register_bundle";
+        String secondItemId = "my.catalog.app.id.reference_bundle";
+        addCatalogItems(
+            "brooklyn.catalog:",
+            "  id: " + firstItemId,
+            "  version: " + TEST_VERSION,
+            "  libraries:",
+            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
+            "",
+            "services:",
+            "- type: " + SIMPLE_ENTITY_TYPE);
+        deleteCatalogEntity(firstItemId);
+
+        addCatalogItems(
+            "brooklyn.catalog:",
+            "  id: " + secondItemId,
+            "  version: " + TEST_VERSION,
+            "  libraries:",
+            "  - name: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_NAME,
+            "    version: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_VERSION,
+            "",
+            "services:",
+            "- type: " + SIMPLE_ENTITY_TYPE);
+
+        deleteCatalogEntity(secondItemId);
+    }
+
+    @Test
+    public void testReferenceNonInstalledBundledByNameFails() {
+        String nonExistentId = "none-existent-id";
+        String nonExistentVersion = "9.9.9";
+        try {
+            addCatalogItems(
+                "brooklyn.catalog:",
+                "  id: my.catalog.app.id.non_existing.ref",
+                "  version: " + TEST_VERSION,
+                "  libraries:",
+                "  - name: " + nonExistentId,
+                "    version: " + nonExistentVersion,
+                "",
+                "services:",
+                "- type: " + SIMPLE_ENTITY_TYPE);
+            fail();
+        } catch (IllegalStateException e) {
+            Assert.assertEquals(e.getMessage(), "Bundle from null failed to install: Bundle CatalogBundleDto{symbolicName=" + nonExistentId + ", version=" + nonExistentVersion + ", url=null} not previously registered, but URL is empty.");
+        }
+    }
+
+    @Test
+    public void testPartialBundleReferenceFails() {
+        try {
+            addCatalogItems(
+                "brooklyn.catalog:",
+                "  id: my.catalog.app.id.non_existing.ref",
+                "  version: " + TEST_VERSION,
+                "  libraries:",
+                "  - name: io.brooklyn.brooklyn-test-osgi-entities",
+                "",
+                "services:",
+                "- type: " + SIMPLE_ENTITY_TYPE);
+            fail();
+        } catch (NullPointerException e) {
+            Assert.assertEquals(e.getMessage(), "both name and version are required");
+        }
+        try {
+            addCatalogItems(
+                "brooklyn.catalog:",
+                "  id: my.catalog.app.id.non_existing.ref",
+                "  version: " + TEST_VERSION,
+                "  libraries:",
+                "  - version: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_VERSION,
+                "",
+                "services:",
+                "- type: " + SIMPLE_ENTITY_TYPE);
+            fail();
+        } catch (NullPointerException e) {
+            Assert.assertEquals(e.getMessage(), "both name and version are required");
+        }
+    }
+
+    @Test
+    public void testFullBundleReference() {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+        String itemId = "my.catalog.app.id.full_ref";
+        addCatalogItems(
+            "brooklyn.catalog:",
+            "  id: " + itemId,
+            "  version: " + TEST_VERSION,
+            "  libraries:",
+            "  - name: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_NAME,
+            "    version: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_VERSION,
+            "    url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
+            "",
+            "services:",
+            "- type: " + SIMPLE_ENTITY_TYPE);
+        deleteCatalogEntity(itemId);
+    }
+
+    /**
+     * Test that the name:version contained in the OSGi bundle will
+     * override the values supplied in the YAML.
+     */
+    @Test
+    public void testFullBundleReferenceUrlMetaOverridesLocalNameVersion() {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+        String firstItemId = "my.catalog.app.id.register_bundle";
+        String nonExistentId = "non_existent_id";
+        String nonExistentVersion = "9.9.9";
+        try {
+            addCatalogItems(
+                "brooklyn.catalog:",
+                "  id: " + firstItemId,
+                "  version: " + TEST_VERSION,
+                "  libraries:",
+                "  - name: " + nonExistentId,
+                "    version: " + nonExistentVersion,
+                "    url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
+                "",
+                "services:",
+                "- type: " + SIMPLE_ENTITY_TYPE);
+            fail();
+        } catch (IllegalStateException e) {
+            assertEquals(e.getMessage(), "Bundle from " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL + " failed to install: " +
+                    "Bundle already installed as " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_NAME + ":" +
+                    OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_VERSION + " but user explicitly requested " +
+                    "CatalogBundleDto{symbolicName=" + nonExistentId + ", version=" + nonExistentVersion + ", url=" +
+                    OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL + "}");
+        }
+    }
+
+    @Test
+    public void testUpdatingItemAllowedIfSame() {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+        String id = "my.catalog.app.id.duplicate";
+        addCatalogOSGiEntity(id);
+        addCatalogOSGiEntity(id);
+    }
+    
+    @Test(expectedExceptions = IllegalStateException.class)
+    public void testUpdatingItemFailsIfDifferent() {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+        String id = "my.catalog.app.id.duplicate";
+        addCatalogOSGiEntity(id);
+        addCatalogOSGiEntity(id, SIMPLE_ENTITY_TYPE, true);
+    }
+
+    @Test
+    public void testForcedUpdatingItem() {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+        String id = "my.catalog.app.id.duplicate";
+        addCatalogOSGiEntity(id);
+        forceCatalogUpdate();
+        addCatalogOSGiEntity(id);
+        deleteCatalogEntity(id);
+    }
+
+    @Test
+    public void testCreateSpecFromCatalogItem() {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+        String id = "my.catalog.app.id.create_spec";
+        addCatalogOSGiEntity(id);
+        BrooklynCatalog catalog = mgmt().getCatalog();
+        CatalogItem<?, ?> item = catalog.getCatalogItem(id, TEST_VERSION);
+        Object spec = catalog.createSpec(item);
+        Assert.assertNotNull(spec);
+    }
+    
+    @Test
+    public void testLoadResourceFromBundle() throws Exception {
+        String id = "resource.test";
+        addCatalogOSGiEntity(id, SIMPLE_ENTITY_TYPE);
+        String yaml =
+                "services: \n" +
+                "  - serviceType: "+ver(id);
+        Entity app = createAndStartApplication(yaml);
+        Entity simpleEntity = Iterables.getOnlyElement(app.getChildren());
+        InputStream icon = new ResourceUtils(simpleEntity).getResourceFromUrl("classpath:/brooklyn/osgi/tests/icon.gif");
+        assertTrue(icon != null);
+        icon.close();
+    }
+    
+    @Test
+    public void testMissingTypeDoesNotRecurse() {
+        String symbolicName = "my.catalog.app.id.basic";
+        addCatalogItems(
+            "brooklyn.catalog:",
+            "  id: " + symbolicName,
+            "  version: " + TEST_VERSION,
+            "",
+            "services:",
+            "- type: brooklyn.entity.basic.BasicEntity");
+
+        try {
+            addCatalogItems(
+                    "brooklyn.catalog:",
+                    "  id: " + symbolicName,
+                    "  version: " + TEST_VERSION + "-update",
+                    "",
+                    "services:",
+                    "- type: " + symbolicName);
+            fail("Catalog addition expected to fail due to non-existent java type " + symbolicName);
+        } catch (IllegalStateException e) {
+            assertTrue(e.toString().contains("recursive"), "Unexpected error message: "+e);
+        }
+    }
+    
+    @Test
+    public void testVersionedTypeDoesNotRecurse() {
+        String symbolicName = "my.catalog.app.id.basic";
+        addCatalogItems(
+            "brooklyn.catalog:",
+            "  id: " + symbolicName,
+            "  version: " + TEST_VERSION,
+            "",
+            "services:",
+            "- type: brooklyn.entity.basic.BasicEntity");
+
+        String versionedId = CatalogUtils.getVersionedId(symbolicName, TEST_VERSION);
+        try {
+            addCatalogItems(
+                "brooklyn.catalog:",
+                "  id: " + symbolicName,
+                "  version: " + TEST_VERSION + "-update",
+                "",
+                "services:",
+                "- type: " + versionedId);
+            fail("Catalog addition expected to fail due to non-existent java type " + versionedId);
+        } catch (IllegalStateException e) {
+            assertTrue(e.toString().contains("recursive"), "Unexpected error message: "+e);
+        }
+    }
+
+    @Test
+    public void testOsgiNotLeakingToParent() {
+        addCatalogOSGiEntity(SIMPLE_ENTITY_TYPE);
+        try {
+            addCatalogItems(
+                    "brooklyn.catalog:",
+                    "  id: " + SIMPLE_ENTITY_TYPE,
+                    "  version: " + TEST_VERSION + "-update",
+                    "",
+                    "services:",
+                    "- type: " + SIMPLE_ENTITY_TYPE);
+            fail("Catalog addition expected to fail due to non-existent java type " + SIMPLE_ENTITY_TYPE);
+        } catch (IllegalStateException e) {
+            assertTrue(e.toString().contains("recursive"), "Unexpected error message: "+e);
+        }
+    }
+
+    @Test
+    public void testConfigAppliedToCatalogItem() throws Exception {
+        addCatalogOSGiEntity("test", TestEntity.class.getName());
+        String testName = "test-applies-config-on-catalog-item";
+        Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + ver("test"),
+                "  brooklyn.config:",
+                "    test.confName: " + testName);
+        Entity testEntity = Iterables.getOnlyElement(app.getChildren());
+        assertEquals(testEntity.config().get(TestEntity.CONF_NAME), testName);
+    }
+
+    @Test
+    public void testFlagsAppliesToCatalogItem() throws Exception {
+        addCatalogOSGiEntity("test", TestEntity.class.getName());
+        String testName = "test-applies-config-on-catalog-item";
+        Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + ver("test"),
+                "  confName: " + testName);
+        Entity testEntity = Iterables.getOnlyElement(app.getChildren());
+        assertEquals(testEntity.config().get(TestEntity.CONF_NAME), testName);
+    }
+
+    @Test
+    public void testExplicitFlagsAppliesToCatalogItem() throws Exception {
+        addCatalogOSGiEntity("test", TestEntity.class.getName());
+        String testName = "test-applies-config-on-catalog-item";
+        Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + ver("test"),
+                "  brooklyn.flags:",
+                "    confName: " + testName);
+        Entity testEntity = Iterables.getOnlyElement(app.getChildren());
+        assertEquals(testEntity.config().get(TestEntity.CONF_NAME), testName);
+    }
+    
+
+    @Test
+    public void testConfigAppliedToCatalogItemImpl() throws Exception {
+        addCatalogOSGiEntity("test", TestEntityImpl.class.getName());
+        String testName = "test-applies-config-on-catalog-item";
+        Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + ver("test"),
+                "  brooklyn.config:",
+                "    test.confName: " + testName);
+        Entity testEntity = Iterables.getOnlyElement(app.getChildren());
+        assertEquals(testEntity.config().get(TestEntity.CONF_NAME), testName);
+    }
+
+    @Test
+    public void testFlagsAppliesToCatalogItemImpl() throws Exception {
+        addCatalogOSGiEntity("test", TestEntityImpl.class.getName());
+        String testName = "test-applies-config-on-catalog-item";
+        Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + ver("test"),
+                "  confName: " + testName);
+        Entity testEntity = Iterables.getOnlyElement(app.getChildren());
+        assertEquals(testEntity.config().get(TestEntity.CONF_NAME), testName);
+    }
+
+    @Test
+    public void testExplicitFlagsAppliesToCatalogItemImpl() throws Exception {
+        addCatalogOSGiEntity("test", TestEntityImpl.class.getName());
+        String testName = "test-applies-config-on-catalog-item";
+        Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + ver("test"),
+                "  brooklyn.flags:",
+                "    confName: " + testName);
+        Entity testEntity = Iterables.getOnlyElement(app.getChildren());
+        assertEquals(testEntity.config().get(TestEntity.CONF_NAME), testName);
+    }
+    
+    private void registerAndLaunchAndAssertSimpleEntity(String symbolicName, String serviceType) throws Exception {
+        addCatalogOSGiEntity(symbolicName, serviceType);
+        String yaml = "name: simple-app-yaml\n" +
+                      "location: localhost\n" +
+                      "services: \n" +
+                      "  - serviceType: "+ver(symbolicName);
+        Entity app = createAndStartApplication(yaml);
+
+        Entity simpleEntity = Iterables.getOnlyElement(app.getChildren());
+        assertEquals(simpleEntity.getEntityType().getName(), SIMPLE_ENTITY_TYPE);
+
+        deleteCatalogEntity(symbolicName);
+    }
+
+    private void addCatalogOSGiEntity(String symbolicName) {
+        addCatalogOSGiEntity(symbolicName, SIMPLE_ENTITY_TYPE);
+    }
+
+    private void addCatalogOSGiEntity(String symbolicName, String serviceType) {
+        addCatalogOSGiEntity(symbolicName, serviceType, false);
+    }
+    
+    private void addCatalogOSGiEntity(String symbolicName, String serviceType, boolean extraLib) {
+        addCatalogItems(
+            "brooklyn.catalog:",
+            "  id: " + symbolicName,
+            "  name: My Catalog App",
+            "  description: My description",
+            "  icon_url: classpath://path/to/myicon.jpg",
+            "  version: " + TEST_VERSION,
+            "  libraries:",
+            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL +
+            (extraLib ? "\n"+"  - url: "+OsgiStandaloneTest.BROOKLYN_OSGI_TEST_A_0_1_0_URL : ""),
+            "  item:",
+            "    type: " + serviceType);
+    }
+
+    private void addCatalogOSGiEntities(String ...namesAndTypes) {
+        List<String> lines = MutableList.of(
+            "brooklyn.catalog:",
+            "  name: My Catalog App",
+            "  description: My description",
+            "  icon_url: classpath://path/to/myicon.jpg",
+            "  version: " + TEST_VERSION,
+            "  libraries:",
+            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
+            "  items:");
+        
+        for (int i=0; i<namesAndTypes.length; i+=2) {
+            lines.addAll(MutableList.of(
+            "  - id: " + namesAndTypes[i],
+            "    item:",
+            "      type: " + namesAndTypes[i+1]));
+        }
+            
+        addCatalogItems(lines);
+    }
+    private void addCatalogChildOSGiEntityWithServicesBlock(String symbolicName, String serviceType) {
+        addCatalogItems(
+            "brooklyn.catalog:",
+            "  id: " + symbolicName,
+            "  name: My Catalog App",
+            "  description: My description",
+            "  icon_url: classpath://path/to/myicon.jpg",
+            "  version: " + TEST_VERSION,
+            "  libraries:",
+            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
+            "  item:",
+            "    services:",
+            "    - type: " + BasicEntity.class.getName(),
+            "      brooklyn.children:",
+            "      - type: " + serviceType);
+    }
+    private void addCatalogChildOSGiEntity(String symbolicName, String serviceType) {
+        addCatalogItems(
+            "brooklyn.catalog:",
+            "  id: " + symbolicName,
+            "  name: My Catalog App",
+            "  description: My description",
+            "  icon_url: classpath://path/to/myicon.jpg",
+            "  version: " + TEST_VERSION,
+            "  libraries:",
+            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
+            "  item:",
+            "    type: " + BasicEntity.class.getName(),
+            "    brooklyn.children:",
+            "    - type: " + serviceType);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
new file mode 100644
index 0000000..b46ed92
--- /dev/null
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
@@ -0,0 +1,247 @@
+/*
+ * 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.brooklyn.camp.brooklyn.catalog;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
+import org.apache.brooklyn.catalog.CatalogItem;
+import org.apache.brooklyn.catalog.CatalogItem.CatalogBundle;
+import brooklyn.catalog.CatalogPredicates;
+import brooklyn.entity.Entity;
+import brooklyn.event.basic.BasicConfigKey;
+import brooklyn.location.Location;
+import brooklyn.location.LocationDefinition;
+import brooklyn.location.LocationSpec;
+import brooklyn.location.basic.LocalhostMachineProvisioningLocation;
+import brooklyn.management.osgi.OsgiStandaloneTest;
+import org.apache.brooklyn.test.TestResourceUnavailableException;
+import brooklyn.util.text.StringFunctions;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+public class CatalogYamlLocationTest extends AbstractYamlTest {
+    private static final String LOCALHOST_LOCATION_SPEC = "localhost";
+    private static final String LOCALHOST_LOCATION_TYPE = LocalhostMachineProvisioningLocation.class.getName();
+    private static final String SIMPLE_LOCATION_TYPE = "brooklyn.osgi.tests.SimpleLocation";
+
+    @AfterMethod
+    public void tearDown() {
+        for (CatalogItem<Location, LocationSpec<?>> ci : mgmt().getCatalog().getCatalogItems(CatalogPredicates.IS_LOCATION)) {
+            mgmt().getCatalog().deleteCatalogItem(ci.getSymbolicName(), ci.getVersion());
+        }
+    }
+    
+    @Test
+    public void testAddCatalogItem() throws Exception {
+        assertEquals(countCatalogLocations(), 0);
+
+        String symbolicName = "my.catalog.location.id.load";
+        addCatalogLocation(symbolicName, LOCALHOST_LOCATION_TYPE, null);
+        assertAdded(symbolicName, LOCALHOST_LOCATION_TYPE);
+        removeAndAssert(symbolicName);
+    }
+
+    @Test
+    public void testAddCatalogItemOsgi() throws Exception {
+        assertEquals(countCatalogLocations(), 0);
+
+        String symbolicName = "my.catalog.location.id.load";
+        addCatalogLocation(symbolicName, SIMPLE_LOCATION_TYPE, getOsgiLibraries());
+        assertAdded(symbolicName, SIMPLE_LOCATION_TYPE);
+        assertOsgi(symbolicName);
+        removeAndAssert(symbolicName);
+    }
+
+    @Test
+    public void testAddCatalogItemTopLevelItemSyntax() throws Exception {
+        assertEquals(countCatalogLocations(), 0);
+
+        String symbolicName = "my.catalog.location.id.load";
+        addCatalogLocationTopLevelItemSyntax(symbolicName, LOCALHOST_LOCATION_TYPE, null);
+        assertAdded(symbolicName, LOCALHOST_LOCATION_TYPE);
+        removeAndAssert(symbolicName);
+    }
+
+    @Test
+    public void testAddCatalogItemOsgiTopLevelItemSyntax() throws Exception {
+        assertEquals(countCatalogLocations(), 0);
+
+        String symbolicName = "my.catalog.location.id.load";
+        addCatalogLocationTopLevelItemSyntax(symbolicName, SIMPLE_LOCATION_TYPE, getOsgiLibraries());
+        assertAdded(symbolicName, SIMPLE_LOCATION_TYPE);
+        assertOsgi(symbolicName);
+        removeAndAssert(symbolicName);
+    }
+
+    private void assertOsgi(String symbolicName) {
+        CatalogItem<?, ?> item = mgmt().getCatalog().getCatalogItem(symbolicName, TEST_VERSION);
+        Collection<CatalogBundle> libs = item.getLibraries();
+        assertEquals(libs.size(), 1);
+        assertEquals(Iterables.getOnlyElement(libs).getUrl(), Iterables.getOnlyElement(getOsgiLibraries()));
+    }
+
+    private void assertAdded(String symbolicName, String expectedJavaType) {
+        CatalogItem<?, ?> item = mgmt().getCatalog().getCatalogItem(symbolicName, TEST_VERSION);
+        assertEquals(item.getSymbolicName(), symbolicName);
+        assertEquals(countCatalogLocations(), 1);
+
+        // Item added to catalog should automatically be available in location registry
+        LocationDefinition def = mgmt().getLocationRegistry().getDefinedLocationByName(symbolicName);
+        assertEquals(def.getId(), symbolicName);
+        assertEquals(def.getName(), symbolicName);
+        
+        LocationSpec<?> spec = (LocationSpec<?>)mgmt().getCatalog().createSpec(item);
+        assertEquals(spec.getType().getName(), expectedJavaType);
+    }
+    
+    private void removeAndAssert(String symbolicName) {
+        // Deleting item: should be gone from catalog, and from location registry
+        deleteCatalogEntity(symbolicName);
+
+        assertEquals(countCatalogLocations(), 0);
+        assertNull(mgmt().getLocationRegistry().getDefinedLocationByName(symbolicName));
+    }
+
+    @Test
+    public void testLaunchApplicationReferencingLocationClass() throws Exception {
+        String symbolicName = "my.catalog.location.id.launch";
+        addCatalogLocation(symbolicName, LOCALHOST_LOCATION_TYPE, null);
+        runLaunchApplicationReferencingLocation(symbolicName, LOCALHOST_LOCATION_TYPE);
+
+        deleteCatalogEntity(symbolicName);
+    }
+
+    @Test
+    public void testLaunchApplicationReferencingLocationSpec() throws Exception {
+        String symbolicName = "my.catalog.location.id.launch";
+        addCatalogLocation(symbolicName, LOCALHOST_LOCATION_SPEC, null);
+        runLaunchApplicationReferencingLocation(symbolicName, LOCALHOST_LOCATION_TYPE);
+
+        deleteCatalogEntity(symbolicName);
+    }
+
+    @Test
+    public void testLaunchApplicationReferencingLocationClassTopLevelItemSyntax() throws Exception {
+        String symbolicName = "my.catalog.location.id.launch";
+        addCatalogLocationTopLevelItemSyntax(symbolicName, LOCALHOST_LOCATION_TYPE, null);
+        runLaunchApplicationReferencingLocation(symbolicName, LOCALHOST_LOCATION_TYPE);
+
+        deleteCatalogEntity(symbolicName);
+    }
+
+    @Test
+    public void testLaunchApplicationReferencingLocationSpecTopLevelSyntax() throws Exception {
+        String symbolicName = "my.catalog.location.id.launch";
+        addCatalogLocationTopLevelItemSyntax(symbolicName, LOCALHOST_LOCATION_SPEC, null);
+        runLaunchApplicationReferencingLocation(symbolicName, LOCALHOST_LOCATION_TYPE);
+
+        deleteCatalogEntity(symbolicName);
+    }
+
+    @Test
+    public void testLaunchApplicationReferencingOsgiLocation() throws Exception {
+        String symbolicName = "my.catalog.location.id.launch";
+        addCatalogLocation(symbolicName, SIMPLE_LOCATION_TYPE, getOsgiLibraries());
+        runLaunchApplicationReferencingLocation(symbolicName, SIMPLE_LOCATION_TYPE);
+        
+        deleteCatalogEntity(symbolicName);
+    }
+    
+    protected void runLaunchApplicationReferencingLocation(String locTypeInYaml, String locType) throws Exception {
+        Entity app = createAndStartApplication(
+            "name: simple-app-yaml",
+            "location: ",
+            "  "+locTypeInYaml+":",
+            "    config2: config2 override",
+            "    config3: config3",
+            "services: ",
+            "  - type: brooklyn.entity.basic.BasicStartable");
+
+        Entity simpleEntity = Iterables.getOnlyElement(app.getChildren());
+        Location location = Iterables.getOnlyElement(simpleEntity.getLocations());
+        assertEquals(location.getClass().getName(), locType);
+        assertEquals(location.getConfig(new BasicConfigKey<String>(String.class, "config1")), "config1");
+        assertEquals(location.getConfig(new BasicConfigKey<String>(String.class, "config2")), "config2 override");
+        assertEquals(location.getConfig(new BasicConfigKey<String>(String.class, "config3")), "config3");
+    }
+
+    private List<String> getOsgiLibraries() {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+        return ImmutableList.of(OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL);
+    }
+    
+    private void addCatalogLocation(String symbolicName, String locationType, List<String> libraries) {
+        ImmutableList.Builder<String> yaml = ImmutableList.<String>builder().add(
+                "brooklyn.catalog:",
+                "  id: " + symbolicName,
+                "  name: My Catalog Location",
+                "  description: My description",
+                "  version: " + TEST_VERSION);
+        if (libraries!=null && libraries.size() > 0) {
+            yaml.add("  libraries:")
+                .addAll(Lists.transform(libraries, StringFunctions.prepend("  - url: ")));
+        }
+        yaml.add(
+                "  item.type: location",
+                "  item:",
+                "    type: " + locationType,
+                "    brooklyn.config:",
+                "      config1: config1",
+                "      config2: config2");
+        
+        
+        addCatalogItems(yaml.build());
+    }
+
+    private void addCatalogLocationTopLevelItemSyntax(String symbolicName, String locationType, List<String> libraries) {
+        ImmutableList.Builder<String> yaml = ImmutableList.<String>builder().add(
+                "brooklyn.catalog:",
+                "  id: " + symbolicName,
+                "  name: My Catalog Location",
+                "  description: My description",
+                "  version: " + TEST_VERSION);
+        if (libraries!=null && libraries.size() > 0) {
+            yaml.add("  libraries:")
+                .addAll(Lists.transform(libraries, StringFunctions.prepend("  - url: ")));
+        }
+        yaml.add(
+                "",
+                "brooklyn.locations:",
+                "- type: " + locationType,
+                "  brooklyn.config:",
+                "    config1: config1",
+                "    config2: config2");
+        
+        
+        addCatalogItems(yaml.build());
+    }
+
+    private int countCatalogLocations() {
+        return Iterables.size(mgmt().getCatalog().getCatalogItems(CatalogPredicates.IS_LOCATION));
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java
new file mode 100644
index 0000000..ab738b6
--- /dev/null
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java
@@ -0,0 +1,195 @@
+/*
+ * 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.brooklyn.camp.brooklyn.catalog;
+
+import static org.testng.Assert.assertEquals;
+
+import org.testng.annotations.Test;
+import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
+import org.apache.brooklyn.catalog.CatalogItem;
+import brooklyn.catalog.CatalogPredicates;
+import brooklyn.entity.Entity;
+import brooklyn.event.basic.BasicConfigKey;
+import brooklyn.management.osgi.OsgiStandaloneTest;
+import brooklyn.policy.Policy;
+import org.apache.brooklyn.test.TestResourceUnavailableException;
+
+import com.google.common.collect.Iterables;
+
+public class CatalogYamlPolicyTest extends AbstractYamlTest {
+    private static final String SIMPLE_POLICY_TYPE = "brooklyn.osgi.tests.SimplePolicy";
+    private static final String SIMPLE_ENTITY_TYPE = "brooklyn.osgi.tests.SimpleEntity";
+
+    @Test
+    public void testAddCatalogItem() throws Exception {
+        assertEquals(countCatalogPolicies(), 0);
+
+        String symbolicName = "my.catalog.policy.id.load";
+        addCatalogOsgiPolicy(symbolicName, SIMPLE_POLICY_TYPE);
+
+        CatalogItem<?, ?> item = mgmt().getCatalog().getCatalogItem(symbolicName, TEST_VERSION);
+        assertEquals(item.getSymbolicName(), symbolicName);
+        assertEquals(countCatalogPolicies(), 1);
+
+        deleteCatalogEntity(symbolicName);
+    }
+
+    @Test
+    public void testAddCatalogItemTopLevelSyntax() throws Exception {
+        assertEquals(countCatalogPolicies(), 0);
+
+        String symbolicName = "my.catalog.policy.id.load";
+        addCatalogOsgiPolicyTopLevelSyntax(symbolicName, SIMPLE_POLICY_TYPE);
+
+        CatalogItem<?, ?> item = mgmt().getCatalog().getCatalogItem(symbolicName, TEST_VERSION);
+        assertEquals(item.getSymbolicName(), symbolicName);
+        assertEquals(countCatalogPolicies(), 1);
+
+        deleteCatalogEntity(symbolicName);
+    }
+
+    @Test
+    public void testLaunchApplicationReferencingPolicy() throws Exception {
+        String symbolicName = "my.catalog.policy.id.launch";
+        addCatalogOsgiPolicy(symbolicName, SIMPLE_POLICY_TYPE);
+        Entity app = createAndStartApplication(
+            "name: simple-app-yaml",
+            "location: localhost",
+            "services: ",
+            "  - type: brooklyn.entity.basic.BasicEntity\n" +
+            "    brooklyn.policies:\n" +
+            "    - type: " + ver(symbolicName),
+            "      brooklyn.config:",
+            "        config2: config2 override",
+            "        config3: config3");
+
+        Entity simpleEntity = Iterables.getOnlyElement(app.getChildren());
+        Policy policy = Iterables.getOnlyElement(simpleEntity.getPolicies());
+        assertEquals(policy.getPolicyType().getName(), SIMPLE_POLICY_TYPE);
+        assertEquals(policy.getConfig(new BasicConfigKey<String>(String.class, "config1")), "config1");
+        assertEquals(policy.getConfig(new BasicConfigKey<String>(String.class, "config2")), "config2 override");
+        assertEquals(policy.getConfig(new BasicConfigKey<String>(String.class, "config3")), "config3");
+
+        deleteCatalogEntity(symbolicName);
+    }
+
+    @Test
+    public void testLaunchApplicationReferencingPolicyTopLevelSyntax() throws Exception {
+        String symbolicName = "my.catalog.policy.id.launch";
+        addCatalogOsgiPolicyTopLevelSyntax(symbolicName, SIMPLE_POLICY_TYPE);
+        Entity app = createAndStartApplication(
+            "name: simple-app-yaml",
+            "location: localhost",
+            "services: ",
+            "  - type: brooklyn.entity.basic.BasicEntity\n" +
+            "    brooklyn.policies:\n" +
+            "    - type: " + ver(symbolicName),
+            "      brooklyn.config:",
+            "        config2: config2 override",
+            "        config3: config3");
+
+        Entity simpleEntity = Iterables.getOnlyElement(app.getChildren());
+        Policy policy = Iterables.getOnlyElement(simpleEntity.getPolicies());
+        assertEquals(policy.getPolicyType().getName(), SIMPLE_POLICY_TYPE);
+        assertEquals(policy.getConfig(new BasicConfigKey<String>(String.class, "config1")), "config1");
+        assertEquals(policy.getConfig(new BasicConfigKey<String>(String.class, "config2")), "config2 override");
+        assertEquals(policy.getConfig(new BasicConfigKey<String>(String.class, "config3")), "config3");
+
+        deleteCatalogEntity(symbolicName);
+    }
+    
+    @Test
+    public void testLaunchApplicationWithCatalogReferencingOtherCatalog() throws Exception {
+        String referencedSymbolicName = "my.catalog.policy.id.referenced";
+        String referrerSymbolicName = "my.catalog.policy.id.referring";
+        addCatalogOsgiPolicy(referencedSymbolicName, SIMPLE_POLICY_TYPE);
+
+        addCatalogItems(
+            "brooklyn.catalog:",
+            "  id: " + referrerSymbolicName,
+            "  name: My Catalog App",
+            "  description: My description",
+            "  icon_url: classpath://path/to/myicon.jpg",
+            "  version: " + TEST_VERSION,
+            "  libraries:",
+            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
+            "",
+            "services:",
+            "- type: " + SIMPLE_ENTITY_TYPE,
+            "  brooklyn.policies:",
+            "  - type: " + ver(referencedSymbolicName));
+
+        String yaml = "name: simple-app-yaml\n" +
+                      "location: localhost\n" +
+                      "services: \n" +
+                      "- type: "+ ver(referrerSymbolicName);
+
+        Entity app = createAndStartApplication(yaml);
+
+        Entity simpleEntity = Iterables.getOnlyElement(app.getChildren());
+        Policy policy = Iterables.getOnlyElement(simpleEntity.getPolicies());
+        assertEquals(policy.getPolicyType().getName(), SIMPLE_POLICY_TYPE);
+
+        deleteCatalogEntity(referencedSymbolicName);
+    }
+
+    private void addCatalogOsgiPolicy(String symbolicName, String policyType) {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+        addCatalogItems(
+            "brooklyn.catalog:",
+            "  id: " + symbolicName,
+            "  name: My Catalog Policy",
+            "  description: My description",
+            "  icon_url: classpath://path/to/myicon.jpg",
+            "  version: " + TEST_VERSION,
+            "  libraries:",
+            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
+            "  item:",
+            "    type: " + policyType,
+            "    brooklyn.config:",
+            "      config1: config1",
+            "      config2: config2");
+    }
+
+    private void addCatalogOsgiPolicyTopLevelSyntax(String symbolicName, String policyType) {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+        addCatalogItems(
+            "brooklyn.catalog:",
+            "  id: " + symbolicName,
+            "  name: My Catalog Policy",
+            "  description: My description",
+            "  icon_url: classpath://path/to/myicon.jpg",
+            "  version: " + TEST_VERSION,
+            "  libraries:",
+            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
+            "",
+            "brooklyn.policies:",
+            "- type: " + policyType,
+            "  brooklyn.config:",
+            "    config1: config1",
+            "    config2: config2");
+    }
+
+    private int countCatalogPolicies() {
+        return Iterables.size(mgmt().getCatalog().getCatalogItems(CatalogPredicates.IS_POLICY));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlRebindTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlRebindTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlRebindTest.java
new file mode 100644
index 0000000..29a1227
--- /dev/null
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlRebindTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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.brooklyn.camp.brooklyn.catalog;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+
+import org.apache.brooklyn.camp.brooklyn.AbstractYamlRebindTest;
+import org.testng.annotations.Test;
+
+import brooklyn.catalog.internal.CatalogUtils;
+import brooklyn.entity.basic.BasicEntity;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.StartableApplication;
+import brooklyn.internal.BrooklynFeatureEnablement;
+import brooklyn.policy.Enricher;
+import brooklyn.policy.Policy;
+import brooklyn.test.policy.TestEnricher;
+import brooklyn.test.policy.TestPolicy;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
+
+public class CatalogYamlRebindTest extends AbstractYamlRebindTest {
+
+    // TODO Other tests (relating to https://issues.apache.org/jira/browse/BROOKLYN-149) include:
+    //   - entities cannot be instantiated because class no longer on classpath (e.g. was OSGi)
+    //   - config/attribute cannot be instantiated (e.g. because class no longer on classpath)
+    //   - entity file corrupt
+    
+    enum RebindWithCatalogTestMode {
+        NO_OP,
+        DELETE_CATALOG,
+        REPLACE_CATALOG_WITH_NEWER_VERSION;
+    }
+    
+    @Test
+    public void testRebindWithCatalogAndApp() throws Exception {
+        runRebindWithCatalogAndApp(RebindWithCatalogTestMode.NO_OP);
+    }
+    
+    // See https://issues.apache.org/jira/browse/BROOKLYN-149.
+    // Deletes the catalog item before rebind, but the referenced types are still on the 
+    // default classpath.
+    // Will fallback to loading from classpath.
+    @Test
+    public void testRebindWithCatalogDeletedAndAppExisting() throws Exception {
+        runRebindWithCatalogAndApp(RebindWithCatalogTestMode.DELETE_CATALOG);
+    }
+    
+    // Upgrades the catalog item before rebind, deleting the old version.
+    // Will automatically upgrade.
+    @Test
+    public void testRebindWithCatalogUpgradedWithOldDeletedAndAppExisting() throws Exception {
+        BrooklynFeatureEnablement.enable(BrooklynFeatureEnablement.FEATURE_AUTO_FIX_CATALOG_REF_ON_REBIND);
+        runRebindWithCatalogAndApp(RebindWithCatalogTestMode.REPLACE_CATALOG_WITH_NEWER_VERSION);
+    }
+    
+    @SuppressWarnings("unused")
+    protected void runRebindWithCatalogAndApp(RebindWithCatalogTestMode mode) throws Exception {
+        String symbolicName = "my.catalog.app.id.load";
+        String version = "0.1.2";
+        String catalogFormat = Joiner.on("\n").join(
+                "brooklyn.catalog:",
+                "  id: " + symbolicName,
+                "  version: %s",
+                "  item:",
+                "    type: "+ BasicEntity.class.getName(),
+                "    brooklyn.enrichers:",
+                "    - type: "+TestEnricher.class.getName(),
+                "    brooklyn.policies:",
+                "    - type: "+TestPolicy.class.getName());
+        
+        // Create the catalog item
+        addCatalogItems(String.format(catalogFormat, version));
+
+        // Create an app, using that catalog item
+        String yaml = "name: simple-app-yaml\n" +
+                "location: localhost\n" +
+                "services: \n" +
+                "- type: "+CatalogUtils.getVersionedId(symbolicName, version);
+        origApp = (StartableApplication) createAndStartApplication(yaml);
+        BasicEntity origEntity = (BasicEntity) Iterables.getOnlyElement(origApp.getChildren());
+        TestPolicy origPolicy = (TestPolicy) Iterables.getOnlyElement(origEntity.getPolicies());
+        TestEnricher origEnricher = (TestEnricher) Iterables.tryFind(origEntity.getEnrichers(), Predicates.instanceOf(TestEnricher.class)).get();
+        assertEquals(origEntity.getCatalogItemId(), symbolicName+":"+version);
+
+        // Depending on test-mode, delete the catalog item, and then rebind
+        switch (mode) {
+            case DELETE_CATALOG:
+                mgmt().getCatalog().deleteCatalogItem(symbolicName, version);
+                break;
+            case REPLACE_CATALOG_WITH_NEWER_VERSION:
+                mgmt().getCatalog().deleteCatalogItem(symbolicName, version);
+                version = "0.1.3";
+                addCatalogItems(String.format(catalogFormat, version));
+                break;
+            case NO_OP:
+                // no-op
+        }
+        
+        rebind();
+
+        // Ensure app is still there
+        BasicEntity newEntity = (BasicEntity) Iterables.getOnlyElement(newApp.getChildren());
+        Policy newPolicy = Iterables.getOnlyElement(newEntity.getPolicies());
+        Enricher newEnricher = Iterables.tryFind(newEntity.getEnrichers(), Predicates.instanceOf(TestEnricher.class)).get();
+        assertEquals(newEntity.getCatalogItemId(), symbolicName+":"+version);
+
+        // Ensure app is still usable - e.g. "stop" effector functions as expected
+        newApp.stop();
+        assertFalse(Entities.isManaged(newApp));
+        assertFalse(Entities.isManaged(newEntity));
+    }
+}



Mime
View raw message