Convert jsp 2.3 tests from groovy to java (#11827)
This commit is contained in:
parent
14d87e7323
commit
e7a6398c71
|
@ -1,539 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright The OpenTelemetry Authors
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
|
|
||||||
import io.opentelemetry.instrumentation.test.utils.PortUtils
|
|
||||||
import io.opentelemetry.semconv.ExceptionAttributes
|
|
||||||
import io.opentelemetry.semconv.ServerAttributes
|
|
||||||
import io.opentelemetry.semconv.ClientAttributes
|
|
||||||
import io.opentelemetry.semconv.UserAgentAttributes
|
|
||||||
import io.opentelemetry.semconv.ErrorAttributes
|
|
||||||
import io.opentelemetry.semconv.HttpAttributes
|
|
||||||
import io.opentelemetry.semconv.NetworkAttributes
|
|
||||||
import io.opentelemetry.semconv.UrlAttributes
|
|
||||||
import io.opentelemetry.testing.internal.armeria.client.WebClient
|
|
||||||
import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse
|
|
||||||
import io.opentelemetry.testing.internal.armeria.common.HttpMethod
|
|
||||||
import io.opentelemetry.testing.internal.armeria.common.MediaType
|
|
||||||
import io.opentelemetry.testing.internal.armeria.common.RequestHeaders
|
|
||||||
import org.apache.catalina.Context
|
|
||||||
import org.apache.catalina.startup.Tomcat
|
|
||||||
import org.apache.jasper.JasperException
|
|
||||||
import spock.lang.Shared
|
|
||||||
import spock.lang.Unroll
|
|
||||||
|
|
||||||
import java.nio.file.Files
|
|
||||||
|
|
||||||
import static io.opentelemetry.api.trace.SpanKind.SERVER
|
|
||||||
import static io.opentelemetry.api.trace.StatusCode.ERROR
|
|
||||||
|
|
||||||
//TODO should this be HttpServerTest?
|
|
||||||
class JspInstrumentationBasicTests extends AgentInstrumentationSpecification {
|
|
||||||
|
|
||||||
@Shared
|
|
||||||
int port
|
|
||||||
@Shared
|
|
||||||
Tomcat tomcatServer
|
|
||||||
@Shared
|
|
||||||
Context appContext
|
|
||||||
@Shared
|
|
||||||
String jspWebappContext = "jsptest-context"
|
|
||||||
|
|
||||||
@Shared
|
|
||||||
File baseDir
|
|
||||||
@Shared
|
|
||||||
String baseUrl
|
|
||||||
|
|
||||||
@Shared
|
|
||||||
WebClient client
|
|
||||||
|
|
||||||
def setupSpec() {
|
|
||||||
baseDir = Files.createTempDirectory("jsp").toFile()
|
|
||||||
baseDir.deleteOnExit()
|
|
||||||
|
|
||||||
port = PortUtils.findOpenPort()
|
|
||||||
|
|
||||||
tomcatServer = new Tomcat()
|
|
||||||
tomcatServer.setBaseDir(baseDir.getAbsolutePath())
|
|
||||||
tomcatServer.setPort(port)
|
|
||||||
tomcatServer.getConnector()
|
|
||||||
// comment to debug
|
|
||||||
tomcatServer.setSilent(true)
|
|
||||||
// this is needed in tomcat 9, this triggers the creation of a connector, will not
|
|
||||||
// affect tomcat 7 and 8
|
|
||||||
// https://stackoverflow.com/questions/48998387/code-works-with-embedded-apache-tomcat-8-but-not-with-9-whats-changed
|
|
||||||
tomcatServer.getConnector()
|
|
||||||
baseUrl = "http://localhost:$port/$jspWebappContext"
|
|
||||||
client = WebClient.of(baseUrl)
|
|
||||||
|
|
||||||
appContext = tomcatServer.addWebapp("/$jspWebappContext",
|
|
||||||
JspInstrumentationBasicTests.getResource("/webapps/jsptest").getPath())
|
|
||||||
|
|
||||||
tomcatServer.start()
|
|
||||||
System.out.println(
|
|
||||||
"Tomcat server: http://" + tomcatServer.getHost().getName() + ":" + port + "/")
|
|
||||||
}
|
|
||||||
|
|
||||||
def cleanupSpec() {
|
|
||||||
tomcatServer.stop()
|
|
||||||
tomcatServer.destroy()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Unroll
|
|
||||||
def "non-erroneous GET #test test"() {
|
|
||||||
when:
|
|
||||||
AggregatedHttpResponse res = client.get("/${jspFileName}").aggregate().join()
|
|
||||||
|
|
||||||
then:
|
|
||||||
assertTraces(1) {
|
|
||||||
trace(0, 3) {
|
|
||||||
span(0) {
|
|
||||||
def route = "/$jspWebappContext/$jspFileName"
|
|
||||||
|
|
||||||
hasNoParent()
|
|
||||||
name "GET $route"
|
|
||||||
kind SERVER
|
|
||||||
attributes {
|
|
||||||
"$UrlAttributes.URL_SCHEME" "http"
|
|
||||||
"$UrlAttributes.URL_PATH" route
|
|
||||||
"$HttpAttributes.HTTP_REQUEST_METHOD" "GET"
|
|
||||||
"$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200
|
|
||||||
"$UserAgentAttributes.USER_AGENT_ORIGINAL" String
|
|
||||||
"$HttpAttributes.HTTP_ROUTE" route
|
|
||||||
"$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1"
|
|
||||||
"$ServerAttributes.SERVER_ADDRESS" "localhost"
|
|
||||||
"$ServerAttributes.SERVER_PORT" port
|
|
||||||
"$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_PORT" Long
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(1) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Compile /$jspFileName"
|
|
||||||
attributes {
|
|
||||||
"jsp.classFQCN" "org.apache.jsp.$jspClassNamePrefix$jspClassName"
|
|
||||||
"jsp.compiler" "org.apache.jasper.compiler.JDTCompiler"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(2) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Render /$jspFileName"
|
|
||||||
attributes {
|
|
||||||
"jsp.requestURL" "${baseUrl}/${jspFileName}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res.status().code() == 200
|
|
||||||
|
|
||||||
where:
|
|
||||||
test | jspFileName | jspClassName | jspClassNamePrefix
|
|
||||||
"no java jsp" | "nojava.jsp" | "nojava_jsp" | ""
|
|
||||||
"basic loop jsp" | "common/loop.jsp" | "loop_jsp" | "common."
|
|
||||||
"invalid HTML markup" | "invalidMarkup.jsp" | "invalidMarkup_jsp" | ""
|
|
||||||
}
|
|
||||||
|
|
||||||
def "non-erroneous GET with query string"() {
|
|
||||||
setup:
|
|
||||||
String queryString = "HELLO"
|
|
||||||
|
|
||||||
when:
|
|
||||||
AggregatedHttpResponse res = client.get("/getQuery.jsp?${queryString}").aggregate().join()
|
|
||||||
|
|
||||||
then:
|
|
||||||
assertTraces(1) {
|
|
||||||
trace(0, 3) {
|
|
||||||
span(0) {
|
|
||||||
def route = "/$jspWebappContext/getQuery.jsp"
|
|
||||||
|
|
||||||
hasNoParent()
|
|
||||||
name "GET $route"
|
|
||||||
kind SERVER
|
|
||||||
attributes {
|
|
||||||
"$UrlAttributes.URL_SCHEME" "http"
|
|
||||||
"$UrlAttributes.URL_PATH" route
|
|
||||||
"$UrlAttributes.URL_QUERY" queryString
|
|
||||||
"$HttpAttributes.HTTP_REQUEST_METHOD" "GET"
|
|
||||||
"$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200
|
|
||||||
"$UserAgentAttributes.USER_AGENT_ORIGINAL" String
|
|
||||||
"$HttpAttributes.HTTP_ROUTE" route
|
|
||||||
"$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1"
|
|
||||||
"$ServerAttributes.SERVER_ADDRESS" "localhost"
|
|
||||||
"$ServerAttributes.SERVER_PORT" port
|
|
||||||
"$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_PORT" Long
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(1) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Compile /getQuery.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.classFQCN" "org.apache.jsp.getQuery_jsp"
|
|
||||||
"jsp.compiler" "org.apache.jasper.compiler.JDTCompiler"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(2) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Render /getQuery.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.requestURL" "${baseUrl}/getQuery.jsp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res.status().code() == 200
|
|
||||||
}
|
|
||||||
|
|
||||||
def "non-erroneous POST"() {
|
|
||||||
setup:
|
|
||||||
RequestHeaders headers = RequestHeaders.builder(HttpMethod.POST, "/post.jsp")
|
|
||||||
.contentType(MediaType.FORM_DATA)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
when:
|
|
||||||
AggregatedHttpResponse res = client.execute(headers, "name=world").aggregate().join()
|
|
||||||
|
|
||||||
then:
|
|
||||||
assertTraces(1) {
|
|
||||||
trace(0, 3) {
|
|
||||||
span(0) {
|
|
||||||
def route = "/$jspWebappContext/post.jsp"
|
|
||||||
|
|
||||||
hasNoParent()
|
|
||||||
name "POST $route"
|
|
||||||
kind SERVER
|
|
||||||
attributes {
|
|
||||||
"$UrlAttributes.URL_SCHEME" "http"
|
|
||||||
"$UrlAttributes.URL_PATH" route
|
|
||||||
"$HttpAttributes.HTTP_REQUEST_METHOD" "POST"
|
|
||||||
"$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200
|
|
||||||
"$UserAgentAttributes.USER_AGENT_ORIGINAL" String
|
|
||||||
"$HttpAttributes.HTTP_ROUTE" route
|
|
||||||
"$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1"
|
|
||||||
"$ServerAttributes.SERVER_ADDRESS" "localhost"
|
|
||||||
"$ServerAttributes.SERVER_PORT" port
|
|
||||||
"$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1"
|
|
||||||
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_PORT" Long
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(1) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Compile /post.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.classFQCN" "org.apache.jsp.post_jsp"
|
|
||||||
"jsp.compiler" "org.apache.jasper.compiler.JDTCompiler"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(2) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Render /post.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.requestURL" "${baseUrl}/post.jsp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res.status().code() == 200
|
|
||||||
}
|
|
||||||
|
|
||||||
@Unroll
|
|
||||||
def "erroneous runtime errors GET jsp with #test test"() {
|
|
||||||
when:
|
|
||||||
AggregatedHttpResponse res = client.get("/${jspFileName}").aggregate().join()
|
|
||||||
|
|
||||||
then:
|
|
||||||
assertTraces(1) {
|
|
||||||
trace(0, 3) {
|
|
||||||
span(0) {
|
|
||||||
def route = "/$jspWebappContext/$jspFileName"
|
|
||||||
|
|
||||||
hasNoParent()
|
|
||||||
name "GET $route"
|
|
||||||
kind SERVER
|
|
||||||
status ERROR
|
|
||||||
event(0) {
|
|
||||||
eventName("exception")
|
|
||||||
attributes {
|
|
||||||
"$ExceptionAttributes.EXCEPTION_TYPE" { String tagExceptionType ->
|
|
||||||
return tagExceptionType == exceptionClass.getName() || tagExceptionType.contains(exceptionClass.getSimpleName())
|
|
||||||
}
|
|
||||||
"$ExceptionAttributes.EXCEPTION_MESSAGE" { String tagErrorMsg ->
|
|
||||||
return errorMessageOptional || tagErrorMsg instanceof String
|
|
||||||
}
|
|
||||||
"$ExceptionAttributes.EXCEPTION_STACKTRACE" String
|
|
||||||
}
|
|
||||||
}
|
|
||||||
attributes {
|
|
||||||
"$UrlAttributes.URL_SCHEME" "http"
|
|
||||||
"$UrlAttributes.URL_PATH" route
|
|
||||||
"$HttpAttributes.HTTP_REQUEST_METHOD" "GET"
|
|
||||||
"$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 500
|
|
||||||
"$UserAgentAttributes.USER_AGENT_ORIGINAL" String
|
|
||||||
"$HttpAttributes.HTTP_ROUTE" route
|
|
||||||
"$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1"
|
|
||||||
"$ServerAttributes.SERVER_ADDRESS" "localhost"
|
|
||||||
"$ServerAttributes.SERVER_PORT" port
|
|
||||||
"$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_PORT" Long
|
|
||||||
"$ErrorAttributes.ERROR_TYPE" "500"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(1) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Compile /$jspFileName"
|
|
||||||
attributes {
|
|
||||||
"jsp.classFQCN" "org.apache.jsp.$jspClassName"
|
|
||||||
"jsp.compiler" "org.apache.jasper.compiler.JDTCompiler"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(2) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Render /$jspFileName"
|
|
||||||
status ERROR
|
|
||||||
event(0) {
|
|
||||||
eventName("exception")
|
|
||||||
attributes {
|
|
||||||
"$ExceptionAttributes.EXCEPTION_TYPE" { String tagExceptionType ->
|
|
||||||
return tagExceptionType == exceptionClass.getName() || tagExceptionType.contains(exceptionClass.getSimpleName())
|
|
||||||
}
|
|
||||||
"$ExceptionAttributes.EXCEPTION_MESSAGE" { String tagErrorMsg ->
|
|
||||||
return errorMessageOptional || tagErrorMsg instanceof String
|
|
||||||
}
|
|
||||||
"$ExceptionAttributes.EXCEPTION_STACKTRACE" String
|
|
||||||
}
|
|
||||||
}
|
|
||||||
attributes {
|
|
||||||
"jsp.requestURL" "${baseUrl}/${jspFileName}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res.status().code() == 500
|
|
||||||
|
|
||||||
where:
|
|
||||||
test | jspFileName | jspClassName | exceptionClass | errorMessageOptional
|
|
||||||
"java runtime error" | "runtimeError.jsp" | "runtimeError_jsp" | ArithmeticException | false
|
|
||||||
"invalid write" | "invalidWrite.jsp" | "invalidWrite_jsp" | IndexOutOfBoundsException | true
|
|
||||||
"missing query gives null" | "getQuery.jsp" | "getQuery_jsp" | NullPointerException | true
|
|
||||||
}
|
|
||||||
|
|
||||||
def "non-erroneous include plain HTML GET"() {
|
|
||||||
when:
|
|
||||||
AggregatedHttpResponse res = client.get("/includes/includeHtml.jsp").aggregate().join()
|
|
||||||
|
|
||||||
then:
|
|
||||||
assertTraces(1) {
|
|
||||||
trace(0, 3) {
|
|
||||||
span(0) {
|
|
||||||
def route = "/$jspWebappContext/includes/includeHtml.jsp"
|
|
||||||
|
|
||||||
hasNoParent()
|
|
||||||
name "GET $route"
|
|
||||||
kind SERVER
|
|
||||||
attributes {
|
|
||||||
"$UrlAttributes.URL_SCHEME" "http"
|
|
||||||
"$UrlAttributes.URL_PATH" route
|
|
||||||
"$HttpAttributes.HTTP_REQUEST_METHOD" "GET"
|
|
||||||
"$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200
|
|
||||||
"$UserAgentAttributes.USER_AGENT_ORIGINAL" String
|
|
||||||
"$HttpAttributes.HTTP_ROUTE" route
|
|
||||||
"$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1"
|
|
||||||
"$ServerAttributes.SERVER_ADDRESS" "localhost"
|
|
||||||
"$ServerAttributes.SERVER_PORT" port
|
|
||||||
"$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_PORT" Long
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(1) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Compile /includes/includeHtml.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.classFQCN" "org.apache.jsp.includes.includeHtml_jsp"
|
|
||||||
"jsp.compiler" "org.apache.jasper.compiler.JDTCompiler"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(2) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Render /includes/includeHtml.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.requestURL" "${baseUrl}/includes/includeHtml.jsp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res.status().code() == 200
|
|
||||||
}
|
|
||||||
|
|
||||||
def "non-erroneous multi GET"() {
|
|
||||||
when:
|
|
||||||
AggregatedHttpResponse res = client.get("/includes/includeMulti.jsp").aggregate().join()
|
|
||||||
|
|
||||||
then:
|
|
||||||
assertTraces(1) {
|
|
||||||
trace(0, 7) {
|
|
||||||
span(0) {
|
|
||||||
def route = "/$jspWebappContext/includes/includeMulti.jsp"
|
|
||||||
|
|
||||||
hasNoParent()
|
|
||||||
name "GET $route"
|
|
||||||
kind SERVER
|
|
||||||
attributes {
|
|
||||||
"$UrlAttributes.URL_SCHEME" "http"
|
|
||||||
"$UrlAttributes.URL_PATH" route
|
|
||||||
"$HttpAttributes.HTTP_REQUEST_METHOD" "GET"
|
|
||||||
"$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200
|
|
||||||
"$UserAgentAttributes.USER_AGENT_ORIGINAL" String
|
|
||||||
"$HttpAttributes.HTTP_ROUTE" route
|
|
||||||
"$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1"
|
|
||||||
"$ServerAttributes.SERVER_ADDRESS" "localhost"
|
|
||||||
"$ServerAttributes.SERVER_PORT" port
|
|
||||||
"$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_PORT" Long
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(1) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Compile /includes/includeMulti.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.classFQCN" "org.apache.jsp.includes.includeMulti_jsp"
|
|
||||||
"jsp.compiler" "org.apache.jasper.compiler.JDTCompiler"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(2) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Render /includes/includeMulti.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.requestURL" "${baseUrl}/includes/includeMulti.jsp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(3) {
|
|
||||||
childOf span(2)
|
|
||||||
name "Compile /common/javaLoopH2.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.classFQCN" "org.apache.jsp.common.javaLoopH2_jsp"
|
|
||||||
"jsp.compiler" "org.apache.jasper.compiler.JDTCompiler"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(4) {
|
|
||||||
childOf span(2)
|
|
||||||
name "Render /common/javaLoopH2.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.requestURL" "${baseUrl}/includes/includeMulti.jsp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(5) {
|
|
||||||
childOf span(2)
|
|
||||||
name "Compile /common/javaLoopH2.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.classFQCN" "org.apache.jsp.common.javaLoopH2_jsp"
|
|
||||||
"jsp.compiler" "org.apache.jasper.compiler.JDTCompiler"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(6) {
|
|
||||||
childOf span(2)
|
|
||||||
name "Render /common/javaLoopH2.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.requestURL" "${baseUrl}/includes/includeMulti.jsp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res.status().code() == 200
|
|
||||||
}
|
|
||||||
|
|
||||||
def "#test compile error should not produce render traces and spans"() {
|
|
||||||
when:
|
|
||||||
AggregatedHttpResponse res = client.get("/${jspFileName}").aggregate().join()
|
|
||||||
|
|
||||||
then:
|
|
||||||
assertTraces(1) {
|
|
||||||
trace(0, 2) {
|
|
||||||
span(0) {
|
|
||||||
def route = "/$jspWebappContext/$jspFileName"
|
|
||||||
|
|
||||||
hasNoParent()
|
|
||||||
name "GET $route"
|
|
||||||
kind SERVER
|
|
||||||
status ERROR
|
|
||||||
errorEvent(JasperException, String)
|
|
||||||
attributes {
|
|
||||||
"$UrlAttributes.URL_SCHEME" "http"
|
|
||||||
"$UrlAttributes.URL_PATH" route
|
|
||||||
"$HttpAttributes.HTTP_REQUEST_METHOD" "GET"
|
|
||||||
"$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 500
|
|
||||||
"$UserAgentAttributes.USER_AGENT_ORIGINAL" String
|
|
||||||
"$HttpAttributes.HTTP_ROUTE" route
|
|
||||||
"$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1"
|
|
||||||
"$ServerAttributes.SERVER_ADDRESS" "localhost"
|
|
||||||
"$ServerAttributes.SERVER_PORT" port
|
|
||||||
"$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_PORT" Long
|
|
||||||
"$ErrorAttributes.ERROR_TYPE" "500"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(1) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Compile /$jspFileName"
|
|
||||||
status ERROR
|
|
||||||
errorEvent(JasperException, String)
|
|
||||||
attributes {
|
|
||||||
"jsp.classFQCN" "org.apache.jsp.$jspClassNamePrefix$jspClassName"
|
|
||||||
"jsp.compiler" "org.apache.jasper.compiler.JDTCompiler"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res.status().code() == 500
|
|
||||||
|
|
||||||
where:
|
|
||||||
test | jspFileName | jspClassName | jspClassNamePrefix
|
|
||||||
"normal" | "compileError.jsp" | "compileError_jsp" | ""
|
|
||||||
"forward" | "forwards/forwardWithCompileError.jsp" | "forwardWithCompileError_jsp" | "forwards."
|
|
||||||
}
|
|
||||||
|
|
||||||
def "direct static file reference"() {
|
|
||||||
when:
|
|
||||||
AggregatedHttpResponse res = client.get("/${staticFile}").aggregate().join()
|
|
||||||
|
|
||||||
then:
|
|
||||||
res.status().code() == 200
|
|
||||||
assertTraces(1) {
|
|
||||||
trace(0, 1) {
|
|
||||||
span(0) {
|
|
||||||
def route = "/$jspWebappContext/*"
|
|
||||||
|
|
||||||
hasNoParent()
|
|
||||||
name "GET $route"
|
|
||||||
kind SERVER
|
|
||||||
attributes {
|
|
||||||
"$UrlAttributes.URL_SCHEME" "http"
|
|
||||||
"$UrlAttributes.URL_PATH" "/$jspWebappContext/$staticFile"
|
|
||||||
"$HttpAttributes.HTTP_REQUEST_METHOD" "GET"
|
|
||||||
"$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200
|
|
||||||
"$UserAgentAttributes.USER_AGENT_ORIGINAL" String
|
|
||||||
"$HttpAttributes.HTTP_ROUTE" route
|
|
||||||
"$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1"
|
|
||||||
"$ServerAttributes.SERVER_ADDRESS" "localhost"
|
|
||||||
"$ServerAttributes.SERVER_PORT" port
|
|
||||||
"$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_PORT" Long
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
where:
|
|
||||||
staticFile = "common/hello.html"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,490 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright The OpenTelemetry Authors
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
|
|
||||||
import io.opentelemetry.instrumentation.test.utils.PortUtils
|
|
||||||
import io.opentelemetry.semconv.ServerAttributes
|
|
||||||
import io.opentelemetry.semconv.ClientAttributes
|
|
||||||
import io.opentelemetry.semconv.UserAgentAttributes
|
|
||||||
import io.opentelemetry.semconv.ErrorAttributes
|
|
||||||
import io.opentelemetry.semconv.HttpAttributes
|
|
||||||
import io.opentelemetry.semconv.NetworkAttributes
|
|
||||||
import io.opentelemetry.semconv.UrlAttributes
|
|
||||||
import io.opentelemetry.testing.internal.armeria.client.WebClient
|
|
||||||
import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse
|
|
||||||
import org.apache.catalina.Context
|
|
||||||
import org.apache.catalina.startup.Tomcat
|
|
||||||
import org.apache.jasper.JasperException
|
|
||||||
import spock.lang.Shared
|
|
||||||
import spock.lang.Unroll
|
|
||||||
|
|
||||||
import java.nio.file.Files
|
|
||||||
|
|
||||||
import static io.opentelemetry.api.trace.SpanKind.SERVER
|
|
||||||
import static io.opentelemetry.api.trace.StatusCode.ERROR
|
|
||||||
import static io.opentelemetry.api.trace.StatusCode.UNSET
|
|
||||||
|
|
||||||
class JspInstrumentationForwardTests extends AgentInstrumentationSpecification {
|
|
||||||
|
|
||||||
@Shared
|
|
||||||
int port
|
|
||||||
@Shared
|
|
||||||
Tomcat tomcatServer
|
|
||||||
@Shared
|
|
||||||
Context appContext
|
|
||||||
@Shared
|
|
||||||
String jspWebappContext = "jsptest-context"
|
|
||||||
|
|
||||||
@Shared
|
|
||||||
File baseDir
|
|
||||||
@Shared
|
|
||||||
String baseUrl
|
|
||||||
|
|
||||||
@Shared
|
|
||||||
WebClient client
|
|
||||||
|
|
||||||
def setupSpec() {
|
|
||||||
baseDir = Files.createTempDirectory("jsp").toFile()
|
|
||||||
baseDir.deleteOnExit()
|
|
||||||
|
|
||||||
port = PortUtils.findOpenPort()
|
|
||||||
|
|
||||||
tomcatServer = new Tomcat()
|
|
||||||
tomcatServer.setBaseDir(baseDir.getAbsolutePath())
|
|
||||||
tomcatServer.setPort(port)
|
|
||||||
tomcatServer.getConnector()
|
|
||||||
// comment to debug
|
|
||||||
tomcatServer.setSilent(true)
|
|
||||||
// this is needed in tomcat 9, this triggers the creation of a connector, will not
|
|
||||||
// affect tomcat 7 and 8
|
|
||||||
// https://stackoverflow.com/questions/48998387/code-works-with-embedded-apache-tomcat-8-but-not-with-9-whats-changed
|
|
||||||
tomcatServer.getConnector()
|
|
||||||
|
|
||||||
baseUrl = "http://localhost:$port/$jspWebappContext"
|
|
||||||
client = WebClient.of(baseUrl)
|
|
||||||
|
|
||||||
appContext = tomcatServer.addWebapp("/$jspWebappContext",
|
|
||||||
JspInstrumentationForwardTests.getResource("/webapps/jsptest").getPath())
|
|
||||||
|
|
||||||
tomcatServer.start()
|
|
||||||
System.out.println(
|
|
||||||
"Tomcat server: http://" + tomcatServer.getHost().getName() + ":" + port + "/")
|
|
||||||
}
|
|
||||||
|
|
||||||
def cleanupSpec() {
|
|
||||||
tomcatServer.stop()
|
|
||||||
tomcatServer.destroy()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Unroll
|
|
||||||
def "non-erroneous GET forward to #forwardTo"() {
|
|
||||||
when:
|
|
||||||
AggregatedHttpResponse res = client.get("/$forwardFromFileName").aggregate().join()
|
|
||||||
|
|
||||||
then:
|
|
||||||
assertTraces(1) {
|
|
||||||
trace(0, 5) {
|
|
||||||
span(0) {
|
|
||||||
def route = "/$jspWebappContext/$forwardFromFileName"
|
|
||||||
|
|
||||||
hasNoParent()
|
|
||||||
name "GET $route"
|
|
||||||
kind SERVER
|
|
||||||
attributes {
|
|
||||||
"$UrlAttributes.URL_SCHEME" "http"
|
|
||||||
"$UrlAttributes.URL_PATH" route
|
|
||||||
"$HttpAttributes.HTTP_REQUEST_METHOD" "GET"
|
|
||||||
"$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200
|
|
||||||
"$UserAgentAttributes.USER_AGENT_ORIGINAL" String
|
|
||||||
"$HttpAttributes.HTTP_ROUTE" route
|
|
||||||
"$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1"
|
|
||||||
"$ServerAttributes.SERVER_ADDRESS" "localhost"
|
|
||||||
"$ServerAttributes.SERVER_PORT" port
|
|
||||||
"$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_PORT" Long
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(1) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Compile /$forwardFromFileName"
|
|
||||||
attributes {
|
|
||||||
"jsp.classFQCN" "org.apache.jsp.$jspForwardFromClassPrefix$jspForwardFromClassName"
|
|
||||||
"jsp.compiler" "org.apache.jasper.compiler.JDTCompiler"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(2) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Render /$forwardFromFileName"
|
|
||||||
attributes {
|
|
||||||
"jsp.requestURL" "${baseUrl}/$forwardFromFileName"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(3) {
|
|
||||||
childOf span(2)
|
|
||||||
name "Compile /$forwardDestFileName"
|
|
||||||
attributes {
|
|
||||||
"jsp.classFQCN" "org.apache.jsp.$jspForwardDestClassPrefix$jspForwardDestClassName"
|
|
||||||
"jsp.compiler" "org.apache.jasper.compiler.JDTCompiler"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(4) {
|
|
||||||
childOf span(2)
|
|
||||||
name "Render /$forwardDestFileName"
|
|
||||||
attributes {
|
|
||||||
"jsp.forwardOrigin" "/$forwardFromFileName"
|
|
||||||
"jsp.requestURL" "${baseUrl}/$forwardDestFileName"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res.status().code() == 200
|
|
||||||
|
|
||||||
where:
|
|
||||||
forwardTo | forwardFromFileName | forwardDestFileName | jspForwardFromClassName | jspForwardFromClassPrefix | jspForwardDestClassName | jspForwardDestClassPrefix
|
|
||||||
"no java jsp" | "forwards/forwardToNoJavaJsp.jsp" | "nojava.jsp" | "forwardToNoJavaJsp_jsp" | "forwards." | "nojava_jsp" | ""
|
|
||||||
"normal java jsp" | "forwards/forwardToSimpleJava.jsp" | "common/loop.jsp" | "forwardToSimpleJava_jsp" | "forwards." | "loop_jsp" | "common."
|
|
||||||
}
|
|
||||||
|
|
||||||
def "non-erroneous GET forward to plain HTML"() {
|
|
||||||
when:
|
|
||||||
AggregatedHttpResponse res = client.get("/forwards/forwardToHtml.jsp").aggregate().join()
|
|
||||||
|
|
||||||
then:
|
|
||||||
assertTraces(1) {
|
|
||||||
trace(0, 3) {
|
|
||||||
span(0) {
|
|
||||||
def route = "/$jspWebappContext/forwards/forwardToHtml.jsp"
|
|
||||||
|
|
||||||
hasNoParent()
|
|
||||||
name "GET $route"
|
|
||||||
kind SERVER
|
|
||||||
attributes {
|
|
||||||
"$UrlAttributes.URL_SCHEME" "http"
|
|
||||||
"$UrlAttributes.URL_PATH" route
|
|
||||||
"$HttpAttributes.HTTP_REQUEST_METHOD" "GET"
|
|
||||||
"$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200
|
|
||||||
"$UserAgentAttributes.USER_AGENT_ORIGINAL" String
|
|
||||||
"$HttpAttributes.HTTP_ROUTE" route
|
|
||||||
"$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1"
|
|
||||||
"$ServerAttributes.SERVER_ADDRESS" "localhost"
|
|
||||||
"$ServerAttributes.SERVER_PORT" port
|
|
||||||
"$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_PORT" Long
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(1) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Compile /forwards/forwardToHtml.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.classFQCN" "org.apache.jsp.forwards.forwardToHtml_jsp"
|
|
||||||
"jsp.compiler" "org.apache.jasper.compiler.JDTCompiler"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(2) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Render /forwards/forwardToHtml.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.requestURL" "${baseUrl}/forwards/forwardToHtml.jsp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res.status().code() == 200
|
|
||||||
}
|
|
||||||
|
|
||||||
def "non-erroneous GET forwarded to jsp with multiple includes"() {
|
|
||||||
when:
|
|
||||||
AggregatedHttpResponse res = client.get("/forwards/forwardToIncludeMulti.jsp").aggregate().join()
|
|
||||||
|
|
||||||
then:
|
|
||||||
assertTraces(1) {
|
|
||||||
trace(0, 9) {
|
|
||||||
span(0) {
|
|
||||||
def route = "/$jspWebappContext/forwards/forwardToIncludeMulti.jsp"
|
|
||||||
|
|
||||||
hasNoParent()
|
|
||||||
name "GET $route"
|
|
||||||
kind SERVER
|
|
||||||
attributes {
|
|
||||||
"$UrlAttributes.URL_SCHEME" "http"
|
|
||||||
"$UrlAttributes.URL_PATH" route
|
|
||||||
"$HttpAttributes.HTTP_REQUEST_METHOD" "GET"
|
|
||||||
"$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200
|
|
||||||
"$UserAgentAttributes.USER_AGENT_ORIGINAL" String
|
|
||||||
"$HttpAttributes.HTTP_ROUTE" route
|
|
||||||
"$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1"
|
|
||||||
"$ServerAttributes.SERVER_ADDRESS" "localhost"
|
|
||||||
"$ServerAttributes.SERVER_PORT" port
|
|
||||||
"$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_PORT" Long
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(1) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Compile /forwards/forwardToIncludeMulti.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.classFQCN" "org.apache.jsp.forwards.forwardToIncludeMulti_jsp"
|
|
||||||
"jsp.compiler" "org.apache.jasper.compiler.JDTCompiler"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(2) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Render /forwards/forwardToIncludeMulti.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.requestURL" "${baseUrl}/forwards/forwardToIncludeMulti.jsp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(3) {
|
|
||||||
childOf span(2)
|
|
||||||
name "Compile /includes/includeMulti.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.classFQCN" "org.apache.jsp.includes.includeMulti_jsp"
|
|
||||||
"jsp.compiler" "org.apache.jasper.compiler.JDTCompiler"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(4) {
|
|
||||||
childOf span(2)
|
|
||||||
name "Render /includes/includeMulti.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.forwardOrigin" "/forwards/forwardToIncludeMulti.jsp"
|
|
||||||
"jsp.requestURL" "${baseUrl}/includes/includeMulti.jsp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(5) {
|
|
||||||
childOf span(4)
|
|
||||||
name "Compile /common/javaLoopH2.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.classFQCN" "org.apache.jsp.common.javaLoopH2_jsp"
|
|
||||||
"jsp.compiler" "org.apache.jasper.compiler.JDTCompiler"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(6) {
|
|
||||||
childOf span(4)
|
|
||||||
name "Render /common/javaLoopH2.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.forwardOrigin" "/forwards/forwardToIncludeMulti.jsp"
|
|
||||||
"jsp.requestURL" "${baseUrl}/includes/includeMulti.jsp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(7) {
|
|
||||||
childOf span(4)
|
|
||||||
name "Compile /common/javaLoopH2.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.classFQCN" "org.apache.jsp.common.javaLoopH2_jsp"
|
|
||||||
"jsp.compiler" "org.apache.jasper.compiler.JDTCompiler"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(8) {
|
|
||||||
childOf span(4)
|
|
||||||
name "Render /common/javaLoopH2.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.forwardOrigin" "/forwards/forwardToIncludeMulti.jsp"
|
|
||||||
"jsp.requestURL" "${baseUrl}/includes/includeMulti.jsp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res.status().code() == 200
|
|
||||||
}
|
|
||||||
|
|
||||||
def "non-erroneous GET forward to another forward (2 forwards)"() {
|
|
||||||
when:
|
|
||||||
AggregatedHttpResponse res = client.get("/forwards/forwardToJspForward.jsp").aggregate().join()
|
|
||||||
|
|
||||||
then:
|
|
||||||
assertTraces(1) {
|
|
||||||
trace(0, 7) {
|
|
||||||
span(0) {
|
|
||||||
def route = "/$jspWebappContext/forwards/forwardToJspForward.jsp"
|
|
||||||
|
|
||||||
hasNoParent()
|
|
||||||
name "GET $route"
|
|
||||||
kind SERVER
|
|
||||||
attributes {
|
|
||||||
"$UrlAttributes.URL_SCHEME" "http"
|
|
||||||
"$UrlAttributes.URL_PATH" route
|
|
||||||
"$HttpAttributes.HTTP_REQUEST_METHOD" "GET"
|
|
||||||
"$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200
|
|
||||||
"$UserAgentAttributes.USER_AGENT_ORIGINAL" String
|
|
||||||
"$HttpAttributes.HTTP_ROUTE" route
|
|
||||||
"$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1"
|
|
||||||
"$ServerAttributes.SERVER_ADDRESS" "localhost"
|
|
||||||
"$ServerAttributes.SERVER_PORT" port
|
|
||||||
"$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_PORT" Long
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(1) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Compile /forwards/forwardToJspForward.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.classFQCN" "org.apache.jsp.forwards.forwardToJspForward_jsp"
|
|
||||||
"jsp.compiler" "org.apache.jasper.compiler.JDTCompiler"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(2) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Render /forwards/forwardToJspForward.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.requestURL" "${baseUrl}/forwards/forwardToJspForward.jsp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(3) {
|
|
||||||
childOf span(2)
|
|
||||||
name "Compile /forwards/forwardToSimpleJava.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.classFQCN" "org.apache.jsp.forwards.forwardToSimpleJava_jsp"
|
|
||||||
"jsp.compiler" "org.apache.jasper.compiler.JDTCompiler"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(4) {
|
|
||||||
childOf span(2)
|
|
||||||
name "Render /forwards/forwardToSimpleJava.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.forwardOrigin" "/forwards/forwardToJspForward.jsp"
|
|
||||||
"jsp.requestURL" "${baseUrl}/forwards/forwardToSimpleJava.jsp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(5) {
|
|
||||||
childOf span(4)
|
|
||||||
name "Compile /common/loop.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.classFQCN" "org.apache.jsp.common.loop_jsp"
|
|
||||||
"jsp.compiler" "org.apache.jasper.compiler.JDTCompiler"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(6) {
|
|
||||||
childOf span(4)
|
|
||||||
name "Render /common/loop.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.forwardOrigin" "/forwards/forwardToJspForward.jsp"
|
|
||||||
"jsp.requestURL" "${baseUrl}/common/loop.jsp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res.status().code() == 200
|
|
||||||
}
|
|
||||||
|
|
||||||
def "forward to jsp with compile error should not produce a 2nd render span"() {
|
|
||||||
when:
|
|
||||||
AggregatedHttpResponse res = client.get("/forwards/forwardToCompileError.jsp").aggregate().join()
|
|
||||||
|
|
||||||
then:
|
|
||||||
assertTraces(1) {
|
|
||||||
trace(0, 4) {
|
|
||||||
span(0) {
|
|
||||||
def route = "/$jspWebappContext/forwards/forwardToCompileError.jsp"
|
|
||||||
|
|
||||||
hasNoParent()
|
|
||||||
name "GET $route"
|
|
||||||
kind SERVER
|
|
||||||
status ERROR
|
|
||||||
errorEvent(JasperException, String)
|
|
||||||
attributes {
|
|
||||||
"$UrlAttributes.URL_SCHEME" "http"
|
|
||||||
"$UrlAttributes.URL_PATH" route
|
|
||||||
"$HttpAttributes.HTTP_REQUEST_METHOD" "GET"
|
|
||||||
"$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 500
|
|
||||||
"$UserAgentAttributes.USER_AGENT_ORIGINAL" String
|
|
||||||
"$HttpAttributes.HTTP_ROUTE" route
|
|
||||||
"$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1"
|
|
||||||
"$ServerAttributes.SERVER_ADDRESS" "localhost"
|
|
||||||
"$ServerAttributes.SERVER_PORT" port
|
|
||||||
"$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_PORT" Long
|
|
||||||
"$ErrorAttributes.ERROR_TYPE" "500"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(1) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Compile /forwards/forwardToCompileError.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.classFQCN" "org.apache.jsp.forwards.forwardToCompileError_jsp"
|
|
||||||
"jsp.compiler" "org.apache.jasper.compiler.JDTCompiler"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(2) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Render /forwards/forwardToCompileError.jsp"
|
|
||||||
status ERROR
|
|
||||||
errorEvent(JasperException, String)
|
|
||||||
attributes {
|
|
||||||
"jsp.requestURL" "${baseUrl}/forwards/forwardToCompileError.jsp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(3) {
|
|
||||||
childOf span(2)
|
|
||||||
name "Compile /compileError.jsp"
|
|
||||||
status ERROR
|
|
||||||
errorEvent(JasperException, String)
|
|
||||||
attributes {
|
|
||||||
"jsp.classFQCN" "org.apache.jsp.compileError_jsp"
|
|
||||||
"jsp.compiler" "org.apache.jasper.compiler.JDTCompiler"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res.status().code() == 500
|
|
||||||
}
|
|
||||||
|
|
||||||
def "forward to non existent jsp should be 404"() {
|
|
||||||
when:
|
|
||||||
AggregatedHttpResponse res = client.get("/forwards/forwardToNonExistent.jsp").aggregate().join()
|
|
||||||
|
|
||||||
then:
|
|
||||||
assertTraces(1) {
|
|
||||||
trace(0, 4) {
|
|
||||||
span(0) {
|
|
||||||
def route = "/$jspWebappContext/forwards/forwardToNonExistent.jsp"
|
|
||||||
|
|
||||||
hasNoParent()
|
|
||||||
name "GET $route"
|
|
||||||
kind SERVER
|
|
||||||
status UNSET
|
|
||||||
attributes {
|
|
||||||
"$UrlAttributes.URL_SCHEME" "http"
|
|
||||||
"$UrlAttributes.URL_PATH" route
|
|
||||||
"$HttpAttributes.HTTP_REQUEST_METHOD" "GET"
|
|
||||||
"$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 404
|
|
||||||
"$UserAgentAttributes.USER_AGENT_ORIGINAL" String
|
|
||||||
"$HttpAttributes.HTTP_ROUTE" route
|
|
||||||
"$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1"
|
|
||||||
"$ServerAttributes.SERVER_ADDRESS" "localhost"
|
|
||||||
"$ServerAttributes.SERVER_PORT" port
|
|
||||||
"$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1"
|
|
||||||
"$NetworkAttributes.NETWORK_PEER_PORT" Long
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(1) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Compile /forwards/forwardToNonExistent.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.classFQCN" "org.apache.jsp.forwards.forwardToNonExistent_jsp"
|
|
||||||
"jsp.compiler" "org.apache.jasper.compiler.JDTCompiler"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(2) {
|
|
||||||
childOf span(0)
|
|
||||||
name "Render /forwards/forwardToNonExistent.jsp"
|
|
||||||
attributes {
|
|
||||||
"jsp.requestURL" "${baseUrl}/forwards/forwardToNonExistent.jsp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span(3) {
|
|
||||||
childOf span(2)
|
|
||||||
name "ResponseFacade.sendError"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res.status().code() == 404
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,488 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.jsp;
|
||||||
|
|
||||||
|
import static io.opentelemetry.api.common.AttributeKey.stringKey;
|
||||||
|
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
|
||||||
|
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
|
|
||||||
|
import io.opentelemetry.api.trace.SpanKind;
|
||||||
|
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
|
||||||
|
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerUsingTest;
|
||||||
|
import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension;
|
||||||
|
import io.opentelemetry.sdk.trace.data.StatusData;
|
||||||
|
import io.opentelemetry.semconv.ClientAttributes;
|
||||||
|
import io.opentelemetry.semconv.ExceptionAttributes;
|
||||||
|
import io.opentelemetry.semconv.HttpAttributes;
|
||||||
|
import io.opentelemetry.semconv.NetworkAttributes;
|
||||||
|
import io.opentelemetry.semconv.ServerAttributes;
|
||||||
|
import io.opentelemetry.semconv.UrlAttributes;
|
||||||
|
import io.opentelemetry.semconv.UserAgentAttributes;
|
||||||
|
import io.opentelemetry.testing.internal.armeria.client.WebClient;
|
||||||
|
import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse;
|
||||||
|
import io.opentelemetry.testing.internal.armeria.common.HttpMethod;
|
||||||
|
import io.opentelemetry.testing.internal.armeria.common.MediaType;
|
||||||
|
import io.opentelemetry.testing.internal.armeria.common.RequestHeaders;
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import org.apache.catalina.startup.Tomcat;
|
||||||
|
import org.apache.jasper.JasperException;
|
||||||
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
|
import org.junit.jupiter.params.provider.ArgumentsProvider;
|
||||||
|
import org.junit.jupiter.params.provider.ArgumentsSource;
|
||||||
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
|
|
||||||
|
class JspInstrumentationBasicTests extends AbstractHttpServerUsingTest<Tomcat> {
|
||||||
|
|
||||||
|
@RegisterExtension
|
||||||
|
public static final InstrumentationExtension testing =
|
||||||
|
HttpServerInstrumentationExtension.forAgent();
|
||||||
|
|
||||||
|
private static JspSpanAssertions spanAsserts;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Tomcat setupServer() throws Exception {
|
||||||
|
File baseDir = Files.createTempDirectory("jsp").toFile();
|
||||||
|
baseDir.deleteOnExit();
|
||||||
|
|
||||||
|
Tomcat tomcatServer = new Tomcat();
|
||||||
|
tomcatServer.setBaseDir(baseDir.getAbsolutePath());
|
||||||
|
tomcatServer.setPort(port);
|
||||||
|
tomcatServer.getConnector();
|
||||||
|
|
||||||
|
// comment to debug
|
||||||
|
tomcatServer.setSilent(true);
|
||||||
|
|
||||||
|
// this is needed in tomcat 9, this triggers the creation of a connector, will not
|
||||||
|
// affect tomcat 7 and 8
|
||||||
|
// https://stackoverflow.com/questions/48998387/code-works-with-embedded-apache-tomcat-8-but-not-with-9-whats-changed
|
||||||
|
tomcatServer.getConnector();
|
||||||
|
|
||||||
|
String baseUrl = "http://localhost:" + port + "/" + getContextPath();
|
||||||
|
spanAsserts = new JspSpanAssertions(baseUrl, port);
|
||||||
|
client = WebClient.of(baseUrl);
|
||||||
|
|
||||||
|
tomcatServer.addWebapp(
|
||||||
|
"/" + getContextPath(),
|
||||||
|
JspInstrumentationBasicTests.class.getResource("/webapps/jsptest").getPath());
|
||||||
|
|
||||||
|
tomcatServer.start();
|
||||||
|
return tomcatServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void stopServer(Tomcat tomcat) throws Exception {
|
||||||
|
tomcat.stop();
|
||||||
|
tomcat.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getContextPath() {
|
||||||
|
return "jsptest-context";
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
protected void setUp() {
|
||||||
|
startServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
protected void cleanUp() {
|
||||||
|
cleanupServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest(name = "GET {0}")
|
||||||
|
@ArgumentsSource(NonErroneousArgs.class)
|
||||||
|
void testNonErroneousGet(
|
||||||
|
String testName, String jspFileName, String jspClassName, String jspClassNamePrefix) {
|
||||||
|
AggregatedHttpResponse res = client.get(jspFileName).aggregate().join();
|
||||||
|
assertThat(res.status().code()).isEqualTo(200);
|
||||||
|
|
||||||
|
testing.waitAndAssertTraces(
|
||||||
|
trace ->
|
||||||
|
trace.hasSpansSatisfyingExactly(
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertServerSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withMethod("GET")
|
||||||
|
.withRoute("/" + getContextPath() + jspFileName)
|
||||||
|
.withResponseStatus(200)
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertCompileSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(0))
|
||||||
|
.withRoute(jspFileName)
|
||||||
|
.withClassName(jspClassNamePrefix + jspClassName)
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertRenderSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(0))
|
||||||
|
.withRoute(jspFileName)
|
||||||
|
.build())));
|
||||||
|
}
|
||||||
|
|
||||||
|
static class NonErroneousArgs implements ArgumentsProvider {
|
||||||
|
@Override
|
||||||
|
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
|
||||||
|
return Stream.of(
|
||||||
|
Arguments.of("no java jsp", "/nojava.jsp", "nojava_jsp", ""),
|
||||||
|
Arguments.of("basic loop jsp", "/common/loop.jsp", "loop_jsp", "common."),
|
||||||
|
Arguments.of("invalid HTML markup", "/invalidMarkup.jsp", "invalidMarkup_jsp", ""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testNonErroneousGetWithQueryString() {
|
||||||
|
String queryString = "HELLO";
|
||||||
|
String route = "/" + getContextPath() + "/getQuery.jsp";
|
||||||
|
|
||||||
|
AggregatedHttpResponse res = client.get("/getQuery.jsp?" + queryString).aggregate().join();
|
||||||
|
assertThat(res.status().code()).isEqualTo(200);
|
||||||
|
|
||||||
|
testing.waitAndAssertTraces(
|
||||||
|
trace ->
|
||||||
|
trace.hasSpansSatisfyingExactly(
|
||||||
|
span ->
|
||||||
|
span.hasName("GET " + route)
|
||||||
|
.hasNoParent()
|
||||||
|
.hasKind(SpanKind.SERVER)
|
||||||
|
.hasAttributesSatisfyingExactly(
|
||||||
|
equalTo(UrlAttributes.URL_SCHEME, "http"),
|
||||||
|
equalTo(UrlAttributes.URL_PATH, route),
|
||||||
|
equalTo(UrlAttributes.URL_QUERY, queryString),
|
||||||
|
equalTo(HttpAttributes.HTTP_REQUEST_METHOD, "GET"),
|
||||||
|
equalTo(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 200),
|
||||||
|
satisfies(
|
||||||
|
UserAgentAttributes.USER_AGENT_ORIGINAL,
|
||||||
|
val -> val.isInstanceOf(String.class)),
|
||||||
|
equalTo(HttpAttributes.HTTP_ROUTE, route),
|
||||||
|
equalTo(NetworkAttributes.NETWORK_PROTOCOL_VERSION, "1.1"),
|
||||||
|
equalTo(ServerAttributes.SERVER_ADDRESS, "localhost"),
|
||||||
|
equalTo(ServerAttributes.SERVER_PORT, port),
|
||||||
|
equalTo(ClientAttributes.CLIENT_ADDRESS, "127.0.0.1"),
|
||||||
|
equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, "127.0.0.1"),
|
||||||
|
satisfies(
|
||||||
|
NetworkAttributes.NETWORK_PEER_PORT,
|
||||||
|
val -> val.isInstanceOf(Long.class))),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertCompileSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(0))
|
||||||
|
.withRoute("/getQuery.jsp")
|
||||||
|
.withClassName("getQuery_jsp")
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertRenderSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(0))
|
||||||
|
.withRoute("/getQuery.jsp")
|
||||||
|
.build())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testNonErroneousPost() {
|
||||||
|
RequestHeaders headers =
|
||||||
|
RequestHeaders.builder(HttpMethod.POST, "/post.jsp")
|
||||||
|
.contentType(MediaType.FORM_DATA)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
AggregatedHttpResponse res = client.execute(headers, "name=world").aggregate().join();
|
||||||
|
assertThat(res.status().code()).isEqualTo(200);
|
||||||
|
|
||||||
|
testing.waitAndAssertTraces(
|
||||||
|
trace ->
|
||||||
|
trace.hasSpansSatisfyingExactly(
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertServerSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withMethod("POST")
|
||||||
|
.withRoute("/" + getContextPath() + "/post.jsp")
|
||||||
|
.withResponseStatus(200)
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertCompileSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(0))
|
||||||
|
.withRoute("/post.jsp")
|
||||||
|
.withClassName("post_jsp")
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertRenderSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(0))
|
||||||
|
.withRoute("/post.jsp")
|
||||||
|
.build())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest(name = "GET jsp with {0}")
|
||||||
|
@ArgumentsSource(ErroneousRuntimeErrorsArgs.class)
|
||||||
|
void testErroneousRuntimeErrorsGet(
|
||||||
|
String testName,
|
||||||
|
String jspFileName,
|
||||||
|
String jspClassName,
|
||||||
|
Class<?> exceptionClass,
|
||||||
|
boolean errorMessageOptional) {
|
||||||
|
AggregatedHttpResponse res = client.get(jspFileName).aggregate().join();
|
||||||
|
assertThat(res.status().code()).isEqualTo(500);
|
||||||
|
|
||||||
|
testing.waitAndAssertTraces(
|
||||||
|
trace ->
|
||||||
|
trace.hasSpansSatisfyingExactly(
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertServerSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withMethod("GET")
|
||||||
|
.withRoute("/" + getContextPath() + jspFileName)
|
||||||
|
.withResponseStatus(500)
|
||||||
|
.withExceptionClass(exceptionClass)
|
||||||
|
.withErrorMessageOptional(errorMessageOptional)
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertCompileSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(0))
|
||||||
|
.withRoute(jspFileName)
|
||||||
|
.withClassName(jspClassName)
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertRenderSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(0))
|
||||||
|
.withRoute(jspFileName)
|
||||||
|
.withErrorMessageOptional(errorMessageOptional)
|
||||||
|
.build())));
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ErroneousRuntimeErrorsArgs implements ArgumentsProvider {
|
||||||
|
@Override
|
||||||
|
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
|
||||||
|
return Stream.of(
|
||||||
|
Arguments.of(
|
||||||
|
"java runtime error",
|
||||||
|
"/runtimeError.jsp",
|
||||||
|
"runtimeError_jsp",
|
||||||
|
ArithmeticException.class,
|
||||||
|
false),
|
||||||
|
Arguments.of(
|
||||||
|
"invalid write",
|
||||||
|
"/invalidWrite.jsp",
|
||||||
|
"invalidWrite_jsp",
|
||||||
|
IndexOutOfBoundsException.class,
|
||||||
|
true),
|
||||||
|
Arguments.of(
|
||||||
|
"invalid write", "/getQuery.jsp", "getQuery_jsp", NullPointerException.class, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testNonErroneousIncludePlainHtmlGet() {
|
||||||
|
AggregatedHttpResponse res = client.get("/includes/includeHtml.jsp").aggregate().join();
|
||||||
|
assertThat(res.status().code()).isEqualTo(200);
|
||||||
|
|
||||||
|
testing.waitAndAssertTraces(
|
||||||
|
trace ->
|
||||||
|
trace.hasSpansSatisfyingExactly(
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertServerSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withMethod("GET")
|
||||||
|
.withRoute("/" + getContextPath() + "/includes/includeHtml.jsp")
|
||||||
|
.withResponseStatus(200)
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertCompileSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(0))
|
||||||
|
.withRoute("/includes/includeHtml.jsp")
|
||||||
|
.withClassName("includes.includeHtml_jsp")
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertRenderSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(0))
|
||||||
|
.withRoute("/includes/includeHtml.jsp")
|
||||||
|
.build())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testNonErroneousMultiGet() {
|
||||||
|
AggregatedHttpResponse res = client.get("/includes/includeMulti.jsp").aggregate().join();
|
||||||
|
assertThat(res.status().code()).isEqualTo(200);
|
||||||
|
|
||||||
|
testing.waitAndAssertTraces(
|
||||||
|
trace ->
|
||||||
|
trace.hasSpansSatisfyingExactly(
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertServerSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withMethod("GET")
|
||||||
|
.withRoute("/" + getContextPath() + "/includes/includeMulti.jsp")
|
||||||
|
.withResponseStatus(200)
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertCompileSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(0))
|
||||||
|
.withRoute("/includes/includeMulti.jsp")
|
||||||
|
.withClassName("includes.includeMulti_jsp")
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertRenderSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(0))
|
||||||
|
.withRoute("/includes/includeMulti.jsp")
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertCompileSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(2))
|
||||||
|
.withRoute("/common/javaLoopH2.jsp")
|
||||||
|
.withClassName("common.javaLoopH2_jsp")
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertRenderSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(2))
|
||||||
|
.withRoute("/common/javaLoopH2.jsp")
|
||||||
|
.withRequestUrlOverride("/includes/includeMulti.jsp")
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertCompileSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(2))
|
||||||
|
.withRoute("/common/javaLoopH2.jsp")
|
||||||
|
.withClassName("common.javaLoopH2_jsp")
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertRenderSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(2))
|
||||||
|
.withRoute("/common/javaLoopH2.jsp")
|
||||||
|
.withRequestUrlOverride("/includes/includeMulti.jsp")
|
||||||
|
.build())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ArgumentsSource(CompileErrorsArgs.class)
|
||||||
|
void testCompileErrorShouldNotProduceRenderTracesAndSpans(
|
||||||
|
String jspFileName, String jspClassName, String jspClassNamePrefix) {
|
||||||
|
AggregatedHttpResponse res = client.get(jspFileName).aggregate().join();
|
||||||
|
assertThat(res.status().code()).isEqualTo(500);
|
||||||
|
|
||||||
|
testing.waitAndAssertTraces(
|
||||||
|
trace ->
|
||||||
|
trace.hasSpansSatisfyingExactly(
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertServerSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withMethod("GET")
|
||||||
|
.withRoute("/" + getContextPath() + jspFileName)
|
||||||
|
.withResponseStatus(500)
|
||||||
|
.withExceptionClass(JasperException.class)
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
span.hasName("Compile " + jspFileName)
|
||||||
|
.hasParent(trace.getSpan(0))
|
||||||
|
.hasStatus(StatusData.error())
|
||||||
|
.hasEventsSatisfyingExactly(
|
||||||
|
event ->
|
||||||
|
event
|
||||||
|
.hasName("exception")
|
||||||
|
.hasAttributesSatisfyingExactly(
|
||||||
|
equalTo(
|
||||||
|
ExceptionAttributes.EXCEPTION_TYPE,
|
||||||
|
JasperException.class.getCanonicalName()),
|
||||||
|
satisfies(
|
||||||
|
ExceptionAttributes.EXCEPTION_STACKTRACE,
|
||||||
|
val -> val.isInstanceOf(String.class)),
|
||||||
|
satisfies(
|
||||||
|
ExceptionAttributes.EXCEPTION_MESSAGE,
|
||||||
|
val -> val.isInstanceOf(String.class))))
|
||||||
|
.hasAttributesSatisfyingExactly(
|
||||||
|
equalTo(
|
||||||
|
stringKey("jsp.classFQCN"),
|
||||||
|
"org.apache.jsp." + jspClassNamePrefix + jspClassName),
|
||||||
|
equalTo(
|
||||||
|
stringKey("jsp.compiler"),
|
||||||
|
"org.apache.jasper.compiler.JDTCompiler"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
static class CompileErrorsArgs implements ArgumentsProvider {
|
||||||
|
@Override
|
||||||
|
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
|
||||||
|
return Stream.of(
|
||||||
|
Arguments.of("/compileError.jsp", "compileError_jsp", ""),
|
||||||
|
Arguments.of(
|
||||||
|
"/forwards/forwardWithCompileError.jsp", "forwardWithCompileError_jsp", "forwards."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(strings = {"/common/hello.html"})
|
||||||
|
void testDirectStaticFileReference(String staticFile) {
|
||||||
|
String route = "/" + getContextPath() + "/*";
|
||||||
|
|
||||||
|
AggregatedHttpResponse res = client.get(staticFile).aggregate().join();
|
||||||
|
assertThat(res.status().code()).isEqualTo(200);
|
||||||
|
|
||||||
|
testing.waitAndAssertTraces(
|
||||||
|
trace ->
|
||||||
|
trace.hasSpansSatisfyingExactly(
|
||||||
|
span ->
|
||||||
|
span.hasName("GET " + route)
|
||||||
|
.hasNoParent()
|
||||||
|
.hasKind(SpanKind.SERVER)
|
||||||
|
.hasAttributesSatisfyingExactly(
|
||||||
|
equalTo(UrlAttributes.URL_SCHEME, "http"),
|
||||||
|
equalTo(UrlAttributes.URL_PATH, "/" + getContextPath() + staticFile),
|
||||||
|
equalTo(HttpAttributes.HTTP_REQUEST_METHOD, "GET"),
|
||||||
|
equalTo(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 200),
|
||||||
|
satisfies(
|
||||||
|
UserAgentAttributes.USER_AGENT_ORIGINAL,
|
||||||
|
val -> val.isInstanceOf(String.class)),
|
||||||
|
equalTo(HttpAttributes.HTTP_ROUTE, route),
|
||||||
|
equalTo(NetworkAttributes.NETWORK_PROTOCOL_VERSION, "1.1"),
|
||||||
|
equalTo(ServerAttributes.SERVER_ADDRESS, "localhost"),
|
||||||
|
equalTo(ServerAttributes.SERVER_PORT, port),
|
||||||
|
equalTo(ClientAttributes.CLIENT_ADDRESS, "127.0.0.1"),
|
||||||
|
equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, "127.0.0.1"),
|
||||||
|
satisfies(
|
||||||
|
NetworkAttributes.NETWORK_PEER_PORT,
|
||||||
|
val -> val.isInstanceOf(Long.class)))));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,454 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.jsp;
|
||||||
|
|
||||||
|
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
|
||||||
|
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
|
|
||||||
|
import io.opentelemetry.api.trace.SpanKind;
|
||||||
|
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
|
||||||
|
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerUsingTest;
|
||||||
|
import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension;
|
||||||
|
import io.opentelemetry.sdk.trace.data.StatusData;
|
||||||
|
import io.opentelemetry.semconv.ClientAttributes;
|
||||||
|
import io.opentelemetry.semconv.HttpAttributes;
|
||||||
|
import io.opentelemetry.semconv.NetworkAttributes;
|
||||||
|
import io.opentelemetry.semconv.ServerAttributes;
|
||||||
|
import io.opentelemetry.semconv.UrlAttributes;
|
||||||
|
import io.opentelemetry.semconv.UserAgentAttributes;
|
||||||
|
import io.opentelemetry.testing.internal.armeria.client.WebClient;
|
||||||
|
import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse;
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import org.apache.catalina.startup.Tomcat;
|
||||||
|
import org.apache.jasper.JasperException;
|
||||||
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
|
import org.junit.jupiter.params.provider.ArgumentsProvider;
|
||||||
|
import org.junit.jupiter.params.provider.ArgumentsSource;
|
||||||
|
|
||||||
|
class JspInstrumentationForwardTests extends AbstractHttpServerUsingTest<Tomcat> {
|
||||||
|
|
||||||
|
@RegisterExtension
|
||||||
|
public static final InstrumentationExtension testing =
|
||||||
|
HttpServerInstrumentationExtension.forAgent();
|
||||||
|
|
||||||
|
private static JspSpanAssertions spanAsserts;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Tomcat setupServer() throws Exception {
|
||||||
|
File baseDir = Files.createTempDirectory("jsp").toFile();
|
||||||
|
baseDir.deleteOnExit();
|
||||||
|
|
||||||
|
Tomcat tomcatServer = new Tomcat();
|
||||||
|
tomcatServer.setBaseDir(baseDir.getAbsolutePath());
|
||||||
|
tomcatServer.setPort(port);
|
||||||
|
tomcatServer.getConnector();
|
||||||
|
|
||||||
|
// comment to debug
|
||||||
|
tomcatServer.setSilent(true);
|
||||||
|
|
||||||
|
// this is needed in tomcat 9, this triggers the creation of a connector, will not
|
||||||
|
// affect tomcat 7 and 8
|
||||||
|
// https://stackoverflow.com/questions/48998387/code-works-with-embedded-apache-tomcat-8-but-not-with-9-whats-changed
|
||||||
|
tomcatServer.getConnector();
|
||||||
|
|
||||||
|
String baseUrl = "http://localhost:" + port + "/" + getContextPath();
|
||||||
|
spanAsserts = new JspSpanAssertions(baseUrl, port);
|
||||||
|
client = WebClient.of(baseUrl);
|
||||||
|
|
||||||
|
tomcatServer.addWebapp(
|
||||||
|
"/" + getContextPath(),
|
||||||
|
JspInstrumentationForwardTests.class.getResource("/webapps/jsptest").getPath());
|
||||||
|
|
||||||
|
tomcatServer.start();
|
||||||
|
return tomcatServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void stopServer(Tomcat tomcat) throws Exception {
|
||||||
|
tomcat.stop();
|
||||||
|
tomcat.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getContextPath() {
|
||||||
|
return "jsptest-context";
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
protected void setUp() {
|
||||||
|
startServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
protected void cleanUp() {
|
||||||
|
cleanupServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest(name = "Forward to {0}")
|
||||||
|
@ArgumentsSource(NonErroneousGetForwardArgs.class)
|
||||||
|
void testNonErroneousGetForwardTo(
|
||||||
|
String name,
|
||||||
|
String forwardFromFileName,
|
||||||
|
String forwardDestFileName,
|
||||||
|
String jspForwardFromClassName,
|
||||||
|
String jspForwardFromClassPrefix,
|
||||||
|
String jspForwardDestClassName,
|
||||||
|
String jspForwardDestClassPrefix) {
|
||||||
|
AggregatedHttpResponse res = client.get(forwardFromFileName).aggregate().join();
|
||||||
|
assertThat(res.status().code()).isEqualTo(200);
|
||||||
|
|
||||||
|
testing.waitAndAssertTraces(
|
||||||
|
trace ->
|
||||||
|
trace.hasSpansSatisfyingExactly(
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertServerSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withMethod("GET")
|
||||||
|
.withRoute("/" + getContextPath() + forwardFromFileName)
|
||||||
|
.withResponseStatus(200)
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertCompileSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(0))
|
||||||
|
.withRoute(forwardFromFileName)
|
||||||
|
.withClassName(jspForwardFromClassPrefix + jspForwardFromClassName)
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertRenderSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(0))
|
||||||
|
.withRoute(forwardFromFileName)
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertCompileSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(2))
|
||||||
|
.withRoute(forwardDestFileName)
|
||||||
|
.withClassName(jspForwardDestClassPrefix + jspForwardDestClassName)
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertRenderSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(2))
|
||||||
|
.withRoute(forwardDestFileName)
|
||||||
|
.build())));
|
||||||
|
}
|
||||||
|
|
||||||
|
static class NonErroneousGetForwardArgs implements ArgumentsProvider {
|
||||||
|
@Override
|
||||||
|
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
|
||||||
|
return Stream.of(
|
||||||
|
Arguments.of(
|
||||||
|
"no java jsp",
|
||||||
|
"/forwards/forwardToNoJavaJsp.jsp",
|
||||||
|
"/nojava.jsp",
|
||||||
|
"forwardToNoJavaJsp_jsp",
|
||||||
|
"forwards.",
|
||||||
|
"nojava_jsp",
|
||||||
|
""),
|
||||||
|
Arguments.of(
|
||||||
|
"normal java jsp",
|
||||||
|
"/forwards/forwardToSimpleJava.jsp",
|
||||||
|
"/common/loop.jsp",
|
||||||
|
"forwardToSimpleJava_jsp",
|
||||||
|
"forwards.",
|
||||||
|
"loop_jsp",
|
||||||
|
"common."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testNonErroneousGetForwardToPlainHtml() {
|
||||||
|
AggregatedHttpResponse res = client.get("/forwards/forwardToHtml.jsp").aggregate().join();
|
||||||
|
assertThat(res.status().code()).isEqualTo(200);
|
||||||
|
|
||||||
|
testing.waitAndAssertTraces(
|
||||||
|
trace ->
|
||||||
|
trace.hasSpansSatisfyingExactly(
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertServerSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withMethod("GET")
|
||||||
|
.withRoute("/" + getContextPath() + "/forwards/forwardToHtml.jsp")
|
||||||
|
.withResponseStatus(200)
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertCompileSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(0))
|
||||||
|
.withRoute("/forwards/forwardToHtml.jsp")
|
||||||
|
.withClassName("forwards.forwardToHtml_jsp")
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertRenderSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(0))
|
||||||
|
.withRoute("/forwards/forwardToHtml.jsp")
|
||||||
|
.build())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testNonErroneousGetForwardedToJspWithMultipleIncludes() {
|
||||||
|
AggregatedHttpResponse res =
|
||||||
|
client.get("/forwards/forwardToIncludeMulti.jsp").aggregate().join();
|
||||||
|
assertThat(res.status().code()).isEqualTo(200);
|
||||||
|
|
||||||
|
testing.waitAndAssertTraces(
|
||||||
|
trace ->
|
||||||
|
trace.hasSpansSatisfyingExactly(
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertServerSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withMethod("GET")
|
||||||
|
.withRoute(
|
||||||
|
"/" + getContextPath() + "/forwards/forwardToIncludeMulti.jsp")
|
||||||
|
.withResponseStatus(200)
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertCompileSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(0))
|
||||||
|
.withRoute("/forwards/forwardToIncludeMulti.jsp")
|
||||||
|
.withClassName("forwards.forwardToIncludeMulti_jsp")
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertRenderSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(0))
|
||||||
|
.withRoute("/forwards/forwardToIncludeMulti.jsp")
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertCompileSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(2))
|
||||||
|
.withRoute("/includes/includeMulti.jsp")
|
||||||
|
.withClassName("includes.includeMulti_jsp")
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertRenderSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(2))
|
||||||
|
.withRoute("/includes/includeMulti.jsp")
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertCompileSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(4))
|
||||||
|
.withRoute("/common/javaLoopH2.jsp")
|
||||||
|
.withClassName("common.javaLoopH2_jsp")
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertRenderSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(4))
|
||||||
|
.withRoute("/common/javaLoopH2.jsp")
|
||||||
|
.withRequestUrlOverride("/includes/includeMulti.jsp")
|
||||||
|
.withForwardOrigin("/forwards/forwardToIncludeMulti.jsp")
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertCompileSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(4))
|
||||||
|
.withRoute("/common/javaLoopH2.jsp")
|
||||||
|
.withClassName("common.javaLoopH2_jsp")
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertRenderSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(4))
|
||||||
|
.withRoute("/common/javaLoopH2.jsp")
|
||||||
|
.withRequestUrlOverride("/includes/includeMulti.jsp")
|
||||||
|
.withForwardOrigin("/forwards/forwardToIncludeMulti.jsp")
|
||||||
|
.build())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testNonErroneousGetForwardToAnotherForward() {
|
||||||
|
AggregatedHttpResponse res = client.get("/forwards/forwardToJspForward.jsp").aggregate().join();
|
||||||
|
assertThat(res.status().code()).isEqualTo(200);
|
||||||
|
|
||||||
|
testing.waitAndAssertTraces(
|
||||||
|
trace ->
|
||||||
|
trace.hasSpansSatisfyingExactly(
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertServerSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withMethod("GET")
|
||||||
|
.withRoute("/" + getContextPath() + "/forwards/forwardToJspForward.jsp")
|
||||||
|
.withResponseStatus(200)
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertCompileSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(0))
|
||||||
|
.withRoute("/forwards/forwardToJspForward.jsp")
|
||||||
|
.withClassName("forwards.forwardToJspForward_jsp")
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertRenderSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(0))
|
||||||
|
.withRoute("/forwards/forwardToJspForward.jsp")
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertCompileSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(2))
|
||||||
|
.withRoute("/forwards/forwardToSimpleJava.jsp")
|
||||||
|
.withClassName("forwards.forwardToSimpleJava_jsp")
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertRenderSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(2))
|
||||||
|
.withRoute("/forwards/forwardToSimpleJava.jsp")
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertCompileSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(4))
|
||||||
|
.withRoute("/common/loop.jsp")
|
||||||
|
.withClassName("common.loop_jsp")
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertRenderSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(4))
|
||||||
|
.withRoute("/common/loop.jsp")
|
||||||
|
.build())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testForwardToJspWithCompileErrorShouldNotProduceSecondRenderSpan() {
|
||||||
|
AggregatedHttpResponse res =
|
||||||
|
client.get("/forwards/forwardToCompileError.jsp").aggregate().join();
|
||||||
|
assertThat(res.status().code()).isEqualTo(500);
|
||||||
|
|
||||||
|
testing.waitAndAssertTraces(
|
||||||
|
trace ->
|
||||||
|
trace.hasSpansSatisfyingExactly(
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertServerSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withMethod("GET")
|
||||||
|
.withRoute(
|
||||||
|
"/" + getContextPath() + "/forwards/forwardToCompileError.jsp")
|
||||||
|
.withResponseStatus(500)
|
||||||
|
.withExceptionClass(JasperException.class)
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertCompileSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(0))
|
||||||
|
.withRoute("/forwards/forwardToCompileError.jsp")
|
||||||
|
.withClassName("forwards.forwardToCompileError_jsp")
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertRenderSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(0))
|
||||||
|
.withRoute("/forwards/forwardToCompileError.jsp")
|
||||||
|
.withExceptionClass(JasperException.class)
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertCompileSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(2))
|
||||||
|
.withRoute("/compileError.jsp")
|
||||||
|
.withClassName("compileError_jsp")
|
||||||
|
.withExceptionClass(JasperException.class)
|
||||||
|
.build())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testForwardToNonExistentJspShouldBe404() {
|
||||||
|
String route = "/" + getContextPath() + "/forwards/forwardToNonExistent.jsp";
|
||||||
|
|
||||||
|
AggregatedHttpResponse res =
|
||||||
|
client.get("/forwards/forwardToNonExistent.jsp").aggregate().join();
|
||||||
|
assertThat(res.status().code()).isEqualTo(404);
|
||||||
|
|
||||||
|
testing.waitAndAssertTraces(
|
||||||
|
trace ->
|
||||||
|
trace.hasSpansSatisfyingExactly(
|
||||||
|
span ->
|
||||||
|
span.hasName("GET " + route)
|
||||||
|
.hasNoParent()
|
||||||
|
.hasKind(SpanKind.SERVER)
|
||||||
|
.hasStatus(StatusData.unset())
|
||||||
|
.hasAttributesSatisfyingExactly(
|
||||||
|
equalTo(UrlAttributes.URL_SCHEME, "http"),
|
||||||
|
equalTo(UrlAttributes.URL_PATH, route),
|
||||||
|
equalTo(HttpAttributes.HTTP_REQUEST_METHOD, "GET"),
|
||||||
|
equalTo(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 404),
|
||||||
|
satisfies(
|
||||||
|
UserAgentAttributes.USER_AGENT_ORIGINAL,
|
||||||
|
val -> val.isInstanceOf(String.class)),
|
||||||
|
equalTo(HttpAttributes.HTTP_ROUTE, route),
|
||||||
|
equalTo(NetworkAttributes.NETWORK_PROTOCOL_VERSION, "1.1"),
|
||||||
|
equalTo(ServerAttributes.SERVER_ADDRESS, "localhost"),
|
||||||
|
equalTo(ServerAttributes.SERVER_PORT, port),
|
||||||
|
equalTo(ClientAttributes.CLIENT_ADDRESS, "127.0.0.1"),
|
||||||
|
equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, "127.0.0.1"),
|
||||||
|
satisfies(
|
||||||
|
NetworkAttributes.NETWORK_PEER_PORT,
|
||||||
|
val -> val.isInstanceOf(Long.class))),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertCompileSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(0))
|
||||||
|
.withRoute("/forwards/forwardToNonExistent.jsp")
|
||||||
|
.withClassName("forwards.forwardToNonExistent_jsp")
|
||||||
|
.build()),
|
||||||
|
span ->
|
||||||
|
spanAsserts.assertRenderSpan(
|
||||||
|
span,
|
||||||
|
new JspSpanAssertionBuilder()
|
||||||
|
.withParent(trace.getSpan(0))
|
||||||
|
.withRoute("/forwards/forwardToNonExistent.jsp")
|
||||||
|
.build()),
|
||||||
|
span -> span.hasName("ResponseFacade.sendError").hasParent(trace.getSpan(2))));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.jsp;
|
||||||
|
|
||||||
|
import io.opentelemetry.sdk.trace.data.SpanData;
|
||||||
|
|
||||||
|
class JspSpan {
|
||||||
|
private SpanData parent;
|
||||||
|
private String method;
|
||||||
|
private String className;
|
||||||
|
private String requestUrlOverride;
|
||||||
|
private String forwardOrigin;
|
||||||
|
private String route;
|
||||||
|
private int responseStatus;
|
||||||
|
private Class<?> exceptionClass;
|
||||||
|
private boolean errorMessageOptional;
|
||||||
|
|
||||||
|
public SpanData getParent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParent(SpanData parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMethod() {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMethod(String method) {
|
||||||
|
this.method = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClassName() {
|
||||||
|
return className;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClassName(String className) {
|
||||||
|
this.className = className;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRequestUrlOverride() {
|
||||||
|
return requestUrlOverride;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRequestUrlOverride(String requestUrlOverride) {
|
||||||
|
this.requestUrlOverride = requestUrlOverride;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getForwardOrigin() {
|
||||||
|
return forwardOrigin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setForwardOrigin(String forwardOrigin) {
|
||||||
|
this.forwardOrigin = forwardOrigin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRoute() {
|
||||||
|
return route;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRoute(String route) {
|
||||||
|
this.route = route;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getResponseStatus() {
|
||||||
|
return responseStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResponseStatus(int responseStatus) {
|
||||||
|
this.responseStatus = responseStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<?> getExceptionClass() {
|
||||||
|
return exceptionClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExceptionClass(Class<?> exceptionClass) {
|
||||||
|
this.exceptionClass = exceptionClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getErrorMessageOptional() {
|
||||||
|
return errorMessageOptional;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setErrorMessageOptional(boolean errorMessageOptional) {
|
||||||
|
this.errorMessageOptional = errorMessageOptional;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.jsp;
|
||||||
|
|
||||||
|
import io.opentelemetry.sdk.trace.data.SpanData;
|
||||||
|
|
||||||
|
class JspSpanAssertionBuilder {
|
||||||
|
private SpanData parent;
|
||||||
|
private String method;
|
||||||
|
private String route;
|
||||||
|
private String className;
|
||||||
|
private String requestUrlOverride;
|
||||||
|
private String forwardOrigin;
|
||||||
|
private int responseStatus;
|
||||||
|
private Class<?> exceptionClass;
|
||||||
|
private boolean errorMessageOptional;
|
||||||
|
|
||||||
|
public JspSpanAssertionBuilder withParent(SpanData parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JspSpanAssertionBuilder withMethod(String method) {
|
||||||
|
this.method = method;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JspSpanAssertionBuilder withRoute(String route) {
|
||||||
|
this.route = route;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JspSpanAssertionBuilder withClassName(String className) {
|
||||||
|
this.className = className;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JspSpanAssertionBuilder withRequestUrlOverride(String requestUrlOverride) {
|
||||||
|
this.requestUrlOverride = requestUrlOverride;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JspSpanAssertionBuilder withForwardOrigin(String forwardOrigin) {
|
||||||
|
this.forwardOrigin = forwardOrigin;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JspSpanAssertionBuilder withResponseStatus(int responseStatus) {
|
||||||
|
this.responseStatus = responseStatus;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JspSpanAssertionBuilder withExceptionClass(Class<?> exceptionClass) {
|
||||||
|
this.exceptionClass = exceptionClass;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JspSpanAssertionBuilder withErrorMessageOptional(boolean errorMessageOptional) {
|
||||||
|
this.errorMessageOptional = errorMessageOptional;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JspSpan build() {
|
||||||
|
JspSpan serverSpan = new JspSpan();
|
||||||
|
serverSpan.setParent(this.parent);
|
||||||
|
serverSpan.setMethod(this.method);
|
||||||
|
serverSpan.setRoute(this.route);
|
||||||
|
serverSpan.setClassName(this.className);
|
||||||
|
serverSpan.setRequestUrlOverride(this.requestUrlOverride);
|
||||||
|
serverSpan.setForwardOrigin(this.forwardOrigin);
|
||||||
|
serverSpan.setResponseStatus(this.responseStatus);
|
||||||
|
serverSpan.setExceptionClass(this.exceptionClass);
|
||||||
|
serverSpan.setErrorMessageOptional(this.errorMessageOptional);
|
||||||
|
return serverSpan;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,155 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.jsp;
|
||||||
|
|
||||||
|
import static io.opentelemetry.api.common.AttributeKey.stringKey;
|
||||||
|
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
|
||||||
|
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import io.opentelemetry.api.trace.SpanKind;
|
||||||
|
import io.opentelemetry.sdk.testing.assertj.SpanDataAssert;
|
||||||
|
import io.opentelemetry.sdk.trace.data.StatusData;
|
||||||
|
import io.opentelemetry.semconv.ClientAttributes;
|
||||||
|
import io.opentelemetry.semconv.ErrorAttributes;
|
||||||
|
import io.opentelemetry.semconv.ExceptionAttributes;
|
||||||
|
import io.opentelemetry.semconv.HttpAttributes;
|
||||||
|
import io.opentelemetry.semconv.NetworkAttributes;
|
||||||
|
import io.opentelemetry.semconv.ServerAttributes;
|
||||||
|
import io.opentelemetry.semconv.UrlAttributes;
|
||||||
|
import io.opentelemetry.semconv.UserAgentAttributes;
|
||||||
|
|
||||||
|
class JspSpanAssertions {
|
||||||
|
private final String baseUrl;
|
||||||
|
private final int port;
|
||||||
|
|
||||||
|
JspSpanAssertions(String baseUrl, int port) {
|
||||||
|
this.baseUrl = baseUrl;
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpanDataAssert assertServerSpan(SpanDataAssert span, JspSpan spanData) {
|
||||||
|
if (spanData.getExceptionClass() != null) {
|
||||||
|
span.hasStatus(StatusData.error())
|
||||||
|
.hasEventsSatisfyingExactly(
|
||||||
|
event ->
|
||||||
|
event
|
||||||
|
.hasName("exception")
|
||||||
|
.hasAttributesSatisfyingExactly(
|
||||||
|
satisfies(
|
||||||
|
ExceptionAttributes.EXCEPTION_TYPE,
|
||||||
|
val ->
|
||||||
|
val.satisfiesAnyOf(
|
||||||
|
v -> val.isEqualTo(spanData.getExceptionClass().getName()),
|
||||||
|
v ->
|
||||||
|
val.contains(
|
||||||
|
spanData.getExceptionClass().getSimpleName()))),
|
||||||
|
satisfies(
|
||||||
|
ExceptionAttributes.EXCEPTION_MESSAGE,
|
||||||
|
val ->
|
||||||
|
val.satisfiesAnyOf(
|
||||||
|
v -> assertThat(spanData.getErrorMessageOptional()).isTrue(),
|
||||||
|
v -> val.isInstanceOf(String.class))),
|
||||||
|
satisfies(
|
||||||
|
ExceptionAttributes.EXCEPTION_STACKTRACE,
|
||||||
|
val -> val.isInstanceOf(String.class))));
|
||||||
|
}
|
||||||
|
|
||||||
|
return span.hasName(spanData.getMethod() + " " + spanData.getRoute())
|
||||||
|
.hasNoParent()
|
||||||
|
.hasKind(SpanKind.SERVER)
|
||||||
|
.hasAttributesSatisfyingExactly(
|
||||||
|
equalTo(UrlAttributes.URL_SCHEME, "http"),
|
||||||
|
equalTo(UrlAttributes.URL_PATH, spanData.getRoute()),
|
||||||
|
equalTo(HttpAttributes.HTTP_REQUEST_METHOD, spanData.getMethod()),
|
||||||
|
equalTo(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, spanData.getResponseStatus()),
|
||||||
|
satisfies(
|
||||||
|
UserAgentAttributes.USER_AGENT_ORIGINAL, val -> val.isInstanceOf(String.class)),
|
||||||
|
equalTo(HttpAttributes.HTTP_ROUTE, spanData.getRoute()),
|
||||||
|
equalTo(NetworkAttributes.NETWORK_PROTOCOL_VERSION, "1.1"),
|
||||||
|
equalTo(ServerAttributes.SERVER_ADDRESS, "localhost"),
|
||||||
|
equalTo(ServerAttributes.SERVER_PORT, port),
|
||||||
|
equalTo(ClientAttributes.CLIENT_ADDRESS, "127.0.0.1"),
|
||||||
|
equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, "127.0.0.1"),
|
||||||
|
satisfies(NetworkAttributes.NETWORK_PEER_PORT, val -> val.isInstanceOf(Long.class)),
|
||||||
|
satisfies(
|
||||||
|
ErrorAttributes.ERROR_TYPE,
|
||||||
|
val ->
|
||||||
|
val.satisfiesAnyOf(
|
||||||
|
v -> assertThat(spanData.getExceptionClass()).isNull(),
|
||||||
|
v -> assertThat(v).isEqualTo("500"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
SpanDataAssert assertCompileSpan(SpanDataAssert span, JspSpan spanData) {
|
||||||
|
if (spanData.getExceptionClass() != null) {
|
||||||
|
span.hasStatus(StatusData.error())
|
||||||
|
.hasEventsSatisfyingExactly(
|
||||||
|
event ->
|
||||||
|
event
|
||||||
|
.hasName("exception")
|
||||||
|
.hasAttributesSatisfyingExactly(
|
||||||
|
equalTo(
|
||||||
|
ExceptionAttributes.EXCEPTION_TYPE,
|
||||||
|
spanData.getExceptionClass().getCanonicalName()),
|
||||||
|
satisfies(
|
||||||
|
ExceptionAttributes.EXCEPTION_STACKTRACE,
|
||||||
|
val -> val.isInstanceOf(String.class)),
|
||||||
|
satisfies(
|
||||||
|
ExceptionAttributes.EXCEPTION_MESSAGE,
|
||||||
|
val -> val.isInstanceOf(String.class))));
|
||||||
|
}
|
||||||
|
|
||||||
|
return span.hasName("Compile " + spanData.getRoute())
|
||||||
|
.hasParent(spanData.getParent())
|
||||||
|
.hasAttributesSatisfyingExactly(
|
||||||
|
equalTo(stringKey("jsp.classFQCN"), "org.apache.jsp." + spanData.getClassName()),
|
||||||
|
equalTo(stringKey("jsp.compiler"), "org.apache.jasper.compiler.JDTCompiler"));
|
||||||
|
}
|
||||||
|
|
||||||
|
SpanDataAssert assertRenderSpan(SpanDataAssert span, JspSpan spanData) {
|
||||||
|
String requestUrl = spanData.getRoute();
|
||||||
|
if (spanData.getRequestUrlOverride() != null) {
|
||||||
|
requestUrl = spanData.getRequestUrlOverride();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spanData.getExceptionClass() != null) {
|
||||||
|
span.hasStatus(StatusData.error())
|
||||||
|
.hasEventsSatisfyingExactly(
|
||||||
|
event ->
|
||||||
|
event
|
||||||
|
.hasName("exception")
|
||||||
|
.hasAttributesSatisfyingExactly(
|
||||||
|
satisfies(
|
||||||
|
ExceptionAttributes.EXCEPTION_TYPE,
|
||||||
|
val ->
|
||||||
|
val.satisfiesAnyOf(
|
||||||
|
v -> val.isEqualTo(spanData.getExceptionClass().getName()),
|
||||||
|
v ->
|
||||||
|
val.contains(
|
||||||
|
spanData.getExceptionClass().getSimpleName()))),
|
||||||
|
satisfies(
|
||||||
|
ExceptionAttributes.EXCEPTION_MESSAGE,
|
||||||
|
val ->
|
||||||
|
val.satisfiesAnyOf(
|
||||||
|
v -> assertThat(spanData.getErrorMessageOptional()).isTrue(),
|
||||||
|
v -> val.isInstanceOf(String.class))),
|
||||||
|
satisfies(
|
||||||
|
ExceptionAttributes.EXCEPTION_STACKTRACE,
|
||||||
|
val -> val.isInstanceOf(String.class))));
|
||||||
|
}
|
||||||
|
|
||||||
|
return span.hasName("Render " + spanData.getRoute())
|
||||||
|
.hasParent(spanData.getParent())
|
||||||
|
.hasAttributesSatisfyingExactly(
|
||||||
|
equalTo(stringKey("jsp.requestURL"), baseUrl + requestUrl),
|
||||||
|
satisfies(
|
||||||
|
stringKey("jsp.forwardOrigin"),
|
||||||
|
val ->
|
||||||
|
val.satisfiesAnyOf(
|
||||||
|
v -> assertThat(spanData.getForwardOrigin()).isNull(),
|
||||||
|
v -> assertThat(v).isEqualTo(spanData.getForwardOrigin()))));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue