/* * 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.core.catalog.internal; import java.net.URLEncoder; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; import org.apache.brooklyn.api.catalog.BrooklynCatalog; import org.apache.brooklyn.api.catalog.CatalogItem; import org.apache.brooklyn.api.entity.Application; import org.apache.brooklyn.api.entity.EntitySpec; import org.apache.brooklyn.core.catalog.CatalogPredicates; import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog; import org.apache.brooklyn.core.catalog.internal.MyCatalogItems.MySillyAppTemplate; import org.apache.brooklyn.core.entity.Entities; import org.apache.brooklyn.core.internal.BrooklynProperties; import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext; import org.apache.brooklyn.core.server.BrooklynServerConfig; import org.apache.brooklyn.util.core.ResourceUtils; import org.apache.brooklyn.util.net.Urls; import org.apache.brooklyn.util.text.Strings; import com.google.common.base.Predicates; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; public class CatalogScanTest { private static final Logger log = LoggerFactory.getLogger(CatalogScanTest.class); private BrooklynCatalog defaultCatalog, annotsCatalog, fullCatalog; private List<LocalManagementContext> managementContexts = Lists.newCopyOnWriteArrayList(); @AfterMethod(alwaysRun = true) public void tearDown(){ for (LocalManagementContext managementContext : managementContexts) { Entities.destroyAll(managementContext); } managementContexts.clear(); } private LocalManagementContext newManagementContext(BrooklynProperties props) { LocalManagementContext result = new LocalManagementContext(props); managementContexts.add(result); return result; } private synchronized void loadFullCatalog() { if (fullCatalog!=null) return; BrooklynProperties props = BrooklynProperties.Factory.newEmpty(); props.put(BrooklynServerConfig.BROOKLYN_CATALOG_URL.getName(), "data:,"+Urls.encode("<catalog><classpath scan=\"types\"/></catalog>")); fullCatalog = newManagementContext(props).getCatalog(); log.info("ENTITIES loaded for FULL: "+fullCatalog.getCatalogItems(Predicates.alwaysTrue())); } private synchronized void loadTheDefaultCatalog(boolean lookOnDiskForDefaultCatalog) { if (defaultCatalog!=null) return; BrooklynProperties props = BrooklynProperties.Factory.newEmpty(); props.put(BrooklynServerConfig.BROOKLYN_CATALOG_URL.getName(), // if default catalog is picked up from the system, we might get random stuff from ~/.brooklyn/ instead of the default; // useful as an integration check that we default correctly, but irritating for people to use if they have such a catalog installed (lookOnDiskForDefaultCatalog ? "" : "data:,"+Urls.encode(new ResourceUtils(this).getResourceAsString("classpath:/brooklyn/default.catalog.bom")))); LocalManagementContext managementContext = newManagementContext(props); defaultCatalog = managementContext.getCatalog(); log.info("ENTITIES loaded for DEFAULT: "+defaultCatalog.getCatalogItems(Predicates.alwaysTrue())); } @SuppressWarnings("deprecation") private synchronized void loadAnnotationsOnlyCatalog() { if (annotsCatalog!=null) return; BrooklynProperties props = BrooklynProperties.Factory.newEmpty(); props.put(BrooklynServerConfig.BROOKLYN_CATALOG_URL.getName(), "data:,"+URLEncoder.encode("<catalog><classpath scan=\"annotations\"/></catalog>")); LocalManagementContext managementContext = newManagementContext(props); annotsCatalog = managementContext.getCatalog(); log.info("ENTITIES loaded with annotation: "+annotsCatalog.getCatalogItems(Predicates.alwaysTrue())); } @Test public void testLoadAnnotations() { loadAnnotationsOnlyCatalog(); BrooklynCatalog c = annotsCatalog; Iterable<CatalogItem<Object,Object>> bases = c.getCatalogItems(CatalogPredicates.displayName(Predicates.containsPattern("MyBaseEntity"))); Assert.assertEquals(Iterables.size(bases), 0, "should have been empty: "+bases); Iterable<CatalogItem<Object,Object>> asdfjkls = c.getCatalogItems(CatalogPredicates.displayName(Predicates.containsPattern("__asdfjkls__shouldnotbefound"))); Assert.assertEquals(Iterables.size(asdfjkls), 0); Iterable<CatalogItem<Object,Object>> silly1 = c.getCatalogItems(CatalogPredicates.displayName(Predicates.equalTo("MySillyAppTemplate"))); Iterable<CatalogItem<Object,Object>> silly2 = c.getCatalogItems(CatalogPredicates.javaType(Predicates.equalTo(MySillyAppTemplate.class.getName()))); CatalogItem<Object, Object> silly1El = Iterables.getOnlyElement(silly1); Assert.assertEquals(silly1El, Iterables.getOnlyElement(silly2)); CatalogItem<Application,EntitySpec<? extends Application>> s1 = c.getCatalogItem(Application.class, silly1El.getSymbolicName(), silly1El.getVersion()); Assert.assertEquals(s1, silly1El); Assert.assertEquals(s1.getDescription(), "Some silly app test"); @SuppressWarnings({ "unchecked", "rawtypes" }) Class<?> app = c.createSpec((CatalogItem)s1).getType(); Assert.assertEquals(MySillyAppTemplate.class, app); String xml = ((BasicBrooklynCatalog)c).toXmlString(); log.info("Catalog is:\n"+xml); Assert.assertTrue(xml.indexOf("Some silly app test") >= 0); } @Test public void testAnnotationLoadsSomeApps() { loadAnnotationsOnlyCatalog(); Iterable<CatalogItem<Object,Object>> silly1 = annotsCatalog.getCatalogItems(CatalogPredicates.displayName(Predicates.equalTo("MySillyAppTemplate"))); Assert.assertEquals(Iterables.getOnlyElement(silly1).getDescription(), "Some silly app test"); } @Test public void testAnnotationLoadsSomeAppBuilders() { loadAnnotationsOnlyCatalog(); Iterable<CatalogItem<Object,Object>> silly1 = annotsCatalog.getCatalogItems(CatalogPredicates.displayName(Predicates.equalTo("MySillyAppBuilderTemplate"))); Assert.assertEquals(Iterables.getOnlyElement(silly1).getDescription(), "Some silly app builder test"); } @Test public void testMoreTypesThanAnnotations() { loadAnnotationsOnlyCatalog(); loadFullCatalog(); int numFromAnnots = Iterables.size(annotsCatalog.getCatalogItems(Predicates.alwaysTrue())); int numFromTypes = Iterables.size(fullCatalog.getCatalogItems(Predicates.alwaysTrue())); Assert.assertTrue(numFromAnnots < numFromTypes, "full="+numFromTypes+" annots="+numFromAnnots); } @Test public void testMoreTypesThanAnnotationsForApps() { loadAnnotationsOnlyCatalog(); loadFullCatalog(); int numFromAnnots = Iterables.size(annotsCatalog.getCatalogItems(CatalogPredicates.IS_TEMPLATE)); int numFromTypes = Iterables.size(fullCatalog.getCatalogItems(CatalogPredicates.IS_TEMPLATE)); Assert.assertTrue(numFromAnnots < numFromTypes, "full="+numFromTypes+" annots="+numFromAnnots); } @Test public void testAnnotationIsDefault() { doTestAnnotationIsDefault(false); } // see comment in load method; likely fails if a custom catalog is installed in ~/.brooklyn/ @Test(groups="Integration", enabled=false) public void testAnnotationIsDefaultOnDisk() { doTestAnnotationIsDefault(true); } private void doTestAnnotationIsDefault(boolean lookOnDiskForDefaultCatalog) { loadTheDefaultCatalog(false); int numInDefault = Iterables.size(defaultCatalog.getCatalogItems(Predicates.alwaysTrue())); loadAnnotationsOnlyCatalog(); int numFromAnnots = Iterables.size(annotsCatalog.getCatalogItems(Predicates.alwaysTrue())); Assert.assertEquals(numInDefault, numFromAnnots); Assert.assertTrue(numInDefault>0, "Expected more than 0 entries"); } // a simple test asserting no errors when listing the real catalog, and listing them for reference // also useful to test variants in a stored catalog to assert they all load // TODO integration tests which build up catalogs assuming other things are installed @Test public void testListCurrentCatalogItems() { LocalManagementContext mgmt = newManagementContext(BrooklynProperties.Factory.newDefault()); log.info("ITEMS\n"+Strings.join(mgmt.getCatalog().getCatalogItems(), "\n")); } }