Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(379)

Unified Diff: google_apis/gcm/engine/mcs_client_unittest.cc

Issue 117513004: [GCM] Add TTL support (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address comments Created 6 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« google_apis/gcm/base/mcs_util.cc ('K') | « google_apis/gcm/engine/mcs_client.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: google_apis/gcm/engine/mcs_client_unittest.cc
diff --git a/google_apis/gcm/engine/mcs_client_unittest.cc b/google_apis/gcm/engine/mcs_client_unittest.cc
index 0dcf2989b76137a38a431af91413830b716afdf9..79d05fa5edd880250d044d0bc788a38e06b06215 100644
--- a/google_apis/gcm/engine/mcs_client_unittest.cc
+++ b/google_apis/gcm/engine/mcs_client_unittest.cc
@@ -8,6 +8,7 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
+#include "base/test/simple_test_clock.h"
#include "components/webdata/encryptor/encryptor.h"
#include "google_apis/gcm/base/mcs_util.h"
#include "google_apis/gcm/engine/fake_connection_factory.h"
@@ -30,26 +31,34 @@ const int kMessageBatchSize = 6;
// TODO(zea): get this (and other constants) directly from the mcs client.
const int kAckLimitSize = 10;
+// TTL value for reliable messages.
+const int kTTLValue = 5 * 60; // 5 minutes.
+
// Helper for building arbitrary data messages.
MCSMessage BuildDataMessage(const std::string& from,
const std::string& category,
int last_stream_id_received,
- const std::string persistent_id) {
+ const std::string persistent_id,
+ int ttl,
+ uint64 sent) {
mcs_proto::DataMessageStanza data_message;
data_message.set_from(from);
data_message.set_category(category);
data_message.set_last_stream_id_received(last_stream_id_received);
if (!persistent_id.empty())
data_message.set_persistent_id(persistent_id);
+ data_message.set_ttl(ttl);
+ data_message.set_sent(sent);
return MCSMessage(kDataMessageStanzaTag, data_message);
}
// MCSClient with overriden exposed persistent id logic.
class TestMCSClient : public MCSClient {
public:
- TestMCSClient(ConnectionFactory* connection_factory,
+ TestMCSClient(base::Clock* clock,
+ ConnectionFactory* connection_factory,
RMQStore* rmq_store)
- : MCSClient(connection_factory, rmq_store),
+ : MCSClient(clock, connection_factory, rmq_store),
next_id_(0) {
}
@@ -70,6 +79,7 @@ class MCSClientTest : public testing::Test {
void InitializeClient();
void LoginClient(const std::vector<std::string>& acknowledged_ids);
+ base::SimpleTestClock* clock() { return &clock_; }
TestMCSClient* mcs_client() const { return mcs_client_.get(); }
FakeConnectionFactory* connection_factory() {
return &connection_factory_;
@@ -92,6 +102,8 @@ class MCSClientTest : public testing::Test {
void MessageReceivedCallback(const MCSMessage& message);
void MessageSentCallback(const std::string& message_id);
+ base::SimpleTestClock clock_;
+
base::ScopedTempDir temp_directory_;
base::MessageLoop message_loop_;
scoped_ptr<base::RunLoop> run_loop_;
@@ -125,7 +137,9 @@ MCSClientTest::~MCSClientTest() {}
void MCSClientTest::BuildMCSClient() {
rmq_store_.reset(new RMQStore(temp_directory_.path(),
message_loop_.message_loop_proxy()));
- mcs_client_.reset(new TestMCSClient(&connection_factory_, rmq_store_.get()));
+ mcs_client_.reset(new TestMCSClient(&clock_,
+ &connection_factory_,
+ rmq_store_.get()));
}
void MCSClientTest::InitializeClient() {
@@ -189,6 +203,7 @@ void MCSClientTest::MessageReceivedCallback(const MCSMessage& message) {
void MCSClientTest::MessageSentCallback(const std::string& message_id) {
DVLOG(1) << "Message sent callback invoked, killing loop.";
+ sent_message_id_ = message_id;
run_loop_->Quit();
}
@@ -243,11 +258,26 @@ TEST_F(MCSClientTest, SendMessageNoRMQ) {
BuildMCSClient();
InitializeClient();
LoginClient(std::vector<std::string>());
- MCSMessage message(BuildDataMessage("from", "category", 1, ""));
+ MCSMessage message(BuildDataMessage("from", "category", 1, "", 0, 0));
GetFakeHandler()->ExpectOutgoingMessage(message);
- mcs_client()->SendMessage(message, false);
- EXPECT_TRUE(GetFakeHandler()->
- AllOutgoingMessagesReceived());
+ mcs_client()->SendMessage(message);
+ EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
+}
+
+// Send a message without RMQ support while disconnected. Message send should
+// fail immediately, invoking callback.
+TEST_F(MCSClientTest, SendMessageNoRMQWhileDisconnected) {
+ BuildMCSClient();
+ InitializeClient();
+
+ EXPECT_TRUE(sent_message_id().empty());
+ MCSMessage message(BuildDataMessage("from", "category", 1, "", 0, 0));
+ mcs_client()->SendMessage(message);
+
+ // Message sent callback should be invoked, but no message should actually
+ // be sent.
+ EXPECT_FALSE(sent_message_id().empty());
+ EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
}
// Send a message with RMQ support.
@@ -255,11 +285,11 @@ TEST_F(MCSClientTest, SendMessageRMQ) {
BuildMCSClient();
InitializeClient();
LoginClient(std::vector<std::string>());
- MCSMessage message(BuildDataMessage("from", "category", 1, "1"));
+ MCSMessage message(
+ BuildDataMessage("from", "category", 1, "1", kTTLValue, 0));
GetFakeHandler()->ExpectOutgoingMessage(message);
- mcs_client()->SendMessage(message, true);
- EXPECT_TRUE(GetFakeHandler()->
- AllOutgoingMessagesReceived());
+ mcs_client()->SendMessage(message);
+ EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
}
// Send a message with RMQ support while disconnected. On reconnect, the message
@@ -269,7 +299,8 @@ TEST_F(MCSClientTest, SendMessageRMQWhileDisconnected) {
InitializeClient();
LoginClient(std::vector<std::string>());
GetFakeHandler()->set_fail_send(true);
- MCSMessage message(BuildDataMessage("from", "category", 1, "1"));
+ MCSMessage message(
+ BuildDataMessage("from", "category", 1, "1", kTTLValue, 0));
// The initial (failed) send.
GetFakeHandler()->ExpectOutgoingMessage(message);
@@ -280,15 +311,13 @@ TEST_F(MCSClientTest, SendMessageRMQWhileDisconnected) {
PassAs<const google::protobuf::MessageLite>()));
// The second (re)send.
GetFakeHandler()->ExpectOutgoingMessage(message);
- mcs_client()->SendMessage(message, true);
- EXPECT_FALSE(GetFakeHandler()->
- AllOutgoingMessagesReceived());
+ mcs_client()->SendMessage(message);
+ EXPECT_FALSE(GetFakeHandler()->AllOutgoingMessagesReceived());
GetFakeHandler()->set_fail_send(false);
connection_factory()->Connect();
WaitForMCSEvent(); // Wait for the login to finish.
PumpLoop(); // Wait for the send to happen.
- EXPECT_TRUE(GetFakeHandler()->
- AllOutgoingMessagesReceived());
+ EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
}
// Send a message with RMQ support without receiving an acknowledgement. On
@@ -298,14 +327,14 @@ TEST_F(MCSClientTest, SendMessageRMQOnRestart) {
InitializeClient();
LoginClient(std::vector<std::string>());
GetFakeHandler()->set_fail_send(true);
- MCSMessage message(BuildDataMessage("from", "category", 1, "1"));
+ MCSMessage message(
+ BuildDataMessage("from", "category", 1, "1", kTTLValue, 0));
// The initial (failed) send.
GetFakeHandler()->ExpectOutgoingMessage(message);
GetFakeHandler()->set_fail_send(false);
- mcs_client()->SendMessage(message, true);
- EXPECT_TRUE(GetFakeHandler()->
- AllOutgoingMessagesReceived());
+ mcs_client()->SendMessage(message);
+ EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
// Rebuild the client, which should resend the old message.
BuildMCSClient();
@@ -313,8 +342,7 @@ TEST_F(MCSClientTest, SendMessageRMQOnRestart) {
LoginClient(std::vector<std::string>());
GetFakeHandler()->ExpectOutgoingMessage(message);
PumpLoop();
- EXPECT_TRUE(GetFakeHandler()->
- AllOutgoingMessagesReceived());
+ EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
}
// Send messages with RMQ support, followed by receiving a stream ack. On
@@ -327,12 +355,16 @@ TEST_F(MCSClientTest, SendMessageRMQWithStreamAck) {
// Send some messages.
for (int i = 1; i <= kMessageBatchSize; ++i) {
MCSMessage message(
- BuildDataMessage("from", "category", 1, base::IntToString(i)));
+ BuildDataMessage("from",
+ "category",
+ 1,
+ base::IntToString(i),
+ kTTLValue,
+ 0));
GetFakeHandler()->ExpectOutgoingMessage(message);
- mcs_client()->SendMessage(message, true);
+ mcs_client()->SendMessage(message);
}
- EXPECT_TRUE(GetFakeHandler()->
- AllOutgoingMessagesReceived());
+ EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
// Receive the ack.
scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck();
@@ -361,12 +393,11 @@ TEST_F(MCSClientTest, SendMessageRMQAckOnReconnect) {
for (int i = 1; i <= kMessageBatchSize; ++i) {
id_list.push_back(base::IntToString(i));
MCSMessage message(
- BuildDataMessage("from", "category", 1, id_list.back()));
+ BuildDataMessage("from", "category", 1, id_list.back(), kTTLValue, 0));
GetFakeHandler()->ExpectOutgoingMessage(message);
- mcs_client()->SendMessage(message, true);
+ mcs_client()->SendMessage(message);
}
- EXPECT_TRUE(GetFakeHandler()->
- AllOutgoingMessagesReceived());
+ EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
// Rebuild the client, and receive an acknowledgment for the messages as
// part of the login response.
@@ -378,8 +409,7 @@ TEST_F(MCSClientTest, SendMessageRMQAckOnReconnect) {
MCSMessage(kIqStanzaTag,
ack.PassAs<const google::protobuf::MessageLite>()));
WaitForMCSEvent();
- EXPECT_TRUE(GetFakeHandler()->
- AllOutgoingMessagesReceived());
+ EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
}
// Send messages with RMQ support. On restart, receive a SelectiveAck with
@@ -395,12 +425,11 @@ TEST_F(MCSClientTest, SendMessageRMQPartialAckOnReconnect) {
for (int i = 1; i <= kMessageBatchSize; ++i) {
id_list.push_back(base::IntToString(i));
MCSMessage message(
- BuildDataMessage("from", "category", 1, id_list.back()));
+ BuildDataMessage("from", "category", 1, id_list.back(), kTTLValue, 0));
GetFakeHandler()->ExpectOutgoingMessage(message);
- mcs_client()->SendMessage(message, true);
+ mcs_client()->SendMessage(message);
}
- EXPECT_TRUE(GetFakeHandler()->
- AllOutgoingMessagesReceived());
+ EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
// Rebuild the client, and receive an acknowledgment for the messages as
// part of the login response.
@@ -420,7 +449,9 @@ TEST_F(MCSClientTest, SendMessageRMQPartialAckOnReconnect) {
BuildDataMessage("from",
"category",
2,
- remaining_ids[i - 1]));
+ remaining_ids[i - 1],
+ kTTLValue,
+ 0));
GetFakeHandler()->ExpectOutgoingMessage(message);
}
scoped_ptr<mcs_proto::IqStanza> ack(BuildSelectiveAck(acked_ids));
@@ -428,8 +459,7 @@ TEST_F(MCSClientTest, SendMessageRMQPartialAckOnReconnect) {
MCSMessage(kIqStanzaTag,
ack.PassAs<const google::protobuf::MessageLite>()));
WaitForMCSEvent();
- EXPECT_TRUE(GetFakeHandler()->
- AllOutgoingMessagesReceived());
+ EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
}
// Receive some messages. On restart, the login request should contain the
@@ -444,7 +474,7 @@ TEST_F(MCSClientTest, AckOnLogin) {
for (int i = 1; i <= kMessageBatchSize; ++i) {
id_list.push_back(base::IntToString(i));
MCSMessage message(
- BuildDataMessage("from", "category", i, id_list.back()));
+ BuildDataMessage("from", "category", i, id_list.back(), kTTLValue, 0));
GetFakeHandler()->ReceiveMessage(message);
WaitForMCSEvent();
PumpLoop();
@@ -468,7 +498,7 @@ TEST_F(MCSClientTest, AckOnSend) {
for (int i = 1; i <= kMessageBatchSize; ++i) {
id_list.push_back(base::IntToString(i));
MCSMessage message(
- BuildDataMessage("from", "category", i, id_list.back()));
+ BuildDataMessage("from", "category", i, id_list.back(), kTTLValue, 0));
GetFakeHandler()->ReceiveMessage(message);
WaitForMCSEvent();
PumpLoop();
@@ -476,11 +506,15 @@ TEST_F(MCSClientTest, AckOnSend) {
// Trigger a message send, which should acknowledge via stream ack.
MCSMessage message(
- BuildDataMessage("from", "category", kMessageBatchSize + 1, "1"));
+ BuildDataMessage("from",
+ "category",
+ kMessageBatchSize + 1,
+ "1",
+ kTTLValue,
+ 0));
GetFakeHandler()->ExpectOutgoingMessage(message);
- mcs_client()->SendMessage(message, true);
- EXPECT_TRUE(GetFakeHandler()->
- AllOutgoingMessagesReceived());
+ mcs_client()->SendMessage(message);
+ EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
}
// Receive the ack limit in messages, which should trigger an automatic
@@ -502,13 +536,12 @@ TEST_F(MCSClientTest, AckWhenLimitReachedWithHeartbeat) {
for (int i = 1; i <= kAckLimitSize; ++i) {
id_list.push_back(base::IntToString(i));
MCSMessage message(
- BuildDataMessage("from", "category", i, id_list.back()));
+ BuildDataMessage("from", "category", i, id_list.back(), kTTLValue, 0));
GetFakeHandler()->ReceiveMessage(message);
WaitForMCSEvent();
PumpLoop();
}
- EXPECT_TRUE(GetFakeHandler()->
- AllOutgoingMessagesReceived());
+ EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
// Receive a heartbeat confirming the ack (and receive the heartbeat ack).
scoped_ptr<mcs_proto::HeartbeatPing> heartbeat(
@@ -526,15 +559,57 @@ TEST_F(MCSClientTest, AckWhenLimitReachedWithHeartbeat) {
MCSMessage(kHeartbeatPingTag,
heartbeat.PassAs<const google::protobuf::MessageLite>()));
WaitForMCSEvent();
- EXPECT_TRUE(GetFakeHandler()->
- AllOutgoingMessagesReceived());
+ EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
// Rebuild the client. Nothing should be sent on login.
BuildMCSClient();
InitializeClient();
LoginClient(std::vector<std::string>());
- EXPECT_TRUE(GetFakeHandler()->
- AllOutgoingMessagesReceived());
+ EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
+}
+
+// If a message's TTL has expired by the time it reaches the front of the send
+// queue, it should be dropped.
+TEST_F(MCSClientTest, ExpiredTTLOnSend) {
+ BuildMCSClient();
+ InitializeClient();
+ LoginClient(std::vector<std::string>());
+ MCSMessage message(
+ BuildDataMessage("from", "category", 1, "1", kTTLValue, 0));
+
+ // Advance time to after the TTL.
+ clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue + 1));
+ EXPECT_TRUE(sent_message_id().empty());
+ mcs_client()->SendMessage(message);
+
+ // No messages should be sent, but the callback should still be invoked.
+ EXPECT_FALSE(sent_message_id().empty());
+ EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
+}
+
+TEST_F(MCSClientTest, ExpiredTTLOnRestart) {
+ BuildMCSClient();
+ InitializeClient();
+ LoginClient(std::vector<std::string>());
+ GetFakeHandler()->set_fail_send(true);
+ MCSMessage message(
+ BuildDataMessage("from", "category", 1, "1", kTTLValue, 0));
+
+ // The initial (failed) send.
+ GetFakeHandler()->ExpectOutgoingMessage(message);
+ GetFakeHandler()->set_fail_send(false);
+ mcs_client()->SendMessage(message);
+ EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
+
+ // Move the clock forward and rebuild the client, which should fail the
+ // message send on restart.
+ clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue + 1));
+ BuildMCSClient();
+ InitializeClient();
+ LoginClient(std::vector<std::string>());
+ PumpLoop();
+ EXPECT_FALSE(sent_message_id().empty());
+ EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
}
} // namespace
« google_apis/gcm/base/mcs_util.cc ('K') | « google_apis/gcm/engine/mcs_client.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698