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.Grpc; 23 import io.grpc.ManagedChannelBuilder; 24 import io.grpc.TlsChannelCredentials; 25 import io.grpc.netty.NettyChannelBuilder; 26 import java.io.IOException; 27 import java.io.PrintWriter; 28 import java.io.StringWriter; 29 import java.text.SimpleDateFormat; 30 import java.util.Calendar; 31 import java.util.Locale; 32 import java.util.Queue; 33 import java.util.concurrent.ConcurrentLinkedQueue; 34 import java.util.logging.Handler; 35 import java.util.logging.LogRecord; 36 import java.util.logging.Logger; 37 import java.util.logging.SimpleFormatter; 38 import javax.servlet.http.HttpServlet; 39 import javax.servlet.http.HttpServletRequest; 40 import javax.servlet.http.HttpServletResponse; 41 import org.junit.Ignore; 42 import org.junit.runner.JUnitCore; 43 import org.junit.runner.Result; 44 import org.junit.runner.notification.Failure; 45 46 /** 47 * This servlet communicates with {@code grpc-test.sandbox.googleapis.com}, which is a server 48 * managed by the gRPC team. For more information, see 49 * <a href="https://github.com/grpc/grpc/blob/master/doc/interop-test-descriptions.md"> 50 * Interoperability Test Case Descriptions</a>. 51 */ 52 @SuppressWarnings("serial") 53 public final class NettyClientInteropServlet extends HttpServlet { 54 private static final String INTEROP_TEST_ADDRESS = "grpc-test.sandbox.googleapis.com:443"; 55 56 private static final class LogEntryRecorder extends Handler { 57 private Queue<LogRecord> loggedMessages = new ConcurrentLinkedQueue<>(); 58 59 @Override publish(LogRecord logRecord)60 public void publish(LogRecord logRecord) { 61 loggedMessages.add(logRecord); 62 } 63 64 @Override flush()65 public void flush() {} 66 67 @Override close()68 public void close() {} 69 getLogOutput()70 public String getLogOutput() { 71 SimpleFormatter formatter = new SimpleFormatter(); 72 StringBuilder sb = new StringBuilder(); 73 for (LogRecord loggedMessage : loggedMessages) { 74 sb.append(formatter.format(loggedMessage)); 75 } 76 return sb.toString(); 77 } 78 } 79 80 @Override doGet(HttpServletRequest req, HttpServletResponse resp)81 public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { 82 LogEntryRecorder handler = new LogEntryRecorder(); 83 Logger.getLogger("").addHandler(handler); 84 try { 85 doGetHelper(resp); 86 } finally { 87 Logger.getLogger("").removeHandler(handler); 88 } 89 resp.getWriter().append("=======================================\n") 90 .append("Server side java.util.logging messages:\n") 91 .append(handler.getLogOutput()); 92 } 93 doGetHelper(HttpServletResponse resp)94 private void doGetHelper(HttpServletResponse resp) throws IOException { 95 resp.setContentType("text/plain"); 96 PrintWriter writer = resp.getWriter(); 97 writer.println("Test invoked at: "); 98 writer.println(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss Z") 99 .format(Calendar.getInstance().getTime())); 100 101 Result result = new JUnitCore().run(Tester.class); 102 if (result.wasSuccessful()) { 103 resp.setStatus(200); 104 writer.println( 105 String.format( 106 Locale.US, 107 "PASS! Tests ran %d, tests ignored %d", 108 result.getRunCount(), 109 result.getIgnoreCount())); 110 } else { 111 resp.setStatus(500); 112 writer.println( 113 String.format( 114 Locale.US, 115 "FAILED! Tests ran %d, tests failed %d, tests ignored %d", 116 result.getRunCount(), 117 result.getFailureCount(), 118 result.getIgnoreCount())); 119 for (Failure failure : result.getFailures()) { 120 writer.println("================================"); 121 writer.println(failure.getTestHeader()); 122 Throwable thrown = failure.getException(); 123 StringWriter stringWriter = new StringWriter(); 124 PrintWriter printWriter = new PrintWriter(stringWriter); 125 thrown.printStackTrace(printWriter); 126 writer.println(stringWriter); 127 } 128 } 129 } 130 131 public static final class Tester extends AbstractInteropTest { 132 @Override createChannelBuilder()133 protected ManagedChannelBuilder<?> createChannelBuilder() { 134 assertEquals( 135 "jdk8 required", 136 "1.8", 137 System.getProperty("java.specification.version")); 138 ManagedChannelBuilder<?> builder = 139 Grpc.newChannelBuilder(INTEROP_TEST_ADDRESS, TlsChannelCredentials.create()) 140 .maxInboundMessageSize(AbstractInteropTest.MAX_MESSAGE_SIZE); 141 assertTrue(builder instanceof NettyChannelBuilder); 142 ((NettyChannelBuilder) builder) 143 .flowControlWindow(AbstractInteropTest.TEST_FLOW_CONTROL_WINDOW); 144 return builder; 145 } 146 147 @Override metricsExpected()148 protected boolean metricsExpected() { 149 // Server-side metrics won't be found because the server is running remotely. 150 return false; 151 } 152 153 // grpc-test.sandbox.googleapis.com does not support these tests 154 @Ignore 155 @Override customMetadata()156 public void customMetadata() { } 157 158 @Ignore 159 @Override statusCodeAndMessage()160 public void statusCodeAndMessage() { } 161 162 @Ignore 163 @Override exchangeMetadataUnaryCall()164 public void exchangeMetadataUnaryCall() { } 165 166 @Ignore 167 @Override exchangeMetadataStreamingCall()168 public void exchangeMetadataStreamingCall() { } 169 170 @Ignore 171 @Override specialStatusMessage()172 public void specialStatusMessage() {} 173 } 174 } 175