blob: 03f8a1a86341acc680dcb0da79da2dac4ab517b3 [file] [log] [blame]
// // Copyright 2021-2023 Buf Technologies, Inc.
// //
// // Licensed under the Apache License, Version 2.0 (the "License");
// // you may not use this file except in compliance with the License.
// // You may obtain a copy of the License at
// //
// // http://www.apache.org/licenses/LICENSE-2.0
// //
// // Unless required by applicable law or agreed to in writing, software
// // distributed under the License is distributed on an "AS IS" BASIS,
// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// // See the License for the specific language governing permissions and
// // limitations under the License.
package triple_protocol_test
//
//import (
// "context"
// "net/http"
// "net/http/httptest"
// "testing"
//
// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/assert"
// pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/proto/connect/ping/v1"
// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/proto/connect/ping/v1/pingv1connect"
//)
//
//func TestOnionOrderingEndToEnd(t *testing.T) {
// t.Parallel()
// // Helper function: returns a function that asserts that there's some value
// // set for header "expect", and adds a value for header "add".
// newInspector := func(expect, add string) func(triple.Spec, http.Header) {
// return func(spec triple.Spec, header http.Header) {
// if expect != "" {
// assert.NotZero(
// t,
// header.Get(expect),
// assert.Sprintf(
// "%s (IsClient %v): header %q missing: %v",
// spec.Procedure,
// spec.IsClient,
// expect,
// header,
// ),
// )
// }
// header.Set(add, "v")
// }
// }
// // Helper function: asserts that there's a value present for header keys
// // "one", "two", "three", and "four".
// assertAllPresent := func(spec triple.Spec, header http.Header) {
// for _, key := range []string{"one", "two", "three", "four"} {
// assert.NotZero(
// t,
// header.Get(key),
// assert.Sprintf(
// "%s (IsClient %v): checking all headers, %q missing: %v",
// spec.Procedure,
// spec.IsClient,
// key,
// header,
// ),
// )
// }
// }
//
// // The client and handler interceptor onions are the meat of the test. The
// // order of interceptor execution must be the same for unary and streaming
// // procedures.
// //
// // Requests should fall through the client onion from top to bottom, traverse
// // the network, and then fall through the handler onion from top to bottom.
// // Responses should climb up the handler onion, traverse the network, and
// // then climb up the client onion.
// //
// // The request and response sides of this onion are numbered to make the
// // intended order clear.
// clientOnion := triple.WithInterceptors(
// newHeaderInterceptor(
// // 1 (start). request: should see protocol-related headers
// func(_ triple.Spec, h http.Header) {
// assert.NotZero(t, h.Get("Content-Type"))
// },
// // 12 (end). response: check "one"-"four"
// assertAllPresent,
// ),
// newHeaderInterceptor(
// newInspector("", "one"), // 2. request: add header "one"
// newInspector("three", "four"), // 11. response: check "three", add "four"
// ),
// newHeaderInterceptor(
// newInspector("one", "two"), // 3. request: check "one", add "two"
// newInspector("two", "three"), // 10. response: check "two", add "three"
// ),
// )
// handlerOnion := triple.WithInterceptors(
// newHeaderInterceptor(
// newInspector("two", "three"), // 4. request: check "two", add "three"
// newInspector("one", "two"), // 9. response: check "one", add "two"
// ),
// newHeaderInterceptor(
// newInspector("three", "four"), // 5. request: check "three", add "four"
// newInspector("", "one"), // 8. response: add "one"
// ),
// newHeaderInterceptor(
// assertAllPresent, // 6. request: check "one"-"four"
// nil, // 7. response: no-op
// ),
// )
//
// mux := http.NewServeMux()
// mux.Handle(
// pingv1connect.NewPingServiceHandler(
// pingServer{},
// handlerOnion,
// ),
// )
// server := httptest.NewServer(mux)
// defer server.Close()
//
// client := pingv1connect.NewPingServiceClient(
// server.Client(),
// server.URL,
// clientOnion,
// )
//
// _, err := client.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{Number: 10}))
// assert.Nil(t, err)
//
// responses, err := client.CountUp(context.Background(), triple.NewRequest(&pingv1.CountUpRequest{Number: 10}))
// assert.Nil(t, err)
// var sum int64
// for responses.Receive() {
// sum += responses.Msg().Number
// }
// assert.Equal(t, sum, 55)
// assert.Nil(t, responses.Close())
//}
//
//func TestEmptyUnaryInterceptorFunc(t *testing.T) {
// t.Parallel()
// mux := http.NewServeMux()
// interceptor := triple.UnaryInterceptorFunc(func(next triple.UnaryFunc) triple.UnaryFunc {
// return func(ctx context.Context, request triple.AnyRequest) (triple.AnyResponse, error) {
// return next(ctx, request)
// }
// })
// mux.Handle(pingv1connect.NewPingServiceHandler(pingServer{}, triple.WithInterceptors(interceptor)))
// server := httptest.NewServer(mux)
// t.Cleanup(server.Close)
// connectClient := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithInterceptors(interceptor))
// _, err := connectClient.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{}))
// assert.Nil(t, err)
// sumStream, err := connectClient.Sum(context.Background())
// assert.Nil(t, err)
// assert.Nil(t, sumStream.Send(&pingv1.SumRequest{Number: 1}))
// resp, err := sumStream.CloseAndReceive()
// assert.Nil(t, err)
// assert.NotNil(t, resp)
// countUpStream, err := connectClient.CountUp(context.Background(), triple.NewRequest(&pingv1.CountUpRequest{}))
// assert.Nil(t, err)
// for countUpStream.Receive() {
// assert.NotNil(t, countUpStream.Msg())
// }
// assert.Nil(t, countUpStream.Close())
//}
//
//// headerInterceptor makes it easier to write interceptors that inspect or
//// mutate HTTP headers. It applies the same logic to unary and streaming
//// procedures, wrapping the send or receive side of the stream as appropriate.
////
//// It's useful as a testing harness to make sure that we're chaining
//// interceptors in the correct order.
//type headerInterceptor struct {
// inspectRequestHeader func(triple.Spec, http.Header)
// inspectResponseHeader func(triple.Spec, http.Header)
//}
//
//// newHeaderInterceptor constructs a headerInterceptor. Nil function pointers
//// are treated as no-ops.
//func newHeaderInterceptor(
// inspectRequestHeader func(triple.Spec, http.Header),
// inspectResponseHeader func(triple.Spec, http.Header),
//) *headerInterceptor {
// interceptor := headerInterceptor{
// inspectRequestHeader: inspectRequestHeader,
// inspectResponseHeader: inspectResponseHeader,
// }
// if interceptor.inspectRequestHeader == nil {
// interceptor.inspectRequestHeader = func(_ triple.Spec, _ http.Header) {}
// }
// if interceptor.inspectResponseHeader == nil {
// interceptor.inspectResponseHeader = func(_ triple.Spec, _ http.Header) {}
// }
// return &interceptor
//}
//
//func (h *headerInterceptor) WrapUnary(next triple.UnaryFunc) triple.UnaryFunc {
// return func(ctx context.Context, req triple.AnyRequest) (triple.AnyResponse, error) {
// h.inspectRequestHeader(req.Spec(), req.Header())
// res, err := next(ctx, req)
// if err != nil {
// return nil, err
// }
// h.inspectResponseHeader(req.Spec(), res.Header())
// return res, nil
// }
//}
//
//func (h *headerInterceptor) WrapStreamingClient(next triple.StreamingClientFunc) triple.StreamingClientFunc {
// return func(ctx context.Context, spec triple.Spec) triple.StreamingClientConn {
// return &headerInspectingClientConn{
// StreamingClientConn: next(ctx, spec),
// inspectRequestHeader: h.inspectRequestHeader,
// inspectResponseHeader: h.inspectResponseHeader,
// }
// }
//}
//
//func (h *headerInterceptor) WrapStreamingHandler(next triple.StreamingHandlerFunc) triple.StreamingHandlerFunc {
// return func(ctx context.Context, conn triple.StreamingHandlerConn) error {
// h.inspectRequestHeader(conn.Spec(), conn.RequestHeader())
// return next(ctx, &headerInspectingHandlerConn{
// StreamingHandlerConn: conn,
// inspectResponseHeader: h.inspectResponseHeader,
// })
// }
//}
//
//type headerInspectingHandlerConn struct {
// triple.StreamingHandlerConn
//
// inspectedResponse bool
// inspectResponseHeader func(triple.Spec, http.Header)
//}
//
//func (hc *headerInspectingHandlerConn) Send(msg any) error {
// if !hc.inspectedResponse {
// hc.inspectResponseHeader(hc.Spec(), hc.ResponseHeader())
// hc.inspectedResponse = true
// }
// return hc.StreamingHandlerConn.Send(msg)
//}
//
//type headerInspectingClientConn struct {
// triple.StreamingClientConn
//
// inspectedRequest bool
// inspectRequestHeader func(triple.Spec, http.Header)
// inspectedResponse bool
// inspectResponseHeader func(triple.Spec, http.Header)
//}
//
//func (cc *headerInspectingClientConn) Send(msg any) error {
// if !cc.inspectedRequest {
// cc.inspectRequestHeader(cc.Spec(), cc.RequestHeader())
// cc.inspectedRequest = true
// }
// return cc.StreamingClientConn.Send(msg)
//}
//
//func (cc *headerInspectingClientConn) Receive(msg any) error {
// err := cc.StreamingClientConn.Receive(msg)
// if !cc.inspectedResponse {
// cc.inspectResponseHeader(cc.Spec(), cc.ResponseHeader())
// cc.inspectedResponse = true
// }
// return err
//}