Use uint64_t for fingerprints to prevent easy overflows
Instead of using int for state/command/traits/components fingerprints,
use uint64_t and reserve the value of 0 as a special "ignore" whildcard
(instead of former -1).
Change-Id: I3b95b4a8f9f41a963486d31ca6632ec0738dd7e9
Reviewed-on: https://weave-review.googlesource.com/1793
Reviewed-by: Alex Vakulenko <avakulenko@google.com>
diff --git a/src/privet/privet_handler.cc b/src/privet/privet_handler.cc
index 9199c6f..0c9887f 100644
--- a/src/privet/privet_handler.cc
+++ b/src/privet/privet_handler.cc
@@ -389,7 +389,7 @@
void PrivetHandler::OnTraitDefsChanged() {
++traits_fingerprint_;
auto pred = [this](const UpdateRequestParameters& params) {
- return params.traits_fingerprint < 0;
+ return params.traits_fingerprint == 0;
};
auto last =
std::partition(update_requests_.begin(), update_requests_.end(), pred);
@@ -403,7 +403,7 @@
++state_fingerprint_;
++components_fingerprint_;
auto pred = [this](const UpdateRequestParameters& params) {
- return params.state_fingerprint < 0 && params.components_fingerprint < 0;
+ return params.state_fingerprint == 0 && params.components_fingerprint == 0;
};
auto last =
std::partition(update_requests_.begin(), update_requests_.end(), pred);
@@ -415,7 +415,7 @@
void PrivetHandler::OnComponentTreeChanged() {
++components_fingerprint_;
auto pred = [this](const UpdateRequestParameters& params) {
- return params.components_fingerprint < 0;
+ return params.components_fingerprint == 0;
};
auto last =
std::partition(update_requests_.begin(), update_requests_.end(), pred);
@@ -930,10 +930,10 @@
params.request_id = ++last_update_request_id_;
params.callback = callback;
params.traits_fingerprint =
- (ignore_traits && ignore_commands) ? -1 : traits_fingerprint_;
- params.state_fingerprint = ignore_state ? -1 : state_fingerprint_;
+ (ignore_traits && ignore_commands) ? 0 : traits_fingerprint_;
+ params.state_fingerprint = ignore_state ? 0 : state_fingerprint_;
params.components_fingerprint =
- ignore_components ? -1 : components_fingerprint_;
+ ignore_components ? 0 : components_fingerprint_;
update_requests_.push_back(params);
if (timeout != base::TimeDelta::Max()) {
device_->PostDelayedTask(
diff --git a/src/privet/privet_handler.h b/src/privet/privet_handler.h
index 6bc4ac6..fc024d1 100644
--- a/src/privet/privet_handler.h
+++ b/src/privet/privet_handler.h
@@ -130,10 +130,10 @@
void ReplyToUpdateRequest(const RequestCallback& callback) const;
void OnUpdateRequestTimeout(int update_request_id);
- CloudDelegate* cloud_ = nullptr;
- DeviceDelegate* device_ = nullptr;
- SecurityDelegate* security_ = nullptr;
- WifiDelegate* wifi_ = nullptr;
+ CloudDelegate* cloud_{nullptr};
+ DeviceDelegate* device_{nullptr};
+ SecurityDelegate* security_{nullptr};
+ WifiDelegate* wifi_{nullptr};
struct HandlerParameters {
ApiHandler handler;
@@ -144,18 +144,18 @@
struct UpdateRequestParameters {
RequestCallback callback;
- int request_id = 0;
- int state_fingerprint = -1;
- int traits_fingerprint = -1;
- int components_fingerprint = -1;
+ int request_id{0};
+ uint64_t state_fingerprint{0};
+ uint64_t traits_fingerprint{0};
+ uint64_t components_fingerprint{0};
};
std::vector<UpdateRequestParameters> update_requests_;
int last_update_request_id_{0};
uint64_t last_user_id_{0};
- int state_fingerprint_{0};
- int traits_fingerprint_{0};
- int components_fingerprint_{0};
+ uint64_t state_fingerprint_{1};
+ uint64_t traits_fingerprint_{1};
+ uint64_t components_fingerprint_{1};
ScopedObserver<CloudDelegate, CloudDelegate::Observer> cloud_observer_{this};
base::WeakPtrFactory<PrivetHandler> weak_ptr_factory_{this};
diff --git a/src/privet/privet_handler_unittest.cc b/src/privet/privet_handler_unittest.cc
index 77cabdd..746fca9 100644
--- a/src/privet/privet_handler_unittest.cc
+++ b/src/privet/privet_handler_unittest.cc
@@ -589,48 +589,48 @@
}
TEST_F(PrivetHandlerSetupTest, State) {
- EXPECT_JSON_EQ("{'state': {'test': {}}, 'fingerprint': '0'}",
+ EXPECT_JSON_EQ("{'state': {'test': {}}, 'fingerprint': '1'}",
HandleRequest("/privet/v3/state", "{}"));
cloud_.NotifyOnStateChanged();
- EXPECT_JSON_EQ("{'state': {'test': {}}, 'fingerprint': '1'}",
+ EXPECT_JSON_EQ("{'state': {'test': {}}, 'fingerprint': '2'}",
HandleRequest("/privet/v3/state", "{}"));
}
TEST_F(PrivetHandlerSetupTest, CommandsDefs) {
- EXPECT_JSON_EQ("{'commands': {'test':{}}, 'fingerprint': '0'}",
+ EXPECT_JSON_EQ("{'commands': {'test':{}}, 'fingerprint': '1'}",
HandleRequest("/privet/v3/commandDefs", "{}"));
cloud_.NotifyOnTraitDefsChanged();
- EXPECT_JSON_EQ("{'commands': {'test':{}}, 'fingerprint': '1'}",
+ EXPECT_JSON_EQ("{'commands': {'test':{}}, 'fingerprint': '2'}",
HandleRequest("/privet/v3/commandDefs", "{}"));
}
TEST_F(PrivetHandlerSetupTest, Traits) {
- EXPECT_JSON_EQ("{'traits': {'test': {}}, 'fingerprint': '0'}",
+ EXPECT_JSON_EQ("{'traits': {'test': {}}, 'fingerprint': '1'}",
HandleRequest("/privet/v3/traits", "{}"));
cloud_.NotifyOnTraitDefsChanged();
- EXPECT_JSON_EQ("{'traits': {'test': {}}, 'fingerprint': '1'}",
+ EXPECT_JSON_EQ("{'traits': {'test': {}}, 'fingerprint': '2'}",
HandleRequest("/privet/v3/traits", "{}"));
}
TEST_F(PrivetHandlerSetupTest, Components) {
- EXPECT_JSON_EQ("{'components': {'test': {}}, 'fingerprint': '0'}",
+ EXPECT_JSON_EQ("{'components': {'test': {}}, 'fingerprint': '1'}",
HandleRequest("/privet/v3/components", "{}"));
cloud_.NotifyOnComponentTreeChanged();
- EXPECT_JSON_EQ("{'components': {'test': {}}, 'fingerprint': '1'}",
+ EXPECT_JSON_EQ("{'components': {'test': {}}, 'fingerprint': '2'}",
HandleRequest("/privet/v3/components", "{}"));
// State change will also change the components fingerprint.
cloud_.NotifyOnStateChanged();
- EXPECT_JSON_EQ("{'components': {'test': {}}, 'fingerprint': '2'}",
+ EXPECT_JSON_EQ("{'components': {'test': {}}, 'fingerprint': '3'}",
HandleRequest("/privet/v3/components", "{}"));
}
@@ -727,10 +727,10 @@
cloud_.NotifyOnStateChanged();
const char kInput[] = "{}";
const char kExpected[] = R"({
- 'commandsFingerprint': '1',
- 'stateFingerprint': '1',
- 'traitsFingerprint': '1',
- 'componentsFingerprint': '2'
+ 'commandsFingerprint': '2',
+ 'stateFingerprint': '2',
+ 'traitsFingerprint': '2',
+ 'componentsFingerprint': '3'
})";
EXPECT_JSON_EQ(kExpected,
HandleRequest("/privet/v3/checkForUpdates", kInput));
@@ -744,16 +744,16 @@
cloud_.NotifyOnComponentTreeChanged();
cloud_.NotifyOnStateChanged();
const char kInput[] = R"({
- 'commandsFingerprint': '0',
- 'stateFingerprint': '0',
- 'traitsFingerprint': '0',
- 'componentsFingerprint': '0'
- })";
- const char kExpected[] = R"({
'commandsFingerprint': '1',
'stateFingerprint': '1',
'traitsFingerprint': '1',
- 'componentsFingerprint': '2'
+ 'componentsFingerprint': '1'
+ })";
+ const char kExpected[] = R"({
+ 'commandsFingerprint': '2',
+ 'stateFingerprint': '2',
+ 'traitsFingerprint': '2',
+ 'componentsFingerprint': '3'
})";
EXPECT_JSON_EQ(kExpected,
HandleRequest("/privet/v3/checkForUpdates", kInput));
@@ -764,20 +764,20 @@
EXPECT_CALL(device_, GetHttpRequestTimeout())
.WillOnce(Return(base::TimeDelta::Max()));
const char kInput[] = R"({
- 'commandsFingerprint': '0',
- 'stateFingerprint': '0',
- 'traitsFingerprint': '0',
- 'componentsFingerprint': '0'
+ 'commandsFingerprint': '1',
+ 'stateFingerprint': '1',
+ 'traitsFingerprint': '1',
+ 'componentsFingerprint': '1'
})";
EXPECT_JSON_EQ("{}", HandleRequest("/privet/v3/checkForUpdates", kInput));
EXPECT_EQ(0, GetResponseCount());
cloud_.NotifyOnTraitDefsChanged();
EXPECT_EQ(1, GetResponseCount());
const char kExpected[] = R"({
- 'commandsFingerprint': '1',
- 'stateFingerprint': '0',
- 'traitsFingerprint': '1',
- 'componentsFingerprint': '0'
+ 'commandsFingerprint': '2',
+ 'stateFingerprint': '1',
+ 'traitsFingerprint': '2',
+ 'componentsFingerprint': '1'
})";
EXPECT_JSON_EQ(kExpected, GetResponse());
}
@@ -786,20 +786,20 @@
EXPECT_CALL(device_, GetHttpRequestTimeout())
.WillOnce(Return(base::TimeDelta::Max()));
const char kInput[] = R"({
- 'commandsFingerprint': '0',
- 'stateFingerprint': '0',
- 'traitsFingerprint': '0',
- 'componentsFingerprint': '0'
+ 'commandsFingerprint': '1',
+ 'stateFingerprint': '1',
+ 'traitsFingerprint': '1',
+ 'componentsFingerprint': '1'
})";
EXPECT_JSON_EQ("{}", HandleRequest("/privet/v3/checkForUpdates", kInput));
EXPECT_EQ(0, GetResponseCount());
cloud_.NotifyOnTraitDefsChanged();
EXPECT_EQ(1, GetResponseCount());
const char kExpected[] = R"({
- 'commandsFingerprint': '1',
- 'stateFingerprint': '0',
- 'traitsFingerprint': '1',
- 'componentsFingerprint': '0'
+ 'commandsFingerprint': '2',
+ 'stateFingerprint': '1',
+ 'traitsFingerprint': '2',
+ 'componentsFingerprint': '1'
})";
EXPECT_JSON_EQ(kExpected, GetResponse());
}
@@ -808,20 +808,20 @@
EXPECT_CALL(device_, GetHttpRequestTimeout())
.WillOnce(Return(base::TimeDelta::Max()));
const char kInput[] = R"({
- 'commandsFingerprint': '0',
- 'stateFingerprint': '0',
- 'traitsFingerprint': '0',
- 'componentsFingerprint': '0'
+ 'commandsFingerprint': '1',
+ 'stateFingerprint': '1',
+ 'traitsFingerprint': '1',
+ 'componentsFingerprint': '1'
})";
EXPECT_JSON_EQ("{}", HandleRequest("/privet/v3/checkForUpdates", kInput));
EXPECT_EQ(0, GetResponseCount());
cloud_.NotifyOnStateChanged();
EXPECT_EQ(1, GetResponseCount());
const char kExpected[] = R"({
- 'commandsFingerprint': '0',
- 'stateFingerprint': '1',
- 'traitsFingerprint': '0',
- 'componentsFingerprint': '1'
+ 'commandsFingerprint': '1',
+ 'stateFingerprint': '2',
+ 'traitsFingerprint': '1',
+ 'componentsFingerprint': '2'
})";
EXPECT_JSON_EQ(kExpected, GetResponse());
}
@@ -830,60 +830,14 @@
EXPECT_CALL(device_, GetHttpRequestTimeout())
.WillOnce(Return(base::TimeDelta::Max()));
const char kInput[] = R"({
- 'commandsFingerprint': '0',
- 'stateFingerprint': '0',
- 'traitsFingerprint': '0',
- 'componentsFingerprint': '0'
- })";
- EXPECT_JSON_EQ("{}", HandleRequest("/privet/v3/checkForUpdates", kInput));
- EXPECT_EQ(0, GetResponseCount());
- cloud_.NotifyOnComponentTreeChanged();
- EXPECT_EQ(1, GetResponseCount());
- const char kExpected[] = R"({
- 'commandsFingerprint': '0',
- 'stateFingerprint': '0',
- 'traitsFingerprint': '0',
- 'componentsFingerprint': '1'
- })";
- EXPECT_JSON_EQ(kExpected, GetResponse());
-}
-
-TEST_F(PrivetHandlerSetupTest, CheckForUpdates_LongPollIgnoreTraits) {
- EXPECT_CALL(device_, GetHttpRequestTimeout())
- .WillOnce(Return(base::TimeDelta::Max()));
- const char kInput[] = R"({
- 'stateFingerprint': '0',
- 'componentsFingerprint': '0'
- })";
- EXPECT_JSON_EQ("{}", HandleRequest("/privet/v3/checkForUpdates", kInput));
- EXPECT_EQ(0, GetResponseCount());
- cloud_.NotifyOnTraitDefsChanged();
- EXPECT_EQ(0, GetResponseCount());
- cloud_.NotifyOnComponentTreeChanged();
- EXPECT_EQ(1, GetResponseCount());
- const char kExpected[] = R"({
'commandsFingerprint': '1',
- 'stateFingerprint': '0',
+ 'stateFingerprint': '1',
'traitsFingerprint': '1',
'componentsFingerprint': '1'
})";
- EXPECT_JSON_EQ(kExpected, GetResponse());
-}
-
-TEST_F(PrivetHandlerSetupTest, CheckForUpdates_LongPollIgnoreState) {
- EXPECT_CALL(device_, GetHttpRequestTimeout())
- .WillOnce(Return(base::TimeDelta::Max()));
- const char kInput[] = R"({
- 'commandsFingerprint': '0',
- 'traitsFingerprint': '0'
- })";
EXPECT_JSON_EQ("{}", HandleRequest("/privet/v3/checkForUpdates", kInput));
EXPECT_EQ(0, GetResponseCount());
- cloud_.NotifyOnStateChanged();
- EXPECT_EQ(0, GetResponseCount());
cloud_.NotifyOnComponentTreeChanged();
- EXPECT_EQ(0, GetResponseCount());
- cloud_.NotifyOnTraitDefsChanged();
EXPECT_EQ(1, GetResponseCount());
const char kExpected[] = R"({
'commandsFingerprint': '1',
@@ -894,21 +848,67 @@
EXPECT_JSON_EQ(kExpected, GetResponse());
}
+TEST_F(PrivetHandlerSetupTest, CheckForUpdates_LongPollIgnoreTraits) {
+ EXPECT_CALL(device_, GetHttpRequestTimeout())
+ .WillOnce(Return(base::TimeDelta::Max()));
+ const char kInput[] = R"({
+ 'stateFingerprint': '1',
+ 'componentsFingerprint': '1'
+ })";
+ EXPECT_JSON_EQ("{}", HandleRequest("/privet/v3/checkForUpdates", kInput));
+ EXPECT_EQ(0, GetResponseCount());
+ cloud_.NotifyOnTraitDefsChanged();
+ EXPECT_EQ(0, GetResponseCount());
+ cloud_.NotifyOnComponentTreeChanged();
+ EXPECT_EQ(1, GetResponseCount());
+ const char kExpected[] = R"({
+ 'commandsFingerprint': '2',
+ 'stateFingerprint': '1',
+ 'traitsFingerprint': '2',
+ 'componentsFingerprint': '2'
+ })";
+ EXPECT_JSON_EQ(kExpected, GetResponse());
+}
+
+TEST_F(PrivetHandlerSetupTest, CheckForUpdates_LongPollIgnoreState) {
+ EXPECT_CALL(device_, GetHttpRequestTimeout())
+ .WillOnce(Return(base::TimeDelta::Max()));
+ const char kInput[] = R"({
+ 'commandsFingerprint': '1',
+ 'traitsFingerprint': '1'
+ })";
+ EXPECT_JSON_EQ("{}", HandleRequest("/privet/v3/checkForUpdates", kInput));
+ EXPECT_EQ(0, GetResponseCount());
+ cloud_.NotifyOnStateChanged();
+ EXPECT_EQ(0, GetResponseCount());
+ cloud_.NotifyOnComponentTreeChanged();
+ EXPECT_EQ(0, GetResponseCount());
+ cloud_.NotifyOnTraitDefsChanged();
+ EXPECT_EQ(1, GetResponseCount());
+ const char kExpected[] = R"({
+ 'commandsFingerprint': '2',
+ 'stateFingerprint': '2',
+ 'traitsFingerprint': '2',
+ 'componentsFingerprint': '3'
+ })";
+ EXPECT_JSON_EQ(kExpected, GetResponse());
+}
+
TEST_F(PrivetHandlerSetupTest, CheckForUpdates_InstantTimeout) {
EXPECT_CALL(device_, GetHttpRequestTimeout())
.WillOnce(Return(base::TimeDelta::Max()));
const char kInput[] = R"({
- 'commandsFingerprint': '0',
- 'stateFingerprint': '0',
- 'traitsFingerprint': '0',
- 'componentsFingerprint': '0',
+ 'commandsFingerprint': '1',
+ 'stateFingerprint': '1',
+ 'traitsFingerprint': '1',
+ 'componentsFingerprint': '1',
'waitTimeout': 0
})";
const char kExpected[] = R"({
- 'commandsFingerprint': '0',
- 'stateFingerprint': '0',
- 'traitsFingerprint': '0',
- 'componentsFingerprint': '0'
+ 'commandsFingerprint': '1',
+ 'stateFingerprint': '1',
+ 'traitsFingerprint': '1',
+ 'componentsFingerprint': '1'
})";
EXPECT_JSON_EQ(kExpected,
HandleRequest("/privet/v3/checkForUpdates", kInput));
@@ -918,10 +918,10 @@
EXPECT_CALL(device_, GetHttpRequestTimeout())
.WillOnce(Return(base::TimeDelta::Max()));
const char kInput[] = R"({
- 'commandsFingerprint': '0',
- 'stateFingerprint': '0',
- 'traitsFingerprint': '0',
- 'componentsFingerprint': '0',
+ 'commandsFingerprint': '1',
+ 'stateFingerprint': '1',
+ 'traitsFingerprint': '1',
+ 'componentsFingerprint': '1',
'waitTimeout': 3
})";
base::Closure callback;
@@ -932,10 +932,10 @@
callback.Run();
EXPECT_EQ(1, GetResponseCount());
const char kExpected[] = R"({
- 'commandsFingerprint': '0',
- 'stateFingerprint': '0',
- 'traitsFingerprint': '0',
- 'componentsFingerprint': '0'
+ 'commandsFingerprint': '1',
+ 'stateFingerprint': '1',
+ 'traitsFingerprint': '1',
+ 'componentsFingerprint': '1'
})";
EXPECT_JSON_EQ(kExpected, GetResponse());
}
@@ -944,10 +944,10 @@
EXPECT_CALL(device_, GetHttpRequestTimeout())
.WillOnce(Return(base::TimeDelta::FromMinutes(1)));
const char kInput[] = R"({
- 'commandsFingerprint': '0',
- 'stateFingerprint': '0',
- 'traitsFingerprint': '0',
- 'componentsFingerprint': '0'
+ 'commandsFingerprint': '1',
+ 'stateFingerprint': '1',
+ 'traitsFingerprint': '1',
+ 'componentsFingerprint': '1'
})";
base::Closure callback;
EXPECT_CALL(device_, PostDelayedTask(_, _, base::TimeDelta::FromSeconds(50)))
@@ -957,10 +957,10 @@
callback.Run();
EXPECT_EQ(1, GetResponseCount());
const char kExpected[] = R"({
- 'commandsFingerprint': '0',
- 'stateFingerprint': '0',
- 'traitsFingerprint': '0',
- 'componentsFingerprint': '0'
+ 'commandsFingerprint': '1',
+ 'stateFingerprint': '1',
+ 'traitsFingerprint': '1',
+ 'componentsFingerprint': '1'
})";
EXPECT_JSON_EQ(kExpected, GetResponse());
}
@@ -969,10 +969,10 @@
EXPECT_CALL(device_, GetHttpRequestTimeout())
.WillOnce(Return(base::TimeDelta::FromSeconds(5)));
const char kInput[] = R"({
- 'commandsFingerprint': '0',
- 'stateFingerprint': '0',
- 'traitsFingerprint': '0',
- 'componentsFingerprint': '0'
+ 'commandsFingerprint': '1',
+ 'stateFingerprint': '1',
+ 'traitsFingerprint': '1',
+ 'componentsFingerprint': '1'
})";
EXPECT_JSON_EQ(kInput, HandleRequest("/privet/v3/checkForUpdates", kInput));
EXPECT_EQ(1, GetResponseCount());
@@ -982,10 +982,10 @@
EXPECT_CALL(device_, GetHttpRequestTimeout())
.WillOnce(Return(base::TimeDelta::FromMinutes(1)));
const char kInput[] = R"({
- 'commandsFingerprint': '0',
- 'stateFingerprint': '0',
- 'traitsFingerprint': '0',
- 'componentsFingerprint': '0',
+ 'commandsFingerprint': '1',
+ 'stateFingerprint': '1',
+ 'traitsFingerprint': '1',
+ 'componentsFingerprint': '1',
'waitTimeout': 10
})";
base::Closure callback;
@@ -996,10 +996,10 @@
callback.Run();
EXPECT_EQ(1, GetResponseCount());
const char kExpected[] = R"({
- 'commandsFingerprint': '0',
- 'stateFingerprint': '0',
- 'traitsFingerprint': '0',
- 'componentsFingerprint': '0'
+ 'commandsFingerprint': '1',
+ 'stateFingerprint': '1',
+ 'traitsFingerprint': '1',
+ 'componentsFingerprint': '1'
})";
EXPECT_JSON_EQ(kExpected, GetResponse());
}
@@ -1008,10 +1008,10 @@
EXPECT_CALL(device_, GetHttpRequestTimeout())
.WillOnce(Return(base::TimeDelta::Max()));
const char kInput[] = R"({
- 'commandsFingerprint': '0',
- 'stateFingerprint': '0',
- 'traitsFingerprint': '0',
- 'componentsFingerprint': '0',
+ 'commandsFingerprint': '1',
+ 'stateFingerprint': '1',
+ 'traitsFingerprint': '1',
+ 'componentsFingerprint': '1',
'waitTimeout': 10
})";
base::Closure callback;
@@ -1022,10 +1022,10 @@
cloud_.NotifyOnTraitDefsChanged();
EXPECT_EQ(1, GetResponseCount());
const char kExpected[] = R"({
- 'commandsFingerprint': '1',
- 'stateFingerprint': '0',
- 'traitsFingerprint': '1',
- 'componentsFingerprint': '0'
+ 'commandsFingerprint': '2',
+ 'stateFingerprint': '1',
+ 'traitsFingerprint': '2',
+ 'componentsFingerprint': '1'
})";
EXPECT_JSON_EQ(kExpected, GetResponse());
callback.Run();