/* * Copyright 2017 Nokia Solutions and Networks * Licensed under the Apache License, Version 2.0, * see license.txt file for details. */ package org.robotframework.ide.eclipse.main.plugin.project; import static org.assertj.core.api.Assertions.assertThat; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Optional; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.rf.ide.core.dryrun.RobotDryRunKeywordSource; import org.rf.ide.core.project.RobotProjectConfig; import org.rf.ide.core.project.RobotProjectConfig.LibraryType; import org.rf.ide.core.project.RobotProjectConfig.ReferencedLibrary; import org.robotframework.ide.eclipse.main.plugin.model.RobotModel; import org.robotframework.ide.eclipse.main.plugin.model.RobotProject; import org.robotframework.ide.eclipse.main.plugin.project.library.LibrarySpecification; import org.robotframework.red.junit.ProjectProvider; import com.google.common.collect.ImmutableMap; public class KeywordsAutoDiscovererTest { @Rule public ProjectProvider projectProvider = new ProjectProvider(KeywordsAutoDiscovererTest.class); private RobotProject project; private Map<ReferencedLibrary, LibrarySpecification> libraries; @Before public void before() throws Exception { final RobotModel model = new RobotModel(); project = model.createRobotProject(projectProvider.getProject()); libraries = new HashMap<>(); } @Test public void testDifferentKeywordsFromSameLibrary() throws Exception { libraries.putAll(createLibrary("TestLib", new String[] { "#comment", "def kw_x():", " return 0", "def kw_abc ():", " pass" })); configureProject(); new KeywordsAutoDiscoverer(project).start(); verifyKwSource("TestLib.Kw X", "TestLib.py", 1, 4, 4); verifyKwSource("TestLib.Kw Abc", "TestLib.py", 3, 6, 6); } @Test public void testSameKeywordsFromDifferentLibraries() throws Exception { libraries.putAll(createLibrary("First", new String[] { "#comment", "def kw_x():", " pass" })); libraries.putAll(createLibrary("Second", new String[] { "def kw_x():", " pass" })); configureProject(); new KeywordsAutoDiscoverer(project).start(); verifyKwSource("First.Kw X", "First.py", 1, 4, 4); verifyKwSource("Second.Kw X", "Second.py", 0, 4, 4); } @Test public void testKeywordsDefinedWithDecorator() throws Exception { libraries.putAll(createLibrary("Decorated", new String[] { "import robot.api.deco", "from robot.api.deco import keyword", "@robot.api.deco.keyword('Add ${x:\\d+}')", "def add(x):", " pass", "@keyword(name='Deco')", "def decorated_method():", " pass" })); configureProject(); new KeywordsAutoDiscoverer(project).start(); verifyKwSource("Decorated.Add ${x:\\d+}", "Decorated.py", 3, 4, 3); verifyKwSource("Decorated.Deco", "Decorated.py", 6, 4, 16); } @Test public void testKeywordsFromDynamicLibrary() throws Exception { libraries.putAll(createLibrary("DynaLib", new String[] { "class DynaLib:", " def get_keyword_names(self):", " return ['Dyna Kw', 'Other Kw']", " def run_keyword(self, name, args):", " pass" })); configureProject(); new KeywordsAutoDiscoverer(project).start(); verifyKwSource("DynaLib.Dyna Kw", "DynaLib.py", 3, 6, 11); verifyKwSource("DynaLib.Other Kw", "DynaLib.py", 3, 6, 11); } @Test public void testKeywordsFromClassHierarchy() throws Exception { projectProvider.createFile("Parent.py", "class Parent:", " def parent_kw(self, arg):", " pass"); libraries.putAll(createLibrary("Child", new String[] { "import Parent", "class Child(Parent.Parent):", " def child_kw(self, arg):", " pass" })); configureProject(); new KeywordsAutoDiscoverer(project).start(); verifyKwSource("Child.Parent Kw", "Parent.py", 1, 6, 9); verifyKwSource("Child.Child Kw", "Child.py", 2, 6, 8); } @Test public void testKeywordsFromImportedLibraries() throws Exception { projectProvider.createFile("External.py", "def ex_kw(args):", " pass"); libraries.putAll(createLibrary("Internal", new String[] { "from External import ex_kw", "def int_kw(args):", " pass" })); configureProject(); new KeywordsAutoDiscoverer(project).start(); verifyKwSource("Internal.Ex Kw", "External.py", 0, 4, 5); verifyKwSource("Internal.Int Kw", "Internal.py", 1, 4, 6); } private Map<ReferencedLibrary, LibrarySpecification> createLibrary(final String name, final String[] lines) throws IOException, CoreException { final ReferencedLibrary library = new ReferencedLibrary(); library.setType(LibraryType.PYTHON.toString()); library.setName(name); library.setPath(projectProvider.getProject().getName()); final LibrarySpecification libSpec = new LibrarySpecification(); final String filePath = library.getName() + ".py"; final IFile libFile = projectProvider.createFile(filePath, lines); libSpec.setName(library.getName()); libSpec.setSourceFile(libFile); return ImmutableMap.of(library, libSpec); } private void configureProject() throws IOException, CoreException { final RobotProjectConfig config = new RobotProjectConfig(); for (final ReferencedLibrary referencedLibrary : libraries.keySet()) { config.addReferencedLibrary(referencedLibrary); } projectProvider.configure(config); project.setStandardLibraries(new HashMap<String, LibrarySpecification>()); project.setReferencedLibraries(libraries); } private void verifyKwSource(final String qualifiedKwName, final String expectedFilePath, final int expectedLine, final int expectedOffset, final int expectedLength) { final Optional<RobotDryRunKeywordSource> kwSource = project.getKeywordSource(qualifiedKwName); assertThat(kwSource.isPresent()).isTrue(); assertThat(kwSource.get().getFilePath()) .isEqualTo(projectProvider.getFile(expectedFilePath).getLocation().toOSString()); assertThat(kwSource.get().getLine()).isEqualTo(expectedLine); assertThat(kwSource.get().getOffset()).isEqualTo(expectedOffset); assertThat(kwSource.get().getLength()).isEqualTo(expectedLength); } }