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 .net .InetAddress ;
16- import java .net .InetSocketAddress ;
17- import java .net .Socket ;
18- import java .nio . charset . StandardCharsets ;
19- import java .security . NoSuchAlgorithmException ;
20+ import java .net .URI ;
21+ import java .net .http . HttpClient ;
22+ import java .net . http . HttpRequest ;
23+ import java .net . http . HttpResponse ;
2024import java .security .Principal ;
25+ import java .util .List ;
2126import java .util .concurrent .Executors ;
2227import javax .net .ssl .SSLContext ;
2328import javax .security .auth .Subject ;
29+ import org .junit .jupiter .api .BeforeEach ;
2430import org .junit .jupiter .api .Test ;
2531
2632public class HTTPServerTest {
2733
34+ private PrometheusRegistry registry ;
35+
36+ @ BeforeEach
37+ void setUp () {
38+ final MetricMetadata metadata = new MetricMetadata ("my-counter" );
39+ final CounterDataPointSnapshot dataPointSnapshot =
40+ new CounterDataPointSnapshot (1.0 , Labels .EMPTY , null , System .currentTimeMillis ());
41+
42+ registry = new PrometheusRegistry ();
43+ registry .register (() -> new CounterSnapshot (metadata , List .of (dataPointSnapshot )));
44+ }
45+
2846 @ Test
29- @ SuppressWarnings ({"removal" })
3047 public void testSubjectDoAs () throws Exception {
31-
3248 final String user = "joe" ;
3349 final Subject subject = new Subject ();
3450 subject .getPrincipals ().add (() -> user );
@@ -65,61 +81,61 @@ public Result authenticate(HttpExchange exchange) {
6581 .authenticatedSubjectAttributeName ("aa" )
6682 .buildAndStart ();
6783
68- run (server , "204 " , "/ " );
84+ run (server , "/ " , 204 , " " );
6985 }
7086
71- private static void run (HTTPServer server , String expected , String path ) throws IOException {
72- try (Socket socket = new Socket ()) {
73- socket .connect (new InetSocketAddress ("localhost" , server .getPort ()));
74-
75- socket
76- .getOutputStream ()
77- .write (("GET " + path + " HTTP/1.1 \r \n " ).getBytes (StandardCharsets .UTF_8 ));
78- socket .getOutputStream ().write ("HOST: localhost \r \n \r \n " .getBytes (StandardCharsets .UTF_8 ));
79- socket .getOutputStream ().flush ();
80-
81- String actualResponse = "" ;
82- byte [] resp = new byte [500 ];
83- int read = socket .getInputStream ().read (resp , 0 , resp .length );
84- if (read > 0 ) {
85- actualResponse = new String (resp , 0 , read , StandardCharsets .UTF_8 );
86- }
87- assertThat (actualResponse ).contains (expected );
88- }
87+ @ Test
88+ void defaultHandler () throws Exception {
89+ run (
90+ HTTPServer .builder ().port (0 ).buildAndStart (),
91+ "/" ,
92+ 200 ,
93+ "<title>Prometheus Java Client</title>" );
8994 }
9095
9196 @ Test
92- void defaultHandler () throws IOException {
93- run (HTTPServer .builder ().port (0 ).buildAndStart (), "200" , "/" );
97+ void metrics () throws Exception {
98+ run (
99+ HTTPServer .builder ()
100+ .port (0 )
101+ .registry (registry )
102+ .executorService (Executors .newFixedThreadPool (1 ))
103+ .buildAndStart (),
104+ "/metrics" ,
105+ 200 ,
106+ "my_counter_total 1.0" );
94107 }
95108
96109 @ Test
97- void metrics () throws IOException {
110+ void metricsCustomPath () throws Exception {
98111 run (
99112 HTTPServer .builder ()
100113 .port (0 )
101- .registry (new PrometheusRegistry ())
114+ .registry (registry )
115+ .metricsHandlerPath ("/my-metrics" )
102116 .executorService (Executors .newFixedThreadPool (1 ))
103117 .buildAndStart (),
104- "200" ,
105- "/metrics" );
118+ "/my-metrics" ,
119+ 200 ,
120+ "my_counter_total 1.0" );
106121 }
107122
108123 @ Test
109- void metricsCustomPath () throws IOException {
124+ void metricsCustomRootPath () throws Exception {
110125 run (
111126 HTTPServer .builder ()
112127 .port (0 )
113- .registry (new PrometheusRegistry () )
114- .metricsHandlerPath ("/my-metrics " )
128+ .registry (registry )
129+ .metricsHandlerPath ("/" )
115130 .executorService (Executors .newFixedThreadPool (1 ))
116131 .buildAndStart (),
117- "200" ,
118- "/my-metrics" );
132+ "/" ,
133+ 200 ,
134+ "my_counter_total 1.0" );
119135 }
120136
121137 @ Test
122- void registryThrows () throws IOException {
138+ void registryThrows () throws Exception {
123139 HTTPServer server =
124140 HTTPServer .builder ()
125141 .port (0 )
@@ -131,11 +147,12 @@ public MetricSnapshots scrape(PrometheusScrapeRequest scrapeRequest) {
131147 }
132148 })
133149 .buildAndStart ();
134- run (server , "500 " , "/ metrics" );
150+ run (server , "/metrics " , 500 , "An Exception occurred while scraping metrics" );
135151 }
136152
137153 @ Test
138- void config () throws NoSuchAlgorithmException , IOException {
154+ @ SuppressWarnings ("resource" )
155+ void config () {
139156 assertThatExceptionOfType (IllegalStateException .class )
140157 .isThrownBy (
141158 () ->
@@ -146,44 +163,66 @@ void config() throws NoSuchAlgorithmException, IOException {
146163 .buildAndStart ())
147164 .withMessage ("cannot configure 'inetAddress' and 'hostname' at the same time" );
148165
149- // ssl doesn't work without in tests
150- run (
151- HTTPServer .builder ()
152- .port (0 )
153- .httpsConfigurator (new HttpsConfigurator (SSLContext .getDefault ()))
154- .buildAndStart (),
155- "" ,
156- "/" );
166+ // SSL doesn't work in this simple test configuration
167+ assertThatExceptionOfType (IOException .class )
168+ .isThrownBy (
169+ () ->
170+ run (
171+ HTTPServer .builder ()
172+ .port (0 )
173+ .httpsConfigurator (new HttpsConfigurator (SSLContext .getDefault ()))
174+ .buildAndStart (),
175+ "/" ,
176+ 0 ,
177+ "ignored" ));
157178 }
158179
159180 @ Test
160- void health () throws IOException {
161- run (HTTPServer .builder ().port (0 ).buildAndStart (), "200 " , "/-/ healthy" );
181+ void health () throws Exception {
182+ run (HTTPServer .builder ().port (0 ).buildAndStart (), "/-/healthy " , 200 , "Exporter is healthy. " );
162183 }
163184
164185 @ Test
165- void healthEnabled () throws IOException {
186+ void healthEnabled () throws Exception {
166187 HttpHandler handler = exchange -> exchange .sendResponseHeaders (204 , -1 );
167188 run (
168189 HTTPServer .builder ()
169190 .port (0 )
170191 .defaultHandler (handler )
171192 .registerHealthHandler (true )
172193 .buildAndStart (),
173- "200" ,
174- "/-/healthy" );
194+ "/-/healthy" ,
195+ 200 ,
196+ "Exporter is healthy." );
175197 }
176198
177199 @ Test
178- void healthDisabled () throws IOException {
200+ void healthDisabled () throws Exception {
179201 HttpHandler handler = exchange -> exchange .sendResponseHeaders (204 , -1 );
180202 run (
181203 HTTPServer .builder ()
182204 .port (0 )
183205 .defaultHandler (handler )
184206 .registerHealthHandler (false )
185207 .buildAndStart (),
186- "204" ,
187- "/-/healthy" );
208+ "/-/healthy" ,
209+ 204 ,
210+ "" );
211+ }
212+
213+ private static void run (
214+ HTTPServer server , String path , int expectedStatusCode , String expectedBody )
215+ throws Exception {
216+ try (final HttpClient client = HttpClient .newBuilder ().build ()) {
217+ final URI uri = URI .create ("http://localhost:%s%s" .formatted (server .getPort (), path ));
218+ final HttpRequest request = HttpRequest .newBuilder ().uri (uri ).GET ().build ();
219+
220+ final HttpResponse <String > response =
221+ client .send (request , HttpResponse .BodyHandlers .ofString ());
222+ assertThat (response .statusCode ()).isEqualTo (expectedStatusCode );
223+ assertThat (response .body ()).contains (expectedBody );
224+ } finally {
225+ server .stop ();
226+ }
188227 }
189228}
0 commit comments