1010import com .sun .net .httpserver .HttpsConfigurator ;
1111import io .prometheus .metrics .model .registry .PrometheusRegistry ;
1212import io .prometheus .metrics .model .registry .PrometheusScrapeRequest ;
13+ import io .prometheus .metrics .model .snapshots .CounterSnapshot ;
14+ import io .prometheus .metrics .model .snapshots .CounterSnapshot .CounterDataPointSnapshot ;
15+ import io .prometheus .metrics .model .snapshots .Labels ;
16+ import io .prometheus .metrics .model .snapshots .MetricMetadata ;
1317import io .prometheus .metrics .model .snapshots .MetricSnapshots ;
1418import java .io .IOException ;
1519import java .lang .reflect .Method ;
1620import java .net .InetAddress ;
17- import java .net .InetSocketAddress ;
18- import java .net .Socket ;
19- import java .nio . charset . StandardCharsets ;
20- import java .security . NoSuchAlgorithmException ;
21+ import java .net .URI ;
22+ import java .net .http . HttpClient ;
23+ import java .net . http . HttpRequest ;
24+ import java .net . http . HttpResponse ;
2125import java .security .Principal ;
26+ import java .util .List ;
2227import java .util .concurrent .Executors ;
2328import javax .net .ssl .SSLContext ;
2429import javax .security .auth .Subject ;
30+ import org .junit .jupiter .api .BeforeEach ;
2531import org .junit .jupiter .api .Test ;
2632
2733public class HTTPServerTest {
2834
35+ private PrometheusRegistry registry ;
36+
37+ @ BeforeEach
38+ void setUp () {
39+ final MetricMetadata metadata = new MetricMetadata ("my-counter" );
40+ final CounterDataPointSnapshot dataPointSnapshot =
41+ new CounterDataPointSnapshot (1.0 , Labels .EMPTY , null , System .currentTimeMillis ());
42+
43+ registry = new PrometheusRegistry ();
44+ registry .register (() -> new CounterSnapshot (metadata , List .of (dataPointSnapshot )));
45+ }
46+
2947 @ Test
30- @ SuppressWarnings ({"removal" })
3148 public void testSubjectDoAs () throws Exception {
32-
3349 final String user = "joe" ;
3450 final Subject subject = new Subject ();
3551 subject .getPrincipals ().add (() -> user );
@@ -66,61 +82,61 @@ public Result authenticate(HttpExchange exchange) {
6682 .authenticatedSubjectAttributeName ("aa" )
6783 .buildAndStart ();
6884
69- run (server , "204 " , "/ " );
85+ run (server , "/ " , 204 , " " );
7086 }
7187
72- private static void run (HTTPServer server , String expected , String path ) throws IOException {
73- try (Socket socket = new Socket ()) {
74- socket .connect (new InetSocketAddress ("localhost" , server .getPort ()));
75-
76- socket
77- .getOutputStream ()
78- .write (("GET " + path + " HTTP/1.1 \r \n " ).getBytes (StandardCharsets .UTF_8 ));
79- socket .getOutputStream ().write ("HOST: localhost \r \n \r \n " .getBytes (StandardCharsets .UTF_8 ));
80- socket .getOutputStream ().flush ();
81-
82- String actualResponse = "" ;
83- byte [] resp = new byte [500 ];
84- int read = socket .getInputStream ().read (resp , 0 , resp .length );
85- if (read > 0 ) {
86- actualResponse = new String (resp , 0 , read , StandardCharsets .UTF_8 );
87- }
88- assertThat (actualResponse ).contains (expected );
89- }
88+ @ Test
89+ void defaultHandler () throws Exception {
90+ run (
91+ HTTPServer .builder ().port (0 ).buildAndStart (),
92+ "/" ,
93+ 200 ,
94+ "<title>Prometheus Java Client</title>" );
9095 }
9196
9297 @ Test
93- void defaultHandler () throws IOException {
94- run (HTTPServer .builder ().port (0 ).buildAndStart (), "200" , "/" );
98+ void metrics () throws Exception {
99+ run (
100+ HTTPServer .builder ()
101+ .port (0 )
102+ .registry (registry )
103+ .executorService (Executors .newFixedThreadPool (1 ))
104+ .buildAndStart (),
105+ "/metrics" ,
106+ 200 ,
107+ "my_counter_total 1.0" );
95108 }
96109
97110 @ Test
98- void metrics () throws IOException {
111+ void metricsCustomPath () throws Exception {
99112 run (
100113 HTTPServer .builder ()
101114 .port (0 )
102- .registry (new PrometheusRegistry ())
115+ .registry (registry )
116+ .metricsHandlerPath ("/my-metrics" )
103117 .executorService (Executors .newFixedThreadPool (1 ))
104118 .buildAndStart (),
105- "200" ,
106- "/metrics" );
119+ "/my-metrics" ,
120+ 200 ,
121+ "my_counter_total 1.0" );
107122 }
108123
109124 @ Test
110- void metricsCustomPath () throws IOException {
125+ void metricsCustomRootPath () throws Exception {
111126 run (
112127 HTTPServer .builder ()
113128 .port (0 )
114- .registry (new PrometheusRegistry () )
115- .metricsHandlerPath ("/my-metrics " )
129+ .registry (registry )
130+ .metricsHandlerPath ("/" )
116131 .executorService (Executors .newFixedThreadPool (1 ))
117132 .buildAndStart (),
118- "200" ,
119- "/my-metrics" );
133+ "/" ,
134+ 200 ,
135+ "my_counter_total 1.0" );
120136 }
121137
122138 @ Test
123- void registryThrows () throws IOException {
139+ void registryThrows () throws Exception {
124140 HTTPServer server =
125141 HTTPServer .builder ()
126142 .port (0 )
@@ -132,11 +148,12 @@ public MetricSnapshots scrape(PrometheusScrapeRequest scrapeRequest) {
132148 }
133149 })
134150 .buildAndStart ();
135- run (server , "500 " , "/ metrics" );
151+ run (server , "/metrics " , 500 , "An Exception occurred while scraping metrics" );
136152 }
137153
138154 @ Test
139- void config () throws NoSuchAlgorithmException , IOException {
155+ @ SuppressWarnings ("resource" )
156+ void config () {
140157 assertThatExceptionOfType (IllegalStateException .class )
141158 .isThrownBy (
142159 () ->
@@ -147,45 +164,70 @@ void config() throws NoSuchAlgorithmException, IOException {
147164 .buildAndStart ())
148165 .withMessage ("cannot configure 'inetAddress' and 'hostname' at the same time" );
149166
150- // ssl doesn't work without in tests
151- run (
152- HTTPServer .builder ()
153- .port (0 )
154- .httpsConfigurator (new HttpsConfigurator (SSLContext .getDefault ()))
155- .buildAndStart (),
156- "" ,
157- "/" );
167+ // SSL doesn't work in this simple test configuration
168+ assertThatExceptionOfType (IOException .class )
169+ .isThrownBy (
170+ () ->
171+ run (
172+ HTTPServer .builder ()
173+ .port (0 )
174+ .httpsConfigurator (new HttpsConfigurator (SSLContext .getDefault ()))
175+ .buildAndStart (),
176+ "/" ,
177+ 0 ,
178+ "ignored" ));
158179 }
159180
160181 @ Test
161- void health () throws IOException {
162- run (HTTPServer .builder ().port (0 ).buildAndStart (), "200 " , "/-/ healthy" );
182+ void health () throws Exception {
183+ run (HTTPServer .builder ().port (0 ).buildAndStart (), "/-/healthy " , 200 , "Exporter is healthy. " );
163184 }
164185
165186 @ Test
166- void healthEnabled () throws IOException {
187+ void healthEnabled () throws Exception {
167188 HttpHandler handler = exchange -> exchange .sendResponseHeaders (204 , -1 );
168189 run (
169190 HTTPServer .builder ()
170191 .port (0 )
171192 .defaultHandler (handler )
172193 .registerHealthHandler (true )
173194 .buildAndStart (),
174- "200" ,
175- "/-/healthy" );
195+ "/-/healthy" ,
196+ 200 ,
197+ "Exporter is healthy." );
176198 }
177199
178200 @ Test
179- void healthDisabled () throws IOException {
201+ void healthDisabled () throws Exception {
180202 HttpHandler handler = exchange -> exchange .sendResponseHeaders (204 , -1 );
181203 run (
182204 HTTPServer .builder ()
183205 .port (0 )
184206 .defaultHandler (handler )
185207 .registerHealthHandler (false )
186208 .buildAndStart (),
187- "204" ,
188- "/-/healthy" );
209+ "/-/healthy" ,
210+ 204 ,
211+ "" );
212+ }
213+
214+ private static void run (
215+ HTTPServer server , String path , int expectedStatusCode , String expectedBody )
216+ throws Exception {
217+ // we cannot use try-with-resources or even client.close(), or the test will fail with Java 17
218+ @ SuppressWarnings ("resource" )
219+ final HttpClient client = HttpClient .newBuilder ().build ();
220+ try {
221+ final URI uri = URI .create ("http://localhost:%s%s" .formatted (server .getPort (), path ));
222+ final HttpRequest request = HttpRequest .newBuilder ().uri (uri ).GET ().build ();
223+
224+ final HttpResponse <String > response =
225+ client .send (request , HttpResponse .BodyHandlers .ofString ());
226+ assertThat (response .statusCode ()).isEqualTo (expectedStatusCode );
227+ assertThat (response .body ()).contains (expectedBody );
228+ } finally {
229+ server .stop ();
230+ }
189231 }
190232
191233 /**
0 commit comments