mirror of
https://codeberg.org/wownero/wownero-lws
synced 2026-01-09 23:25:16 -08:00
Added webhook tx-confirmation support (#66)
This commit is contained in:
committed by
Lee *!* Clagett
parent
990e86f701
commit
3e0555e07d
@@ -30,8 +30,18 @@ add_library(monero-lws-unit-framework framework.test.cpp)
|
||||
target_include_directories(monero-lws-unit-framework PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} "${CMAKE_SOURCE_DIR}/src")
|
||||
target_link_libraries(monero-lws-unit-framework)
|
||||
|
||||
add_subdirectory(db)
|
||||
add_subdirectory(rpc)
|
||||
add_subdirectory(wire)
|
||||
|
||||
add_executable(monero-lws-unit main.cpp)
|
||||
target_link_libraries(monero-lws-unit monero-lws-unit-framework monero-lws-unit-wire monero-lws-unit-wire-json monero-lws-unit-wire-msgpack)
|
||||
target_link_libraries(
|
||||
monero-lws-unit
|
||||
monero-lws-unit-db
|
||||
monero-lws-unit-framework
|
||||
monero-lws-unit-rpc
|
||||
monero-lws-unit-wire
|
||||
monero-lws-unit-wire-json
|
||||
monero-lws-unit-wire-msgpack
|
||||
)
|
||||
add_test(NAME monero-lws-unit COMMAND monero-lws-unit -v)
|
||||
|
||||
38
tests/unit/db/CMakeLists.txt
Normal file
38
tests/unit/db/CMakeLists.txt
Normal file
@@ -0,0 +1,38 @@
|
||||
# Copyright (c) 2022-2023, The Monero Project
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification, are
|
||||
# permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
# conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
# of conditions and the following disclaimer in the documentation and/or other
|
||||
# materials provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software without specific
|
||||
# prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
# THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
add_library(monero-lws-unit-db OBJECT storage.test.cpp webhook.test.cpp)
|
||||
target_link_libraries(
|
||||
monero-lws-unit-db
|
||||
monero-lws-unit-framework
|
||||
monero-lws-common
|
||||
monero-lws-db
|
||||
monero::libraries
|
||||
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||
)
|
||||
#add_test(monero-lws-unit)
|
||||
70
tests/unit/db/storage.test.cpp
Normal file
70
tests/unit/db/storage.test.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright (c) 2023, The Monero Project
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
#include "storage.test.h"
|
||||
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include "common/util.h" // monero/src/
|
||||
|
||||
namespace lws { namespace db { namespace test
|
||||
{
|
||||
namespace
|
||||
{
|
||||
boost::filesystem::path get_db_location()
|
||||
{
|
||||
return tools::get_default_data_dir() + "light_wallet_server_unit_testing";
|
||||
}
|
||||
}
|
||||
|
||||
cleanup_db::~cleanup_db()
|
||||
{
|
||||
boost::filesystem::remove_all(get_db_location());
|
||||
}
|
||||
|
||||
storage get_fresh_db()
|
||||
{
|
||||
const boost::filesystem::path location = get_db_location();
|
||||
boost::filesystem::remove_all(location);
|
||||
boost::filesystem::create_directories(location);
|
||||
return storage::open(location.c_str(), 5);
|
||||
}
|
||||
|
||||
db::account make_db_account(const account_address& pubs, const crypto::secret_key& key)
|
||||
{
|
||||
view_key converted_key{};
|
||||
std::memcpy(std::addressof(converted_key), std::addressof(unwrap(unwrap(key))), sizeof(key));
|
||||
return {
|
||||
account_id(1), account_time(0), pubs, converted_key
|
||||
};
|
||||
}
|
||||
|
||||
lws::account make_account(const account_address& pubs, const crypto::secret_key& key)
|
||||
{
|
||||
return lws::account{make_db_account(pubs, key), {}, {}};
|
||||
}
|
||||
}}} // lws // db // test
|
||||
46
tests/unit/db/storage.test.h
Normal file
46
tests/unit/db/storage.test.h
Normal file
@@ -0,0 +1,46 @@
|
||||
// Copyright (c) 2023, The Monero Project
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include "crypto/crypto.h" // monero/src/
|
||||
#include "db/account.h"
|
||||
#include "db/data.h"
|
||||
#include "db/storage.h"
|
||||
|
||||
namespace lws { namespace db { namespace test
|
||||
{
|
||||
struct cleanup_db
|
||||
{
|
||||
~cleanup_db();
|
||||
};
|
||||
|
||||
lws::db::storage get_fresh_db();
|
||||
lws::db::account make_db_account(const lws::db::account_address& pubs, const crypto::secret_key& key);
|
||||
lws::account make_account(const lws::db::account_address& pubs, const crypto::secret_key& key);
|
||||
}}} // lws // db // test
|
||||
210
tests/unit/db/webhook.test.cpp
Normal file
210
tests/unit/db/webhook.test.cpp
Normal file
@@ -0,0 +1,210 @@
|
||||
// Copyright (c) 2023, The Monero Project
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "framework.test.h"
|
||||
|
||||
#include <boost/uuid/random_generator.hpp>
|
||||
#include <cstdint>
|
||||
#include "crypto/crypto.h" // monero/src
|
||||
#include "db/data.h"
|
||||
#include "db/storage.h"
|
||||
#include "db/storage.test.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
bool add_out(lws::account& account, const lws::db::block_id last_id, const std::uint64_t payment_id)
|
||||
{
|
||||
crypto::hash8 real_id{};
|
||||
std::memcpy(std::addressof(real_id), std::addressof(payment_id), sizeof(real_id));
|
||||
return account.add_out(
|
||||
lws::db::output{
|
||||
lws::db::transaction_link{
|
||||
lws::db::block_id(lmdb::to_native(last_id) + 1),
|
||||
crypto::rand<crypto::hash>()
|
||||
},
|
||||
lws::db::output::spend_meta_{
|
||||
lws::db::output_id{0, 100},
|
||||
std::uint64_t(1000),
|
||||
std::uint32_t(16),
|
||||
std::uint32_t(1),
|
||||
crypto::rand<crypto::public_key>()
|
||||
},
|
||||
std::uint64_t(10000000),
|
||||
std::uint64_t(0),
|
||||
crypto::rand<crypto::hash>(),
|
||||
crypto::rand<crypto::public_key>(),
|
||||
crypto::rand<rct::key>(),
|
||||
{{}, {}, {}, {}, {}, {}, {}},
|
||||
lws::db::extra_and_length(0),
|
||||
lws::db::output::payment_id_{real_id}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
LWS_CASE("db::storage::*_webhook")
|
||||
{
|
||||
lws::db::account_address account{};
|
||||
crypto::secret_key view{};
|
||||
crypto::generate_keys(account.spend_public, view);
|
||||
crypto::generate_keys(account.view_public, view);
|
||||
|
||||
SETUP("One Account and one Webhook Database")
|
||||
{
|
||||
lws::db::test::cleanup_db on_scope_exit{};
|
||||
lws::db::storage db = lws::db::test::get_fresh_db();
|
||||
const lws::db::block_info last_block =
|
||||
MONERO_UNWRAP(MONERO_UNWRAP(db.start_read()).get_last_block());
|
||||
MONERO_UNWRAP(db.add_account(account, view));
|
||||
|
||||
const boost::uuids::uuid id = boost::uuids::random_generator{}();
|
||||
{
|
||||
lws::db::webhook_value value{
|
||||
lws::db::webhook_dupsort{500, id},
|
||||
lws::db::webhook_data{"http://the_url", "the_token", 3}
|
||||
};
|
||||
MONERO_UNWRAP(
|
||||
db.add_webhook(lws::db::webhook_type::tx_confirmation, account, std::move(value))
|
||||
);
|
||||
}
|
||||
|
||||
SECTION("storage::get_webhooks()")
|
||||
{
|
||||
lws::db::storage_reader reader = MONERO_UNWRAP(db.start_read());
|
||||
const auto result = MONERO_UNWRAP(reader.get_webhooks());
|
||||
EXPECT(result.size() == 1);
|
||||
EXPECT(result[0].first.user == lws::db::account_id(1));
|
||||
EXPECT(result[0].first.type == lws::db::webhook_type::tx_confirmation);
|
||||
EXPECT(result[0].second.size() == 1);
|
||||
EXPECT(result[0].second[0].first.payment_id == 500);
|
||||
EXPECT(result[0].second[0].first.event_id == id);
|
||||
EXPECT(result[0].second[0].second.url == "http://the_url");
|
||||
EXPECT(result[0].second[0].second.token == "the_token");
|
||||
EXPECT(result[0].second[0].second.confirmations == 3);
|
||||
}
|
||||
|
||||
SECTION("storage::clear_webhooks(addresses)")
|
||||
{
|
||||
EXPECT(MONERO_UNWRAP(MONERO_UNWRAP(db.start_read()).get_webhooks()).size() == 1);
|
||||
MONERO_UNWRAP(db.clear_webhooks({std::addressof(account), 1}));
|
||||
|
||||
lws::db::storage_reader reader = MONERO_UNWRAP(db.start_read());
|
||||
const auto result = MONERO_UNWRAP(reader.get_webhooks());
|
||||
EXPECT(result.empty());
|
||||
}
|
||||
|
||||
SECTION("storage::clear_webhooks(uuid)")
|
||||
{
|
||||
EXPECT(MONERO_UNWRAP(MONERO_UNWRAP(db.start_read()).get_webhooks()).size() == 1);
|
||||
MONERO_UNWRAP(db.clear_webhooks({id}));
|
||||
|
||||
lws::db::storage_reader reader = MONERO_UNWRAP(db.start_read());
|
||||
const auto result = MONERO_UNWRAP(reader.get_webhooks());
|
||||
EXPECT(result.empty());
|
||||
}
|
||||
|
||||
SECTION("storage::update(...) one at a time")
|
||||
{
|
||||
lws::account full_account = lws::db::test::make_account(account, view);
|
||||
full_account.updated(last_block.id);
|
||||
EXPECT(add_out(full_account, last_block.id, 500));
|
||||
|
||||
const std::vector<lws::db::output> outs = full_account.outputs();
|
||||
EXPECT(outs.size() == 1);
|
||||
|
||||
lws::db::block_info head = last_block;
|
||||
for (unsigned i = 0; i < 1; ++i)
|
||||
{
|
||||
crypto::hash chain[2] = {head.hash, crypto::rand<crypto::hash>()};
|
||||
|
||||
auto updated = db.update(head.id, chain, {std::addressof(full_account), 1});
|
||||
EXPECT(!updated.has_error());
|
||||
EXPECT(updated->first == 1);
|
||||
if (i < 3)
|
||||
{
|
||||
EXPECT(updated->second.size() == 1);
|
||||
EXPECT(updated->second[0].key.user == lws::db::account_id(1));
|
||||
EXPECT(updated->second[0].key.type == lws::db::webhook_type::tx_confirmation);
|
||||
EXPECT(updated->second[0].value.first.payment_id == 500);
|
||||
EXPECT(updated->second[0].value.first.event_id == id);
|
||||
EXPECT(updated->second[0].value.second.url == "http://the_url");
|
||||
EXPECT(updated->second[0].value.second.token == "the_token");
|
||||
EXPECT(updated->second[0].value.second.confirmations == i + 1);
|
||||
|
||||
EXPECT(updated->second[0].tx_info.link == outs[0].link);
|
||||
EXPECT(updated->second[0].tx_info.spend_meta.id == outs[0].spend_meta.id);
|
||||
EXPECT(updated->second[0].tx_info.pub == outs[0].pub);
|
||||
EXPECT(updated->second[0].tx_info.payment_id.short_ == outs[0].payment_id.short_);
|
||||
}
|
||||
else
|
||||
EXPECT(updated->second.empty());
|
||||
|
||||
full_account.updated(head.id);
|
||||
head = {lws::db::block_id(lmdb::to_native(head.id) + 1), chain[1]};
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("storage::update(...) all at once")
|
||||
{
|
||||
const crypto::hash chain[5] = {
|
||||
last_block.hash,
|
||||
crypto::rand<crypto::hash>(),
|
||||
crypto::rand<crypto::hash>(),
|
||||
crypto::rand<crypto::hash>(),
|
||||
crypto::rand<crypto::hash>()
|
||||
};
|
||||
|
||||
lws::account full_account = lws::db::test::make_account(account, view);
|
||||
full_account.updated(last_block.id);
|
||||
EXPECT(add_out(full_account, last_block.id, 500));
|
||||
|
||||
const std::vector<lws::db::output> outs = full_account.outputs();
|
||||
EXPECT(outs.size() == 1);
|
||||
|
||||
const auto updated = db.update(last_block.id, chain, {std::addressof(full_account), 1});
|
||||
EXPECT(!updated.has_error());
|
||||
EXPECT(updated->first == 1);
|
||||
EXPECT(updated->second.size() == 3);
|
||||
|
||||
for (unsigned i = 0; i < 3; ++i)
|
||||
{
|
||||
EXPECT(updated->second[i].key.user == lws::db::account_id(1));
|
||||
EXPECT(updated->second[i].key.type == lws::db::webhook_type::tx_confirmation);
|
||||
EXPECT(updated->second[i].value.first.payment_id == 500);
|
||||
EXPECT(updated->second[i].value.first.event_id == id);
|
||||
EXPECT(updated->second[i].value.second.url == "http://the_url");
|
||||
EXPECT(updated->second[i].value.second.token == "the_token");
|
||||
EXPECT(updated->second[i].value.second.confirmations == i + 1);
|
||||
|
||||
EXPECT(updated->second[i].tx_info.link == outs[0].link);
|
||||
EXPECT(updated->second[i].tx_info.spend_meta.id == outs[0].spend_meta.id);
|
||||
EXPECT(updated->second[i].tx_info.pub == outs[0].pub);
|
||||
EXPECT(updated->second[i].tx_info.payment_id.short_ == outs[0].payment_id.short_);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
40
tests/unit/rpc/CMakeLists.txt
Normal file
40
tests/unit/rpc/CMakeLists.txt
Normal file
@@ -0,0 +1,40 @@
|
||||
# Copyright (c) 2022-2023, The Monero Project
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification, are
|
||||
# permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
# conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
# of conditions and the following disclaimer in the documentation and/or other
|
||||
# materials provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software without specific
|
||||
# prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
# THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
add_library(monero-lws-unit-rpc OBJECT admin.test.cpp)
|
||||
target_link_libraries(
|
||||
monero-lws-unit-rpc
|
||||
monero-lws-unit-db
|
||||
monero-lws-unit-framework
|
||||
monero-lws-common
|
||||
monero-lws-db
|
||||
monero-lws-rpc
|
||||
monero-lws-wire-json
|
||||
monero::libraries
|
||||
)
|
||||
#add_test(monero-lws-unit)
|
||||
167
tests/unit/rpc/admin.test.cpp
Normal file
167
tests/unit/rpc/admin.test.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
// Copyright (c) 2023, The Monero Project
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "framework.test.h"
|
||||
|
||||
#include <boost/range/algorithm/equal.hpp>
|
||||
#include "db/storage.test.h"
|
||||
#include "db/string.h"
|
||||
#include "error.h"
|
||||
#include "hex.h" // monero/contrib/epee/include
|
||||
#include "rpc/admin.h"
|
||||
#include "wire/json.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr const char address_str[] =
|
||||
u8"42ui2zRV3KBKgHPnQHDZu7WFc397XmhEjL9e6UnSpyHiKh4vydo7atvaQDSDKYPoCb51GQZc7hZZvDrJM7JCyuYqHHbshVn";
|
||||
constexpr const char view_str[] =
|
||||
u8"9ec001644f8d79ecb368083e48e7efb5a48b3563c9a78ba497874fd58285330d";
|
||||
|
||||
template<typename T>
|
||||
expect<epee::byte_slice> call_endpoint(lws::db::storage disk, std::string json)
|
||||
{
|
||||
using request_type = typename T::request;
|
||||
expect<request_type> req = wire::json::from_bytes<request_type>(std::move(json));
|
||||
if (!req)
|
||||
return req.error();
|
||||
wire::json_slice_writer out{};
|
||||
MONERO_CHECK(T{}(out, std::move(disk), std::move(*req)));
|
||||
return out.take_bytes();
|
||||
}
|
||||
}
|
||||
|
||||
LWS_CASE("rpc::admin")
|
||||
{
|
||||
lws::db::account_address account = MONERO_UNWRAP(lws::db::address_string(address_str));
|
||||
crypto::secret_key view{};
|
||||
EXPECT(epee::from_hex::to_buffer(epee::as_mut_byte_span(unwrap(unwrap(view))), view_str));
|
||||
|
||||
SETUP("One Account One Webhook Database")
|
||||
{
|
||||
lws::db::test::cleanup_db on_scope_exit{};
|
||||
lws::db::storage db = lws::db::test::get_fresh_db();
|
||||
const lws::db::block_info last_block =
|
||||
MONERO_UNWRAP(MONERO_UNWRAP(db.start_read()).get_last_block());
|
||||
MONERO_UNWRAP(db.add_account(account, view));
|
||||
|
||||
boost::uuids::uuid id{};
|
||||
epee::byte_slice id_str{};
|
||||
expect<epee::byte_slice> result{lws::error::configuration};
|
||||
{
|
||||
std::string add_json_str{};
|
||||
add_json_str.append(u8"{\"url\":\"http://the_url\", \"token\":\"the_token\",");
|
||||
add_json_str.append(u8"\"address\":\"").append(address_str).append(u8"\",");
|
||||
add_json_str.append(u8"\"payment_id\":\"deadbeefdeadbeef\",");
|
||||
add_json_str.append(u8"\"type\":\"tx-confirmation\",\"confirmations\":3}");
|
||||
result = call_endpoint<lws::rpc::webhook_add_>(db.clone(), std::move(add_json_str));
|
||||
EXPECT(!result.has_error());
|
||||
}
|
||||
|
||||
{
|
||||
static constexpr const char begin[] =
|
||||
u8"{\"payment_id\":\"deadbeefdeadbeef\",\"event_id\":\"";
|
||||
epee::byte_slice begin_ = result->take_slice(sizeof(begin) - 1);
|
||||
EXPECT(boost::range::equal(std::string{begin}, begin_));
|
||||
}
|
||||
{
|
||||
id_str = result->take_slice(32);
|
||||
const boost::string_ref id_hex{
|
||||
reinterpret_cast<const char*>(id_str.data()), id_str.size()
|
||||
};
|
||||
EXPECT(epee::from_hex::to_buffer(epee::as_mut_byte_span(id), id_hex));
|
||||
}
|
||||
|
||||
SECTION("webhook_add")
|
||||
{
|
||||
static constexpr const char end[] =
|
||||
u8"\",\"token\":\"the_token\",\"confirmations\":3,\"url\":\"http://the_url\"}";
|
||||
EXPECT(boost::range::equal(std::string{end}, *result));
|
||||
EXPECT(MONERO_UNWRAP(MONERO_UNWRAP(db.start_read()).get_webhooks()).size() == 1);
|
||||
}
|
||||
|
||||
SECTION("webhook_delete_uuid")
|
||||
{
|
||||
EXPECT(MONERO_UNWRAP(MONERO_UNWRAP(db.start_read()).get_webhooks()).size() == 1);
|
||||
std::string delete_json_str{};
|
||||
delete_json_str.append(u8"{\"addresses\":[\"");
|
||||
delete_json_str.append(address_str);
|
||||
delete_json_str.append(u8"\"]}");
|
||||
|
||||
expect<epee::byte_slice> result2 =
|
||||
call_endpoint<lws::rpc::webhook_delete_>(db.clone(), std::move(delete_json_str));
|
||||
EXPECT(!result2.has_error());
|
||||
EXPECT(boost::range::equal(std::string{u8"{}"}, *result2));
|
||||
EXPECT(MONERO_UNWRAP(MONERO_UNWRAP(db.start_read()).get_webhooks()).empty());
|
||||
}
|
||||
|
||||
SECTION("webhook_delete_uuid")
|
||||
{
|
||||
EXPECT(MONERO_UNWRAP(MONERO_UNWRAP(db.start_read()).get_webhooks()).size() == 1);
|
||||
std::string delete_json_str{};
|
||||
delete_json_str.append(u8"{\"event_ids\":[\"");
|
||||
delete_json_str.append(reinterpret_cast<const char*>(id_str.data()), id_str.size());
|
||||
delete_json_str.append(u8"\"]}");
|
||||
|
||||
expect<epee::byte_slice> result2 =
|
||||
call_endpoint<lws::rpc::webhook_del_uuid_>(db.clone(), std::move(delete_json_str));
|
||||
EXPECT(!result2.has_error());
|
||||
EXPECT(boost::range::equal(std::string{u8"{}"}, *result2));
|
||||
EXPECT(MONERO_UNWRAP(MONERO_UNWRAP(db.start_read()).get_webhooks()).empty());
|
||||
}
|
||||
|
||||
SECTION("webhook_list")
|
||||
{
|
||||
wire::json_slice_writer out{};
|
||||
EXPECT(lws::rpc::webhook_list(out, db.clone()));
|
||||
expect<epee::byte_slice> bytes = out.take_bytes();
|
||||
EXPECT(!bytes.has_error());
|
||||
|
||||
{
|
||||
static constexpr const char begin[] =
|
||||
u8"{\"webhooks\":[{\"key\":{\"user\":1,\"type\":\"tx-confirmation\"}"
|
||||
",\"value\":[{\"payment_id\":\"deadbeefdeadbeef\",\"event_id\":\"";
|
||||
epee::byte_slice begin_ = bytes->take_slice(sizeof(begin) - 1);
|
||||
EXPECT(boost::range::equal(std::string{begin}, begin_));
|
||||
}
|
||||
{
|
||||
boost::uuids::uuid id_{};
|
||||
epee::byte_slice id_str_ = bytes->take_slice(32);
|
||||
const boost::string_ref id_hex{
|
||||
reinterpret_cast<const char*>(id_str_.data()), id_str_.size()
|
||||
};
|
||||
EXPECT(epee::from_hex::to_buffer(epee::as_mut_byte_span(id_), id_hex));
|
||||
EXPECT(id_ == id);
|
||||
}
|
||||
{
|
||||
static constexpr const char end[] =
|
||||
u8"\",\"token\":\"the_token\",\"confirmations\":3,\"url\":\"http://the_url\"}]}]}";
|
||||
EXPECT(boost::range::equal(std::string{end}, *bytes));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user