How to populate parameter "defaultValue" in Maven "AbstractMojoTestCase"? - maven-3

I have a Maven plugin that I am attempting to test using a subclass of the AbstractMojoTestCase. The plugin Mojo defines an outputFolder parameter with a defaultValue. This parameter is not generally expected to be provided by the user in the POM.
#Parameter(defaultValue = "${project.build.directory}/someOutputFolder")
private File outputFolder;
And if I use the plugin in a real scenario then the outputFolder gets defaulted as expected.
But if I test the Mojo using the AbstractMojoTestCase then while parameters defined in the test POM are populated, parameters with a defaultValue that are not defined in the POM are not populated.
public class MyPluginTestCase extends AbstractMojoTestCase {
public void testAssembly() throws Exception {
final File pom = getTestFile( "src/test/resources/test-pom.xml");
assertNotNull(pom);
assertTrue(pom.exists());
final MyMojo myMojo = (BaselineAssemblyMojo) lookupMojo("assemble", pom);
assertNotNull(myMojo);
myMojo.execute(); // Dies due to NullPointerException on outputFolder.
}
}
Further: if I define the outputFolder parameter in the POM like so:
<outputFolder>${project.build.directory}/someOutputFolder</outputFolder>
then ${project.build.directory} is NOT resolved within the AbstractMojoTestCase.
So what do I need to do to get the defaultvalue populated when testing?
Or is this a fault in the AbstractMojoTestCase?
This is Maven-3.2.3, maven-plugin-plugin-3.2, JDK 8

You need to use lookupConfiguredMojo.
Here's what I ended up using:
public class MyPluginTest
{
#Rule
public MojoRule mojoRule = new MojoRule();
#Test
public void noSource() throws Exception
{
// Just give the location, where the pom.xml is located
MyPlugin plugin = (MyPlugin) mojoRule.lookupConfiguredMojo(getResourcesFile("basic-test"), "myGoal");
plugin.execute();
assertThat(plugin.getSomeInformation()).isEmpty();
}
public File getResourcesFile(String filename)
{
return new File("src/test/resources", filename);
}
}
Of course you need to replace myGoal with your plugin's goal. You also need to figure out how to assert that your plugin executed successfully.
For a more complete example, check out the tests I wrote for fmt-maven-plugin

Related

Import groovy class in a pipeline Jenkinsfile

I need to be able to create classes and use them within a Jenkins pipeline.
Let's say I have a very simple groovy class, declared in a groovy script, looking as this:
class MyClass {
#Override
public String toString() {
return "toto";
}
}
return MyClass();
This class is located in the folder: Project\Buildfiles\Jenkins\com\external
Then in my Jenkinsfile I would do:
node('mynode') {
toto = load 'Project\Buildfiles\Jenkins\com\external\MyClass.groovy'
echo toto.toString()
}
And this actually works
However this do pose a certain numbers of issues with my IDE which does not understand what is happening. Also, this prevents me to have several constructor in my custom class.
What I have been trying to do, and for which I need help, is the following. In a file named ExternalClasses.groovy:
class Toto{
#Override
public String toString() {
return "toto";
}
}
class Tata{
#Override
public String toString() {
return "tata";
}
}
return this;
In the JenkinsFile:
node('mynode') {
external= load 'Project\Buildfiles\Jenkins\com\external\ExternalClasses.groovy'
toto = new Toto();
tata = new Tata();
}
And this fails
I have tried several approaches, used packages names, used the Toto.new() syntax, but none worked.
Any ideas ?
Edit about Shared Libraries:
I actually have a Shared library, it is used by several teams and contains very specific data which should be own by the teams and not by the library.
We need to be able to put out of the library things which does not belong to it. The purpose of this work is to alleviate the said library of non generic code.
You could use the Shared Library Feature. Upload your scripts into a VCS like Github/Bitbucket and use Jenkins-Jobs to execute them. They are available for all projects/jobs.

How to customize an existing Grails plugin functionality, modifying behavior of doWithSpring method

I am new to grails and while working with Spring Security LDAP plugin it was identified that it accepts the ldap server password in plain text only. The task in hand is to pass an encrypted password which is decrypted before it is consumed by the plugin during its initialization phase.
I have already searched for all possible blogs and stackoverflow questions but could not find a way to extend the main plugin class to simply override the doWithSpring() method so that i can simply add the required decryption logic for the Ldap server password. Any help here will be appreciated.
I have already seen and tried jasypt plugin but it also does not work well if the password is stored in some external file and not application yml. So I am looking for a solution to extend the Spring security plugin main class, add the required behavior and register the custom class.
EDIT
Adding the snippet from Grails LDAP Security plugin, which I am trying to override. So If i am successfully able to update the value of securityConfig object before the plugin loads, the purpose is solved.
Some snippet from the plugin:
def conf = SpringSecurityUtils.securityConfig
...
...
contextSource(DefaultSpringSecurityContextSource, conf.ldap.context.server) { // 'ldap://localhost:389'
authenticationSource = ref('ldapAuthenticationSource')
authenticationStrategy = ref('authenticationStrategy')
userDn = conf.ldap.context.managerDn // 'cn=admin,dc=example,dc=com'
**password = conf.ldap.context.managerPassword // 'secret'**
contextFactory = contextFactoryClass
dirObjectFactory = dirObjectFactoryClass
baseEnvironmentProperties = conf.ldap.context.baseEnvironmentProperties // none
cacheEnvironmentProperties = conf.ldap.context.cacheEnvironmentProperties // true
anonymousReadOnly = conf.ldap.context.anonymousReadOnly // false
referral = conf.ldap.context.referral // null
}
ldapAuthenticationSource(SimpleAuthenticationSource) {
principal = conf.ldap.context.managerDn // 'cn=admin,dc=example,dc=com'
**credentials = conf.ldap.context.managerPassword // 'secret'**
}
You don't need to override the doWithSpring() method in the existing plugin. You can provide your own plugin which loads after the one you want to affect and have your doWithSpring() add whatever you want to the context. If you add beans with the same name as the ones added by the other plugin, yours will replace the ones provided by the other plugin as long as you configure your plugin to load after the other one. Similarly, you could do the same think in resources.groovy of the app if you don't want to write a plugin for this.
You have other options too. You could write a bean post processor or bean definition post processor that affects the beans created by the other plugin. Depending on the particulars, that might be a better idea.
EDIT:
After seeing your comment below I created a simple example that shows how you might use a definition post processor. See the project at https://github.com/jeffbrown/postprocessordemo.
The interesting bits:
https://github.com/jeffbrown/postprocessordemo/blob/master/src/main/groovy/demo/SomeBean.groovy
package demo
class SomeBean {
String someValue
}
https://github.com/jeffbrown/postprocessordemo/blob/master/src/main/groovy/demo/SomePostProcessor.groovy
package demo
import org.springframework.beans.BeansException
import org.springframework.beans.MutablePropertyValues
import org.springframework.beans.PropertyValue
import org.springframework.beans.factory.config.BeanDefinition
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory
import org.springframework.beans.factory.support.BeanDefinitionRegistry
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor
class SomePostProcessor implements BeanDefinitionRegistryPostProcessor{
#Override
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
BeanDefinition definition = registry.getBeanDefinition('someBean')
MutablePropertyValues values = definition.getPropertyValues()
PropertyValue value = values.getPropertyValue('someValue')
def originalValue = value.getValue()
// this is where you could do your decrypting...
values.addPropertyValue('someValue', "MODIFIED: ${originalValue}".toString())
}
#Override
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
https://github.com/jeffbrown/postprocessordemo/blob/master/grails-app/conf/spring/resources.groovy
beans = {
someBean(demo.SomeBean) {
someValue = 'Some Value'
}
somePostProcessor demo.SomePostProcessor
}
https://github.com/jeffbrown/postprocessordemo/blob/master/grails-app/init/postprocessordemo/BootStrap.groovy
package postprocessordemo
import demo.SomeBean
class BootStrap {
SomeBean someBean
def init = { servletContext ->
log.info "The Value: ${someBean.someValue}"
}
def destroy = {
}
}
At application startup you will see log output that looks something like this...
2017-10-23 19:04:54.356 INFO --- [ main] postprocessordemo.BootStrap : The Value: MODIFIED: Some Value
The "MODIFIED" there is evidence that the bean definition post processor modified the property value in the bean. In my example I am simply prepending some text to the string. In your implementation you could decrypt a password or do whatever you want to do there.
I hope that helps.
After trying Jasypt plugin and BeanPostProcessor solutions unsuccessfully for my use case, I found below solution to work perfectly.
To describe again the problem statement here,
a) we had to keep the passwords in an encrypted format inside properties files
b) and given we were packaging as a war file so the properties must not be kept inside the war to allow automated deployment scripts update the encrypted passwords depending on the environment
Jasypt plugin was a perfect solution for the use case a), but it was not able to cover the b) scenario
Moreover, the Grails LDAP Security plugin was getting loaded quite early hence Bean Post processors were also not helping out here.
Solution:
Created a new class by implementing the interface SpringApplicationRunListener. Extended its methods and parsed the properties file using YamlPropertySourceLoader
Sample code:
YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
PropertySource<?> applicationYamlPropertySource = loader.load(
"application.yml", new ClassPathResource("application.yml"),"default");
return applicationYamlPropertySource;
Once the properties were loaded inside the MapPropertySource object, parsed them for the encrypted values and applied the decryption logic.
This whole implementation was executed before any plugins were initialized during Grails bootup process solving the purpose.
Hope it will help others.

Creating the new allure adapter for own framework

I'm trying to create the adapter for our own framework. Our framework uses its own assert mechanism so I need to write the adapter.
The adapter class is very simple and it looks like this:
public class AllureReportListener {
private static AllureReportListener object = new AllureReportListener();
private Allure lifecycle = Allure.LIFECYCLE;
private String suiteUid = UUID.randomUUID().toString();
private Set<String> startedTestNames = Collections.newSetFromMap(
new ConcurrentHashMap<String, Boolean>());
public static AllureReportListener getReportListener()
{
return object;
}
public void onTestSuiteStart(String testCaseName)
{
getLifecycle().fire(new TestSuiteStartedEvent(
suiteUid,testCaseName
));
}
public void onTestSuiteFinish()
{
getLifecycle().fire(new TestSuiteFinishedEvent(suiteUid));
}
Allure getLifecycle() {
return lifecycle;
}
}
Our own test suite class calls these methods on right event times.
Since we have our own testing framework, we have our own ant task called ownrunner like this:
<target name="test">
<ownrunner classpathref="classpath" file="config/usecase/SEEDLoginCase.xml" parallel="Scenario" output="${build.report}">
</ownrunner>
</target>
I ran the ant build, but I didn't see any allure results in the build folder.
Now I'm struck. I want this ant task generates the allure xml results. What I need to do?
You need to start the aspect jar too, part of the ant build. Add this line to your build:
<jvmarg value="-javaagent:${currentDir}/aspectjweaver-1.8.0.jar"/>
This will help you to get the allure results, under the directory you have configured.

access configuration/property files from src/groovy

I have a file under src/groovy and I have some properties that are in my Config.groovy and in external property file too. Normally if one want access properties its possible to use grailsApplication .configuration.property.name expression. I want to be able to access all those properties from this file that is under src/groovy directory. What I've tried so far
import grails.util.Holders
class ForkedTomcatCustomizer {
def application
void customize(Tomcat tomcat) {
println Holders.grailsApplication.config.property.name
}
}
gave me NPE saying that grailsAppliction is null
import org.codehaus.groovy.grails.web.context.ServletContextHolder as SCH
import org.codehaus.groovy.grails.web.servlet.GrailsApplicationAttributes as GA
class ForkedTomcatCustomizer {
def application
void customize(Tomcat tomcat) {
def ctx = SCH.servletContext.getAttribute(GA.APPLICATION_CONTEXT)
def grailsAppliction = ctx.grailsApplication.getObject()
println grailsAppliction.config.property.name
}
}
the same - NPE because grailsAppliction is null
Is it possible to handle this situation somehow? Thank you!
Use the below and see if it works
println Holders.config.property.name
You don't need grailsApplication when using Holders.
The examples below are probably a little more complex than what you need, but they show how to get a configuration property at build time. I use them to merge two configuration files, but you might not need to do that.
This method returns a config property when called here at the CompileEnd event.
You could define a similar method in your app's _Events.groovy file that calls your own configuration holder class.
import org.codehaus.groovy.grails.commons.ConfigurationHolder;
class KeyAndSecret{
public static String consumerKey = ConfigurationHolder.config.consumerKey;
public static String consumerSecret = ConfigurationHolder.config.consumerSecret;
}
Try like this

toString() in Grails Java Domain Class Causes

By default, grails seems to return <class name>:<id> for toString() of an Java domain object. That's not at all what I want of course, so I tried to #Override
the toString() to return what I want. When I tried grails generate-all Tagtype, I got the following error:
java.lang.LinkageError: loader constraint violation: loader (instance of <bootloader>) previously initiated loading for a differen
t type with name "org/w3c/dom/NamedNodeMap"
My code is below. Any help would be greatly appreciated.
#Entity
#Table(name = "tagtype", catalog = "tigger")
#SuppressWarnings("serial")
public class Tagtype implements Serializable {
/**
* Attribute id.
*/
private Integer id;
/**
* Attribute tagtype.
*/
private String tagtype;
/**
* Attribute regexpression
*/
private Regexpression regexpression;
. . .
#Override public String toString() {
StringBuilder result = new StringBuilder();
result.append(this.tagtype);
return result.toString();
}
}
I've overriden toString() in Grails domain classes without any problems, so that can't be the reason. This blog suggests it could be a result of name collisions, either temporary (have you tried running "grails clean"?) or perhaps your class name Tagtype collides with some grails internals.
Another thing you could try is using different versions of Grails, especially the latest 1.1.1 if you aren't already using that. This ML post describes an identical error message that was apparently version dependant.

Resources