func officialAddr(unresolvedAddr string, resolvedAddr net.Addr) (*util.UnresolvedAddr, error) { unresolvedHost, unresolvedPort, err := net.SplitHostPort(unresolvedAddr) if err != nil { return nil, err } resolvedHost, resolvedPort, err := net.SplitHostPort(resolvedAddr.String()) if err != nil { return nil, err } var host string if unresolvedHost != "" { // A host was provided, use it. host = unresolvedHost } else { // A host was not provided. Ask the system, and fall back to the listener. if hostname, err := os.Hostname(); err == nil { host = hostname } else { host = resolvedHost } } var port string if unresolvedPort != "0" { // A port was provided, use it. port = unresolvedPort } else { // A port was not provided, but the system assigned one. port = resolvedPort } return util.NewUnresolvedAddr(resolvedAddr.Network(), net.JoinHostPort(host, port)), nil }
func (tr *testResolver) GetAddress() (net.Addr, error) { defer func() { tr.numTries++ }() if tr.numTries < tr.numFails { return nil, errors.New("bad address") } return util.NewUnresolvedAddr("tcp", tr.addr), nil }
func checkOfficialize(t *testing.T, network, oldAddrString, newAddrString, expAddrString string) { resolvedAddr := util.NewUnresolvedAddr(network, newAddrString) if unresolvedAddr, err := officialAddr(oldAddrString, resolvedAddr); err != nil { t.Fatal(err) } else if retAddrString := unresolvedAddr.String(); retAddrString != expAddrString { t.Errorf("officialAddr(%s, %s) was %s; expected %s", oldAddrString, newAddrString, retAddrString, expAddrString) } }
// setupSendNextTest sets up a situation in which SendNextTimeout has // caused RPCs to be sent to all three replicas simultaneously. The // caller may then cause those RPCs to finish by writing to one of the // 'done' channels in the first return value; the second returned // channel will contain the final result of the send() call. // // TODO(bdarnell): all the 'done' channels are currently the same. // Either give each call its own channel, return a list of (replica // descriptor, channel) pair, or decide we don't care about // distinguishing them and just send a single channel. func setupSendNextTest(t *testing.T) ([]chan<- BatchCall, chan BatchCall, *stop.Stopper) { stopper := stop.NewStopper() nodeContext := newNodeTestContext(hlc.NewClock(hlc.UnixNano, time.Nanosecond), stopper) addrs := []net.Addr{ util.NewUnresolvedAddr("dummy", "1"), util.NewUnresolvedAddr("dummy", "2"), util.NewUnresolvedAddr("dummy", "3"), } doneChanChan := make(chan chan<- BatchCall, len(addrs)) opts := SendOptions{ ctx: context.Background(), SendNextTimeout: 1 * time.Millisecond, transportFactory: func(_ SendOptions, _ *rpc.Context, replicas ReplicaSlice, _ roachpb.BatchRequest, ) (Transport, error) { return &channelSaveTransport{ ch: doneChanChan, remaining: len(replicas), }, nil }, } sendChan := make(chan BatchCall, 1) go func() { // Send the batch. This will block until we signal one of the done // channels. br, err := sendBatch(opts, addrs, nodeContext) sendChan <- BatchCall{br, err} }() doneChans := make([]chan<- BatchCall, len(addrs)) for i := range doneChans { // Note that this blocks until the replica has been contacted. doneChans[i] = <-doneChanChan } return doneChans, sendChan, stopper }
// GetAddress returns a net.Addr or error. func (sr *socketResolver) GetAddress() (net.Addr, error) { switch sr.typ { case "tcp": _, err := net.ResolveTCPAddr("tcp", sr.addr) if err != nil { return nil, err } return util.NewUnresolvedAddr("tcp", sr.addr), nil } return nil, errors.Errorf("unknown address type: %q", sr.typ) }
// TestComplexScenarios verifies various complex success/failure scenarios by // mocking sendOne. func TestComplexScenarios(t *testing.T) { defer leaktest.AfterTest(t)() stopper := stop.NewStopper() defer stopper.Stop() nodeContext := newNodeTestContext(hlc.NewClock(hlc.UnixNano, time.Nanosecond), stopper) // TODO(bdarnell): the retryable flag is no longer used for RPC errors. // Rework this test to incorporate application-level errors carried in // the BatchResponse. testCases := []struct { numServers int numErrors int success bool }{ // --- Success scenarios --- {1, 0, true}, {5, 0, true}, // There are some errors, but enough RPCs succeed. {5, 1, true}, {5, 4, true}, {5, 2, true}, // --- Failure scenarios --- // All RPCs fail. {5, 5, false}, } for i, test := range testCases { var serverAddrs []net.Addr for j := 0; j < test.numServers; j++ { serverAddrs = append(serverAddrs, util.NewUnresolvedAddr("dummy", strconv.Itoa(j))) } opts := SendOptions{ ctx: context.Background(), transportFactory: func(_ SendOptions, _ *rpc.Context, replicas ReplicaSlice, args roachpb.BatchRequest, ) (Transport, error) { return &firstNErrorTransport{ replicas: replicas, args: args, numErrors: test.numErrors, }, nil }, } reply, err := sendBatch(opts, serverAddrs, nodeContext) if test.success { if err != nil { t.Errorf("%d: unexpected error: %s", i, err) } if reply == nil { t.Errorf("%d: expected reply", i) } } else { if err == nil { t.Errorf("%d: unexpected success", i) } } } }