blob: 861e4da6bbb21916ce31fd3cc7e2d5b114d4904d [file] [log] [blame]
/*
* 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.jmeter.functions;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.engine.util.CompoundVariable;
import org.apache.jmeter.junit.JMeterTest;
import org.apache.jmeter.junit.JMeterTestCase;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
@TestInstance(TestInstance.Lifecycle.PER_CLASS) // shares funcTitles between tests
public class ComponentReferenceFunctionTest extends JMeterTestCase {
private static final Logger log = LoggerFactory.getLogger(ComponentReferenceFunctionTest.class);
private Map<String, Boolean> funcTitles;
static class Holder {
static final Collection<Function> FUNCTIONS;
static {
try {
FUNCTIONS = JMeterTest.getObjects(Function.class)
.stream()
.filter(f -> f.getClass() != CompoundVariable.class)
.map(Function.class::cast)
.collect(Collectors.toList());
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}
/*
* Test Functions - create the suite of tests
*/
static Collection<Function> functions() throws Throwable {
return Holder.FUNCTIONS;
}
private Element getBodyFromXMLDocument(InputStream stream)
throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setIgnoringElementContentWhitespace(true);
dbf.setIgnoringComments(true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new InputSource(stream));
org.w3c.dom.Element root = doc.getDocumentElement();
org.w3c.dom.Element body = (org.w3c.dom.Element) root.getElementsByTagName("body").item(0);
return body;
}
/*
* Extract titles from functions.xml
*/
@BeforeAll
public void createFunctionSet() throws Exception {
funcTitles = new HashMap<>(20);
String compref = "../xdocs/usermanual/functions.xml";
try (InputStream stream = new FileInputStream(findTestFile(compref))) {
Element body = getBodyFromXMLDocument(stream);
Element section = (Element) body.getElementsByTagName("section").item(0);
NodeList subSections = section.getElementsByTagName("subsection");
for (int i = 0; i < subSections.getLength(); i++) {
NodeList components = ((Element)subSections.item(i)).getElementsByTagName("component");
for (int j = 0; j < components.getLength(); j++) {
org.w3c.dom.Element comp = (org.w3c.dom.Element)
components.item(j);
funcTitles.put(comp.getAttribute("name"), Boolean.FALSE);
String tag = comp.getAttribute("tag");
if (!StringUtils.isEmpty(tag)){
funcTitles.put(tag, Boolean.FALSE);
}
}
}
}
}
@AfterAll
public void checkFunctionSet() throws Exception {
Assertions.assertEquals("[]", JMeterTest.keysWithFalseValues(funcTitles).toString(), "Should not have any names left over in funcTitles");
}
/*
* run the function test
*/
@ParameterizedTest
@MethodSource("functions")
public void runFunction(Function funcItem) throws Exception {
if (funcTitles.size() > 0) {
String title = funcItem.getReferenceKey();
boolean ct = funcTitles.containsKey(title);
if (ct) {
funcTitles.put(title, Boolean.TRUE);// For detecting extra entries
}
// Is this a work in progress ?
if (!title.contains("(ALPHA") && !title.contains("(EXPERIMENTAL")) {
// No, not a work in progress ...
String s = "functions.xml needs '" + title + "' entry for " + funcItem.getClass().getName();
if (!ct) {
log.warn(s); // Record in log as well
}
Assertions.assertTrue(ct, s);
}
}
}
/*
* Check that function descriptions are OK
*/
@ParameterizedTest
@MethodSource("functions")
public void runFunction2(Function funcItem) throws Exception {
for (String o : funcItem.getArgumentDesc()) {
assertInstanceOf(String.class, o, "Description must be a String");
assertFalse(o.startsWith("[refkey"), "Description must not start with [refkey");
}
}
}