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