rippled
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 <ripple/app/misc/ValidatorSite.h>
21 #include <ripple/basics/base64.h>
22 #include <ripple/basics/Slice.h>
23 #include <ripple/basics/strHex.h>
24 #include <ripple/protocol/digest.h>
25 #include <ripple/protocol/HashPrefix.h>
26 #include <ripple/protocol/jss.h>
27 #include <ripple/protocol/PublicKey.h>
28 #include <ripple/protocol/SecretKey.h>
29 #include <ripple/protocol/Sign.h>
30 #include <test/jtx.h>
31 #include <test/jtx/TrustedPublisherServer.h>
32 #include <test/unit_test/FileDirGuard.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 
39 namespace ripple {
40 namespace test {
41 namespace detail {
42 constexpr const char* realValidatorContents()
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 
54 auto constexpr default_expires = std::chrono::seconds{3600};
55 }
56 
57 class ValidatorSite_test : public beast::unit_test::suite
58 {
59 private:
60 
62 
63  void
65  {
66  testcase ("Config Load");
67 
68  using namespace jtx;
69 
70  Env env (*this);
71  auto trustedSites = std::make_unique<ValidatorSite> (
72  env.app(), env.journal);
73 
74  // load should accept empty sites list
75  std::vector<std::string> emptyCfgSites;
76  BEAST_EXPECT(trustedSites->load (emptyCfgSites));
77 
78  // load should accept valid validator site uris
79  std::vector<std::string> cfgSites({
80  "http://ripple.com/",
81  "http://ripple.com/validators",
82  "http://ripple.com:8080/validators",
83  "http://207.261.33.37/validators",
84  "http://207.261.33.37:8080/validators",
85  "https://ripple.com/validators",
86  "https://ripple.com:443/validators",
87  "file:///etc/opt/ripple/validators.txt",
88  "file:///C:/Lib/validators.txt"
89 #if !_MSC_VER
90  , "file:///"
91 #endif
92  });
93  BEAST_EXPECT(trustedSites->load (cfgSites));
94 
95  // load should reject validator site uris with invalid schemes
96  std::vector<std::string> badSites(
97  {"ftp://ripple.com/validators"});
98  BEAST_EXPECT(!trustedSites->load (badSites));
99 
100  badSites[0] = "wss://ripple.com/validators";
101  BEAST_EXPECT(!trustedSites->load (badSites));
102 
103  badSites[0] = "ripple.com/validators";
104  BEAST_EXPECT(!trustedSites->load (badSites));
105 
106  // Host names are not supported for file URLs
107  badSites[0] = "file://ripple.com/vl.txt";
108  BEAST_EXPECT(!trustedSites->load (badSites));
109 
110  // Even local host names are not supported for file URLs
111  badSites[0] = "file://localhost/home/user/vl.txt";
112  BEAST_EXPECT(!trustedSites->load (badSites));
113 
114  // Nor IP addresses
115  badSites[0] = "file://127.0.0.1/home/user/vl.txt";
116  BEAST_EXPECT(!trustedSites->load (badSites));
117 
118  // File URL path can not be empty
119  badSites[0] = "file://";
120  BEAST_EXPECT(!trustedSites->load (badSites));
121 
122 #if _MSC_VER // Windows paths strip off the leading /, leaving the path empty
123  // File URL path can not be a directory
124  // (/ is the only path we can reasonably assume is a directory)
125  badSites[0] = "file:///";
126  BEAST_EXPECT(!trustedSites->load (badSites));
127 #endif
128  }
129 
131  {
134  bool ssl;
135  bool failFetch = false;
136  bool failApply = false;
137  int serverVersion = 1;
140  };
141  void
143  {
144  testcase << "Fetch list - " <<
145  boost::algorithm::join (paths |
146  boost::adaptors::transformed(
147  [](FetchListConfig const& cfg){
148  return cfg.path + (cfg.ssl ? " [https]" : " [http]");}),
149  ", ");
150  using namespace jtx;
151 
152  Env env (*this);
153  auto& trustedKeys = env.app ().validators ();
154 
155  test::StreamSink sink;
156  beast::Journal journal{sink};
157 
158  PublicKey emptyLocalKey;
159  std::vector<std::string> emptyCfgKeys;
160  struct publisher
161  {
162  publisher(FetchListConfig const& c) : cfg{c} {}
165  std::string uri;
166  FetchListConfig const& cfg;
167  bool isRetry;
168  };
169  std::vector<publisher> servers;
170 
171  auto constexpr listSize = 20;
172  std::vector<std::string> cfgPublishers;
173 
174  for (auto const& cfg : paths)
175  {
176  servers.push_back(cfg);
177  auto& item = servers.back();
178  item.isRetry = cfg.path == "/bad-resource";
179  item.list.reserve (listSize);
180  while (item.list.size () < listSize)
181  item.list.push_back (TrustedPublisherServer::randomValidator());
182 
183  item.server = std::make_unique<TrustedPublisherServer> (
184  env.app().getIOService(),
185  item.list,
186  env.timeKeeper().now() + cfg.expiresFromNow,
187  cfg.ssl,
188  cfg.serverVersion);
189  cfgPublishers.push_back(strHex(item.server->publisherPublic()));
190 
191  std::stringstream uri;
192  uri << (cfg.ssl ? "https://" : "http://") << item.server->local_endpoint() << cfg.path;
193  item.uri = uri.str();
194  }
195 
196  BEAST_EXPECT(trustedKeys.load (
197  emptyLocalKey, emptyCfgKeys, cfgPublishers));
198 
199  using namespace std::chrono_literals;
200  auto sites = std::make_unique<ValidatorSite> (
201  env.app(), journal, 2s);
202 
204  for (auto const& u : servers)
205  uris.push_back(u.uri);
206  sites->load (uris);
207  sites->start();
208  sites->join();
209 
210  auto const jv = sites->getJson();
211  for (auto const& u : servers)
212  {
213  for (auto const& val : u.list)
214  {
215  BEAST_EXPECT(
216  trustedKeys.listed (val.masterPublic) != u.cfg.failApply);
217  BEAST_EXPECT(
218  trustedKeys.listed (val.signingPublic) != u.cfg.failApply);
219  }
220 
221  Json::Value myStatus;
222  for (auto const& vs : jv[jss::validator_sites])
223  if (vs[jss::uri].asString().find(u.uri) != std::string::npos)
224  myStatus = vs;
225  BEAST_EXPECTS(
226  myStatus[jss::last_refresh_message].asString().empty()
227  != u.cfg.failFetch,
228  to_string(myStatus) + "\n" + sink.messages().str());
229 
230  if (! u.cfg.msg.empty())
231  {
232  BEAST_EXPECTS(
233  sink.messages().str().find(u.cfg.msg) != std::string::npos,
234  sink.messages().str());
235  }
236 
237  if (u.cfg.expectedRefreshMin)
238  {
239  BEAST_EXPECTS(
240  myStatus[jss::refresh_interval_min].asInt()
241  == u.cfg.expectedRefreshMin,
242  to_string(myStatus));
243  }
244 
245  if (u.cfg.failFetch)
246  {
247  using namespace std::chrono;
248  log << " -- Msg: " <<
249  myStatus[jss::last_refresh_message].asString() << std::endl;
250  std::stringstream nextRefreshStr
251  {myStatus[jss::next_refresh_time].asString()};
252  system_clock::time_point nextRefresh;
253  date::from_stream (nextRefreshStr, "%Y-%b-%d %T", nextRefresh);
254  BEAST_EXPECT(!nextRefreshStr.fail());
255  auto now = system_clock::now();
256  BEAST_EXPECTS(
257  nextRefresh <= now + (u.isRetry ? seconds{30} : minutes{5}),
258  "Now: " + to_string(now) + ", NR: " + nextRefreshStr.str());
259  }
260  }
261  }
262 
263  void
266  {
267  testcase << "File list - " << paths[0].first <<
268  (paths.size() > 1 ? ", " + paths[1].first : "");
269 
270  using namespace jtx;
271 
272  Env env (*this);
273 
274  test::StreamSink sink;
275  beast::Journal journal{sink};
276 
277  struct publisher
278  {
279  std::string uri;
280  std::string expectMsg;
281  bool shouldFail;
282  };
283  std::vector<publisher> servers;
284 
285  for (auto const& cfg : paths)
286  {
287  servers.push_back({});
288  auto& item = servers.back();
289  item.shouldFail = ! cfg.second.empty();
290  item.expectMsg = cfg.second;
291 
292  std::stringstream uri;
293  uri << "file://" << cfg.first;
294  item.uri = uri.str();
295  }
296 
297  auto sites = std::make_unique<ValidatorSite> (env.app(), journal);
298 
300  for (auto const& u : servers)
301  uris.push_back(u.uri);
302  sites->load (uris);
303  sites->start();
304  sites->join();
305 
306  for (auto const& u : servers)
307  {
308  auto const jv = sites->getJson();
309  Json::Value myStatus;
310  for (auto const& vs : jv[jss::validator_sites])
311  if (vs[jss::uri].asString().find(u.uri) != std::string::npos)
312  myStatus = vs;
313  BEAST_EXPECTS(
314  myStatus[jss::last_refresh_message].asString().empty()
315  != u.shouldFail, to_string(myStatus));
316  if (u.shouldFail)
317  {
318  BEAST_EXPECTS(
319  sink.messages().str().find(u.expectMsg) != std::string::npos,
320  sink.messages().str());
321  log << " -- Msg: " <<
322  myStatus[jss::last_refresh_message].asString() << std::endl;
323  }
324  }
325  }
326 
328  {
329  auto fullPath = [](detail::FileDirGuard const& guard)
330  {
331  auto absPath = absolute(guard.file()).string();
332  if (absPath.front() != '/')
333  absPath.insert(absPath.begin(), '/');
334  return absPath;
335  };
336  {
337  // Create a file with a real validator list
338  detail::FileDirGuard good(*this, "test_val", "vl.txt",
340  // Create a file with arbitrary content
341  detail::FileDirGuard hello(*this, "test_val", "helloworld.txt",
342  "Hello, world!");
343  // Create a file with malformed Json
344  detail::FileDirGuard json(*this, "test_val", "json.txt",
345  R"json({ "version": 2, "extra" : "value" })json");
346  auto const goodPath = fullPath(good);
347  auto const helloPath = fullPath(hello);
348  auto const jsonPath = fullPath(json);
349  auto const missingPath = jsonPath + ".bad";
350  testFileList({
351  {goodPath, "" },
352  {helloPath, "Unable to parse JSON response from file://" + helloPath},
353  {jsonPath, "Missing fields in JSON response from file://" + jsonPath},
354  {missingPath, "Problem retrieving from file://" + missingPath },
355  });
356  }
357  }
358 
359 public:
360  void
361  run() override
362  {
363  testConfigLoad ();
364 
365 
366  for (auto ssl : {true, false})
367  {
368  // fetch single site
369  testFetchList ({{"/validators", "", ssl}});
370  // fetch multiple sites
371  testFetchList ({{"/validators", "", ssl}, {"/validators", "", ssl}});
372  // fetch single site with single redirects
373  testFetchList ({{"/redirect_once/301", "", ssl}});
374  testFetchList ({{"/redirect_once/302", "", ssl}});
375  testFetchList ({{"/redirect_once/307", "", ssl}});
376  testFetchList ({{"/redirect_once/308", "", ssl}});
377  // one redirect, one not
378  testFetchList ({
379  {"/validators", "", ssl},
380  {"/redirect_once/302", "", ssl}});
381  // fetch single site with undending redirect (fails to load)
382  testFetchList ({
383  {"/redirect_forever/301", "Exceeded max redirects", ssl, true, true}});
384  // two that redirect forever
385  testFetchList ({
386  {"/redirect_forever/307", "Exceeded max redirects", ssl, true, true},
387  {"/redirect_forever/308", "Exceeded max redirects", ssl, true, true}});
388  // one undending redirect, one not
389  testFetchList (
390  {{"/validators", "", ssl},
391  {"/redirect_forever/302", "Exceeded max redirects", ssl, true, true}});
392  // invalid redir Location
393  testFetchList ({
394  {"/redirect_to/ftp://invalid-url/302",
395  "Invalid redirect location",
396  ssl,
397  true,
398  true}});
399  testFetchList ({
400  {"/redirect_to/file://invalid-url/302",
401  "Invalid redirect location",
402  ssl,
403  true,
404  true}});
405  // invalid json
406  testFetchList ({
407  {"/validators/bad", "Unable to parse JSON response", ssl, true, true}});
408  // error status returned
409  testFetchList ({
410  {"/bad-resource", "returned bad status", ssl, true, true}});
411  // location field missing
412  testFetchList ({
413  {"/redirect_nolo/308",
414  "returned a redirect with no Location",
415  ssl,
416  true,
417  true}});
418  // json fields missing
419  testFetchList ({
420  {"/validators/missing",
421  "Missing fields in JSON response",
422  ssl,
423  true,
424  true}});
425  // timeout
426  testFetchList ({
427  {"/sleep/3", "took too long", ssl, true, true}});
428  // bad manifest version
429  testFetchList ({
430  {"/validators", "Unsupported version", ssl, false, true, 4}});
431  using namespace std::chrono_literals;
432  // get old validator list
433  testFetchList ({
434  {"/validators", "Stale validator list", ssl, false, true, 1, 0s}});
435  // force an out-of-range expiration value
436  testFetchList ({
437  {"/validators",
438  "Invalid validator list",
439  ssl,
440  false,
441  true,
442  1,
444  // verify refresh intervals are properly clamped
445  testFetchList ({
446  {"/validators/refresh/0",
447  "",
448  ssl,
449  false,
450  false,
451  1,
453  1}}); // minimum of 1 minute
454  testFetchList ({
455  {"/validators/refresh/10",
456  "",
457  ssl,
458  false,
459  false,
460  1,
462  10}}); // 10 minutes is fine
463  testFetchList ({
464  {"/validators/refresh/2000",
465  "",
466  ssl,
467  false,
468  false,
469  1,
471  60*24}}); // max of 24 hours
472  }
473  testFileURLs();
474  }
475 };
476 
478 
479 } // test
480 } // ripple
ripple::test::jtx::json
Inject raw JSON.
Definition: jtx_json.h:31
ripple::test::ValidatorSite_test::testConfigLoad
void testConfigLoad()
Definition: ValidatorSite_test.cpp:64
ripple::test::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountDelete, app, ripple)
std::string
STL class.
ripple::test::ValidatorSite_test::FetchListConfig::ssl
bool ssl
Definition: ValidatorSite_test.cpp:134
ripple::ValidatorSite
Definition: ValidatorSite.h:67
std::pair
std::string::reserve
T reserve(T... args)
std::vector< std::string >
std::chrono::seconds
ripple::test::ValidatorSite_test::testFileURLs
void testFileURLs()
Definition: ValidatorSite_test.cpp:327
std::stringstream
STL class.
ripple::test::jtx::Env::journal
const beast::Journal journal
Definition: Env.h:143
ripple::test::jtx::Env::timeKeeper
ManualTimeKeeper & timeKeeper()
Definition: Env.h:249
ripple::test::jtx::Env::app
Application & app()
Definition: Env.h:237
std::vector::back
T back(T... args)
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:41
ripple::test::ValidatorSite_test::FetchListConfig::expectedRefreshMin
int expectedRefreshMin
Definition: ValidatorSite_test.cpp:139
ripple::test::detail::realValidatorContents
constexpr const char * realValidatorContents()
Definition: ValidatorSite_test.cpp:42
std::vector::push_back
T push_back(T... args)
ripple::test::ValidatorSite_test::testFetchList
void testFetchList(std::vector< FetchListConfig > const &paths)
Definition: ValidatorSite_test.cpp:142
Json::Value::maxInt
static const Int maxInt
Definition: json_value.h:155
ripple::test::ValidatorSite_test::testFileList
void testFileList(std::vector< std::pair< std::string, std::string >> const &paths)
Definition: ValidatorSite_test.cpp:264
ripple::PublicKey
A public key.
Definition: PublicKey.h:59
chrono
ripple::test::TrustedPublisherServer::Validator
Definition: TrustedPublisherServer.h:94
ripple::test::ValidatorSite_test::FetchListConfig::serverVersion
int serverVersion
Definition: ValidatorSite_test.cpp:137
ripple::test::ValidatorSite_test::FetchListConfig::path
std::string path
Definition: ValidatorSite_test.cpp:132
ripple::test::jtx::paths
Set Paths, SendMax on a JTx.
Definition: paths.h:32
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:60
ripple::test::TrustedPublisherServer::randomValidator
static Validator randomValidator()
Definition: TrustedPublisherServer.h:128
ripple::test::ValidatorSite_test::FetchListConfig::failFetch
bool failFetch
Definition: ValidatorSite_test.cpp:135
ripple::test::detail::default_expires
constexpr auto default_expires
Definition: ValidatorSite_test.cpp:54
ripple::Application::validators
virtual ValidatorList & validators()=0
ripple::Application::getIOService
virtual boost::asio::io_service & getIOService()=0
ripple::test::StreamSink
Definition: SuiteJournal.h:100
ripple::test::StreamSink::messages
std::stringstream const & messages() const
Definition: SuiteJournal.h:117
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
std::endl
T endl(T... args)
ripple::test::ValidatorSite_test
Definition: ValidatorSite_test.cpp:57
ripple::test::ValidatorSite_test::FetchListConfig
Definition: ValidatorSite_test.cpp:130
ripple::test::ValidatorSite_test::FetchListConfig::expiresFromNow
std::chrono::seconds expiresFromNow
Definition: ValidatorSite_test.cpp:138
ripple::test::ValidatorSite_test::run
void run() override
Definition: ValidatorSite_test.cpp:361
ripple::test::ValidatorSite_test::FetchListConfig::failApply
bool failApply
Definition: ValidatorSite_test.cpp:136
std::stringstream::str
T str(T... args)
ripple::strHex
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:70
ripple::test::detail::FileDirGuard
Write a file in a directory and remove when done.
Definition: FileDirGuard.h:110
ripple::test::ManualTimeKeeper::now
time_point now() const override
Returns the estimate of wall time, in network time.
Definition: ManualTimeKeeper.cpp:39
ripple::test::ValidatorSite_test::FetchListConfig::msg
std::string msg
Definition: ValidatorSite_test.cpp:133
std::unique_ptr
STL class.
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:117
Json::Value
Represents a JSON value.
Definition: json_value.h:141
Json::Value::asString
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:482
std::chrono