(ctx context.Context, in *testpb.SimpleRequest)
| 101 | } |
| 102 | |
| 103 | func (s *testServiceImpl) UnaryCall(ctx context.Context, in *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { |
| 104 | response := &testpb.SimpleResponse{ServerId: s.serverID, Hostname: s.hostname} |
| 105 | if in.ResponseSize > 0 { |
| 106 | response.Payload = &testpb.Payload{ |
| 107 | Body: make([]byte, in.ResponseSize), |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | forLoop: |
| 112 | for _, headerVal := range getRPCBehaviorMetadata(ctx) { |
| 113 | // A value can have a prefix "hostname=<string>" followed by a space. |
| 114 | // In that case, the rest of the value should only be applied |
| 115 | // if the specified hostname matches the server's hostname. |
| 116 | if strings.HasPrefix(headerVal, hostnamePfx) { |
| 117 | splitVal := strings.Split(headerVal, " ") |
| 118 | if len(splitVal) <= 1 { |
| 119 | return nil, status.Errorf(codes.InvalidArgument, "invalid format for rpc-behavior header %v, must be 'hostname=<string> <header>=<value>' instead", headerVal) |
| 120 | } |
| 121 | |
| 122 | if s.hostname != splitVal[0][len(hostnamePfx):] { |
| 123 | continue forLoop |
| 124 | } |
| 125 | headerVal = splitVal[1] |
| 126 | } |
| 127 | |
| 128 | switch { |
| 129 | // If the value matches "sleep-<int>", the server should wait |
| 130 | // the specified number of seconds before resuming |
| 131 | // behavior matching and RPC processing. |
| 132 | case strings.HasPrefix(headerVal, sleepPfx): |
| 133 | sleep, err := strconv.Atoi(headerVal[len(sleepPfx):]) |
| 134 | if err != nil { |
| 135 | return nil, status.Errorf(codes.InvalidArgument, "invalid format for rpc-behavior header %v, must be 'sleep-<int>' instead", headerVal) |
| 136 | } |
| 137 | time.Sleep(time.Duration(sleep) * time.Second) |
| 138 | |
| 139 | // If the value matches "keep-open", the server should |
| 140 | // never respond to the request and behavior matching ends. |
| 141 | case strings.HasPrefix(headerVal, keepOpenVal): |
| 142 | <-ctx.Done() |
| 143 | return nil, nil |
| 144 | |
| 145 | // If the value matches "error-code-<int>", the server should |
| 146 | // respond with the specified status code and behavior matching ends. |
| 147 | case strings.HasPrefix(headerVal, errorCodePfx): |
| 148 | code, err := strconv.Atoi(headerVal[len(errorCodePfx):]) |
| 149 | if err != nil { |
| 150 | return nil, status.Errorf(codes.InvalidArgument, "invalid format for rpc-behavior header %v, must be 'error-code-<int>' instead", headerVal) |
| 151 | } |
| 152 | return nil, status.Errorf(codes.Code(code), "rpc failed as per the rpc-behavior header value: %v", headerVal) |
| 153 | |
| 154 | // If the value matches "success-on-retry-attempt-<int>", and the |
| 155 | // value of the "grpc-previous-rpc-attempts" metadata field is equal to |
| 156 | // the specified number, the normal RPC processing should resume |
| 157 | // and behavior matching ends. |
| 158 | case strings.HasPrefix(headerVal, succeedOnRetryPfx): |
| 159 | wantRetry, err := strconv.Atoi(headerVal[len(succeedOnRetryPfx):]) |
| 160 | if err != nil { |
nothing calls this directly
no test coverage detected