-
Notifications
You must be signed in to change notification settings - Fork 114
Identity: refactor routing key creation #882
Identity: refactor routing key creation #882
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Identity: use snprintf to create routing key
lol, I never want to read that sentence again.
Let's not use any C functions for routing key generation / in this function. I'd like to see a smarter / safer implementation of this function.
I know that's beyond the purview of this PR but if you're interested in doing more that (work on this function) then I can hold on merging - just let me know. We could also resolve the windows build (that this PR breaks) in the process.
and "hu" specifiers to silence format truncation warnings.
What warnings? I can't reproduce.
😄 felt gross writing it, too.
I'm using boost input/output facets for stream formatting in another branch I'm working on. Would this count as smarter/safer? For this PR, I was just following the TODO, and trying to minimally change the code. I'm willing to implement the facets, if you think this is a reasonable approach. If not, I'm open to suggestions.
Using gcc8 on your
|
Ah, I see now. But the format is for unsigned and the type is signed:
So, gcc says one thing and clang says another - but both are correct 🤷♂️. I don't suspect overflow given the parameters but obviously this should be resolved during the refactor.
Probably not smarter since the standard library would work fine with this function.
Ok, then please just patch up this PR to work with windows, add a TODO to the function, and do the usual referencing of PR number in gitlog. Thanks. |
937767e
to
78354e4
Compare
Create routing key using standard library functions for memory safety. Referencing monero-project#882
78354e4
to
4753687
Compare
Create routing key using standard library functions for memory safety. Referencing monero-project#882
Right, I don't know either. Side-stepping the issue by using
Agreed, I found a better way. Thanks for the hint.
I didn't mean that I wouldn't fully patch the issue, only explaining my reasoning for using For some reason the documentation on cppreference is incorrect for argument order with |
Whatever you end up doing, a unit-test will be extremely helpful. Also please consider rebasing against master so you can eliminate unrelated build warnings. |
Agreed, will add a unit-test, and rebase against master. edit: I made the changes, but will wait until |
Create routing key using standard library functions for memory safety. Move responsibility for error handling to callers. Referencing monero-project#882
src/core/router/identity.cc
Outdated
tm.tm_year += 1900; | ||
tm.tm_mon += 1; | ||
ss << std::put_time(&tm, "%Y%m%d"); | ||
std::memcpy(reinterpret_cast<char *>((buf + 32)), ss.str().data(), 9); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't get 1. why this is not done with std::strftime
2. why platform specific gmtime_r/s
?
What is wrong with:
std::time_t current_time = std::time(nullptr);
char time_string[9] = {};
auto ret = std::strftime(time_string, sizeof(time_string),
"%Y%m%d", std::gmtime(¤t_time));
This should work for both platforms.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see that std::gmtime
may not be thread-safe.
gmtime_s
is C11 standard alternative for POSIX gmtime_r
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why this is not done with std::strftime
Good question :). I wasn't familiar with the function, and must have missed it when looking at the reference material.
I see that std::gmtime may not be thread-safe.
Originally, I had left those alternatives in for this reason, and will add them back. Thanks for the review @rakhimov.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After looking at the documentation, std::put_time
makes more sense for use with streams. If arrays and memcpy
are better, then I'll use your suggestion.
Ideally, I would like to get rid of the gmtime_*
calls as well. Boost.DateTime seems the only viable thread-safe alternative, but looks like a lot of overhead for such a simple use-case. Maybe it's worth it...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please consider doing whatever it takes to present a clean, streamlined, simple, efficient implementation of this function. A simple cross-platform thread-safe solution is welcome.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do, I'll try Boost.DateTime, and see if it comes out cleaner.
src/core/router/identity.cc
Outdated
time_t t = time(nullptr); | ||
struct tm tm; | ||
// TODO(unassigned): never use sprintf, use snprintf instead. | ||
std::stringstream ss; | ||
ss.imbue(std::locale(std::locale::classic())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ss.imbue(std::locale(std::locale::classic()));
Why do you want this? I understand conceptually why but this doesn't appear necessary (and the router works fine without it in this branch).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this doesn't appear necessary
I realize now that this is the default, but wanted to ensure UTC with no localization leaks before.
src/core/router/identity.cc
Outdated
@@ -730,27 +730,23 @@ Keys CreateRandomKeys() { | |||
IdentHash CreateRoutingKey( | |||
const IdentHash& ident) { | |||
std::uint8_t buf[41]; // ident + yyyymmdd | |||
memcpy(buf, (const std::uint8_t *)ident, 32); | |||
std::memcpy(buf, (const std::uint8_t *)ident, 32); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This cast is unnecessary because of Tags
functor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I'll remove it in the next refactor, if I keep the memcpy
s.
src/core/router/identity.cc
Outdated
tm.tm_year += 1900; | ||
tm.tm_mon += 1; | ||
ss << std::put_time(&tm, "%Y%m%d"); | ||
std::memcpy(reinterpret_cast<char *>((buf + 32)), ss.str().data(), 9); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you're going to keep the memcpy's then you should setup the empty buffer with ByteStream
and refactor accordingly.
As for keeping a stringstream for time, that's TBD depending on what else you plan on doing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you're going to keep the memcpy's then you should setup the empty buffer with ByteStream and refactor accordingly.
Will do, I'll look at setting this up with ByteStream
. Will try both refactors (memcpy and Boost.DateTime), and see which comes out cleaner.
Thanks for the review, and the pointers on where to go next 👍
4753687
to
f6b2046
Compare
The latest set of changes includes Boost DateTime refactors, and refactors to Left off the reference to the PR, if throwing (or something else) is preferred. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's coming along. Two points in addition to the others:
- Can you please drop all netdb additions. They should go in a separate PR.
- Please update your submodule (rebase against master and, when switching branches, update the submodule) before committing
src/core/router/identity.cc
Outdated
return key; | ||
} | ||
std::stringstream ss; | ||
ss.exceptions(std::ios::failbit | std::ios::badbit); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you want this? This isn't necessary because we want to catch / process all exceptions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got confused from the Boost examples, and this excerpt from LWG 23.9.4, that I would need to also mask for badbit
to enable the stringstream to rethrow all exceptions.
I also incorrectly assumed I would need to set exceptions for output, I'll remove the line.
src/core/router/identity.cc
Outdated
kovri::core::Exception ex(__func__); | ||
ex.Dispatch(); | ||
IdentHash fail_key; | ||
return fail_key; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IdentHash fail_key;
return fail_key;
We don't want to create an object simply to satisfy a return type. We should rather re-throw and deal with consequences in any callers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, that makes sense. I'll make the changes.
BOOST_CHECK_THROW(core::CreateRoutingKey(nullptr), std::invalid_argument); | ||
BOOST_CHECK(core::CreateRoutingKey(zeroed_ident).IsZero()); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test-case needs to ensure proper / spec-defined date formatting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How can we inspect the date formatting without re-implementing the function, or is that what you mean? I'm confused...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How can we inspect the date formatting without re-implementing the function, or is that what you mean?
That would be expected if you wish to adequately test the data before it is hashed. Perhaps split into multiple functions (formatting versus key creation / hashing)?
src/core/router/identity.cc
Outdated
{ | ||
LOG(error) << __func__ | ||
<< ": cannot create routing key from zero-initialized ident"; | ||
return key; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't want to return an object simply to satisfy a return type. IsZero()
was a hack to work with the union and should be eliminated / not built upon. We can keep IsZero for now but we should throw and deal with consequences in any callers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, that makes sense. I'll try to think of alternatives too (for another PR).
7fe3e12
to
25b1e9d
Compare
Create routing key using Boost DateTime for memory and thread safety. Callers are responsibile for error handling. Referencing monero-project#882
Separate routing key formatting from creation. Useful for testing proper formatting according to spec. Referencing monero-project#882
25b1e9d
to
ba20fb2
Compare
Create routing key using Boost DateTime for memory and thread safety. Callers are responsibile for error handling. Referencing monero-project#882
Separate routing key formatting from creation. Useful for testing proper formatting according to spec. Referencing monero-project#882
src/core/router/identity.h
Outdated
/// @param ident Identity hash used as the basis for the routing key | ||
/// @throw std::invalid_argument if supplied a zero-initialized ident | ||
/// @throw std::ios_base::failure on date formatting failure | ||
/// @throw CryptoPP::Exception on hashing failure |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// @throw std::ios_base::failure on date formatting failure
/// @throw CryptoPP::Exception on hashing failure
We don't need this. We shouldn't keep track of every throw point that isn't directly related to the function's return or interface. Doing so only clutters the code and documentation, and is a pain to maintain should an implementation change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wasn't sure about the level of detail to include. I agree with you though, I'll remove it.
src/core/router/identity.h
Outdated
/// @brief Format routing key with mod date according to spec | ||
/// @param ident Identity hash used as the basis for the routing key | ||
/// @throw std::invalid_argument if supplied a zero-initialized ident | ||
/// @throw std::ios_base::failure on date formatting failure |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// @throw std::ios_base::failure on date formatting failure
We don't need this. We shouldn't keep track of every throw point that isn't directly related to the function's return or interface. Doing so only clutters the code and documentation, and is a pain to maintain should an implementation change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wasn't sure about the level of detail to include. I agree with you though, I'll remove it.
src/core/router/identity.h
Outdated
/// @throw std::invalid_argument if supplied a zero-initialized ident | ||
/// @throw std::ios_base::failure on date formatting failure | ||
std::string FormatRoutingKey( | ||
const IdentHash& ident); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this really greater than 80 chars (it's 53, clang-format shouldn't do this)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I'm not sure why the line broke here, I'll fix it.
BOOST_CHECK_NO_THROW(core::FormatRoutingKey(ident.GetIdentHash())); | ||
const std::string formatted_key = core::FormatRoutingKey(ident.GetIdentHash()); | ||
const core::IdentHash formatted_ident(reinterpret_cast<const std::uint8_t*>( | ||
formatted_key.substr(0, ident.GetIdentHash().size()).data())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const std::string formatted_key = core::FormatRoutingKey(ident.GetIdentHash());
const core::IdentHash formatted_ident(reinterpret_cast<const std::uint8_t*>(
formatted_key.substr(0, ident.GetIdentHash().size()).data()));
This block is logically related to the comment below, not the check above. For sake of readability, you should put this block below the line // Ensure formatted routing key contains the original ident hash.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I must have missed that when making changes to the tests. I'll fix it.
// TODO(anonimal): review if we need to safely break control, ensure exception handling by callers | ||
throw; | ||
} | ||
try |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extend this try block to:
diff --git a/src/core/router/identity.cc b/src/core/router/identity.cc
index ccd6c862..ed793bc2 100644
--- a/src/core/router/identity.cc
+++ b/src/core/router/identity.cc
@@ -725,16 +725,17 @@ Keys CreateRandomKeys() {
return keys;
}
-IdentHash CreateRoutingKey(
- const IdentHash& ident) {
- if (ident.IsZero())
- {
- throw std::invalid_argument(
- "Identity: cannot create routing key from zero-initialized ident");
- }
+IdentHash CreateRoutingKey(const IdentHash& ident)
+{
IdentHash key;
try
{
+ if (ident.IsZero())
+ {
+ throw std::invalid_argument(
+ "Identity: cannot create routing key from zero-initialized "
+ "ident");
+ }
const std::string formatted_key = FormatRoutingKey(ident);
kovri::core::SHA256().CalculateDigest(
key(),
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I extended the try-block, but Github is still picking it up as unchanged.
ident.FromBuffer(m_AliceIdentity.data(), m_AliceIdentity.size())); | ||
|
||
BOOST_CHECK_NO_THROW(core::FormatRoutingKey(ident.GetIdentHash())); | ||
const std::string formatted_key = core::FormatRoutingKey(ident.GetIdentHash()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This case does not test for a valid format. You will have to supply an extra argument to the formatting function (a ptime object), and then process accordingly (ensuring that time given is properly formatted).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used boost::gregorian::from_undelimited_string()
below, which I thought would throw when supplied an invalid ISO date string. If you prefer an explicit ptime
argument, I can try to implement that in the next set of refactors.
src/core/router/identity.cc
Outdated
return key; | ||
} | ||
|
||
std::string FormatRoutingKey(const IdentHash& ident) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JFTR: our key is more akin to a vector of bytes and not a string. Changing this would then not justify all the stringstream use within the function. A note for future optimizations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
our key is more akin to a vector of bytes and not a string
I understand, and thought that using stringstream was the most straight-forward way to use the Boost.DateTime functions. Will try to use a vector of bytes instead on this next set of refactors. Thanks for the tips.
ba20fb2
to
bb50ea3
Compare
@anonimal I made the latest recommended changes, and replaced uses of stringstream. If these changes away from stringstream use are unwanted, I can revert back. Left off the commit references to this PR, just in case you do want me to revert. |
src/core/router/identity.cc
Outdated
return key; | ||
} | ||
|
||
std::vector<std::uint8_t> FormatRoutingKey(const IdentHash& ident) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not add the boost::gregorian::date
object as a second parameter, since I thought passing it by non-const reference may lead to thread-unsafe usage. Instead, I extract the date and ident from the result in tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See revert comment.
src/core/router/identity.cc
Outdated
// Add date string to the formatted buffer | ||
for (const auto& c : date_string) | ||
formatted_buf.emplace_back(static_cast<std::uint8_t>(c)); | ||
return formatted_buf; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If these changes away from stringstream use are unwanted, I can revert back.
This is incredibly inefficient, worse than before. Please revert (and put some newlines in here so other people can more easily read the code).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't intend to make it hard to read. Will think about other future refactors, and revert to stringstream for now.
deb08e3
to
44b3ec8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please apply this patch:
diff --git a/src/core/router/identity.cc b/src/core/router/identity.cc
index 858b9ae5..cf7a01a6 100644
--- a/src/core/router/identity.cc
+++ b/src/core/router/identity.cc
@@ -725,25 +725,31 @@ Keys CreateRandomKeys() {
return keys;
}
-IdentHash CreateRoutingKey(
- const IdentHash& ident) {
+// TODO(unassigned): should not be a free function
+IdentHash CreateRoutingKey(const IdentHash& ident)
+{
IdentHash key;
try
{
if (ident.IsZero())
- {
- throw std::invalid_argument(
- "Identity: cannot create routing key from zero-initialized "
- "ident");
- }
+ throw std::invalid_argument("Identity: zero-initialized ident");
+
+ // Get spec-defined formatted date
+ std::string const date(GetFormattedDate());
+
+ // Create buffer for key
+ std::vector<std::uint8_t> buf(
+ ident(), ident() + (ident.size() + date.size()));
- // Format the routing key
- const std::vector<std::uint8_t> buf = FormatRoutingKey(ident);
- // Hash the formatted buffer to create the routing key
+ // Append the ISO date
+ buf.insert(buf.end(), date.begin(), date.end());
+
+ // Hash the key
+ assert(key.size() <= buf.size());
kovri::core::SHA256().CalculateDigest(key(), buf.data(), buf.size());
}
catch (...)
- { // Error formatting or hashing the key
+ {
kovri::core::Exception ex(__func__);
ex.Dispatch();
throw;
@@ -751,29 +757,11 @@ IdentHash CreateRoutingKey(
return key;
}
-std::vector<std::uint8_t> FormatRoutingKey(const IdentHash& ident)
+// TODO(unassigned): should not be a free function
+std::string GetFormattedDate()
{
- if (ident.IsZero())
- {
- throw std::invalid_argument(
- "Identity: cannot create routing key from zero-initialized ident");
- }
-
- // Get current UTC date
boost::gregorian::date date(boost::gregorian::day_clock::universal_day());
- const std::string date_str = boost::gregorian::to_iso_string(date);
-
- std::vector<std::uint8_t> buf;
- buf.reserve(ident.size() + date_str.size());
-
- // Append the ident
- for (std::size_t i = 0; i < ident.size(); ++i)
- buf.push_back(ident[i]);
-
- // Append the ISO date
- buf.insert(buf.end(), date_str.begin(), date_str.end());
-
- return buf;
+ return boost::gregorian::to_iso_string(date);
}
XORMetric operator^(
diff --git a/src/core/router/identity.h b/src/core/router/identity.h
index 6743b922..ee82a02b 100644
--- a/src/core/router/identity.h
+++ b/src/core/router/identity.h
@@ -292,15 +292,16 @@ struct XORMetric {
}
};
+// TODO(unassigned): should not be a free function
/// @brief Hash identity with appended mod date according to spec
/// @param ident Identity hash used as the basis for the routing key
/// @throw std::invalid_argument if supplied a zero-initialized ident
IdentHash CreateRoutingKey(const IdentHash& ident);
-/// @brief Format routing key with mod date according to spec
-/// @param ident Identity hash used as the basis for the routing key
-/// @throw std::invalid_argument if supplied a zero-initialized ident
-std::vector<std::uint8_t> FormatRoutingKey(const IdentHash& ident);
+// TODO(unassigned): should not be a free function
+/// @return Formatted UTC date used in routing key
+/// @notes Must return yyyyMMdd
+std::string GetFormattedDate();
XORMetric operator^(
const IdentHash& key1,
diff --git a/tests/unit_tests/core/router/identity.cc b/tests/unit_tests/core/router/identity.cc
index 1beb829c..6acacf0d 100644
--- a/tests/unit_tests/core/router/identity.cc
+++ b/tests/unit_tests/core/router/identity.cc
@@ -35,6 +35,7 @@
#include <array>
#include <memory>
+#include <regex>
#include "core/crypto/signature.h"
#include "core/router/identity.h"
@@ -86,63 +87,24 @@ BOOST_AUTO_TEST_CASE(ParseIdentityFailure)
0);
}
-BOOST_AUTO_TEST_CASE(ValidCreateRoutingKey)
+BOOST_AUTO_TEST_CASE(ValidRoutingKey)
{
core::IdentityEx ident;
- BOOST_CHECK(
- ident.FromBuffer(m_AliceIdentity.data(), m_AliceIdentity.size()));
+ BOOST_CHECK(ident.FromBuffer(m_AliceIdentity.data(), m_AliceIdentity.size()));
BOOST_CHECK_NO_THROW(core::CreateRoutingKey(ident.GetIdentHash()));
- // Ensure a valid identity hash is returned
- BOOST_CHECK(core::CreateRoutingKey(ident.GetIdentHash()).ToBase32().size());
}
-BOOST_AUTO_TEST_CASE(CreateInvalidRoutingKey)
+BOOST_AUTO_TEST_CASE(InvalidRoutingKey)
{
- kovri::core::IdentHash zeroed_ident;
+ kovri::core::IdentHash hash;
BOOST_CHECK_THROW(core::CreateRoutingKey(nullptr), std::invalid_argument);
- BOOST_CHECK_THROW(core::CreateRoutingKey(zeroed_ident), std::invalid_argument);
-}
-
-BOOST_AUTO_TEST_CASE(ValidFormatRoutingKey)
-{
- core::IdentityEx ident;
- BOOST_CHECK(
- ident.FromBuffer(m_AliceIdentity.data(), m_AliceIdentity.size()));
-
- // Ensure no thrown errors when formatting a valid key
- BOOST_CHECK_NO_THROW(core::FormatRoutingKey(ident.GetIdentHash()));
- auto formatted_key = core::FormatRoutingKey(ident.GetIdentHash());
-
- // Extract the date from the formatted key
- std::vector<std::uint8_t> date_vec;
- // Set the capacity for the expected date size
- date_vec.reserve(formatted_key.size() - ident.GetIdentHash().size());
-
- for (std::size_t i = 0; i < date_vec.capacity(); ++i)
- { // insert the date in reverse order
- date_vec.emplace(date_vec.begin(), formatted_key.back());
- formatted_key.pop_back();
- }
- const std::string date_string(date_vec.begin(), date_vec.end());
-
- // Ensure the date is a proper UTC date
- BOOST_CHECK_NO_THROW(boost::gregorian::from_undelimited_string(date_string));
- BOOST_CHECK(
- !boost::gregorian::from_undelimited_string(date_string).is_not_a_date());
-
- // Formatted key should now only contain the original ident
- const core::IdentHash formatted_ident(formatted_key.data());
-
- // Ensure extracted key matches the original ident
- BOOST_CHECK(ident.GetIdentHash() == formatted_ident);
+ BOOST_CHECK_THROW(core::CreateRoutingKey(hash), std::invalid_argument);
}
-BOOST_AUTO_TEST_CASE(InvalidFormatRoutingKey)
+BOOST_AUTO_TEST_CASE(ValidDateFormat)
{
- core::IdentHash ident;
- BOOST_CHECK_THROW(core::FormatRoutingKey(nullptr), std::invalid_argument);
- // Ensure formatting a zero-initialized ident hash throws
- BOOST_CHECK_THROW(core::FormatRoutingKey(ident), std::invalid_argument);
+ std::regex regex("(20\\d{2})(\\d{2})(\\d{2})"); // Valid for only this century
+ BOOST_CHECK(std::regex_search(core::GetFormattedDate(), regex));
}
BOOST_AUTO_TEST_SUITE_END()
b15b381
to
e4cda16
Compare
Create routing key using Boost DateTime for memory and thread safety. Callers are responsibile for error handling. Referencing monero-project#882
e4cda16
to
ebebffc
Compare
Tests for creating and formatting routing keys. Referencing monero-project#882
By submitting this pull-request, I confirm the following:
Resolves TODO replacing
sprintf
with calls to standard library functions, and fixes gcc8 format truncation warning.