blob: 3e21a541151b72ae0d16f2212224ccd66c2b4fd3 [file] [log] [blame]
John Boiles57852792018-01-05 14:37:05 -08001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20package common
21
22import (
23 "context"
24 "fmt"
25 "net"
26 "net/http"
27 "net/url"
28 "os"
29 "syscall"
30 "testing"
John Boiles57852792018-01-05 14:37:05 -080031 "time"
Yuxuan 'fishy' Wangb71f11e2021-03-22 15:01:00 -070032
33 "github.com/apache/thrift/lib/go/thrift"
John Boiles57852792018-01-05 14:37:05 -080034)
35
36type slowHttpHandler struct{}
37
38func (slowHttpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
39 time.Sleep(1 * time.Second)
40}
41
42func TestHttpContextTimeout(t *testing.T) {
43 certPath = "../../../keys"
44
45 unit := test_unit{"127.0.0.1", 9096, "", "http", "binary", false}
46
47 server := &http.Server{Addr: unit.host + fmt.Sprintf(":%d", unit.port), Handler: slowHttpHandler{}}
48 go server.ListenAndServe()
49
50 client, trans, err := StartClient(unit.host, unit.port, unit.domain_socket, unit.transport, unit.protocol, unit.ssl)
51 if err != nil {
52 t.Errorf("Unable to start client: %v", err)
53 return
54 }
55 defer trans.Close()
56
57 unwrapErr := func(err error) error {
58 for {
59 switch err.(type) {
60 case thrift.TTransportException:
61 err = err.(thrift.TTransportException).Err()
62 case *url.Error:
63 err = err.(*url.Error).Err
64 case *net.OpError:
65 err = err.(*net.OpError).Err
66 case *os.SyscallError:
67 err = err.(*os.SyscallError).Err
68 default:
69 return err
70 }
71 }
72 }
73
74 serverStartupDeadline := time.Now().Add(5 * time.Second)
75 for {
76 ctx, _ := context.WithTimeout(context.Background(), 50*time.Millisecond)
77 err = client.TestVoid(ctx)
78 err = unwrapErr(err)
79 if err != syscall.ECONNREFUSED || time.Now().After(serverStartupDeadline) {
80 break
81 }
82 time.Sleep(time.Millisecond)
83 }
84
85 if err == nil {
86 t.Errorf("Request completed (should have timed out)")
87 return
88 }
89
90 // We've got to switch on `err.Error()` here since go1.7 doesn't properly return
91 // `context.DeadlineExceeded` error and `http.errRequestCanceled` is not exported.
92 // See https://github.com/golang/go/issues/17711
93 switch err.Error() {
94 case context.DeadlineExceeded.Error(), "net/http: request canceled":
95 // Expected error
96 default:
97 t.Errorf("Unexpected error: %s", err)
98 }
99}