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/Slice.h>
22 #include <ripple/basics/base64.h>
23 #include <ripple/basics/strHex.h>
24 #include <ripple/protocol/HashPrefix.h>
25 #include <ripple/protocol/PublicKey.h>
26 #include <ripple/protocol/SecretKey.h>
27 #include <ripple/protocol/Sign.h>
28 #include <ripple/protocol/digest.h>
29 #include <ripple/protocol/jss.h>
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 #include <chrono>
35 #include <date/date.h>
36 #include <test/jtx.h>
37 #include <test/jtx/TrustedPublisherServer.h>
38 #include <test/unit_test/FileDirGuard.h>
39 
40 namespace ripple {
41 namespace test {
42 namespace detail {
43 constexpr 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 
56 auto constexpr default_expires = std::chrono::seconds{3600};
58 } // namespace detail
59 
60 class ValidatorSite_test : public beast::unit_test::suite
61 {
62 private:
64 
65  void
67  {
68  testcase("Config Load");
69 
70  using namespace jtx;
71 
72  Env env(*this);
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
81  std::vector<std::string> cfgSites({
82  "http://ripple.com/", "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 
132  {
135  bool ssl;
136  bool failFetch = false;
137  bool failApply = false;
138  int serverVersion = 1;
143  };
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  PublicKey emptyLocalKey;
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  };
188  std::vector<publisher> servers;
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 
226  std::stringstream uri;
227  uri << (cfg.ssl ? "https://" : "http://")
228  << item.server->local_endpoint() << cfg.path;
229  item.uri = uri.str();
230  }
231 
232  BEAST_EXPECT(
233  trustedKeys.load(emptyLocalKey, emptyCfgKeys, cfgPublishers));
234 
235  // Normally, tests will only need a fraction of this time,
236  // but sometimes DNS resolution takes an inordinate amount
237  // of time, so the test will just wait.
238  auto sites = std::make_unique<ValidatorSite>(env.app(), journal, 12s);
239 
241  for (auto const& u : servers)
242  uris.push_back(u.uri);
243  sites->load(uris);
244  sites->start();
245  sites->join();
246 
247  auto const jv = sites->getJson();
248  for (auto const& u : servers)
249  {
250  for (auto const& val : u.list)
251  {
252  BEAST_EXPECT(
253  trustedKeys.listed(val.masterPublic) != u.cfg.failApply);
254  BEAST_EXPECT(
255  trustedKeys.listed(val.signingPublic) != u.cfg.failApply);
256  }
257 
258  Json::Value myStatus;
259  for (auto const& vs : jv[jss::validator_sites])
260  if (vs[jss::uri].asString().find(u.uri) != std::string::npos)
261  myStatus = vs;
262  BEAST_EXPECTS(
263  myStatus[jss::last_refresh_message].asString().empty() !=
264  u.cfg.failFetch,
265  to_string(myStatus) + "\n" + sink.messages().str());
266 
267  if (!u.cfg.msg.empty())
268  {
269  BEAST_EXPECTS(
270  sink.messages().str().find(u.cfg.msg) != std::string::npos,
271  sink.messages().str());
272  }
273 
274  if (u.cfg.expectedRefreshMin)
275  {
276  BEAST_EXPECTS(
277  myStatus[jss::refresh_interval_min].asInt() ==
278  u.cfg.expectedRefreshMin,
279  to_string(myStatus));
280  }
281 
282  if (u.cfg.failFetch)
283  {
284  using namespace std::chrono;
285  log << " -- Msg: "
286  << myStatus[jss::last_refresh_message].asString()
287  << std::endl;
288  std::stringstream nextRefreshStr{
289  myStatus[jss::next_refresh_time].asString()};
290  system_clock::time_point nextRefresh;
291  date::from_stream(nextRefreshStr, "%Y-%b-%d %T", nextRefresh);
292  BEAST_EXPECT(!nextRefreshStr.fail());
293  auto now = system_clock::now();
294  BEAST_EXPECTS(
295  nextRefresh <= now + (u.isRetry ? seconds{30} : minutes{5}),
296  "Now: " + to_string(now) + ", NR: " + nextRefreshStr.str());
297  }
298  }
299  }
300 
301  void
303  {
304  testcase << "File list - " << paths[0].first
305  << (paths.size() > 1 ? ", " + paths[1].first : "");
306 
307  using namespace jtx;
308 
309  Env env(*this);
310 
311  test::StreamSink sink;
312  beast::Journal journal{sink};
313 
314  struct publisher
315  {
316  std::string uri;
317  std::string expectMsg;
318  bool shouldFail;
319  };
320  std::vector<publisher> servers;
321 
322  for (auto const& cfg : paths)
323  {
324  servers.push_back({});
325  auto& item = servers.back();
326  item.shouldFail = !cfg.second.empty();
327  item.expectMsg = cfg.second;
328 
329  std::stringstream uri;
330  uri << "file://" << cfg.first;
331  item.uri = uri.str();
332  }
333 
334  auto sites = std::make_unique<ValidatorSite>(env.app(), journal);
335 
337  for (auto const& u : servers)
338  uris.push_back(u.uri);
339  sites->load(uris);
340  sites->start();
341  sites->join();
342 
343  for (auto const& u : servers)
344  {
345  auto const jv = sites->getJson();
346  Json::Value myStatus;
347  for (auto const& vs : jv[jss::validator_sites])
348  if (vs[jss::uri].asString().find(u.uri) != std::string::npos)
349  myStatus = vs;
350  BEAST_EXPECTS(
351  myStatus[jss::last_refresh_message].asString().empty() !=
352  u.shouldFail,
353  to_string(myStatus));
354  if (u.shouldFail)
355  {
356  BEAST_EXPECTS(
357  sink.messages().str().find(u.expectMsg) !=
358  std::string::npos,
359  sink.messages().str());
360  log << " -- Msg: "
361  << myStatus[jss::last_refresh_message].asString()
362  << std::endl;
363  }
364  }
365  }
366 
367  void
369  {
370  auto fullPath = [](detail::FileDirGuard const& guard) {
371  auto absPath = absolute(guard.file()).string();
372  if (absPath.front() != '/')
373  absPath.insert(absPath.begin(), '/');
374  return absPath;
375  };
376  {
377  // Create a file with a real validator list
379  *this, "test_val", "vl.txt", detail::realValidatorContents());
380  // Create a file with arbitrary content
381  detail::FileDirGuard hello(
382  *this, "test_val", "helloworld.txt", "Hello, world!");
383  // Create a file with malformed Json
385  *this,
386  "test_val",
387  "json.txt",
388  R"json({ "version": 2, "extra" : "value" })json");
389  auto const goodPath = fullPath(good);
390  auto const helloPath = fullPath(hello);
391  auto const jsonPath = fullPath(json);
392  auto const missingPath = jsonPath + ".bad";
393  testFileList({
394  {goodPath, ""},
395  {helloPath,
396  "Unable to parse JSON response from file://" + helloPath},
397  {jsonPath,
398  "Missing fields in JSON response from file://" + jsonPath},
399  {missingPath, "Problem retrieving from file://" + missingPath},
400  });
401  }
402  }
403 
404 public:
405  void
406  run() override
407  {
408  testConfigLoad();
409 
410  detail::DirGuard good(*this, "test_fetch");
411  for (auto ssl : {true, false})
412  {
413  // fetch single site
414  testFetchList(good, {{"/validators", "", ssl}});
415  testFetchList(good, {{"/validators2", "", ssl}});
416  // fetch multiple sites
418  good, {{"/validators", "", ssl}, {"/validators", "", ssl}});
420  good, {{"/validators", "", ssl}, {"/validators2", "", ssl}});
422  good, {{"/validators2", "", ssl}, {"/validators", "", ssl}});
424  good, {{"/validators2", "", ssl}, {"/validators2", "", ssl}});
425  // fetch single site with single redirects
426  testFetchList(good, {{"/redirect_once/301", "", ssl}});
427  testFetchList(good, {{"/redirect_once/302", "", ssl}});
428  testFetchList(good, {{"/redirect_once/307", "", ssl}});
429  testFetchList(good, {{"/redirect_once/308", "", ssl}});
430  // one redirect, one not
432  good,
433  {{"/validators", "", ssl}, {"/redirect_once/302", "", ssl}});
435  good,
436  {{"/validators2", "", ssl}, {"/redirect_once/302", "", ssl}});
437  // UNLs with a "gap" between validUntil of one and validFrom of the
438  // next
440  good,
441  {{"/validators2",
442  "",
443  ssl,
444  false,
445  false,
446  1,
448  std::chrono::seconds{-90}}});
449  // fetch single site with undending redirect (fails to load)
451  good,
452  {{"/redirect_forever/301",
453  "Exceeded max redirects",
454  ssl,
455  true,
456  true}});
457  // two that redirect forever
459  good,
460  {{"/redirect_forever/307",
461  "Exceeded max redirects",
462  ssl,
463  true,
464  true},
465  {"/redirect_forever/308",
466  "Exceeded max redirects",
467  ssl,
468  true,
469  true}});
470  // one undending redirect, one not
472  good,
473  {{"/validators", "", ssl},
474  {"/redirect_forever/302",
475  "Exceeded max redirects",
476  ssl,
477  true,
478  true}});
479  // one undending redirect, one not
481  good,
482  {{"/validators2", "", ssl},
483  {"/redirect_forever/302",
484  "Exceeded max redirects",
485  ssl,
486  true,
487  true}});
488  // invalid redir Location
490  good,
491  {{"/redirect_to/ftp://invalid-url/302",
492  "Invalid redirect location",
493  ssl,
494  true,
495  true}});
497  good,
498  {{"/redirect_to/file://invalid-url/302",
499  "Invalid redirect location",
500  ssl,
501  true,
502  true}});
503  // invalid json
505  good,
506  {{"/validators/bad",
507  "Unable to parse JSON response",
508  ssl,
509  true,
510  true}});
512  good,
513  {{"/validators2/bad",
514  "Unable to parse JSON response",
515  ssl,
516  true,
517  true}});
518  // error status returned
520  good,
521  {{"/bad-resource", "returned bad status", ssl, true, true}});
522  // location field missing
524  good,
525  {{"/redirect_nolo/308",
526  "returned a redirect with no Location",
527  ssl,
528  true,
529  true}});
530  // json fields missing
532  good,
533  {{"/validators/missing",
534  "Missing fields in JSON response",
535  ssl,
536  true,
537  true}});
539  good,
540  {{"/validators2/missing",
541  "Missing fields in JSON response",
542  ssl,
543  true,
544  true}});
545  // timeout
547  good, {{"/sleep/13", "took too long", ssl, true, true}});
548  // bad manifest format using known versions
549  // * Retrieves a v1 formatted list claiming version 2
551  good, {{"/validators", "Missing fields", ssl, true, true, 2}});
552  // * Retrieves a v2 formatted list claiming version 1
554  good, {{"/validators2", "Missing fields", ssl, true, true, 0}});
555  // bad manifest version
556  // Because versions other than 1 are treated as v2, the v1
557  // list won't have the blobs_v2 fields, and thus will claim to have
558  // missing fields
560  good, {{"/validators", "Missing fields", ssl, true, true, 4}});
562  good,
563  {{"/validators2",
564  "1 unsupported version",
565  ssl,
566  false,
567  true,
568  4}});
569  using namespace std::chrono_literals;
570  // get expired validator list
572  good,
573  {{"/validators",
574  "Applied 1 expired validator list(s)",
575  ssl,
576  false,
577  false,
578  1,
579  0s}});
581  good,
582  {{"/validators2",
583  "Applied 1 expired validator list(s)",
584  ssl,
585  false,
586  false,
587  1,
588  0s,
589  -1s}});
590  // force an out-of-range validUntil value
592  good,
593  {{"/validators",
594  "1 invalid validator list(s)",
595  ssl,
596  false,
597  true,
598  1,
600  // force an out-of-range validUntil value on the future list
601  // The first list is accepted. The second fails. The parser
602  // returns the "best" result, so this looks like a success.
604  good,
605  {{"/validators2",
606  "",
607  ssl,
608  false,
609  false,
610  1,
612  299s}});
613  // force an out-of-range validFrom value
614  // The first list is accepted. The second fails. The parser
615  // returns the "best" result, so this looks like a success.
617  good,
618  {{"/validators2",
619  "",
620  ssl,
621  false,
622  false,
623  1,
625  301s}});
626  // force an out-of-range validUntil value on _both_ lists
628  good,
629  {{"/validators2",
630  "2 invalid validator list(s)",
631  ssl,
632  false,
633  true,
634  1,
637  // verify refresh intervals are properly clamped
639  good,
640  {{"/validators/refresh/0",
641  "",
642  ssl,
643  false,
644  false,
645  1,
648  1}}); // minimum of 1 minute
650  good,
651  {{"/validators2/refresh/0",
652  "",
653  ssl,
654  false,
655  false,
656  1,
659  1}}); // minimum of 1 minute
661  good,
662  {{"/validators/refresh/10",
663  "",
664  ssl,
665  false,
666  false,
667  1,
670  10}}); // 10 minutes is fine
672  good,
673  {{"/validators2/refresh/10",
674  "",
675  ssl,
676  false,
677  false,
678  1,
681  10}}); // 10 minutes is fine
683  good,
684  {{"/validators/refresh/2000",
685  "",
686  ssl,
687  false,
688  false,
689  1,
692  60 * 24}}); // max of 24 hours
694  good,
695  {{"/validators2/refresh/2000",
696  "",
697  ssl,
698  false,
699  false,
700  1,
703  60 * 24}}); // max of 24 hours
704  }
705  using namespace boost::filesystem;
706  for (auto const& file : directory_iterator(good.subdir()))
707  {
708  remove_all(file);
709  }
710 
711  testFileURLs();
712  }
713 };
714 
716 
717 } // namespace test
718 } // namespace ripple
ripple::test::jtx::json
Inject raw JSON.
Definition: jtx_json.h:31
ripple::test::ValidatorSite_test::testConfigLoad
void testConfigLoad()
Definition: ValidatorSite_test.cpp:66
std::string
STL class.
ripple::test::ValidatorSite_test::FetchListConfig::ssl
bool ssl
Definition: ValidatorSite_test.cpp:135
std::shared_ptr
STL class.
ripple::test::ValidatorSite_test::testFetchList
void testFetchList(detail::DirGuard const &good, std::vector< FetchListConfig > const &paths)
Definition: ValidatorSite_test.cpp:145
ripple::test::detail::DirGuard
Create a directory and remove it when it's done.
Definition: FileDirGuard.h:34
ripple::ValidatorSite
Definition: ValidatorSite.h:69
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:368
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:252
ripple::test::jtx::Env::app
Application & app()
Definition: Env.h:240
std::vector::back
T back(T... args)
ripple::test::jtx::envconfig
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition: envconfig.h:49
ripple::test::ValidatorSite_test::FetchListConfig::expectedRefreshMin
int expectedRefreshMin
Definition: ValidatorSite_test.cpp:142
ripple::test::BEAST_DEFINE_TESTSUITE_PRIO
BEAST_DEFINE_TESTSUITE_PRIO(AccountDelete, app, ripple, 2)
ripple::test::detail::DirGuard::subdir
path const & subdir() const
Definition: FileDirGuard.h:101
ripple::test::detail::default_effective_overlap
constexpr auto default_effective_overlap
Definition: ValidatorSite_test.cpp:57
ripple::test::detail::realValidatorContents
constexpr const char * realValidatorContents()
Definition: ValidatorSite_test.cpp:44
std::vector::push_back
T push_back(T... args)
Json::Value::maxInt
static const Int maxInt
Definition: json_value.h:159
std::log
T log(T... args)
ripple::test::ValidatorSite_test::testFileList
void testFileList(std::vector< std::pair< std::string, std::string >> const &paths)
Definition: ValidatorSite_test.cpp:302
ripple::PublicKey
A public key.
Definition: PublicKey.h:59
std::ofstream
STL class.
chrono
ripple::test::TrustedPublisherServer::Validator
Definition: TrustedPublisherServer.h:112
ripple::test::ValidatorSite_test::FetchListConfig::serverVersion
int serverVersion
Definition: ValidatorSite_test.cpp:138
std::to_string
T to_string(T... args)
ripple::test::ValidatorSite_test::FetchListConfig::path
std::string path
Definition: ValidatorSite_test.cpp:133
ripple::test::jtx::paths
Set Paths, SendMax on a JTx.
Definition: paths.h:32
std::chrono::time_point
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::test::TrustedPublisherServer::randomValidator
static Validator randomValidator()
Definition: TrustedPublisherServer.h:148
ripple::test::ValidatorSite_test::FetchListConfig::failFetch
bool failFetch
Definition: ValidatorSite_test.cpp:136
ripple::test::detail::default_expires
constexpr auto default_expires
Definition: ValidatorSite_test.cpp:56
ripple::test::ValidatorSite_test::FetchListConfig::effectiveOverlap
std::chrono::seconds effectiveOverlap
Definition: ValidatorSite_test.cpp:140
ripple::Application::validators
virtual ValidatorList & validators()=0
ripple::Application::getIOService
virtual boost::asio::io_service & getIOService()=0
ripple::test::StreamSink
Definition: SuiteJournal.h:114
ripple::test::StreamSink::messages
std::stringstream const & messages() const
Definition: SuiteJournal.h:134
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:60
ripple::test::ValidatorSite_test::FetchListConfig
Definition: ValidatorSite_test.cpp:131
ripple::test::ValidatorSite_test::FetchListConfig::expiresFromNow
std::chrono::seconds expiresFromNow
Definition: ValidatorSite_test.cpp:139
ripple::test::ValidatorSite_test::run
void run() override
Definition: ValidatorSite_test.cpp:406
ripple::test::ValidatorSite_test::FetchListConfig::failApply
bool failApply
Definition: ValidatorSite_test.cpp:137
ripple::test::make_TrustedPublisherServer
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)
Definition: TrustedPublisherServer.h:712
std::stringstream::str
T str(T... args)
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:39
ripple::strHex
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:45
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:37
ripple::test::ManualTimeKeeper::set
void set(time_point now)
Definition: ManualTimeKeeper.cpp:81
ripple::test::ValidatorSite_test::FetchListConfig::msg
std::string msg
Definition: ValidatorSite_test.cpp:134
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:115
Json::Value
Represents a JSON value.
Definition: json_value.h:145
Json::Value::asString
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:469
std::chrono
std::chrono::system_clock::now
T now(T... args)