• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017 The gRPC Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.grpc.testing.integration;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertTrue;
21 
22 import io.grpc.ManagedChannel;
23 import io.grpc.ManagedChannelBuilder;
24 import io.grpc.netty.NettyChannelBuilder;
25 import java.io.IOException;
26 import java.io.PrintWriter;
27 import java.io.StringWriter;
28 import java.text.SimpleDateFormat;
29 import java.util.Calendar;
30 import java.util.Queue;
31 import java.util.concurrent.ConcurrentLinkedQueue;
32 import java.util.logging.Handler;
33 import java.util.logging.LogRecord;
34 import java.util.logging.Logger;
35 import java.util.logging.SimpleFormatter;
36 import javax.servlet.http.HttpServlet;
37 import javax.servlet.http.HttpServletRequest;
38 import javax.servlet.http.HttpServletResponse;
39 import org.junit.Ignore;
40 import org.junit.runner.JUnitCore;
41 import org.junit.runner.Result;
42 import org.junit.runner.notification.Failure;
43 
44 /**
45  * This servlet communicates with {@code grpc-test.sandbox.googleapis.com}, which is a server
46  * managed by the gRPC team. For more information, see
47  * <a href="https://github.com/grpc/grpc/blob/master/doc/interop-test-descriptions.md">
48  *   Interoperability Test Case Descriptions</a>.
49  */
50 @SuppressWarnings("serial")
51 public final class NettyClientInteropServlet extends HttpServlet {
52   private static final String INTEROP_TEST_ADDRESS = "grpc-test.sandbox.googleapis.com:443";
53 
54   private static final class LogEntryRecorder extends Handler {
55     private Queue<LogRecord> loggedMessages = new ConcurrentLinkedQueue<>();
56 
57     @Override
publish(LogRecord logRecord)58     public void publish(LogRecord logRecord) {
59       loggedMessages.add(logRecord);
60     }
61 
62     @Override
flush()63     public void flush() {}
64 
65     @Override
close()66     public void close() {}
67 
getLogOutput()68     public String getLogOutput() {
69       SimpleFormatter formatter = new SimpleFormatter();
70       StringBuilder sb = new StringBuilder();
71       for (LogRecord loggedMessage : loggedMessages) {
72         sb.append(formatter.format(loggedMessage));
73       }
74       return sb.toString();
75     }
76   }
77 
78   @Override
doGet(HttpServletRequest req, HttpServletResponse resp)79   public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
80     LogEntryRecorder handler = new LogEntryRecorder();
81     Logger.getLogger("").addHandler(handler);
82     try {
83       doGetHelper(req, resp);
84     } finally {
85       Logger.getLogger("").removeHandler(handler);
86     }
87     resp.getWriter().append("=======================================\n")
88         .append("Server side java.util.logging messages:\n")
89         .append(handler.getLogOutput());
90   }
91 
doGetHelper(HttpServletRequest req, HttpServletResponse resp)92   private void doGetHelper(HttpServletRequest req, HttpServletResponse resp) throws IOException {
93     resp.setContentType("text/plain");
94     PrintWriter writer = resp.getWriter();
95     writer.println("Test invoked at: ");
96     writer.println(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss Z")
97         .format(Calendar.getInstance().getTime()));
98 
99     Result result = new JUnitCore().run(Tester.class);
100     if (result.wasSuccessful()) {
101       resp.setStatus(200);
102       writer.println(
103           String.format(
104               "PASS! Tests ran %d, tests ignored %d",
105               result.getRunCount(),
106               result.getIgnoreCount()));
107     } else {
108       resp.setStatus(500);
109       writer.println(
110           String.format(
111               "FAILED! Tests ran %d, tests failed %d, tests ignored %d",
112               result.getRunCount(),
113               result.getFailureCount(),
114               result.getIgnoreCount()));
115       for (Failure failure : result.getFailures()) {
116         writer.println("================================");
117         writer.println(failure.getTestHeader());
118         Throwable thrown = failure.getException();
119         StringWriter stringWriter = new StringWriter();
120         PrintWriter printWriter = new PrintWriter(stringWriter);
121         thrown.printStackTrace(printWriter);
122         writer.println(stringWriter);
123       }
124     }
125   }
126 
127   public static final class Tester extends AbstractInteropTest {
128     @Override
createChannel()129     protected ManagedChannel createChannel() {
130       assertEquals(
131           "jdk8 required",
132           "1.8",
133           System.getProperty("java.specification.version"));
134       ManagedChannelBuilder<?> builder =
135           ManagedChannelBuilder.forTarget(INTEROP_TEST_ADDRESS)
136               .maxInboundMessageSize(AbstractInteropTest.MAX_MESSAGE_SIZE);
137       assertTrue(builder instanceof NettyChannelBuilder);
138       ((NettyChannelBuilder) builder).flowControlWindow(65 * 1024);
139       return builder.build();
140     }
141 
142     @Override
metricsExpected()143     protected boolean metricsExpected() {
144       // Server-side metrics won't be found because the server is running remotely.
145       return false;
146     }
147 
148     // grpc-test.sandbox.googleapis.com does not support these tests
149     @Ignore
150     @Override
customMetadata()151     public void customMetadata() { }
152 
153     @Ignore
154     @Override
statusCodeAndMessage()155     public void statusCodeAndMessage() { }
156 
157     @Ignore
158     @Override
exchangeMetadataUnaryCall()159     public void exchangeMetadataUnaryCall() { }
160 
161     @Ignore
162     @Override
exchangeMetadataStreamingCall()163     public void exchangeMetadataStreamingCall() { }
164 
165     @Ignore
166     @Override
specialStatusMessage()167     public void specialStatusMessage() {}
168   }
169 }
170