|  | @@ -68,6 +68,7 @@ namespace testing {
 | 
	
		
			
				|  |  |  namespace {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void* tag(int i) { return (void*)(intptr_t)i; }
 | 
	
		
			
				|  |  | +int detag(void* p) { return static_cast<int>(reinterpret_cast<intptr_t>(p)); }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #ifdef GPR_POSIX_SOCKET
 | 
	
		
			
				|  |  |  static int maybe_assert_non_blocking_poll(struct pollfd* pfds, nfds_t nfds,
 | 
	
	
		
			
				|  | @@ -106,37 +107,50 @@ class PollingOverrider {
 | 
	
		
			
				|  |  |  class Verifier {
 | 
	
		
			
				|  |  |   public:
 | 
	
		
			
				|  |  |    explicit Verifier(bool spin) : spin_(spin) {}
 | 
	
		
			
				|  |  | +  // Expect sets the expected ok value for a specific tag
 | 
	
		
			
				|  |  |    Verifier& Expect(int i, bool expect_ok) {
 | 
	
		
			
				|  |  |      expectations_[tag(i)] = expect_ok;
 | 
	
		
			
				|  |  |      return *this;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  // Next waits for 1 async tag to complete, checks its
 | 
	
		
			
				|  |  | +  // expectations, and returns the tag
 | 
	
		
			
				|  |  | +  int Next(CompletionQueue* cq, bool ignore_ok) {
 | 
	
		
			
				|  |  | +    bool ok;
 | 
	
		
			
				|  |  | +    void* got_tag;
 | 
	
		
			
				|  |  | +    if (spin_) {
 | 
	
		
			
				|  |  | +      for (;;) {
 | 
	
		
			
				|  |  | +        auto r = cq->AsyncNext(&got_tag, &ok, gpr_time_0(GPR_CLOCK_REALTIME));
 | 
	
		
			
				|  |  | +        if (r == CompletionQueue::TIMEOUT) continue;
 | 
	
		
			
				|  |  | +        if (r == CompletionQueue::GOT_EVENT) break;
 | 
	
		
			
				|  |  | +        gpr_log(GPR_ERROR, "unexpected result from AsyncNext");
 | 
	
		
			
				|  |  | +        abort();
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +      EXPECT_TRUE(cq->Next(&got_tag, &ok));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    auto it = expectations_.find(got_tag);
 | 
	
		
			
				|  |  | +    EXPECT_TRUE(it != expectations_.end());
 | 
	
		
			
				|  |  | +    if (!ignore_ok) {
 | 
	
		
			
				|  |  | +      EXPECT_EQ(it->second, ok);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    expectations_.erase(it);
 | 
	
		
			
				|  |  | +    return detag(got_tag);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Verify keeps calling Next until all currently set
 | 
	
		
			
				|  |  | +  // expected tags are complete
 | 
	
		
			
				|  |  |    void Verify(CompletionQueue* cq) { Verify(cq, false); }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  // This version of Verify allows optionally ignoring the
 | 
	
		
			
				|  |  | +  // outcome of the expectation
 | 
	
		
			
				|  |  |    void Verify(CompletionQueue* cq, bool ignore_ok) {
 | 
	
		
			
				|  |  |      GPR_ASSERT(!expectations_.empty());
 | 
	
		
			
				|  |  |      while (!expectations_.empty()) {
 | 
	
		
			
				|  |  | -      bool ok;
 | 
	
		
			
				|  |  | -      void* got_tag;
 | 
	
		
			
				|  |  | -      if (spin_) {
 | 
	
		
			
				|  |  | -        for (;;) {
 | 
	
		
			
				|  |  | -          auto r = cq->AsyncNext(&got_tag, &ok, gpr_time_0(GPR_CLOCK_REALTIME));
 | 
	
		
			
				|  |  | -          if (r == CompletionQueue::TIMEOUT) continue;
 | 
	
		
			
				|  |  | -          if (r == CompletionQueue::GOT_EVENT) break;
 | 
	
		
			
				|  |  | -          gpr_log(GPR_ERROR, "unexpected result from AsyncNext");
 | 
	
		
			
				|  |  | -          abort();
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -      } else {
 | 
	
		
			
				|  |  | -        EXPECT_TRUE(cq->Next(&got_tag, &ok));
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -      auto it = expectations_.find(got_tag);
 | 
	
		
			
				|  |  | -      EXPECT_TRUE(it != expectations_.end());
 | 
	
		
			
				|  |  | -      if (!ignore_ok) {
 | 
	
		
			
				|  |  | -        EXPECT_EQ(it->second, ok);
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -      expectations_.erase(it);
 | 
	
		
			
				|  |  | +      Next(cq, ignore_ok);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | +  // This version of Verify stops after a certain deadline
 | 
	
		
			
				|  |  |    void Verify(CompletionQueue* cq,
 | 
	
		
			
				|  |  |                std::chrono::system_clock::time_point deadline) {
 | 
	
		
			
				|  |  |      if (expectations_.empty()) {
 | 
	
	
		
			
				|  | @@ -793,7 +807,8 @@ TEST_P(AsyncEnd2endTest, UnimplementedRpc) {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // This class is for testing scenarios where RPCs are cancelled on the server
 | 
	
		
			
				|  |  | -// by calling ServerContext::TryCancel()
 | 
	
		
			
				|  |  | +// by calling ServerContext::TryCancel(). Server uses AsyncNotifyWhenDone
 | 
	
		
			
				|  |  | +// API to check for cancellation
 | 
	
		
			
				|  |  |  class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
 | 
	
		
			
				|  |  |   protected:
 | 
	
		
			
				|  |  |    typedef enum {
 | 
	
	
		
			
				|  | @@ -803,13 +818,6 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
 | 
	
		
			
				|  |  |      CANCEL_AFTER_PROCESSING
 | 
	
		
			
				|  |  |    } ServerTryCancelRequestPhase;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  void ServerTryCancel(ServerContext* context) {
 | 
	
		
			
				|  |  | -    EXPECT_FALSE(context->IsCancelled());
 | 
	
		
			
				|  |  | -    context->TryCancel();
 | 
	
		
			
				|  |  | -    gpr_log(GPR_INFO, "Server called TryCancel()");
 | 
	
		
			
				|  |  | -    EXPECT_TRUE(context->IsCancelled());
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    // Helper for testing client-streaming RPCs which are cancelled on the server.
 | 
	
		
			
				|  |  |    // Depending on the value of server_try_cancel parameter, this will test one
 | 
	
		
			
				|  |  |    // of the following three scenarios:
 | 
	
	
		
			
				|  | @@ -843,6 +851,7 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // On the server, request to be notified of 'RequestStream' calls
 | 
	
		
			
				|  |  |      // and receive the 'RequestStream' call just made by the client
 | 
	
		
			
				|  |  | +    srv_ctx.AsyncNotifyWhenDone(tag(11));
 | 
	
		
			
				|  |  |      service_.RequestRequestStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
 | 
	
		
			
				|  |  |                                    tag(2));
 | 
	
		
			
				|  |  |      Verifier(GetParam()).Expect(2, true).Verify(cq_.get());
 | 
	
	
		
			
				|  | @@ -858,9 +867,12 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      bool expected_server_cq_result = true;
 | 
	
		
			
				|  |  |      bool ignore_cq_result = false;
 | 
	
		
			
				|  |  | +    bool want_done_tag = false;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      if (server_try_cancel == CANCEL_BEFORE_PROCESSING) {
 | 
	
		
			
				|  |  | -      ServerTryCancel(&srv_ctx);
 | 
	
		
			
				|  |  | +      srv_ctx.TryCancel();
 | 
	
		
			
				|  |  | +      Verifier(GetParam()).Expect(11, true).Verify(cq_.get());
 | 
	
		
			
				|  |  | +      EXPECT_TRUE(srv_ctx.IsCancelled());
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |        // Since cancellation is done before server reads any results, we know
 | 
	
		
			
				|  |  |        // for sure that all cq results will return false from this point forward
 | 
	
	
		
			
				|  | @@ -868,22 +880,39 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      std::thread* server_try_cancel_thd = NULL;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    auto verif = Verifier(GetParam());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      if (server_try_cancel == CANCEL_DURING_PROCESSING) {
 | 
	
		
			
				|  |  | -      server_try_cancel_thd = new std::thread(
 | 
	
		
			
				|  |  | -          &AsyncEnd2endServerTryCancelTest::ServerTryCancel, this, &srv_ctx);
 | 
	
		
			
				|  |  | +      server_try_cancel_thd =
 | 
	
		
			
				|  |  | +          new std::thread(&ServerContext::TryCancel, &srv_ctx);
 | 
	
		
			
				|  |  |        // Server will cancel the RPC in a parallel thread while reading the
 | 
	
		
			
				|  |  |        // requests from the client. Since the cancellation can happen at anytime,
 | 
	
		
			
				|  |  |        // some of the cq results (i.e those until cancellation) might be true but
 | 
	
		
			
				|  |  |        // its non deterministic. So better to ignore the cq results
 | 
	
		
			
				|  |  |        ignore_cq_result = true;
 | 
	
		
			
				|  |  | +      // Expect that we might possibly see the done tag that
 | 
	
		
			
				|  |  | +      // indicates cancellation completion in this case
 | 
	
		
			
				|  |  | +      want_done_tag = true;
 | 
	
		
			
				|  |  | +      verif.Expect(11, true);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // Server reads 3 messages (tags 6, 7 and 8)
 | 
	
		
			
				|  |  | +    // But if want_done_tag is true, we might also see tag 11
 | 
	
		
			
				|  |  |      for (int tag_idx = 6; tag_idx <= 8; tag_idx++) {
 | 
	
		
			
				|  |  |        srv_stream.Read(&recv_request, tag(tag_idx));
 | 
	
		
			
				|  |  | -      Verifier(GetParam())
 | 
	
		
			
				|  |  | -          .Expect(tag_idx, expected_server_cq_result)
 | 
	
		
			
				|  |  | -          .Verify(cq_.get(), ignore_cq_result);
 | 
	
		
			
				|  |  | +      // Note that we'll add something to the verifier and verify that
 | 
	
		
			
				|  |  | +      // something was seen, but it might be tag 11 and not what we
 | 
	
		
			
				|  |  | +      // just added
 | 
	
		
			
				|  |  | +      int got_tag = verif.Expect(tag_idx, expected_server_cq_result)
 | 
	
		
			
				|  |  | +                        .Next(cq_.get(), ignore_cq_result);
 | 
	
		
			
				|  |  | +      GPR_ASSERT((got_tag == tag_idx) || (got_tag == 11 && want_done_tag));
 | 
	
		
			
				|  |  | +      if (got_tag == 11) {
 | 
	
		
			
				|  |  | +        EXPECT_TRUE(srv_ctx.IsCancelled());
 | 
	
		
			
				|  |  | +        want_done_tag = false;
 | 
	
		
			
				|  |  | +        // Now get the other entry that we were waiting on
 | 
	
		
			
				|  |  | +        EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_result), tag_idx);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      if (server_try_cancel_thd != NULL) {
 | 
	
	
		
			
				|  | @@ -892,7 +921,15 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      if (server_try_cancel == CANCEL_AFTER_PROCESSING) {
 | 
	
		
			
				|  |  | -      ServerTryCancel(&srv_ctx);
 | 
	
		
			
				|  |  | +      srv_ctx.TryCancel();
 | 
	
		
			
				|  |  | +      want_done_tag = true;
 | 
	
		
			
				|  |  | +      verif.Expect(11, true);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (want_done_tag) {
 | 
	
		
			
				|  |  | +      verif.Verify(cq_.get());
 | 
	
		
			
				|  |  | +      EXPECT_TRUE(srv_ctx.IsCancelled());
 | 
	
		
			
				|  |  | +      want_done_tag = false;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // The RPC has been cancelled at this point for sure (i.e irrespective of
 | 
	
	
		
			
				|  | @@ -945,6 +982,7 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
 | 
	
		
			
				|  |  |      Verifier(GetParam()).Expect(1, true).Verify(cq_.get());
 | 
	
		
			
				|  |  |      // On the server, request to be notified of 'ResponseStream' calls and
 | 
	
		
			
				|  |  |      // receive the call just made by the client
 | 
	
		
			
				|  |  | +    srv_ctx.AsyncNotifyWhenDone(tag(11));
 | 
	
		
			
				|  |  |      service_.RequestResponseStream(&srv_ctx, &recv_request, &srv_stream,
 | 
	
		
			
				|  |  |                                     cq_.get(), cq_.get(), tag(2));
 | 
	
		
			
				|  |  |      Verifier(GetParam()).Expect(2, true).Verify(cq_.get());
 | 
	
	
		
			
				|  | @@ -952,9 +990,12 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      bool expected_cq_result = true;
 | 
	
		
			
				|  |  |      bool ignore_cq_result = false;
 | 
	
		
			
				|  |  | +    bool want_done_tag = false;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      if (server_try_cancel == CANCEL_BEFORE_PROCESSING) {
 | 
	
		
			
				|  |  | -      ServerTryCancel(&srv_ctx);
 | 
	
		
			
				|  |  | +      srv_ctx.TryCancel();
 | 
	
		
			
				|  |  | +      Verifier(GetParam()).Expect(11, true).Verify(cq_.get());
 | 
	
		
			
				|  |  | +      EXPECT_TRUE(srv_ctx.IsCancelled());
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |        // We know for sure that all cq results will be false from this point
 | 
	
		
			
				|  |  |        // since the server cancelled the RPC
 | 
	
	
		
			
				|  | @@ -962,24 +1003,41 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      std::thread* server_try_cancel_thd = NULL;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    auto verif = Verifier(GetParam());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      if (server_try_cancel == CANCEL_DURING_PROCESSING) {
 | 
	
		
			
				|  |  | -      server_try_cancel_thd = new std::thread(
 | 
	
		
			
				|  |  | -          &AsyncEnd2endServerTryCancelTest::ServerTryCancel, this, &srv_ctx);
 | 
	
		
			
				|  |  | +      server_try_cancel_thd =
 | 
	
		
			
				|  |  | +          new std::thread(&ServerContext::TryCancel, &srv_ctx);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |        // Server will cancel the RPC in a parallel thread while writing responses
 | 
	
		
			
				|  |  |        // to the client. Since the cancellation can happen at anytime, some of
 | 
	
		
			
				|  |  |        // the cq results (i.e those until cancellation) might be true but it is
 | 
	
		
			
				|  |  |        // non deterministic. So better to ignore the cq results
 | 
	
		
			
				|  |  |        ignore_cq_result = true;
 | 
	
		
			
				|  |  | +      // Expect that we might possibly see the done tag that
 | 
	
		
			
				|  |  | +      // indicates cancellation completion in this case
 | 
	
		
			
				|  |  | +      want_done_tag = true;
 | 
	
		
			
				|  |  | +      verif.Expect(11, true);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // Server sends three messages (tags 3, 4 and 5)
 | 
	
		
			
				|  |  | +    // But if want_done tag is true, we might also see tag 11
 | 
	
		
			
				|  |  |      for (int tag_idx = 3; tag_idx <= 5; tag_idx++) {
 | 
	
		
			
				|  |  |        send_response.set_message("Pong " + std::to_string(tag_idx));
 | 
	
		
			
				|  |  |        srv_stream.Write(send_response, tag(tag_idx));
 | 
	
		
			
				|  |  | -      Verifier(GetParam())
 | 
	
		
			
				|  |  | -          .Expect(tag_idx, expected_cq_result)
 | 
	
		
			
				|  |  | -          .Verify(cq_.get(), ignore_cq_result);
 | 
	
		
			
				|  |  | +      // Note that we'll add something to the verifier and verify that
 | 
	
		
			
				|  |  | +      // something was seen, but it might be tag 11 and not what we
 | 
	
		
			
				|  |  | +      // just added
 | 
	
		
			
				|  |  | +      int got_tag = verif.Expect(tag_idx, expected_cq_result)
 | 
	
		
			
				|  |  | +                        .Next(cq_.get(), ignore_cq_result);
 | 
	
		
			
				|  |  | +      GPR_ASSERT((got_tag == tag_idx) || (got_tag == 11 && want_done_tag));
 | 
	
		
			
				|  |  | +      if (got_tag == 11) {
 | 
	
		
			
				|  |  | +        EXPECT_TRUE(srv_ctx.IsCancelled());
 | 
	
		
			
				|  |  | +        want_done_tag = false;
 | 
	
		
			
				|  |  | +        // Now get the other entry that we were waiting on
 | 
	
		
			
				|  |  | +        EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_result), tag_idx);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      if (server_try_cancel_thd != NULL) {
 | 
	
	
		
			
				|  | @@ -988,13 +1046,21 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      if (server_try_cancel == CANCEL_AFTER_PROCESSING) {
 | 
	
		
			
				|  |  | -      ServerTryCancel(&srv_ctx);
 | 
	
		
			
				|  |  | +      srv_ctx.TryCancel();
 | 
	
		
			
				|  |  | +      want_done_tag = true;
 | 
	
		
			
				|  |  | +      verif.Expect(11, true);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |        // Client reads may fail bacause it is notified that the stream is
 | 
	
		
			
				|  |  |        // cancelled.
 | 
	
		
			
				|  |  |        ignore_cq_result = true;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    if (want_done_tag) {
 | 
	
		
			
				|  |  | +      verif.Verify(cq_.get());
 | 
	
		
			
				|  |  | +      EXPECT_TRUE(srv_ctx.IsCancelled());
 | 
	
		
			
				|  |  | +      want_done_tag = false;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      // Client attemts to read the three messages from the server
 | 
	
		
			
				|  |  |      for (int tag_idx = 6; tag_idx <= 8; tag_idx++) {
 | 
	
		
			
				|  |  |        cli_stream->Read(&recv_response, tag(tag_idx));
 | 
	
	
		
			
				|  | @@ -1052,6 +1118,7 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // On the server, request to be notified of the 'BidiStream' call and
 | 
	
		
			
				|  |  |      // receive the call just made by the client
 | 
	
		
			
				|  |  | +    srv_ctx.AsyncNotifyWhenDone(tag(11));
 | 
	
		
			
				|  |  |      service_.RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
 | 
	
		
			
				|  |  |                                 tag(2));
 | 
	
		
			
				|  |  |      Verifier(GetParam()).Expect(2, true).Verify(cq_.get());
 | 
	
	
		
			
				|  | @@ -1063,9 +1130,12 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      bool expected_cq_result = true;
 | 
	
		
			
				|  |  |      bool ignore_cq_result = false;
 | 
	
		
			
				|  |  | +    bool want_done_tag = false;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      if (server_try_cancel == CANCEL_BEFORE_PROCESSING) {
 | 
	
		
			
				|  |  | -      ServerTryCancel(&srv_ctx);
 | 
	
		
			
				|  |  | +      srv_ctx.TryCancel();
 | 
	
		
			
				|  |  | +      Verifier(GetParam()).Expect(11, true).Verify(cq_.get());
 | 
	
		
			
				|  |  | +      EXPECT_TRUE(srv_ctx.IsCancelled());
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |        // We know for sure that all cq results will be false from this point
 | 
	
		
			
				|  |  |        // since the server cancelled the RPC
 | 
	
	
		
			
				|  | @@ -1073,42 +1143,84 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      std::thread* server_try_cancel_thd = NULL;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    auto verif = Verifier(GetParam());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      if (server_try_cancel == CANCEL_DURING_PROCESSING) {
 | 
	
		
			
				|  |  | -      server_try_cancel_thd = new std::thread(
 | 
	
		
			
				|  |  | -          &AsyncEnd2endServerTryCancelTest::ServerTryCancel, this, &srv_ctx);
 | 
	
		
			
				|  |  | +      server_try_cancel_thd =
 | 
	
		
			
				|  |  | +          new std::thread(&ServerContext::TryCancel, &srv_ctx);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |        // Since server is going to cancel the RPC in a parallel thread, some of
 | 
	
		
			
				|  |  |        // the cq results (i.e those until the cancellation) might be true. Since
 | 
	
		
			
				|  |  |        // that number is non-deterministic, it is better to ignore the cq results
 | 
	
		
			
				|  |  |        ignore_cq_result = true;
 | 
	
		
			
				|  |  | +      // Expect that we might possibly see the done tag that
 | 
	
		
			
				|  |  | +      // indicates cancellation completion in this case
 | 
	
		
			
				|  |  | +      want_done_tag = true;
 | 
	
		
			
				|  |  | +      verif.Expect(11, true);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    int got_tag;
 | 
	
		
			
				|  |  |      srv_stream.Read(&recv_request, tag(4));
 | 
	
		
			
				|  |  | -    Verifier(GetParam())
 | 
	
		
			
				|  |  | -        .Expect(4, expected_cq_result)
 | 
	
		
			
				|  |  | -        .Verify(cq_.get(), ignore_cq_result);
 | 
	
		
			
				|  |  | +    verif.Expect(4, expected_cq_result);
 | 
	
		
			
				|  |  | +    got_tag = verif.Next(cq_.get(), ignore_cq_result);
 | 
	
		
			
				|  |  | +    GPR_ASSERT((got_tag == 4) || (got_tag == 11 && want_done_tag));
 | 
	
		
			
				|  |  | +    if (got_tag == 11) {
 | 
	
		
			
				|  |  | +      EXPECT_TRUE(srv_ctx.IsCancelled());
 | 
	
		
			
				|  |  | +      want_done_tag = false;
 | 
	
		
			
				|  |  | +      // Now get the other entry that we were waiting on
 | 
	
		
			
				|  |  | +      EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_result), 4);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      send_response.set_message("Pong");
 | 
	
		
			
				|  |  |      srv_stream.Write(send_response, tag(5));
 | 
	
		
			
				|  |  | -    Verifier(GetParam())
 | 
	
		
			
				|  |  | -        .Expect(5, expected_cq_result)
 | 
	
		
			
				|  |  | -        .Verify(cq_.get(), ignore_cq_result);
 | 
	
		
			
				|  |  | +    verif.Expect(5, expected_cq_result);
 | 
	
		
			
				|  |  | +    got_tag = verif.Next(cq_.get(), ignore_cq_result);
 | 
	
		
			
				|  |  | +    GPR_ASSERT((got_tag == 5) || (got_tag == 11 && want_done_tag));
 | 
	
		
			
				|  |  | +    if (got_tag == 11) {
 | 
	
		
			
				|  |  | +      EXPECT_TRUE(srv_ctx.IsCancelled());
 | 
	
		
			
				|  |  | +      want_done_tag = false;
 | 
	
		
			
				|  |  | +      // Now get the other entry that we were waiting on
 | 
	
		
			
				|  |  | +      EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_result), 5);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      cli_stream->Read(&recv_response, tag(6));
 | 
	
		
			
				|  |  | -    Verifier(GetParam())
 | 
	
		
			
				|  |  | -        .Expect(6, expected_cq_result)
 | 
	
		
			
				|  |  | -        .Verify(cq_.get(), ignore_cq_result);
 | 
	
		
			
				|  |  | +    verif.Expect(6, expected_cq_result);
 | 
	
		
			
				|  |  | +    got_tag = verif.Next(cq_.get(), ignore_cq_result);
 | 
	
		
			
				|  |  | +    GPR_ASSERT((got_tag == 6) || (got_tag == 11 && want_done_tag));
 | 
	
		
			
				|  |  | +    if (got_tag == 11) {
 | 
	
		
			
				|  |  | +      EXPECT_TRUE(srv_ctx.IsCancelled());
 | 
	
		
			
				|  |  | +      want_done_tag = false;
 | 
	
		
			
				|  |  | +      // Now get the other entry that we were waiting on
 | 
	
		
			
				|  |  | +      EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_result), 6);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // This is expected to succeed in all cases
 | 
	
		
			
				|  |  |      cli_stream->WritesDone(tag(7));
 | 
	
		
			
				|  |  | -    Verifier(GetParam()).Expect(7, true).Verify(cq_.get());
 | 
	
		
			
				|  |  | +    verif.Expect(7, true);
 | 
	
		
			
				|  |  | +    got_tag = verif.Next(cq_.get(), ignore_cq_result);
 | 
	
		
			
				|  |  | +    GPR_ASSERT((got_tag == 7) || (got_tag == 11 && want_done_tag));
 | 
	
		
			
				|  |  | +    if (got_tag == 11) {
 | 
	
		
			
				|  |  | +      EXPECT_TRUE(srv_ctx.IsCancelled());
 | 
	
		
			
				|  |  | +      want_done_tag = false;
 | 
	
		
			
				|  |  | +      // Now get the other entry that we were waiting on
 | 
	
		
			
				|  |  | +      EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_result), 7);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // This is expected to fail in all cases i.e for all values of
 | 
	
		
			
				|  |  |      // server_try_cancel. This is because at this point, either there are no
 | 
	
		
			
				|  |  |      // more msgs from the client (because client called WritesDone) or the RPC
 | 
	
		
			
				|  |  |      // is cancelled on the server
 | 
	
		
			
				|  |  |      srv_stream.Read(&recv_request, tag(8));
 | 
	
		
			
				|  |  | -    Verifier(GetParam()).Expect(8, false).Verify(cq_.get());
 | 
	
		
			
				|  |  | +    verif.Expect(8, false);
 | 
	
		
			
				|  |  | +    got_tag = verif.Next(cq_.get(), ignore_cq_result);
 | 
	
		
			
				|  |  | +    GPR_ASSERT((got_tag == 8) || (got_tag == 11 && want_done_tag));
 | 
	
		
			
				|  |  | +    if (got_tag == 11) {
 | 
	
		
			
				|  |  | +      EXPECT_TRUE(srv_ctx.IsCancelled());
 | 
	
		
			
				|  |  | +      want_done_tag = false;
 | 
	
		
			
				|  |  | +      // Now get the other entry that we were waiting on
 | 
	
		
			
				|  |  | +      EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_result), 8);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      if (server_try_cancel_thd != NULL) {
 | 
	
		
			
				|  |  |        server_try_cancel_thd->join();
 | 
	
	
		
			
				|  | @@ -1116,7 +1228,15 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      if (server_try_cancel == CANCEL_AFTER_PROCESSING) {
 | 
	
		
			
				|  |  | -      ServerTryCancel(&srv_ctx);
 | 
	
		
			
				|  |  | +      srv_ctx.TryCancel();
 | 
	
		
			
				|  |  | +      want_done_tag = true;
 | 
	
		
			
				|  |  | +      verif.Expect(11, true);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (want_done_tag) {
 | 
	
		
			
				|  |  | +      verif.Verify(cq_.get());
 | 
	
		
			
				|  |  | +      EXPECT_TRUE(srv_ctx.IsCancelled());
 | 
	
		
			
				|  |  | +      want_done_tag = false;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // The RPC has been cancelled at this point for sure (i.e irrespective of
 |