View Javadoc
1   /*
2    * The MIT License (MIT)
3    *
4    * Copyright (c) 2013 - 2023, Tapio Rautonen
5    *
6    * Permission is hereby granted, free of charge, to any person obtaining a copy
7    * of this software and associated documentation files (the "Software"), to deal
8    * in the Software without restriction, including without limitation the rights
9    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10   * copies of the Software, and to permit persons to whom the Software is
11   * furnished to do so, subject to the following conditions:
12   *
13   * The above copyright notice and this permission notice shall be included in
14   * all copies or substantial portions of the Software.
15   *
16   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22   * THE SOFTWARE.
23   */
24  package org.eluder.coveralls.maven.plugin.httpclient;
25  
26  import static org.junit.jupiter.api.Assertions.assertNotNull;
27  import static org.junit.jupiter.api.Assertions.assertThrows;
28  import static org.mockito.ArgumentMatchers.any;
29  import static org.mockito.Mockito.mock;
30  import static org.mockito.Mockito.when;
31  
32  import com.fasterxml.jackson.core.JsonProcessingException;
33  import com.fasterxml.jackson.databind.ObjectMapper;
34  
35  import java.io.ByteArrayInputStream;
36  import java.io.File;
37  import java.io.IOException;
38  import java.io.InputStream;
39  import java.nio.charset.StandardCharsets;
40  import java.nio.file.Files;
41  import java.nio.file.Path;
42  
43  import org.apache.http.Header;
44  import org.apache.http.HeaderElement;
45  import org.apache.http.HttpEntity;
46  import org.apache.http.HttpResponse;
47  import org.apache.http.HttpVersion;
48  import org.apache.http.NameValuePair;
49  import org.apache.http.StatusLine;
50  import org.apache.http.client.ClientProtocolException;
51  import org.apache.http.client.HttpClient;
52  import org.apache.http.client.methods.HttpUriRequest;
53  import org.apache.http.message.BasicStatusLine;
54  import org.eluder.coveralls.maven.plugin.ProcessingException;
55  import org.eluder.coveralls.maven.plugin.domain.CoverallsResponse;
56  import org.junit.jupiter.api.BeforeEach;
57  import org.junit.jupiter.api.Test;
58  import org.junit.jupiter.api.extension.ExtendWith;
59  import org.junit.jupiter.api.io.CleanupMode;
60  import org.junit.jupiter.api.io.TempDir;
61  import org.mockito.Mock;
62  import org.mockito.junit.jupiter.MockitoExtension;
63  
64  @ExtendWith(MockitoExtension.class)
65  class CoverallsClientTest {
66  
67      @Mock
68      private HttpClient httpClientMock;
69  
70      @Mock
71      private HttpResponse httpResponseMock;
72  
73      @Mock
74      private HttpEntity httpEntityMock;
75  
76      @TempDir(cleanup = CleanupMode.ON_SUCCESS)
77      public Path folder;
78  
79      private File file;
80  
81      @BeforeEach
82      public void init() throws IOException {
83          file = Files.createFile(folder.resolve("coverallsClientTest.tmp")).toFile();
84      }
85  
86      @Test
87      void testConstructors() {
88          assertNotNull(new CoverallsClient("http://test.com/coveralls"));
89          assertNotNull(new CoverallsClient("http://test.com/coveralls", httpClientMock, new ObjectMapper()));
90      }
91  
92      @Test
93      void testSubmit() throws UnsupportedOperationException, Exception  {
94          StatusLine statusLine = new BasicStatusLine(HttpVersion.HTTP_1_1, 200, "OK");
95          when(httpResponseMock.getStatusLine()).thenReturn(statusLine);
96          when(httpClientMock.execute(any(HttpUriRequest.class))).thenReturn(httpResponseMock);
97          when(httpResponseMock.getEntity()).thenReturn(httpEntityMock);
98          when(httpEntityMock.getContent()).thenReturn(coverallsResponse(new CoverallsResponse("success", false, "")));
99          CoverallsClient client = new CoverallsClient("http://test.com/coveralls", httpClientMock, new ObjectMapper());
100         client.submit(file);
101     }
102 
103     @Test
104     void testFailOnServiceError() throws ClientProtocolException, IOException  {
105         StatusLine statusLine = new BasicStatusLine(HttpVersion.HTTP_1_1, 500, "Internal Error");
106         when(httpClientMock.execute(any(HttpUriRequest.class))).thenReturn(httpResponseMock);
107         when(httpResponseMock.getStatusLine()).thenReturn(statusLine);
108         CoverallsClient client = new CoverallsClient("http://test.com/coveralls", httpClientMock, new ObjectMapper());
109         assertThrows(IOException.class, () -> {
110             client.submit(file);
111         });
112     }
113 
114     @Test
115     void testParseInvalidResponse() throws ClientProtocolException, IOException {
116         StatusLine statusLine = new BasicStatusLine(HttpVersion.HTTP_1_1, 200, "OK");
117         when(httpClientMock.execute(any(HttpUriRequest.class))).thenReturn(httpResponseMock);
118         when(httpResponseMock.getStatusLine()).thenReturn(statusLine);
119         when(httpResponseMock.getEntity()).thenReturn(httpEntityMock);
120         when(httpEntityMock.getContent()).thenReturn(new ByteArrayInputStream("{bogus}".getBytes(StandardCharsets.UTF_8)));
121         CoverallsClient client = new CoverallsClient("http://test.com/coveralls", httpClientMock, new ObjectMapper());
122         assertThrows(ProcessingException.class, () -> {
123             client.submit(file);
124         });
125     }
126 
127     @Test
128     void testParseErrorousResponse() throws UnsupportedOperationException, Exception {
129         StatusLine statusLine = new BasicStatusLine(HttpVersion.HTTP_1_1, 400, "Bad Request");
130         when(httpClientMock.execute(any(HttpUriRequest.class))).thenReturn(httpResponseMock);
131         when(httpResponseMock.getStatusLine()).thenReturn(statusLine);
132         when(httpResponseMock.getEntity()).thenReturn(httpEntityMock);
133         when(httpEntityMock.getContent()).thenReturn(coverallsResponse(new CoverallsResponse("failure", true, "submission failed")));
134         CoverallsClient client = new CoverallsClient("http://test.com/coveralls", httpClientMock, new ObjectMapper());
135         assertThrows(ProcessingException.class, () -> {
136             client.submit(file);
137         });
138     }
139 
140     @Test
141     void testParseFailingEntity() throws ClientProtocolException, IOException {
142         StatusLine statusLine = new BasicStatusLine(HttpVersion.HTTP_1_1, 200, "OK");
143         when(httpClientMock.execute(any(HttpUriRequest.class))).thenReturn(httpResponseMock);
144         when(httpResponseMock.getStatusLine()).thenReturn(statusLine);
145         when(httpResponseMock.getEntity()).thenReturn(httpEntityMock);
146         when(httpEntityMock.getContent()).thenThrow(IOException.class);
147         CoverallsClient client = new CoverallsClient("http://test.com/coveralls", httpClientMock, new ObjectMapper());
148         assertThrows(IOException.class, () -> {
149             client.submit(file);
150         });
151     }
152 
153     @Test
154     void testParseEntityWithoutContentType() throws ClientProtocolException, IOException {
155         StatusLine statusLine = new BasicStatusLine(HttpVersion.HTTP_1_1, 400, "Bad Request");
156         when(httpResponseMock.getStatusLine()).thenReturn(statusLine);
157         when(httpClientMock.execute(any(HttpUriRequest.class))).thenReturn(httpResponseMock);
158         when(httpResponseMock.getEntity()).thenReturn(httpEntityMock);
159         Header header = mock(Header.class);
160         HeaderElement element = mock(HeaderElement.class);
161         when(element.getName()).thenReturn("HeaderName");
162         NameValuePair pair = mock(NameValuePair.class);
163         when(pair.getName()).thenReturn("name");
164         when(element.getParameters()).thenReturn(new NameValuePair[] { pair } );
165         when(header.getElements()).thenReturn(new HeaderElement[] { element } );
166         when(httpEntityMock.getContentType()).thenReturn(header);
167         CoverallsClient client = new CoverallsClient("http://test.com/coveralls", httpClientMock, new ObjectMapper());
168         assertThrows(ProcessingException.class, () -> {
169             client.submit(file);
170         });
171     }
172 
173     private InputStream coverallsResponse(final CoverallsResponse coverallsResponse) throws JsonProcessingException {
174         String content = new ObjectMapper().writeValueAsString(coverallsResponse);
175         return new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
176     }
177 
178 }