Skip to content

Commit fbea923

Browse files
committed
fix: Test coverage script should ignore generated code in the .mdx package.
1 parent c910796 commit fbea923

4 files changed

Lines changed: 126 additions & 54 deletions

File tree

.kokoro/check_coverage.sh

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,23 @@
1616
# `-e` enables the script to automatically fail when a command fails
1717
set -e
1818

19-
export CUR_COVER=$(cat core/target/site/jacoco/index.html | grep -o 'Total[^%]*' | sed 's/<.*>//; s/Total//')
20-
echo "Current Coverage is $CUR_COVER%"
19+
# Calculate total coverage, skipping the generated protobuf file.
20+
# The CSV file generated by Jacoco has the test coverage for each. We use AWK to process this CSV file.
21+
# here's what the AWK program means:
22+
#
23+
# NR > 1 && Skip the first line, it only has field names
24+
# $3 != "com.google.cloud.sql.core.mdx" Skip any line for class in the protobuf generated package 'mdx'
25+
# { covered += $6; total += $6+$5; } For each line add a running sum of covered lines and total lines
26+
# END { printf "%2.f", covered/total * 100}' At the end, print out the coverage percentage, no decimals
27+
#
28+
29+
CUR_COVER=$( awk -F, \
30+
'NR > 1 && $3 != "com.google.cloud.sql.core.mdx" { covered += $6; total += $6+$5; } END { printf "%2.f", covered/total * 100}' \
31+
< "core/target/site/jacoco/jacoco.csv")
32+
2133
if [ "$CUR_COVER" -lt 75 ]; then
34+
echo "FAIL: Current Coverage is $CUR_COVER%, less than the required 75%"
2235
exit 1;
36+
else
37+
echo "PASS: Current Coverage is $CUR_COVER%"
2338
fi

build.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,13 @@ function clean() {
3030
}
3131

3232
## build - Builds the project without running tests.
33-
function test() {
33+
function build() {
3434
mvn install -DskipTests=true
3535
}
3636

3737
## test - Runs local unit tests.
3838
function test() {
39-
mvn install
39+
mvn -P coverage test
4040
}
4141

4242
## e2e - Runs end-to-end integration tests.

core/src/main/java/com/google/cloud/sql/core/MdxSocket.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class MdxSocket extends SSLSocket {
4646
private final AtomicBoolean firstWriteAttempted = new AtomicBoolean(false);
4747
private final AtomicBoolean firstReadAttempted = new AtomicBoolean(false);
4848
private final AtomicReference<MetadataExchange.MetadataExchangeResponse> response =
49-
new AtomicReference();
49+
new AtomicReference<>();
5050
private final MetadataExchange.MetadataExchangeRequest.ClientProtocolType clientProtocolType;
5151

5252
MdxSocket(
@@ -61,6 +61,10 @@ class MdxSocket extends SSLSocket {
6161
this.clientProtocolType = clientProtocolType;
6262
}
6363

64+
MetadataExchange.MetadataExchangeResponse getMdxResponse() {
65+
return response.get();
66+
}
67+
6468
void sendMdxIfFirstWrite() throws IOException {
6569
if (firstWriteAttempted.compareAndSet(false, true)) {
6670
protocolHandler.sendMdx(out, this.clientProtocolType);

core/src/test/java/com/google/cloud/sql/core/ProtocolHandlerTest.java

Lines changed: 102 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.net.InetAddress;
3030
import java.net.ServerSocket;
3131
import java.net.Socket;
32+
import java.net.SocketException;
3233
import java.nio.charset.StandardCharsets;
3334
import java.security.KeyPair;
3435
import java.security.KeyPairGenerator;
@@ -55,6 +56,21 @@
5556

5657
public class ProtocolHandlerTest {
5758

59+
public static final byte[] SERVER_DATA = "hello".getBytes(StandardCharsets.UTF_8);
60+
public static final byte[] CLIENT_DATA = "from client".getBytes(StandardCharsets.UTF_8);
61+
public static final byte[] MDX_REQUEST_DATA;
62+
public static final byte[] WANT_FULL_REQUEST_BYTES;
63+
64+
static {
65+
byte[] wantClientMessage = CLIENT_DATA;
66+
MDX_REQUEST_DATA = wantRequestBytes();
67+
byte[] wantRequest = new byte[wantClientMessage.length + MDX_REQUEST_DATA.length];
68+
System.arraycopy(MDX_REQUEST_DATA, 0, wantRequest, 0, MDX_REQUEST_DATA.length);
69+
System.arraycopy(
70+
wantClientMessage, 0, wantRequest, MDX_REQUEST_DATA.length, wantClientMessage.length);
71+
WANT_FULL_REQUEST_BYTES = wantRequest;
72+
}
73+
5874
@Test
5975
public void testSendMdx() throws IOException {
6076
ByteArrayOutputStream out = new ByteArrayOutputStream();
@@ -85,35 +101,42 @@ public void testReadMdx_WithMdxResponse() throws IOException {
85101
public void testMdxSocket_clientWritesFirst_noMdxResponse() throws Exception {
86102
// 1. The client connects, writes to the server, sending an MDX request,
87103
// reads from the server but receives no MDX response
104+
AtomicReference<byte[]> requestBytes = new AtomicReference<>();
88105

89106
// Setup SSL server that expects an MDX request, but does not send an MDX response.
90107
SslServer server =
91108
new SslServer(
92109
(in, out) -> {
93110
// Server reads the client's MDX request.
94-
byte[] req = new byte[wantRequestBytes().length];
111+
byte[] req = new byte[CLIENT_DATA.length];
95112
new DataInputStream(in).readFully(req);
96-
assertThat(req).isEqualTo(wantRequestBytes());
113+
requestBytes.set(req);
97114

98115
// Server writes a non-MDX response.
99116
out.write("hello".getBytes(StandardCharsets.UTF_8));
117+
out.flush();
100118
});
101119
SslServer.SslServerParams p = server.start();
102120

103121
// Setup client socket
104-
Socket socket = new ProtocolHandler("ua").connect(p.getSocket(), "tls");
122+
MdxSocket socket = new ProtocolHandler("ua").connect(p.getSocket(), "tls");
105123

106124
// Client writes, which should trigger the MDX exchange.
107-
socket.getOutputStream().write("from client".getBytes(StandardCharsets.UTF_8));
125+
socket.getOutputStream().write(CLIENT_DATA);
126+
socket.getOutputStream().flush();
108127

109128
// The server should not have sent an MDX response, so the client should
110129
// read the raw "hello" from the server.
111130
byte[] fromServer = new byte[5];
112131
new DataInputStream(socket.getInputStream()).readFully(fromServer);
113-
assertThat(fromServer).isEqualTo("hello".getBytes(StandardCharsets.UTF_8));
132+
while (requestBytes.get() == null) {
133+
Thread.sleep(10);
134+
}
114135

115136
socket.close();
116137
server.stop();
138+
assertThat(fromServer).isEqualTo(SERVER_DATA);
139+
assertThat(socket.getMdxResponse()).isNull();
117140
}
118141

119142
@Test
@@ -127,35 +150,42 @@ public void testMdxSocket_clientWritesFirst_receivesMdxResponse() throws Excepti
127150
new SslServer(
128151
(in, out) -> {
129152
// Server reads the client's MDX request.
130-
byte[] req = new byte[wantRequestBytes().length];
153+
byte[] req = new byte[WANT_FULL_REQUEST_BYTES.length];
131154
new DataInputStream(in).readFully(req);
132155
requestBytes.set(req);
133156
// Server writes an MDX response.
134157
out.write(wantResponseBytes("hello".getBytes(StandardCharsets.UTF_8)));
158+
out.flush();
135159
});
136160

137161
SslServer.SslServerParams p = server.start();
138162

139163
// Setup client socket
140-
Socket socket = new ProtocolHandler("ua").connect(p.getSocket(), "tls");
164+
MdxSocket socket = new ProtocolHandler("ua").connect(p.getSocket(), "tls");
141165

142166
// Client writes, which should trigger the MDX exchange.
143-
socket.getOutputStream().write("from client".getBytes(StandardCharsets.UTF_8));
167+
socket.getOutputStream().write(CLIENT_DATA);
168+
socket.getOutputStream().flush();
144169

145170
// The server should have sent an MDX response, so the client should
146171
// read the "hello" from the server.
147172
byte[] fromServer = new byte[5];
148173
new DataInputStream(socket.getInputStream()).readFully(fromServer);
149-
assertThat(fromServer).isEqualTo("hello".getBytes(StandardCharsets.UTF_8));
150-
151-
assertThat(requestBytes.get()).isEqualTo(wantRequestBytes());
174+
while (requestBytes.get() == null) {
175+
Thread.sleep(10);
176+
}
152177

153178
socket.close();
154179
server.stop();
180+
181+
assertThat(fromServer).isEqualTo("hello".getBytes(StandardCharsets.UTF_8));
182+
assertThat(requestBytes.get()).isEqualTo(WANT_FULL_REQUEST_BYTES);
183+
assertThat(socket.getMdxResponse()).isNotNull();
155184
}
156185

157186
@Test
158187
public void testMdxSocket_clientReadsFirst_noMdxResponse() throws Exception {
188+
159189
// 3. The client connects, reads from the server but receives no MDX response,
160190
// then writes to the server, sending an MDX request
161191
AtomicReference<byte[]> requestBytes = new AtomicReference<>();
@@ -166,36 +196,43 @@ public void testMdxSocket_clientReadsFirst_noMdxResponse() throws Exception {
166196
(in, out) -> {
167197
// Server writes a non-MDX response.
168198
out.write("hello".getBytes(StandardCharsets.UTF_8));
199+
out.flush();
169200

170201
// Server reads the client's MDX request.
171-
byte[] req = new byte[wantRequestBytes().length];
202+
byte[] req = new byte[WANT_FULL_REQUEST_BYTES.length];
172203
new DataInputStream(in).readFully(req);
173204
requestBytes.set(req);
174205
});
175206
SslServer.SslServerParams p = server.start();
176207

177208
// Setup client socket
178-
Socket socket = new ProtocolHandler("ua").connect(p.getSocket(), "tls");
209+
MdxSocket socket = new ProtocolHandler("ua").connect(p.getSocket(), "tls");
179210

180211
// The server should not have sent an MDX response, so the client should
181212
// read the raw "hello" from the server.
182213
byte[] fromServer = new byte[5];
183214
new DataInputStream(socket.getInputStream()).readFully(fromServer);
184-
assertThat(fromServer).isEqualTo("hello".getBytes(StandardCharsets.UTF_8));
185-
assertThat(requestBytes.get()).isNull();
186215

187216
// Client writes, which should trigger the MDX exchange.
188-
socket.getOutputStream().write("from client".getBytes(StandardCharsets.UTF_8));
217+
socket.getOutputStream().write(CLIENT_DATA);
218+
socket.getOutputStream().flush();
219+
while (requestBytes.get() == null) {
220+
Thread.sleep(10);
221+
}
189222

190223
socket.close();
191224
server.stop();
225+
226+
assertThat(fromServer).isEqualTo("hello".getBytes(StandardCharsets.UTF_8));
227+
assertThat(requestBytes.get()).isEqualTo(WANT_FULL_REQUEST_BYTES);
228+
assertThat(socket.getMdxResponse()).isNull();
192229
}
193230

194231
@Test
195-
public void testMdxSocket_clientReadsFirst_receivesMdxResponse() throws Exception {
196-
// 4. The client connects, reads from the server and receives an MDX response,
232+
public void testMdxSocket_clientReadsFirst_receivesMdxResponse_writesMdxRequest()
233+
throws Exception {
234+
// 4. The client connects, reads from the server and receives no MDX response,
197235
// then writes to the server, sending an MDX request
198-
199236
AtomicReference<byte[]> requestBytes = new AtomicReference<>();
200237

201238
// Setup SSL server that expects an MDX request and sends an MDX response.
@@ -204,32 +241,39 @@ public void testMdxSocket_clientReadsFirst_receivesMdxResponse() throws Exceptio
204241
(in, out) -> {
205242
// Server writes a non-MDX response.
206243
out.write("hello".getBytes(StandardCharsets.UTF_8));
244+
out.flush();
207245

208246
// Server reads the client's MDX request.
209-
byte[] req = new byte[wantRequestBytes().length];
247+
byte[] req = new byte[WANT_FULL_REQUEST_BYTES.length];
210248
new DataInputStream(in).readFully(req);
211249
requestBytes.set(req);
212250
});
213251
SslServer.SslServerParams p = server.start();
214252

215253
// Setup client socket
216-
Socket socket = new ProtocolHandler("ua").connect(p.getSocket(), "tls");
254+
MdxSocket socket = new ProtocolHandler("ua").connect(p.getSocket(), "tls");
217255

218-
// The server should have sent an MDX response, so the client should
256+
// The server should not send MDX response, so the client should
219257
// read the "hello" from the server.
220258
byte[] fromServer = new byte[5];
221259
new DataInputStream(socket.getInputStream()).readFully(fromServer);
222-
assertThat(fromServer).isEqualTo("hello".getBytes(StandardCharsets.UTF_8));
223260

224261
// Client writes, which should trigger the MDX exchange.
225-
socket.getOutputStream().write("from client".getBytes(StandardCharsets.UTF_8));
226-
assertThat(requestBytes.get()).isNull();
262+
socket.getOutputStream().write(CLIENT_DATA);
263+
socket.getOutputStream().flush();
264+
while (requestBytes.get() == null) {
265+
Thread.sleep(10);
266+
}
227267

228268
socket.close();
229269
server.stop();
270+
271+
assertThat(fromServer).isEqualTo("hello".getBytes(StandardCharsets.UTF_8));
272+
assertThat(requestBytes.get()).isEqualTo(WANT_FULL_REQUEST_BYTES);
273+
assertThat(socket.getMdxResponse()).isNull();
230274
}
231275

232-
private static byte[] wantRequestBytes() throws IOException {
276+
private static byte[] wantRequestBytes() {
233277
ByteArrayOutputStream wantOut = new ByteArrayOutputStream();
234278
MetadataExchange.MetadataExchangeRequest req =
235279
MetadataExchange.MetadataExchangeRequest.newBuilder()
@@ -238,39 +282,46 @@ private static byte[] wantRequestBytes() throws IOException {
238282
.build();
239283
int size = req.getSerializedSize();
240284

241-
// Write the protocoal header
242-
wantOut.write("CSQLMDEX".getBytes(StandardCharsets.UTF_8));
243-
// Write the uint32 size
244-
wantOut.write((size >>> 24) & 0xFF);
245-
wantOut.write((size >>> 16) & 0xFF);
246-
wantOut.write((size >>> 8) & 0xFF);
247-
wantOut.write(size & 0xFF);
248-
// Write the protobuf
249-
req.writeTo(wantOut);
250-
wantOut.flush();
285+
try {
286+
// Write the protocoal header
287+
wantOut.write("CSQLMDEX".getBytes(StandardCharsets.UTF_8));
288+
// Write the uint32 size
289+
wantOut.write((byte) ((size >>> 24) & 0xFF));
290+
wantOut.write((byte) ((size >>> 16) & 0xFF));
291+
wantOut.write((byte) ((size >>> 8) & 0xFF));
292+
wantOut.write((byte) (size & 0xFF));
293+
// Write the protobuf
294+
req.writeTo(wantOut);
295+
} catch (IOException e) {
296+
throw new RuntimeException(e);
297+
}
298+
251299
return wantOut.toByteArray();
252300
}
253301

254-
private static byte[] wantResponseBytes(byte[] data) throws IOException {
302+
private static byte[] wantResponseBytes(byte[] data) {
255303
ByteArrayOutputStream wantOut = new ByteArrayOutputStream();
256304
MetadataExchange.MetadataExchangeResponse res =
257305
MetadataExchange.MetadataExchangeResponse.newBuilder()
258306
.setResponseStatusCode(MetadataExchange.MetadataExchangeResponse.ResponseStatusCode.OK)
259307
.build();
260-
261308
int size = res.getSerializedSize();
262309

263-
// Write the protocoal header
264-
wantOut.write("CSQLMDEX".getBytes(StandardCharsets.UTF_8));
265-
// Write the uint32 size
266-
wantOut.write((size >>> 24) & 0xFF);
267-
wantOut.write((size >>> 16) & 0xFF);
268-
wantOut.write((size >>> 8) & 0xFF);
269-
wantOut.write(size & 0xFF);
270-
// Write the protobuf
271-
res.writeTo(wantOut);
272-
wantOut.write(data);
273-
wantOut.flush();
310+
try {
311+
// Write the protocoal header
312+
wantOut.write("CSQLMDEX".getBytes(StandardCharsets.UTF_8));
313+
// Write the uint32 size
314+
wantOut.write((size >>> 24) & 0xFF);
315+
wantOut.write((size >>> 16) & 0xFF);
316+
wantOut.write((size >>> 8) & 0xFF);
317+
wantOut.write(size & 0xFF);
318+
// Write the protobuf
319+
res.writeTo(wantOut);
320+
wantOut.write(data);
321+
wantOut.flush();
322+
} catch (IOException e) {
323+
throw new RuntimeException(e);
324+
}
274325
return wantOut.toByteArray();
275326
}
276327

@@ -312,6 +363,8 @@ private SslServerParams start() throws Exception {
312363
}
313364
handler.accept(s.getInputStream(), s.getOutputStream());
314365
}
366+
} catch (SocketException e) {
367+
// do nothing, we don't care if the socket was closed.
315368
} catch (Exception e) {
316369
throw new RuntimeException(e);
317370
}

0 commit comments

Comments
 (0)