@@ -8,17 +8,6 @@ package io.opentelemetry.javaagent.instrumentation.akkahttp
88import akka .actor .ActorSystem
99import akka .http .scaladsl .Http
1010import akka .http .scaladsl .server .Directives ._
11- import akka .http .scaladsl .server .Directives .{
12- IntNumber ,
13- complete ,
14- concat ,
15- path ,
16- pathEndOrSingleSlash ,
17- pathPrefix ,
18- pathSingleSlash ,
19- JavaUUID ,
20- Segment
21- }
2211import akka .http .scaladsl .server .Route
2312import akka .stream .ActorMaterializer
2413import io .opentelemetry .instrumentation .test .utils .PortUtils
@@ -32,6 +21,8 @@ import io.opentelemetry.testing.internal.armeria.common.{
3221import org .assertj .core .api .Assertions .assertThat
3322import org .junit .jupiter .api .{AfterAll , Test , TestInstance }
3423import org .junit .jupiter .api .extension .RegisterExtension
24+ import org .junit .jupiter .params .ParameterizedTest
25+ import org .junit .jupiter .params .provider .CsvSource
3526
3627import java .net .{URI , URISyntaxException }
3728import java .util .function .Consumer
@@ -62,24 +53,164 @@ class AkkaHttpServerRouteTest {
6253 test(route, " /test" , " GET /test" )
6354 }
6455
65- @ Test def testRoute (): Unit = {
56+ @ Test def testPathPrefix (): Unit = {
57+ val route =
58+ pathPrefix(" a" ) {
59+ pathPrefix(" b" ) {
60+ path(" c" ) {
61+ complete(" ok" )
62+ }
63+ }
64+ }
65+
66+ test(route, " /a/b/c" , " GET /a/b/c" )
67+ }
68+
69+ @ Test def testTrailingSlash (): Unit = {
70+ val route = path(" foo" ./ ) { complete(" ok" ) }
71+ test(route, " /foo/" , " GET /foo/" )
72+ }
73+
74+ @ Test def testSlash (): Unit = {
75+ val route = path(" foo" / " bar" ) { complete(" ok" ) }
76+ test(route, " /foo/bar" , " GET /foo/bar" )
77+ }
78+
79+ @ Test def testEncodedSlash (): Unit = {
80+ val route = path(" foo/bar" ) { complete(" ok" ) }
81+ test(route, " /foo%2Fbar" , " GET /foo%2Fbar" )
82+ }
83+
84+ @ Test def testSeparateOnSlashes (): Unit = {
85+ val route = path(separateOnSlashes(" foo/bar" )) { complete(" ok" ) }
86+ test(route, " /foo/bar" , " GET /foo/bar" )
87+ }
88+
89+ @ Test def testMatchRegex (): Unit = {
90+ val route = path(" foo" / """ number-\d+""" .r) { _ => complete(" ok" ) }
91+ test(route, " /foo/number-123" , " GET /foo/*" )
92+ }
93+
94+ @ ParameterizedTest
95+ @ CsvSource (
96+ Array (
97+ " /i42, GET /i*" ,
98+ " /hCAFE, GET /h*"
99+ )
100+ )
101+ def testPipe (requestPath : String , expectedName : String ): Unit = {
102+ val route = path(" i" ~ IntNumber | " h" ~ HexIntNumber ) { _ =>
103+ complete(" ok" )
104+ }
105+ test(route, requestPath, expectedName)
106+ }
107+
108+ @ ParameterizedTest
109+ @ CsvSource (
110+ Array (
111+ " /colours/red, GET /colours/red" ,
112+ " /colours/green, GET /colours/green"
113+ )
114+ )
115+ def testMapExtractor (requestPath : String , expectedName : String ): Unit = {
116+ val route = path(" colours" / Map (" red" -> 1 , " green" -> 2 , " blue" -> 3 )) {
117+ _ => complete(" ok" )
118+ }
119+ test(route, requestPath, expectedName)
120+ }
121+
122+ @ ParameterizedTest
123+ @ CsvSource (
124+ Array (
125+ " /fooish, GET /foo*" ,
126+ " /fooish/123, GET /foo*"
127+ )
128+ )
129+ def testNotMatch (requestPath : String , expectedName : String ): Unit = {
130+ val route = pathPrefix(" foo" ~ ! " bar" ) { complete(" ok" ) }
131+ test(route, requestPath, expectedName)
132+ }
133+
134+ @ Test def testProvide (): Unit = {
135+ val route = pathPrefix(" foo" ) {
136+ provide(" hi" ) { _ =>
137+ path(" bar" ) {
138+ complete(" ok" )
139+ }
140+ }
141+ }
142+ test(route, " /foo/bar" , " GET /foo/bar" )
143+ }
144+
145+ @ ParameterizedTest
146+ @ CsvSource (
147+ Array (
148+ " /foo/bar/X42/edit, GET /foo/bar/X*/edit" ,
149+ " /foo/bar/X/edit, GET /foo/bar/X/edit"
150+ )
151+ )
152+ def testOptional (requestPath : String , expectedName : String ): Unit = {
153+ val route = path(" foo" / " bar" / " X" ~ IntNumber .? / (" edit" | " create" )) {
154+ _ => complete(" ok" )
155+ }
156+ test(route, requestPath, expectedName)
157+ }
158+
159+ @ Test def testNoMatches (): Unit = {
160+ val route = path(" foo" / " bar" ) { complete(" ok" ) }
161+ test(
162+ route,
163+ " /foo/wrong" ,
164+ " GET" ,
165+ 404 ,
166+ " The requested resource could not be found."
167+ )
168+ }
169+
170+ @ Test def testError (): Unit = {
171+ val route = path(" foo" / IntNumber ) { _ =>
172+ failWith(new RuntimeException (" oops" ))
173+ }
174+ test(
175+ route,
176+ " /foo/123" ,
177+ " GET /foo/*" ,
178+ 500 ,
179+ " There was an internal server error."
180+ )
181+ }
182+
183+ @ Test def testConcat (): Unit = {
66184 val route = concat(
67185 pathEndOrSingleSlash {
68186 complete(" root" )
69187 },
188+ path(" .+" .r / " wrong1" ) { _ =>
189+ complete(" wrong1" )
190+ },
70191 pathPrefix(" test" ) {
71192 concat(
72193 pathSingleSlash {
73194 complete(" test" )
74195 },
75- path(IntNumber ) { _ =>
76- complete(" ok" )
196+ pathPrefix(" foo" ) {
197+ concat(
198+ path(IntNumber ) { _ =>
199+ complete(" ok" )
200+ }
201+ )
202+ },
203+ path(" something-else" ) {
204+ complete(" test" )
77205 }
78206 )
207+ },
208+ path(" test" / " wrong2" ) {
209+ complete(" wrong2" )
79210 }
80211 )
81212
82- test(route, " /test/1" , " GET /test/*" )
213+ test(route, " /test/foo/ 1" , " GET /test/foo /*" )
83214 }
84215
85216 @ Test def testRouteWithUUID (): Unit = {
@@ -127,7 +258,13 @@ class AkkaHttpServerRouteTest {
127258 test(route, " /api/v2/orders/order123/status" , " GET /api/v2/orders/*/status" )
128259 }
129260
130- def test (route : Route , path : String , spanName : String ): Unit = {
261+ def test (
262+ route : Route ,
263+ path : String ,
264+ spanName : String ,
265+ expectedStatus : Int = 200 ,
266+ expectedMsg : String = " ok"
267+ ): Unit = {
131268 val port = PortUtils .findOpenPort
132269 val address : URI = buildAddress(port)
133270 val binding =
@@ -138,8 +275,8 @@ class AkkaHttpServerRouteTest {
138275 address.resolve(path).toString
139276 )
140277 val response = client.execute(request).aggregate.join
141- assertThat(response.status.code).isEqualTo(200 )
142- assertThat(response.contentUtf8).isEqualTo(" ok " )
278+ assertThat(response.status.code).isEqualTo(expectedStatus )
279+ assertThat(response.contentUtf8).isEqualTo(expectedMsg )
143280
144281 testing.waitAndAssertTraces(new Consumer [TraceAssert ] {
145282 override def accept (trace : TraceAssert ): Unit =
0 commit comments