rippled
Loading...
Searching...
No Matches
ValidatorSite_test.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright 2016 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <test/jtx.h>
21#include <test/jtx/TrustedPublisherServer.h>
22#include <test/unit_test/FileDirGuard.h>
23
24#include <xrpld/app/misc/ValidatorSite.h>
25
26#include <xrpl/basics/strHex.h>
27#include <xrpl/protocol/PublicKey.h>
28#include <xrpl/protocol/jss.h>
29
30#include <boost/algorithm/string/join.hpp>
31#include <boost/algorithm/string/predicate.hpp>
32#include <boost/asio.hpp>
33#include <boost/range/adaptor/transformed.hpp>
34
35#include <date/date.h>
36
37#include <chrono>
38
39namespace ripple {
40namespace detail {
41constexpr char const*
43{
44 return R"vl({
45 "public_key": "ED2677ABFFD1B33AC6FBC3062B71F1E8397C1505E1C42C64D11AD1B28FF73F4734",
46 "manifest": "JAAAAAFxIe0md6v/0bM6xvvDBitx8eg5fBUF4cQsZNEa0bKP9z9HNHMh7V0AnEi5D4odY9X2sx+cY8B3OHNjJvMhARRPtTHmWnAhdkDFcg53dAQS1WDMQDLIs2wwwHpScrUnjp1iZwwTXVXXsaRxLztycioto3JgImGdukXubbrjeqCNU02f7Y/+6w0BcBJA3M0EOU+39hmB8vwfgernXZIDQ1+o0dnuXjX73oDLgsacwXzLBVOdBpSAsJwYD+nW8YaSacOHEsWaPlof05EsAg==",
47 "blob" : "eyJzZXF1ZW5jZSI6MzcsImV4cGlyYXRpb24iOjU5NDE3MjgwMCwidmFsaWRhdG9ycyI6W3sidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRUQ0OUY4RUI4MDcxRTI2RDRFMDY3MjM4RDYyRDY3Q0E2RUJGQjI5OEI0QTcyRENGQUQ1MzZBN0VDODkyNUM1MTlCIiwibWFuaWZlc3QiOiJKQUFBQUFGeEllMUorT3VBY2VKdFRnWnlPTll0WjhwdXY3S1l0S2N0ejYxVGFuN0lrbHhSbTNNaEFvZ01tUVRSQUZLLyttL1hXUWZKdlhUZU1jYWl5RjZna2hnQXNzZExPY2lJZGtZd1JBSWdOeFlhdkpQeUhBTnV4b2dRWTdSTkJQOXRab2daSnhGMXdacXptNGEzN0dnQ0lCT3ZiZVE4K1A0NkNDSWN5NFpDWkE1clpaKzkzSDBhS0paUTMrSUEwT091Y0JKQUFTVHBRS3RFSmtlcXdIeitqS1dOdldsMHNIUlFaU1NKdVlpTXl5VWE3eXRwc2V2Nk5Hb0ZuMWJOcFlUZ3ZzYVB4b3o3dkhza0RoMlo2Z2ViU0RDUkNBPT0ifSx7InZhbGlkYXRpb25fcHVibGljX2tleSI6IkVEODEwOEY3RDlFRTc3OURDMTA3NUVDM0NGOEVCOTAwNERERjg0Q0QwQTBGRjU3NzVDOUUzNzVDQ0FDREFBMzAyMiIsIm1hbmlmZXN0IjoiSkFBQUFBRnhJZTJCQ1BmWjduZWR3UWRldzgrT3VRQk4zNFROQ2cvMWQxeWVOMXpLemFvd0luTWhBbHZQSkFOUWNSVVNOVVIrTmxadW80a0dwWUY4bDlwSFBQMVpST09VY05ZUmRrWXdSQUlnUldaWnVKTEFmM1NOTUdvRnlnVWx1K2VBRDUxWm9IRk1jeW9pY24wV0t1Y0NJR3c0bjljVkRQT0JHQzh3bEpEeTkyODJ4OVJkT3dvMWNvMmcrTlpsYy9ETmNCSkFLSmhLL2FtNkw3S0U0NTBOVnpocFZWb0w4T0ZNbzBtRnhrOEJERzZRTzJjU05NTjNPeXdmNDBEK0lsZXM5TFh4eHZ2UEI2Z1dTbVBsd0Y3ZE5SOUdBUT09In0seyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFRDdFM0JBRkY5MDFERTUyNUIwMEIyQzFGRTE5QUY0NDlBMDgwQjVGMzEwMEM2RUMxODJDODY3QUY2MUY3MTBGRkQiLCJtYW5pZmVzdCI6IkpBQUFBQUZ4SWUxK082LzVBZDVTV3dDeXdmNFpyMFNhQ0F0Zk1RREc3QmdzaG5yMkgzRVAvWE1oQTUrR0RKaDJBcFdLQ2gyTjVvbXg0RkFPRkVxWE1qcXkxSEo1RTdXQTNGck9ka2N3UlFJaEFNUmV6d2pUQUwzNWpwamoxNWpxb0hVdlJtNys3aUhwVTQ3YUtFNkhFQ2haQWlCU01JWmFNV3Y2cU5KSG5pWXBzWUh4NE9QUHBCb0NNTWRNVkFHZkZpOWZLM0FTUUUwVFlpSXNHdjAveWxwcUdFQmlMa2syWGpyQTgrK0FrenByOXZjVHRya0hpRERvMGNIS085bVJVTEFYZXNSck95RmI1UWNPMGwwVnN3ZXZENWpsc3drPSJ9LHsidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRUQ0NUU4MEEwNEQ3OUNCOURGMDBBRUJEODZEQ0RDMTY4NkQ2NDE5RUE5RTVFMEU3MUYxQTgxN0UwOEI1MDc2QTU1IiwibWFuaWZlc3QiOiJKQUFBQUFGeEllMUY2QW9FMTV5NTN3Q3V2WWJjM0JhRzFrR2VxZVhnNXg4YWdYNEl0UWRxVlhNaEF4Wm8xNTdwY0I5ZGU2U21rN2hvSzN3TkNBcjRhRlp0ZkFQaTdDRTRtTkpsZGtjd1JRSWhBTGxWalhDZml5L210WEJXc050Nzd0NGpLY05FQnBSVjh6ditTcFU1bENoMEFpQmE4dm84eHhwdmlZbGY0emRHK25RaEIyT2dma1FaWlBNSE90N0NhWHpYZ1hBU1FMOE81cDA4M21nNEtLTDh1WmZNYVVxZGd6dUowR3RhMWx5VVdQY3RUUEN4WTEzNVh3SytuSkFkRnNJVUZOSjlNUGpucENtU2pZVnpWYTZNNS9uQWNBST0ifSx7InZhbGlkYXRpb25fcHVibGljX2tleSI6IkVERDhDODg2NDI3OTVDRTY5QzVCNzgwRTAxNzAyQzM3MEY5NTA3RDBCNjQ0MzNGMTdFRkU3MEYyNjM3QTQwQURCNyIsIm1hbmlmZXN0IjoiSkFBQUFBRnhJZTNZeUlaQ2VWem1uRnQ0RGdGd0xEY1BsUWZRdGtRejhYNytjUEpqZWtDdHQzTWhBbkZmcityOUJYZHNYRS9jQmxKTXlkL1hzTzFBNVhFWUNjdHJzdkxFWCtEbWRrY3dSUUloQU5SY1JNZzlTQVhvYU92SERaMmF2OVJ6RWFaYVZFTmZRaVZnc2krT3gzRjBBaUIyc25TSU9tNmM0L2luYnRVMFVtV0xRVHp1d2tPZFVGUElCOEF4OGRtR3VIQVNRTVVJZlhNajk2a2NGVFNKbk1GQy9tVy9BUThiS1hrRnJyazBDVVRGRkt3ZUVqVHErU1RyRmk2cUxMMk1UN252ZUd4c1hCQ2d6dGpjMHFHYXM5S0ZXZ009In0seyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFREJERUI5MDFGN0M3NUQwRTIwQzZDNDJBRjAzQkUwREE0MDM3N0FGMTkzOUExOEIzQ0IzNjc5NjYxREQ1RjlGNzQiLCJtYW5pZmVzdCI6IkpBQUFBQUZ4SWUyOTY1QWZmSFhRNGd4c1FxOER2ZzJrQTNldkdUbWhpenl6WjVaaDNWK2ZkSE1oQWczY3lLTlBNUHFLZ1I3a0lpN2MvOEdML1lnZEJ0ZzRtU0FXdndtYWV2Vkdka1l3UkFJZ1d6RzhHcVlnM1lwd0RzOHhYYTlYcUxIc3M3NktUMnVBSFJoVVhGVlVxQ1FDSUcyRXZiRktueGV6UmQ5Y3BQSFN0MzJIWEsrUDQrYUwzcDIrdnFsQ3hSUjljQkpBYm9YVG1ZVGF5b2NBM3pmOWRXRVh0eWFlT0dDMWs1V2RZVVJ6UGxlZXZ2YWxSNHhWb1h6czM4aUdQeEZyL3BBOW5MK000ZHV1MEdLQ0hsVmlyK2ZCQWc9PSJ9LHsidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRURBMTc4NzFFNzJCMEM1NzBBQzQzNDVDNjBDRjAyQUZCQkI3NDBBNjMxQjdBRDBFMUU1NzMyMTY1NzREOUFFQTAyIiwibWFuaWZlc3QiOiJKQUFBQUFGeEllMmhlSEhuS3d4WENzUTBYR0RQQXErN3QwQ21NYmV0RGg1WE1oWlhUWnJxQW5NaEFvanl1emd0cmVRa3hRajhwckh4T3NiRGNGNWZ1NFhYYjBLeEVML1BxNUhoZGtjd1JRSWhBTmZQRExaUDQ3YUNXd3Q1a0JucDc1QnV1Q2dwOWM0QmZKUGQ2NlNGQ3c2MUFpQUp2ZWdCdnZQSXJlYytYT1N6S1JmaTV1dVhXeHRsOUV5cjJhUEJZWHZiUkhBU1FNVUxZRW83YmVSZm9VQ25qazFzVFl5WTkxdExJR0xnbm5hV1hoVW04MCt6czVJR2VnazhxaWpLQXRCT011QkM3MWxBQjRLaEpjK2RCMnJwTU9GYzVndz0ifSx7InZhbGlkYXRpb25fcHVibGljX2tleSI6IkVERjQ2RUUyN0FEMEUxQTcxNEFGRUNEQTgxNkVBQjcxMTQ2MTRGQ0I5MkQwQ0I0RDk3QjZBODhFRDQzNDM0QUZDOSIsIm1hbmlmZXN0IjoiSkFBQUFBRnhJZTMwYnVKNjBPR25GSy9zMm9GdXEzRVVZVS9Ma3RETFRaZTJxSTdVTkRTdnlYTWhBdzBBVFdqVlR0NEZmZUtPN2t2NmZGZ2QvZ28yK2Q1QlN5VWNVUm1SV25UdGRrY3dSUUloQU13T2dEZWM3UVlZTm5nc3BnOTB3RXZWYnNvaDJ1eDE0UlBUdytHSGFYTmxBaUFMZ2ZFc3orQUY0ZXlYL1k1aTQ0VnJGakZGSU1XVWZPWmFRSnRzeHRlTTFYQVNRTE9hRjB0MlpwcVZLZDhKRVNRVlkrelU1NjdpQUFHMmFtVFBaeDk1ODc1UzlBNlBsK2tINVRHSE1BZVdqZ1dTcWZoM20ySEJKWDdOSWNYYjk4dnk5QUE9In0seyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFRDZFNEM0MUU1OUZGQkVCNTE3MjZFNTQ0Njg1MDJGRTY0MzcyMzhGQTc4RUE1MTYzNEU3QkYwRDA5MTcxQUVFOEYiLCJtYW5pZmVzdCI6IkpBQUFBQUZ4SWUxdVRFSGxuL3ZyVVhKdVZFYUZBdjVrTnlPUHA0NmxGalRudncwSkZ4cnVqM01oQXV6dEdXYi9PaTEvVjVtNWR1aldyOUhtYktSeUs0WFlrK2ttdUZQU2dBRnJka1l3UkFJZ2ZRK0JnWFg2UWJsWnk0SDA1bzdHUFNJd3FTN1FRUlVXN2RxRjU0SUFpaU1DSUg0WGZMdzk1NmlFYW94Wk9rN0tjdGluMlg5aE1mYUxON3d5czl5QVVGb1pjQkpBdWVFaTg0WFIzTGwxR0xKV2FuVzFnMU1kVWovMFBBeEpidzZFRVFSdUczemRudVJITlhsZDZVWkFiSWtWY1AwenRmcXVsQnpqYmNzTERPS0ZFaWNTQmc9PSJ9LHsidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRURCNkZDOEU4MDNFRThFREMyNzkzRjFFQzkxN0IyRUU0MUQzNTI1NTYxOERFQjkxRDNGOUIxRkM4OUI3NUQ0NTM5IiwibWFuaWZlc3QiOiJKQUFBQUFGeEllMjIvSTZBUHVqdHduay9Ic2tYc3U1QjAxSlZZWTNya2RQNXNmeUp0MTFGT1hNaEE4VmR2SEZ5U2NCeVFHVFlOR2VPdkIwKzY3Z1dhcWVmY2Z2Ums1K0t3Z1YxZGtZd1JBSWdaRnVsTy9BaU1vY3puZzZpLzRCa2Z6VDdqOWx4RjRQUDF1ZmdyT1FhSjhzQ0lCWC9FOFpicG43dFdxZ0F5TnlXcFZQa2hGbWFVTXFFcnk4V29VVDFmZEdRY0JKQXY1MVJxSnhnZy9Wcm5yWndpTEsyRGMwQ0tiaUxQTzVISjRaTXNqZFBUMmdSYzk3cldrQVh1VjJMNlBORk81OXh5dW9hWm1TTWxaWXZxU0dQcGZGN0J3PT0ifSx7InZhbGlkYXRpb25fcHVibGljX2tleSI6IkVENjkxMzAzOTkyRkVDNjRFNkJDNEJBQ0QzNkFFNkU1QUVEQzIzRjI4NjFCNkQ4RUZCOUZENzdFRTNFQURFMzQzNSIsIm1hbmlmZXN0IjoiSkFBQUFBRnhJZTFwRXdPWkwreGs1cnhMck5OcTV1V3UzQ1B5aGh0dGp2dWYxMzdqNnQ0ME5YTWhBaTJBWEpRZ28vSnVXM3I3Zi82Q2NWc0dOMVltSWoxMUdpSUVTSEJuUVNrOGRrY3dSUUloQU5DREVReW1yZDZ2ZVQzb3VhY0Y2ZmhCcjV3THczR21YZzFyTUNMVnZCelpBaUE4dVdRK3RxZDQ2V21mQmV4alNCUTJKZDZVQUdkckh2amNDUTJaZ1Nvb0NuQVNRRmtIbCtENy9VM1dCeVlQMzg0K3BjRkRmMkdpNFdJUkhWVG81OGNxZGs1Q0Rpd2MxVDByRG9MaG1vNDFhM2YrZHNmdGZ3UjRhTW13RmNQWExucmpyQUk9In0seyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFREFEMTY2NjdGMDE4NUREQkI3RkE2NUIyMkY0QjdEMzEwQkY1QzNFMkQ5QjgyM0ZCMDZBM0E0MUFGOEFDODNCQzEiLCJtYW5pZmVzdCI6IkpBQUFBQUZ4SWUydEZtWi9BWVhkdTMrbVd5TDB0OU1RdjF3K0xadUNQN0JxT2tHdmlzZzd3WE1oQXF3ZUUzUElTM0U0NEtoTXFLakt0YmtCZThIOEdiaXVvQVhBWURSb1ZSSG9ka1l3UkFJZ2FnR2tYdG93VXliZGx0S29qdjBsdnZmbHJsUTlJUm5QT2pla0Y2MGlIemdDSUNnNlpvY0lNemtVdXZPOTFCRW9ybUlXbVg0Ry9NR1QyenJvNkkvUHZCOFhjQkpBY0pMWGt0L3cva2N3RXZOaVptaTJpMm5NbjF3aVAzTFM5TkpqQlBqdThLRkxBTWcwTzl5ZFFUNjdVL0FMWU9lVFBUTzIvaTJZdzlPU2xpYnRxaGd6REE9PSJ9LHsidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRURDMjQ1MDI3QTUyRUU1MzE4MDk1NTk4RUMzQUI2NUZGNEEzQjlGOTQyOEUxMEIyRjNDNkYzOURFMTVBMTVDOTBBIiwibWFuaWZlc3QiOiJKQUFBQUFGeEllM0NSUUo2VXU1VEdBbFZtT3c2dGwvMG83bjVRbzRRc3ZQRzg1M2hXaFhKQ25NaEEvOC85cktVZEE2MWovZklFUC9jcUxweEJsbUloUDJyZzFkN05hRVB5S1YrZGtjd1JRSWhBSXhFME0vRko1MHZmWlc2ZlBweTR5Q1p1bVk5bjBvYnJPb2pVa2ptNTVhMEFpQmo1Nk8wTXBvcEdvWTlIeEMvKzR3Tk8zNkhvN0U5Q1FlSHNuS3JlRGRzQVhBU1FJWVVkODFqYmlWVWxFVDRkR29HMnArY2YrMkdxRVhYNWZKTVNTeVgvcWUwWGZSNGNPKzRxbGdtak1RZENSREJXQUJIVnZkTi95WnlpL3JMMmMrV3JRYz0ifSx7InZhbGlkYXRpb25fcHVibGljX2tleSI6IkVENDI0NkFBM0FFOUQyOTg2Mzk0NDgwMENDQTkxODI5RTQ0NDc0OThBMjBDRDlDMzk3M0E2QjU5MzQ2Qzc1QUI5NSIsIm1hbmlmZXN0IjoiSkFBQUFBRnhJZTFDUnFvNjZkS1lZNVJJQU15cEdDbmtSSFNZb2d6Wnc1YzZhMWswYkhXcmxYTWhBa20xbHowYzhRWFdmSjliMXZCNzJkTGFidzh3WUlkOE10bnBzSEhCRUM4cGRrWXdSQUlnUWxiNkhKNTNoc1RBZlZpZCtBT2RCVnZNRjdyYWhJS05MQkhVZ241MnpCRUNJR0xVcUZ1OGExQUFIUkpjVm9uS1lFbm1oSndiQ1hMbitqZTduYTFXRDEvb2NCSkFFNHZmdnJHU21aQzJ1QVVHbU01ZElCdG9TZ0VVZXkrMlZsZURZRXNjZTk0dHhZY2pSOFo3UUxOYWxpRDh3L2JENS9odllROG1lVjFXZzFqSkZOZTBDQT09In0seyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFRDJDMTQ2OEI0QTExRDI4MUY5M0VGMzM3Qzk1RTRBMDhERjAwMDBGREVGQjZEMEVBOUJDMDVGQkQ1RDYxQTFGNUEiLCJtYW5pZmVzdCI6IkpBQUFBQUZ4SWUwc0ZHaTBvUjBvSDVQdk0zeVY1S0NOOEFBUDN2dHREcW04QmZ2VjFob2ZXbk1oQWtNVW1DRDJhUG1nRkREUm1pbXZTaWNTSVNjdzZZTnI0MkR3NFJBZHdyT0Fka2N3UlFJaEFKRk9ITWc2cVRHOHY2MGRocmVuWVlrNmN3T2FSWHEwUk5tTGp5eUNpejVsQWlBZFUwWWtEVUpRaG5OOFJ5OHMrNnpUSkxpTkxidE04b08vY0xudXJWcFJNM0FTUUdBTGFySEFzSmtTWlF0R2RNMkFhUi9qb0ZLL2poRFU1NytsK1JTWWpyaS95ZEUyMERhS2Fud2tNRW9WbEJUZzdsWDRoWWpFbm1rcW83M3dJdGhMT0FRPSJ9LHsidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRURBNTRDODVGOTEyMTlGRDI1OTEzNEI2QjEyNkFENjRBRTcyMDRCODFERDQwNTI1MTA2NTdFMUE1Njk3MjQ2QUQyIiwibWFuaWZlc3QiOiJKQUFBQUFKeEllMmxUSVg1RWhuOUpaRTB0ckVtcldTdWNnUzRIZFFGSlJCbGZocFdseVJxMG5NaEFsOGNKZXJQdit2bzFCSzYxMXhWVHBHeGpqci9DdXhQVGdVOFVSTTRlVFo1ZGtZd1JBSWdkSzNjUVYyWS92aVpuZS9QYm9LU0tld25nVHVJTjJNNmM4YXp3cWMyMHVVQ0lBYzZHb05UK1AyWUJ5NDlnZGF1NFA3eVN3V29RWDVuZjlkUXhpUWF2NXdJY0JKQXFpQ0swZDZRUlpTcGlWSHA4TzlubEtYQ1NFaHNpU05jV2NFRm0vZkdoSkFuQU4wT3Y5SElOSWQxcHhyQm4yZEtSZWdMVHZZRzNCcGJ6Ly9ITGdFZERBPT0ifSx7InZhbGlkYXRpb25fcHVibGljX2tleSI6IkVEOUFFNEY1ODg3QkEwMjlFQjdDMDg4NDQ4NkQyM0NGMjgxOTc1Rjc3M0Y0NEJEMjEzMDU0MjE5ODgyQzQxMUNDNyIsIm1hbmlmZXN0IjoiSkFBQUFBRnhJZTJhNVBXSWU2QXA2M3dJaEVodEk4OG9HWFgzYy9STDBoTUZRaG1JTEVFY3gzTWhBbUcyemd2OEZCWnNaSlU4YVBhcHdvOWNJcVF2NC9NU1Mxb1ZBNWVWTWl3TGRrWXdSQUlnRitMT2U0ZVkwZ3A5dHRxaDJnbnYrejc1T3FMeU9RTXBHUEFMZ20rTnRPc0NJQ0RYQlpWUHRwcm1CRGtCSmtQRlNuRTU1RDllS1lSSDh6L2lZMUV0cE5wbGNCSkFBREVXR1ZUODBPd2hkMWxoMkpzVS9vWmxtZU5GNVdON1l2bEI4bGxFeGFSS0VWQytHVzlXZytpTklRM3JtVjdQOGFOYVZ1YWFiRzAwZk9na2d6TmhEdz09In0seyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFREE4RDI5RjQwQ0VCMjg5OTU2MTc2NDFBM0JDNDI2OTJFMURFODgzMjE0RjYxMkZCQjYyMDg3QTE0OEU1RjZGOUEiLCJtYW5pZmVzdCI6IkpBQUFBQUZ4SWUybzBwOUF6cktKbFdGMlFhTzhRbWt1SGVpRElVOWhMN3RpQ0hvVWpsOXZtbk1oQW5ZblA3RWc2VmdObkVVVFJFMjlkNjRqUVQvaUJjV1RRdE5yVXp5RDZNSitka2N3UlFJaEFPRXNWNWFuVGtsb1NtVFpSYmltTXlCS3FIb0pZWGNCQmU4bExpUFlDN21VQWlBejJhTk9wZlEvMUx5Y1dsb0lNdmRoeHppbnE1WDdVYXMvdU9TYjl3aDhkM0FTUUxWa2ZwVy9HTzZ3ZFQ2QXV1U0o1NlR0TTM0M3BETkgraVN6eGx0SWZkclBpVXhUNXJmNGsyMWxRUXVQQ2xYbTkrU2ZLckNpVVhaSzdkajAvR1dUWVFnPSJ9LHsidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRUQzOEIwMjg4RUEyNDBCNENERUMxOEExQTYyODlFQjQ5MDA3RTRFQkMwREU5NDQ4MDNFQjdFRjE0MUM1NjY0MDczIiwibWFuaWZlc3QiOiJKQUFBQUFGeEllMDRzQ2lPb2tDMHpld1lvYVlvbnJTUUIrVHJ3TjZVU0FQcmZ2RkJ4V1pBYzNNaEFnT0tjdkl1Y2hhbHJady9nbFR1T3hWM0lPQ2Nwb3J4TUI3SnFBVnVwazFlZGtjd1JRSWhBT3ZSenBlK0lZWksxTXlJbklRWjg3SnZQMko4U0lYQ1haTVBCQ2RJVEJhbUFpQVNhdkpYaTlwd3M4ckRESlN4aEdNbG1FN3pJNWJTQThpdnRSQzlMZ3ErVVhBU1FEbDNlb3FMSUQrRVRKTk0remJNdXZ3dmNIRUl4ZUJaa1o5ZnA1akp2Nk9DVFB3bGo0VEpTdXkxYXZFV3FVWVMycml2NUR2bDJoYUZVb0NIZjR5YXdBQT0ifSx7InZhbGlkYXRpb25fcHVibGljX2tleSI6IkVERUUxMERDMzZBQ0Q5OTVDOEUwRTg2RTNDRDJGQkY4MzAxQTRBQzJCODg0N0I2MUExOTM1REU0OTczQjQwN0MwRSIsIm1hbmlmZXN0IjoiSkFBQUFBRnhJZTN1RU53MnJObVZ5T0RvYmp6UysvZ3dHa3JDdUlSN1lhR1RYZVNYTzBCOERuTWhBbVgwdmI3aitsZ0JqRmpiTjlSbEE4Nko3QU8yVm42SExxdU8zYWlzSzRtd2RrWXdSQUlnZnhCTG43aTRqZy9kaTBVMjVxNmtJYlZmVHpxYkEwU0NwUTBJNTdUT0ZrY0NJRk10SlFwRU5qQjJLMkVtdkJIUHZOY3d1U1BjM3ZzRWVxRTJyTkovY1Q1RGNCSkFmNjhYUEZ1NVJqQ2VMZ3BGSk03UEtGTGdvVjhlMW54TzVld2pxOVErVEFFR25GeVMwSU93ZjZwT090SVZNZFZlWHUxdjZwNGZoWFFrZGloSHQxeDZBZz09In0seyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFRDU4M0VDRDA2QzNCNzM2OTk4MEU2NUM3OEM0NDBBNTI5MzAwRjU1N0VEODEyNTYyODNGN0RENUFBMzUxM0EzMzQiLCJtYW5pZmVzdCI6IkpBQUFBQUZ4SWUxWVBzMEd3N2MybVlEbVhIakVRS1VwTUE5VmZ0Z1NWaWcvZmRXcU5ST2pOSE1oQXl1VW56WloxbjIvR2FUbUUxbTdIL3Y5WWxaeURFd0hZM2dTSFVBM0lDTDlka1l3UkFJZ0h4MlBIdmlkb04rNXlHOVdlQVMyazdud0lNOGFqeFFXNndqdnQ4a0JlbkFDSUROeFFQUWtEeURKSDlzZVM1QzYybUFhclFtZ2lOODlZUzNqaE50bnZFSXFjQkpBajdKaDBLYWMrYUpkcG9lcHUvK2VKS25uRlE3WUJ5WkI4ZU1aK1NTMXpMaEUrbGlwLzQ5cXFWTmNwQXhFcWZhR3R4SnpvREREMS9RYnVVN05PU1BrQ2c9PSJ9LHsidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRUQ5NUM1MTcyQjJBRDdEMzk0MzRFRUJDNDM2QjY1QjNCQjdFNThENUMxQ0VGQzgyMEI2OTcyQUNBRDc3NkUyODZBIiwibWFuaWZlc3QiOiJKQUFBQUFGeEllMlZ4UmNyS3RmVGxEVHV2RU5yWmJPN2ZsalZ3Yzc4Z2d0cGNxeXRkMjRvYW5NaEFpcWNSZGUzTVFaMDc1ZmE0Wk5OeVJhWUpHTWRCTmtCbm4zYlFyS3NlQkRRZGtZd1JBSWdVK0xmY0U3MURQVnJPK0t0VUJqUTlEMnUway9QcjdsdWtPMW5QUmo2aFNBQ0lETkxZQy9KRmdvYkNzSWEwQkd3KzZiVW5PdzltZVUzRmRYZ1I3UTdTb3FKY0JKQVhRYWtPb1FuUHAzcGNMTDd6ZEtDUFVYNGIrL0ZDOVVuaHFwK085eFFGblJhQ1dWR21rNU1KT0lNczRXT1FkcE0xajNPZ1NzQUJtUnVDWFl2d28vbkR3PT0ifSx7InZhbGlkYXRpb25fcHVibGljX2tleSI6IkVEOTAxNjNEMkJGMEI3Nzg4OTA0QzRBNDExOEQ3RDk2ODkyMEU4NDdEODhCNzkxNzgzOTA4MzdERTNDQTI2MTU2MiIsIm1hbmlmZXN0IjoiSkFBQUFBRnhJZTJRRmowcjhMZDRpUVRFcEJHTmZaYUpJT2hIMkl0NUY0T1FnMzNqeWlZVlluTWhBNzJWVFJpR2hrSkJ0cWdHSER6SGo3WWJDNitOc0VLckZITnVFL0xPM1RuNWRrWXdSQUlnZjhzK2ZZdDBsbHJLUTJxaVdQbkdtYjZxSlBvZThPbkNNM1ZTMjlYS2JZWUNJSEdubEo0T1RzMmRYdWdPNkJ0bzYzTnBEdnZxSitXSXdkWUtxWjZCaUJmemNCSkFHdk50a29nNHBmRTVkWlJ3bWljODdaQmVldW5PaDRZcEwwU0VSZHhXajQzQ3M5ODE1ekZKdVp5c1NhVVgyUi92ZEUyVktxdlNncXF0REVuck1vMm9Bdz09In1dfQ==",
48 "signature" : "9FF30EDC4DED7ABCD0D36389B7C716EED4B5E4F043902853534EBAC7BE966BB3813D5CF25E4DADA5E657CCF019FFD11847FD3CC44B5559A6FCEEE4C3DCFF8D0E",
49 "version": 1
50}
51)vl";
52}
53
56} // namespace detail
57
58namespace test {
60{
61private:
63
64 void
66 {
67 testcase("Config Load");
68
69 using namespace jtx;
70
71 Env env(*this, envconfig(), nullptr, beast::severities::kDisabled);
72 auto trustedSites =
74
75 // load should accept empty sites list
76 std::vector<std::string> emptyCfgSites;
77 BEAST_EXPECT(trustedSites->load(emptyCfgSites));
78
79 // load should accept valid validator site uris
81 {"http://ripple.com/",
82 "http://ripple.com/validators",
83 "http://ripple.com:8080/validators",
84 "http://207.261.33.37/validators",
85 "http://207.261.33.37:8080/validators",
86 "https://ripple.com/validators",
87 "https://ripple.com:443/validators",
88 "file:///etc/opt/ripple/validators.txt",
89 "file:///C:/Lib/validators.txt"
90#if !_MSC_VER
91 ,
92 "file:///"
93#endif
94 });
95 BEAST_EXPECT(trustedSites->load(cfgSites));
96
97 // load should reject validator site uris with invalid schemes
98 std::vector<std::string> badSites({"ftp://ripple.com/validators"});
99 BEAST_EXPECT(!trustedSites->load(badSites));
100
101 badSites[0] = "wss://ripple.com/validators";
102 BEAST_EXPECT(!trustedSites->load(badSites));
103
104 badSites[0] = "ripple.com/validators";
105 BEAST_EXPECT(!trustedSites->load(badSites));
106
107 // Host names are not supported for file URLs
108 badSites[0] = "file://ripple.com/vl.txt";
109 BEAST_EXPECT(!trustedSites->load(badSites));
110
111 // Even local host names are not supported for file URLs
112 badSites[0] = "file://localhost/home/user/vl.txt";
113 BEAST_EXPECT(!trustedSites->load(badSites));
114
115 // Nor IP addresses
116 badSites[0] = "file://127.0.0.1/home/user/vl.txt";
117 BEAST_EXPECT(!trustedSites->load(badSites));
118
119 // File URL path can not be empty
120 badSites[0] = "file://";
121 BEAST_EXPECT(!trustedSites->load(badSites));
122
123#if _MSC_VER // Windows paths strip off the leading /, leaving the path empty
124 // File URL path can not be a directory
125 // (/ is the only path we can reasonably assume is a directory)
126 badSites[0] = "file:///";
127 BEAST_EXPECT(!trustedSites->load(badSites));
128#endif
129 }
130
144 void
146 detail::DirGuard const& good,
148 {
149 testcase << "Fetch list - "
150 << boost::algorithm::join(
151 paths |
152 boost::adaptors::transformed(
153 [](FetchListConfig const& cfg) {
154 return cfg.path +
155 (cfg.ssl ? " [https] v" : " [http] v") +
157 " " + cfg.msg;
158 }),
159 ", ");
160
161 using namespace jtx;
162 using namespace std::chrono_literals;
163
164 Env env(*this, [&]() {
165 auto p = test::jtx::envconfig();
166 p->legacy("database_path", good.subdir().string());
167 return p;
168 }());
169 auto& trustedKeys = env.app().validators();
170 env.timeKeeper().set(env.timeKeeper().now() + 30s);
171
172 test::StreamSink sink;
173 beast::Journal journal{sink};
174
175 std::vector<std::string> emptyCfgKeys;
176 struct publisher
177 {
178 publisher(FetchListConfig const& c) : cfg{c}
179 {
180 }
183 std::string uri;
184 FetchListConfig const& cfg;
185 bool isRetry;
186 };
188
189 auto constexpr listSize = 20;
190 std::vector<std::string> cfgPublishers;
191
192 for (auto const& cfg : paths)
193 {
194 servers.push_back(cfg);
195 auto& item = servers.back();
196 item.isRetry = cfg.path == "/bad-resource";
197 item.list.reserve(listSize);
198 while (item.list.size() < listSize)
199 item.list.push_back(TrustedPublisherServer::randomValidator());
200
201 NetClock::time_point const expires =
202 env.timeKeeper().now() + cfg.expiresFromNow;
203 NetClock::time_point const effective2 =
204 expires - cfg.effectiveOverlap;
205 NetClock::time_point const expires2 =
206 effective2 + cfg.expiresFromNow;
207 item.server = make_TrustedPublisherServer(
208 env.app().getIOContext(),
209 item.list,
210 expires,
211 {{effective2, expires2}},
212 cfg.ssl,
213 cfg.serverVersion);
214 std::string pubHex = strHex(item.server->publisherPublic());
215 cfgPublishers.push_back(pubHex);
216
217 if (item.cfg.failFetch)
218 {
219 // Create a cache file
220 auto const name = good.subdir() / ("cache." + pubHex);
221 std::ofstream o(name.string());
222 o << "{}";
223 }
224
226 uri << (cfg.ssl ? "https://" : "http://")
227 << item.server->local_endpoint() << cfg.path;
228 item.uri = uri.str();
229 }
230
231 BEAST_EXPECT(trustedKeys.load({}, emptyCfgKeys, cfgPublishers));
232
233 // Normally, tests will only need a fraction of this time,
234 // but sometimes DNS resolution takes an inordinate amount
235 // of time, so the test will just wait.
236 auto sites = std::make_unique<ValidatorSite>(env.app(), journal, 12s);
237
239 for (auto const& u : servers)
240 {
241 log << "Testing " << u.uri << std::endl;
242 uris.push_back(u.uri);
243 }
244 sites->load(uris);
245 sites->start();
246 sites->join();
247
248 auto const jv = sites->getJson();
249 for (auto const& u : servers)
250 {
251 for (auto const& val : u.list)
252 {
253 BEAST_EXPECT(
254 trustedKeys.listed(val.masterPublic) != u.cfg.failApply);
255 BEAST_EXPECT(
256 trustedKeys.listed(val.signingPublic) != u.cfg.failApply);
257 }
258
259 Json::Value myStatus;
260 for (auto const& vs : jv[jss::validator_sites])
261 if (vs[jss::uri].asString().find(u.uri) != std::string::npos)
262 myStatus = vs;
263 BEAST_EXPECTS(
264 myStatus[jss::last_refresh_message].asString().empty() !=
265 u.cfg.failFetch,
266 to_string(myStatus) + "\n" + sink.messages().str());
267
268 if (!u.cfg.msg.empty())
269 {
270 BEAST_EXPECTS(
271 sink.messages().str().find(u.cfg.msg) != std::string::npos,
272 sink.messages().str());
273 }
274
275 if (u.cfg.expectedRefreshMin)
276 {
277 BEAST_EXPECTS(
278 myStatus[jss::refresh_interval_min].asInt() ==
279 u.cfg.expectedRefreshMin,
280 to_string(myStatus));
281 }
282
283 if (u.cfg.failFetch)
284 {
285 using namespace std::chrono;
286 std::stringstream nextRefreshStr{
287 myStatus[jss::next_refresh_time].asString()};
288 system_clock::time_point nextRefresh;
289 date::from_stream(nextRefreshStr, "%Y-%b-%d %T", nextRefresh);
290 BEAST_EXPECT(!nextRefreshStr.fail());
291 auto now = system_clock::now();
292 BEAST_EXPECTS(
293 nextRefresh <= now + (u.isRetry ? seconds{30} : minutes{5}),
294 "Now: " + to_string(now) + ", NR: " + nextRefreshStr.str());
295 }
296 }
297 }
298
299 void
301 {
302 testcase << "File list - " << paths[0].first
303 << (paths.size() > 1 ? ", " + paths[1].first : "");
304
305 using namespace jtx;
306
307 Env env(*this);
308
309 test::StreamSink sink;
310 beast::Journal journal{sink};
311
312 struct publisher
313 {
314 std::string uri;
315 std::string expectMsg;
316 bool shouldFail;
317 };
319
320 for (auto const& cfg : paths)
321 {
322 servers.push_back({});
323 auto& item = servers.back();
324 item.shouldFail = !cfg.second.empty();
325 item.expectMsg = cfg.second;
326
328 uri << "file://" << cfg.first;
329 item.uri = uri.str();
330 }
331
332 auto sites = std::make_unique<ValidatorSite>(env.app(), journal);
333
335 for (auto const& u : servers)
336 uris.push_back(u.uri);
337 sites->load(uris);
338 sites->start();
339 sites->join();
340
341 for (auto const& u : servers)
342 {
343 auto const jv = sites->getJson();
344 Json::Value myStatus;
345 for (auto const& vs : jv[jss::validator_sites])
346 if (vs[jss::uri].asString().find(u.uri) != std::string::npos)
347 myStatus = vs;
348 BEAST_EXPECTS(
349 myStatus[jss::last_refresh_message].asString().empty() !=
350 u.shouldFail,
351 to_string(myStatus));
352 if (u.shouldFail)
353 {
354 BEAST_EXPECTS(
355 sink.messages().str().find(u.expectMsg) !=
356 std::string::npos,
357 sink.messages().str());
358 }
359 }
360 }
361
362 void
364 {
365 auto fullPath = [](detail::FileDirGuard const& guard) {
366 auto absPath = absolute(guard.file()).string();
367 if (absPath.front() != '/')
368 absPath.insert(absPath.begin(), '/');
369 return absPath;
370 };
371 {
372 // Create a file with a real validator list
374 *this, "test_val", "vl.txt", detail::realValidatorContents());
375 // Create a file with arbitrary content
377 *this, "test_val", "helloworld.txt", "Hello, world!");
378 // Create a file with malformed Json
380 *this,
381 "test_val",
382 "json.txt",
383 R"json({ "version": 2, "extra" : "value" })json");
384 auto const goodPath = fullPath(good);
385 auto const helloPath = fullPath(hello);
386 auto const jsonPath = fullPath(json);
387 auto const missingPath = jsonPath + ".bad";
388 testFileList({
389 {goodPath, ""},
390 {helloPath,
391 "Unable to parse JSON response from file://" + helloPath},
392 {jsonPath,
393 "Missing fields in JSON response from file://" + jsonPath},
394 {missingPath, "Problem retrieving from file://" + missingPath},
395 });
396 }
397 }
398
399public:
400 void
401 run() override
402 {
403 testConfigLoad();
404
405 detail::DirGuard good(*this, "test_fetch");
406 for (auto ssl : {true, false})
407 {
408 // fetch single site
409 testFetchList(good, {{"/validators", "", ssl}});
410 testFetchList(good, {{"/validators2", "", ssl}});
411 // fetch multiple sites
412 testFetchList(
413 good, {{"/validators", "", ssl}, {"/validators", "", ssl}});
414 testFetchList(
415 good, {{"/validators", "", ssl}, {"/validators2", "", ssl}});
416 testFetchList(
417 good, {{"/validators2", "", ssl}, {"/validators", "", ssl}});
418 testFetchList(
419 good, {{"/validators2", "", ssl}, {"/validators2", "", ssl}});
420 // fetch single site with single redirects
421 testFetchList(good, {{"/redirect_once/301", "", ssl}});
422 testFetchList(good, {{"/redirect_once/302", "", ssl}});
423 testFetchList(good, {{"/redirect_once/307", "", ssl}});
424 testFetchList(good, {{"/redirect_once/308", "", ssl}});
425 // one redirect, one not
426 testFetchList(
427 good,
428 {{"/validators", "", ssl}, {"/redirect_once/302", "", ssl}});
429 testFetchList(
430 good,
431 {{"/validators2", "", ssl}, {"/redirect_once/302", "", ssl}});
432 // UNLs with a "gap" between validUntil of one and validFrom of the
433 // next
434 testFetchList(
435 good,
436 {{"/validators2",
437 "",
438 ssl,
439 false,
440 false,
441 1,
443 std::chrono::seconds{-90}}});
444 // fetch single site with undending redirect (fails to load)
445 testFetchList(
446 good,
447 {{"/redirect_forever/301",
448 "Exceeded max redirects",
449 ssl,
450 true,
451 true}});
452 // two that redirect forever
453 testFetchList(
454 good,
455 {{"/redirect_forever/307",
456 "Exceeded max redirects",
457 ssl,
458 true,
459 true},
460 {"/redirect_forever/308",
461 "Exceeded max redirects",
462 ssl,
463 true,
464 true}});
465 // one undending redirect, one not
466 testFetchList(
467 good,
468 {{"/validators", "", ssl},
469 {"/redirect_forever/302",
470 "Exceeded max redirects",
471 ssl,
472 true,
473 true}});
474 // one undending redirect, one not
475 testFetchList(
476 good,
477 {{"/validators2", "", ssl},
478 {"/redirect_forever/302",
479 "Exceeded max redirects",
480 ssl,
481 true,
482 true}});
483 // invalid redir Location
484 testFetchList(
485 good,
486 {{"/redirect_to/ftp://invalid-url/302",
487 "Invalid redirect location",
488 ssl,
489 true,
490 true}});
491 testFetchList(
492 good,
493 {{"/redirect_to/file://invalid-url/302",
494 "Invalid redirect location",
495 ssl,
496 true,
497 true}});
498 // invalid json
499 testFetchList(
500 good,
501 {{"/validators/bad",
502 "Unable to parse JSON response",
503 ssl,
504 true,
505 true}});
506 testFetchList(
507 good,
508 {{"/validators2/bad",
509 "Unable to parse JSON response",
510 ssl,
511 true,
512 true}});
513 // error status returned
514 testFetchList(
515 good,
516 {{"/bad-resource", "returned bad status", ssl, true, true}});
517 // location field missing
518 testFetchList(
519 good,
520 {{"/redirect_nolo/308",
521 "returned a redirect with no Location",
522 ssl,
523 true,
524 true}});
525 // json fields missing
526 testFetchList(
527 good,
528 {{"/validators/missing",
529 "Missing fields in JSON response",
530 ssl,
531 true,
532 true}});
533 testFetchList(
534 good,
535 {{"/validators2/missing",
536 "Missing fields in JSON response",
537 ssl,
538 true,
539 true}});
540 // timeout
541 testFetchList(
542 good, {{"/sleep/13", "took too long", ssl, true, true}});
543 // bad manifest format using known versions
544 // * Retrieves a v1 formatted list claiming version 2
545 testFetchList(
546 good, {{"/validators", "Missing fields", ssl, true, true, 2}});
547 // * Retrieves a v2 formatted list claiming version 1
548 testFetchList(
549 good, {{"/validators2", "Missing fields", ssl, true, true, 0}});
550 // bad manifest version
551 // Because versions other than 1 are treated as v2, the v1
552 // list won't have the blobs_v2 fields, and thus will claim to have
553 // missing fields
554 testFetchList(
555 good, {{"/validators", "Missing fields", ssl, true, true, 4}});
556 testFetchList(
557 good,
558 {{"/validators2",
559 "1 unsupported version",
560 ssl,
561 false,
562 true,
563 4}});
564 using namespace std::chrono_literals;
565 // get expired validator list
566 testFetchList(
567 good,
568 {{"/validators",
569 "Applied 1 expired validator list(s)",
570 ssl,
571 false,
572 false,
573 1,
574 0s}});
575 testFetchList(
576 good,
577 {{"/validators2",
578 "Applied 1 expired validator list(s)",
579 ssl,
580 false,
581 false,
582 1,
583 0s,
584 -1s}});
585 // force an out-of-range validUntil value
586 testFetchList(
587 good,
588 {{"/validators",
589 "1 invalid validator list(s)",
590 ssl,
591 false,
592 true,
593 1,
595 // force an out-of-range validUntil value on the future list
596 // The first list is accepted. The second fails. The parser
597 // returns the "best" result, so this looks like a success.
598 testFetchList(
599 good,
600 {{"/validators2",
601 "",
602 ssl,
603 false,
604 false,
605 1,
607 299s}});
608 // force an out-of-range validFrom value
609 // The first list is accepted. The second fails. The parser
610 // returns the "best" result, so this looks like a success.
611 testFetchList(
612 good,
613 {{"/validators2",
614 "",
615 ssl,
616 false,
617 false,
618 1,
620 301s}});
621 // force an out-of-range validUntil value on _both_ lists
622 testFetchList(
623 good,
624 {{"/validators2",
625 "2 invalid validator list(s)",
626 ssl,
627 false,
628 true,
629 1,
632 // verify refresh intervals are properly clamped
633 testFetchList(
634 good,
635 {{"/validators/refresh/0",
636 "",
637 ssl,
638 false,
639 false,
640 1,
643 1}}); // minimum of 1 minute
644 testFetchList(
645 good,
646 {{"/validators2/refresh/0",
647 "",
648 ssl,
649 false,
650 false,
651 1,
654 1}}); // minimum of 1 minute
655 testFetchList(
656 good,
657 {{"/validators/refresh/10",
658 "",
659 ssl,
660 false,
661 false,
662 1,
665 10}}); // 10 minutes is fine
666 testFetchList(
667 good,
668 {{"/validators2/refresh/10",
669 "",
670 ssl,
671 false,
672 false,
673 1,
676 10}}); // 10 minutes is fine
677 testFetchList(
678 good,
679 {{"/validators/refresh/2000",
680 "",
681 ssl,
682 false,
683 false,
684 1,
687 60 * 24}}); // max of 24 hours
688 testFetchList(
689 good,
690 {{"/validators2/refresh/2000",
691 "",
692 ssl,
693 false,
694 false,
695 1,
698 60 * 24}}); // max of 24 hours
699 }
700 using namespace boost::filesystem;
701 for (auto const& file : directory_iterator(good.subdir()))
702 {
703 remove_all(file);
704 }
705
706 testFileURLs();
707 }
708};
709
710BEAST_DEFINE_TESTSUITE_PRIO(ValidatorSite, app, ripple, 2);
711
712} // namespace test
713} // namespace ripple
T back(T... args)
Represents a JSON value.
Definition json_value.h:149
std::string asString() const
Returns the unquoted string value.
static Int const maxInt
Definition json_value.h:162
A generic endpoint for log messages.
Definition Journal.h:60
A testsuite class.
Definition suite.h:55
log_os< char > log
Logging output stream.
Definition suite.h:152
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:155
virtual ValidatorList & validators()=0
virtual boost::asio::io_context & getIOContext()=0
Create a directory and remove it when it's done.
path const & subdir() const
Write a file in a directory and remove when done.
time_point now() const override
Returns the current time.
std::stringstream const & messages() const
void testFetchList(detail::DirGuard const &good, std::vector< FetchListConfig > const &paths)
void run() override
Runs the suite.
void testFileList(std::vector< std::pair< std::string, std::string > > const &paths)
A transaction testing environment.
Definition Env.h:121
Application & app()
Definition Env.h:261
beast::Journal const journal
Definition Env.h:162
ManualTimeKeeper & timeKeeper()
Definition Env.h:273
Inject raw JSON.
Definition jtx_json.h:33
Set Paths, SendMax on a JTx.
Definition paths.h:35
T endl(T... args)
T is_same_v
constexpr char const * realValidatorContents()
auto constexpr default_expires
auto constexpr default_effective_overlap
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition envconfig.h:54
std::shared_ptr< TrustedPublisherServer > make_TrustedPublisherServer(boost::asio::io_context &ioc, std::vector< TrustedPublisherServer::Validator > const &validators, NetClock::time_point validUntil, std::vector< std::pair< NetClock::time_point, NetClock::time_point > > const &futures, bool useSSL=false, int version=1, bool immediateStart=true, int sequence=1)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
std::string strHex(FwdIt begin, FwdIt end)
Definition strHex.h:30
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:630
STL namespace.
T push_back(T... args)
T reserve(T... args)
T str(T... args)
T to_string(T... args)