/* * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.hibernate.tool.ide.completion; import java.io.File; import java.net.URL; import java.net.URLClassLoader; import java.nio.file.Files; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.hibernate.boot.Metadata; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.dialect.HSQLDialect; import org.hibernate.tool.util.MetadataHelper; import org.hibernate.tools.test.util.JavaUtil; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; import org.junit.rules.TemporaryFolder; /** * @author leon * @author koen */ public class ModelCompletionTest { private final class Collector implements IHQLCompletionRequestor { private List<HQLCompletionProposal> proposals = new ArrayList<HQLCompletionProposal>(); public void clear() { proposals.clear(); } public HQLCompletionProposal[] getCompletionProposals() { Collections.sort( proposals, new Comparator<HQLCompletionProposal>() { public int compare(HQLCompletionProposal o1, HQLCompletionProposal o2) { return o1.getSimpleName().compareTo( o2.getSimpleName() ); } }); return (HQLCompletionProposal[]) proposals.toArray(new HQLCompletionProposal[proposals.size()]); } public boolean accept(HQLCompletionProposal proposal) { proposals.add(proposal); return true; } public void completionFailure(String errorMessage) {} } @ClassRule public static TemporaryFolder temporaryFolder = new TemporaryFolder(); private Configuration sf; private ConfigurationCompletion cc; private ClassLoader originalClassLoader = null; @BeforeClass public static void beforeClass() throws Exception { File folder = temporaryFolder.getRoot(); File originFolder = new File(ModelCompletionTest.class .getClassLoader() .getResource("org/hibernate/tool/ide/completion/resources") .toURI()) .getParentFile(); File destinationFolder = new File( folder, "org/hibernate/tool/ide/completion"); destinationFolder.mkdirs(); for (File f : originFolder.listFiles()) { String fileName = f.getName(); if (fileName.endsWith(".java") || fileName.endsWith(".hbm.xml")) { Files.copy( f.toPath(), new File(destinationFolder, f.getName()).toPath()); } } JavaUtil.compile(temporaryFolder.getRoot()); } @Before public void setUp() throws Exception { originalClassLoader = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader( new URLClassLoader( new URL[] { temporaryFolder.getRoot().toURI().toURL() }, originalClassLoader)); sf = buildConfiguration(); Metadata md = MetadataHelper.getMetadata(sf); cc = new ConfigurationCompletion(md); } @After public void tearDown() throws Exception { Thread.currentThread().setContextClassLoader(originalClassLoader); } @Test public void testGetMappedClasses() { Collector hcc = new Collector(); cc.getMatchingImports("", hcc); Assert.assertEquals("Invalid entity names count", 11, hcc.getCompletionProposals().length); hcc.clear(); cc.getMatchingImports( " ", hcc ); Assert.assertTrue("Space prefix should have no classes", hcc.getCompletionProposals().length==0); hcc.clear(); cc.getMatchingImports( "pro", hcc ); Assert.assertTrue("Completion should not be case sensitive", hcc.getCompletionProposals().length==2); hcc.clear(); cc.getMatchingImports( "StoreC", hcc ); Assert.assertEquals("Invalid entity names count", 1, hcc.getCompletionProposals().length); Assert.assertEquals("StoreCity should have been found", "StoreCity", hcc.getCompletionProposals()[0].getSimpleName()); hcc.clear(); cc.getMatchingImports( "NotThere", hcc ); Assert.assertTrue(hcc.getCompletionProposals().length==0); hcc.clear(); cc.getMatchingImports( "Uni", hcc ); Assert.assertEquals("Universe", hcc.getCompletionProposals()[0].getSimpleName()); } @Test public void testGetProductFields() { Collector hcc = new Collector(); cc.getMatchingProperties( "Product", "", hcc ); doTestFields(hcc.getCompletionProposals(), new String[] {"id", "otherOwners", "owner", "price", "stores", "version", "weight" }); hcc.clear(); cc.getMatchingProperties( "Product", " ", hcc ); doTestFields(hcc.getCompletionProposals(), new String[] {}); hcc.clear(); cc.getMatchingProperties( "Product", "v", hcc ); doTestFields(hcc.getCompletionProposals(), new String[] {"version"}); hcc.clear(); cc.getMatchingProperties( "Product", "V", hcc ); doTestFields(hcc.getCompletionProposals(), new String[] {"version"} ); hcc.clear(); cc.getMatchingProperties( "Product", "X", hcc ); doTestFields(hcc.getCompletionProposals(), new String[0] ); } @Test public void testGetStoreFields() { Collector hcc = new Collector(); cc.getMatchingProperties( "Store", "", hcc ); doTestFields(hcc.getCompletionProposals(), new String[] {"city", "id", "name", "name2"}); hcc.clear(); cc.getMatchingProperties( "Store", "name", hcc ); doTestFields(hcc.getCompletionProposals(), new String[] {"name", "name2"}); hcc.clear(); cc.getMatchingProperties( "Store", "name2", hcc ); doTestFields(hcc.getCompletionProposals(), new String[] {"name2"}); hcc.clear(); } @Test public void testKeywordFunction() { Collector hcc = new Collector(); cc.getMatchingKeywords( "f", 2, hcc ); HQLCompletionProposal[] completionProposals = hcc.getCompletionProposals(); Assert.assertEquals(4, completionProposals.length); Assert.assertEquals("alse", completionProposals[0].getCompletion()); hcc.clear(); cc.getMatchingFunctions( "ma", 2, hcc ); completionProposals = hcc.getCompletionProposals(); Assert.assertEquals(1, completionProposals.length); Assert.assertEquals("x", completionProposals[0].getCompletion()); hcc.clear(); cc.getMatchingKeywords("FR", 3, hcc); completionProposals = hcc.getCompletionProposals(); Assert.assertEquals(1, completionProposals.length); hcc.clear(); cc.getMatchingFunctions( "MA", 2, hcc ); completionProposals = hcc.getCompletionProposals(); Assert.assertEquals(1, completionProposals.length); } @Test public void testUnmappedClassFields() { Collector hcc = new Collector(); cc.getMatchingProperties( "UnmappedClass", "", hcc ); doTestFields(hcc.getCompletionProposals(), new String[0]); } private void doTestFields(HQLCompletionProposal[] proposals, String[] fields) { if (fields == null || fields.length==0) { Assert.assertTrue("No fields should have been found", proposals.length==0); return; } Assert.assertEquals("Invalid field count", fields.length, proposals.length); for (int j = 0; j < fields.length; j++) { String f = fields[j]; HQLCompletionProposal proposal = proposals[j]; Assert.assertEquals("Invalid field name at " + j, f, proposal.getSimpleName()); Assert.assertEquals("Invalid kind at " + j, proposal.getCompletionKind(), HQLCompletionProposal.PROPERTY); } } @Test public void testProductOwnerAddress() { String query = "select p from Product p where p.owner."; List<EntityNameReference> visible = getVisibleEntityNames(query.toCharArray()); Collector hcc = new Collector(); cc.getMatchingProperties( cc.getCanonicalPath(visible, "p.owner"), "", hcc ); doTestFields(hcc.getCompletionProposals(), new String[] {"address", "firstName", "lastName"}); hcc.clear(); query = "select p from Product p where p.owner.address."; visible = getVisibleEntityNames(query.toCharArray()); cc.getMatchingProperties( cc.getCanonicalPath(visible, "p.owner.address"), "", hcc ); doTestFields(hcc.getCompletionProposals(), new String[] {"id", "number", "street"}); } private List<EntityNameReference> getVisibleEntityNames(char[] cs) { return new HQLAnalyzer().getVisibleEntityNames( cs, cs.length); } @Test public void testStoreCity() { String query = "select p from Product p join p.stores store where store"; List<EntityNameReference> visible = getVisibleEntityNames(query.toCharArray()); Collector hcc = new Collector(); String canonicalPath = cc.getCanonicalPath(visible, "store.city"); cc.getMatchingProperties( canonicalPath, "", hcc ); doTestFields(hcc.getCompletionProposals(), new String[] {"id", "name", "number"}); } @Test public void testUnaliasedProductQuery() { doTestUnaliasedProductQuery("delete Product where owner."); doTestUnaliasedProductQuery("update Product where owner."); doTestUnaliasedProductQuery("select from Product where owner."); } private void doTestUnaliasedProductQuery(final String query) { Collector hcc = new Collector(); List<EntityNameReference> visible = getVisibleEntityNames(query.toCharArray()); cc.getMatchingProperties( cc.getCanonicalPath(visible, "owner"), "f", hcc ); HQLCompletionProposal[] completionProposals = hcc.getCompletionProposals(); // Assert.assertEquals(1, completionProposals.length); Assert.assertEquals("firstName", completionProposals[0].getSimpleName()); // hcc.clear(); cc.getMatchingProperties( cc.getCanonicalPath(visible, "owner"), "l", hcc ); completionProposals = hcc.getCompletionProposals(); Assert.assertEquals(1, completionProposals.length); Assert.assertEquals("lastName", completionProposals[0].getSimpleName()); // hcc.clear(); cc.getMatchingProperties( cc.getCanonicalPath(visible, "owner"), "", hcc ); // firstname, lastname, owner Assert.assertEquals(3, hcc.getCompletionProposals().length); // hcc.clear(); cc.getMatchingProperties( cc.getCanonicalPath(visible, "owner"), "g", hcc ); Assert.assertEquals(0, hcc.getCompletionProposals().length); } @Test public void testBasicFrom() { Collector c = new Collector(); IHQLCodeAssist hqlEval = new HQLCodeAssist(sf); String query = "from | "; int caretPosition = getCaretPosition(query); hqlEval.codeComplete(query, caretPosition, c); HQLCompletionProposal[] completionProposals = c.getCompletionProposals(); Assert.assertEquals(11, completionProposals.length); for (int i = 0; i < completionProposals.length; i++) { HQLCompletionProposal proposal = completionProposals[i]; Assert.assertEquals(HQLCompletionProposal.ENTITY_NAME, proposal.getCompletionKind()); Assert.assertEquals(caretPosition, proposal.getCompletionLocation()); Assert.assertEquals(caretPosition, proposal.getReplaceStart()); Assert.assertEquals(proposal.getReplaceStart(), proposal.getReplaceEnd()); // nothing to replace Assert.assertNotNull(proposal.getShortEntityName()); Assert.assertNotNull(proposal.getEntityName()); //assertNotNull(proposal.getShortEntityName()); } c.clear(); query = "from Store, | "; caretPosition = getCaretPosition(query); hqlEval.codeComplete(query, caretPosition, c); completionProposals = c.getCompletionProposals(); Assert.assertEquals(11, completionProposals.length); } @Test public void testFromNonWhitespace() { Collector c = new Collector(); IHQLCodeAssist hqlEval = new HQLCodeAssist(sf); String query = null; int caretPosition = -1; HQLCompletionProposal[] completionProposals = null; c.clear(); query = "from Store,| "; caretPosition = getCaretPosition(query); hqlEval.codeComplete(query, caretPosition, c); completionProposals = c.getCompletionProposals(); Assert.assertEquals("should get results after a nonwhitespace separator", 11, completionProposals.length); c.clear(); query = "from Store s where "; caretPosition = getCaretPosition(query); hqlEval.codeComplete(query, caretPosition, c); completionProposals = c.getCompletionProposals(); Assert.assertTrue(completionProposals.length > 0); c.clear(); query = "from Store s where ("; caretPosition = getCaretPosition(query); hqlEval.codeComplete(query, caretPosition, c); completionProposals = c.getCompletionProposals(); Assert.assertTrue(completionProposals.length > 0); } @Test public void testFromWithTabs() { Collector c = new Collector(); IHQLCodeAssist hqlEval = new HQLCodeAssist(sf); String query = null; int caretPosition = -1; HQLCompletionProposal[] completionProposals = null; c.clear(); final String codeCompletionPlaceMarker = " from "; query = "select\t \tt1." + codeCompletionPlaceMarker + "Product t1"; caretPosition = query.indexOf(codeCompletionPlaceMarker); hqlEval.codeComplete(query, caretPosition, c); completionProposals = c.getCompletionProposals(); Assert.assertTrue(completionProposals.length == 0); c.clear(); query = query.replace('\t', ' '); hqlEval.codeComplete(query, caretPosition, c); completionProposals = c.getCompletionProposals(); Assert.assertTrue(completionProposals.length > 0); } @Test public void testBasicFromPartialEntityName() { Collector c = new Collector(); IHQLCodeAssist hqlEval = new HQLCodeAssist(sf); String query = "from Pro| "; int caretPosition = getCaretPosition(query); hqlEval.codeComplete(query, caretPosition, c); HQLCompletionProposal[] completionProposals = c.getCompletionProposals(); Assert.assertEquals(2, completionProposals.length); Assert.assertEquals("Product", completionProposals[0].getSimpleName()); Assert.assertEquals("duct", completionProposals[0].getCompletion()); Assert.assertEquals("ProductOwnerAddress", completionProposals[1].getSimpleName()); Assert.assertEquals("ductOwnerAddress", completionProposals[1].getCompletion()); for (int i = 0; i < completionProposals.length; i++) { HQLCompletionProposal proposal = completionProposals[i]; Assert.assertEquals(HQLCompletionProposal.ENTITY_NAME, proposal.getCompletionKind()); Assert.assertEquals(caretPosition, proposal.getCompletionLocation()); Assert.assertEquals(caretPosition, proposal.getReplaceStart()); Assert.assertEquals(caretPosition, proposal.getReplaceEnd()); } } @Test public void testBasicFromPartialDifferentCaseEntityName() { Collector c = new Collector(); IHQLCodeAssist hqlEval = new HQLCodeAssist(sf); String query = "from pro| "; int caretPosition = getCaretPosition(query); hqlEval.codeComplete(query, caretPosition, c); HQLCompletionProposal[] completionProposals = c.getCompletionProposals(); Assert.assertEquals(2, completionProposals.length); Assert.assertEquals("Product", completionProposals[0].getSimpleName()); Assert.assertEquals("Product", completionProposals[0].getCompletion()); Assert.assertEquals("ProductOwnerAddress", completionProposals[1].getSimpleName()); Assert.assertEquals("ProductOwnerAddress", completionProposals[1].getCompletion()); for (int i = 0; i < completionProposals.length; i++) { HQLCompletionProposal proposal = completionProposals[i]; Assert.assertEquals(HQLCompletionProposal.ENTITY_NAME, proposal.getCompletionKind()); Assert.assertEquals(caretPosition, proposal.getCompletionLocation()); Assert.assertEquals(caretPosition-3, proposal.getReplaceStart()); Assert.assertEquals(caretPosition, proposal.getReplaceEnd()); } } @Test public void testDottedFromPartialEntityName() { Collector c = new Collector(); IHQLCodeAssist hqlEval = new HQLCodeAssist(sf); String query = "from org.hibernate.t| "; int caretPosition = getCaretPosition(query); hqlEval.codeComplete(query, caretPosition, c); HQLCompletionProposal[] completionProposals = c.getCompletionProposals(); Assert.assertEquals(5, completionProposals.length); for (int i = 0; i < completionProposals.length; i++) { HQLCompletionProposal proposal = completionProposals[i]; Assert.assertEquals(HQLCompletionProposal.ENTITY_NAME, proposal.getCompletionKind()); Assert.assertEquals(caretPosition, proposal.getCompletionLocation()); Assert.assertEquals(caretPosition, proposal.getReplaceStart()); Assert.assertEquals(caretPosition, proposal.getReplaceEnd()); Assert.assertTrue(proposal.getCompletion().startsWith( "ool.ide.completion" )); } } @Test public void testBadInputBeforeCursor() { Collector c = new Collector(); IHQLCodeAssist hqlEval = new HQLCodeAssist(sf); String query = "from org.;hibernate.t| "; int caretPosition = getCaretPosition(query); hqlEval.codeComplete(query, caretPosition, c); HQLCompletionProposal[] completionProposals = c.getCompletionProposals(); Assert.assertEquals(0, completionProposals.length); } @Test public void testBadInputAfterCursor() { Collector c = new Collector(); IHQLCodeAssist hqlEval = new HQLCodeAssist(sf); String query = "from org.hibernate.t| ;"; int caretPosition = getCaretPosition(query); hqlEval.codeComplete(query, caretPosition, c); HQLCompletionProposal[] completionProposals = c.getCompletionProposals(); Assert.assertEquals(5, completionProposals.length); } @Test public void testAliasRef() { Collector c = new Collector(); IHQLCodeAssist hqlEval = new HQLCodeAssist(sf); String query = "from Product as pr_od where pr_|"; int caretPosition = getCaretPosition(query); hqlEval.codeComplete(getCleanQuery(query), caretPosition, c); HQLCompletionProposal[] completionProposals = c.getCompletionProposals(); Assert.assertEquals(1, completionProposals.length); HQLCompletionProposal proposal = completionProposals[0]; Assert.assertEquals( "od", proposal.getCompletion()); Assert.assertEquals(HQLCompletionProposal.ALIAS_REF, proposal.getCompletionKind()); Assert.assertEquals(caretPosition, proposal.getCompletionLocation()); Assert.assertEquals(caretPosition, proposal.getReplaceStart()); Assert.assertEquals(caretPosition, proposal.getReplaceEnd()); Assert.assertEquals("org.hibernate.tool.ide.completion.Product", proposal.getEntityName()); } private String getCleanQuery(String query) { return query.replaceAll("\\|", ""); } @Test public void testBasicPropertyNames() { Collector c = new Collector(); IHQLCodeAssist hqlEval = new HQLCodeAssist(sf); String query = "from Product as p where p.v|"; //TODO: is non-aliased references allowed ? int caretPosition = getCaretPosition(query); hqlEval.codeComplete(getCleanQuery(query), caretPosition, c); HQLCompletionProposal[] completionProposals = c.getCompletionProposals(); Assert.assertEquals(1, completionProposals.length); HQLCompletionProposal proposal = completionProposals[0]; Assert.assertEquals( "ersion", proposal.getCompletion()); Assert.assertEquals(HQLCompletionProposal.PROPERTY, proposal.getCompletionKind()); Assert.assertEquals(caretPosition, proposal.getCompletionLocation()); Assert.assertEquals(caretPosition, proposal.getReplaceStart()); Assert.assertEquals(caretPosition, proposal.getReplaceEnd()); //TODO: keep a path/context assertEquals("Product", proposal.getShortEntityName()); Assert.assertEquals("org.hibernate.tool.ide.completion.Product", proposal.getEntityName()); Assert.assertEquals("version", proposal.getPropertyName()); Assert.assertNotNull(proposal.getProperty()); Assert.assertEquals(proposal.getPropertyName(), proposal.getProperty().getName()); } @Test public void testComponentPropertyNames() { Collector c = new Collector(); IHQLCodeAssist hqlEval = new HQLCodeAssist(sf); String query = "from Product as p where p.owner.|"; int caretPosition = getCaretPosition(query); hqlEval.codeComplete(getCleanQuery(query), caretPosition, c); HQLCompletionProposal[] completionProposals = c.getCompletionProposals(); Assert.assertEquals(3, completionProposals.length); Assert.assertNotNull(completionProposals[0]); c.clear(); query = "from Product as p where p.owner.address."; caretPosition = getCaretPosition(query); hqlEval.codeComplete(getCleanQuery(query), caretPosition, c); completionProposals = c.getCompletionProposals(); Assert.assertEquals(3, completionProposals.length); c.clear(); query = "from Product as p join p.otherOwners o where o."; caretPosition = getCaretPosition(query); hqlEval.codeComplete(getCleanQuery(query), caretPosition, c); completionProposals = c.getCompletionProposals(); Assert.assertEquals(3, completionProposals.length); } @Test public void testInFromAfterEntityAlias() { Collector c = new Collector(); IHQLCodeAssist hqlEval = new HQLCodeAssist(sf); String query = "from Product as p, | where p.v"; int caretPosition = getCaretPosition(query); hqlEval.codeComplete(getCleanQuery(query), caretPosition, c); HQLCompletionProposal[] completionProposals = c.getCompletionProposals(); Assert.assertEquals(11, completionProposals.length); HQLCompletionProposal proposal = completionProposals[0]; Assert.assertEquals(HQLCompletionProposal.ENTITY_NAME, proposal.getCompletionKind()); Assert.assertEquals(caretPosition, proposal.getCompletionLocation()); Assert.assertEquals(caretPosition, proposal.getReplaceStart()); Assert.assertEquals(caretPosition, proposal.getReplaceEnd()); } @Test public void testKeywordsFunctions() { Collector c = new Collector(); IHQLCodeAssist hqlEval = new HQLCodeAssist(sf); String query = ""; int caretPosition = getCaretPosition(query); hqlEval.codeComplete(getCleanQuery(query), caretPosition, c); HQLCompletionProposal[] completionProposals = c.getCompletionProposals(); Assert.assertTrue(completionProposals.length>0); for (int i = 0; i < completionProposals.length; i++) { HQLCompletionProposal proposal = completionProposals[i]; Assert.assertTrue(HQLCompletionProposal.KEYWORD==proposal.getCompletionKind() || HQLCompletionProposal.FUNCTION==proposal.getCompletionKind()); Assert.assertEquals(caretPosition, proposal.getCompletionLocation()); Assert.assertEquals(caretPosition, proposal.getReplaceStart()); Assert.assertEquals(caretPosition, proposal.getReplaceEnd()); } } protected int getCaretPosition(String str) { int indexOf = str.indexOf("|"); return indexOf!=-1?indexOf:str.length(); } private Configuration buildConfiguration() { Configuration cfg = new Configuration(); cfg.setProperty(Environment.DIALECT, HSQLDialect.class.getName()); cfg .addInputStream(getClass().getResourceAsStream("Product.hbm.xml")) .addInputStream(getClass().getResourceAsStream("Store.hbm.xml")) .addInputStream(getClass().getResourceAsStream("ProductOwnerAddress.hbm.xml")) .addInputStream(getClass().getResourceAsStream("City.hbm.xml")) .addInputStream(getClass().getResourceAsStream("StoreCity.hbm.xml")); MetadataHelper.getMetadata(cfg); return cfg; } }