@@ -243,7 +243,7 @@ var (
243243 name : "litrpc-accounts" ,
244244 macaroonFn : litMacaroonFn ,
245245 requestFn : litAccountRequestFn ,
246- successPattern : "\" accounts\" :[] " ,
246+ successPattern : "\" accounts\" :[" ,
247247 allowedThroughLNC : false ,
248248 grpcWebURI : "/litrpc.Accounts/ListAccounts" ,
249249 }, {
@@ -270,25 +270,72 @@ var (
270270 }
271271)
272272
273+ // testSuite defines the signature of a test suite. The boolean parameter
274+ // indicates if the UI password is set or disabled.
275+ type testSuite func (context.Context , * NetworkHarness , * testing.T , bool , int )
276+
277+ // testWithAndWithoutUIPassword runs the given test suite against the given node
278+ // both with the UI password set and without the UI password with the UI
279+ // disabled.
280+ func testWithAndWithoutUIPassword (ctx context.Context , net * NetworkHarness ,
281+ t * testing.T , test testSuite , node * HarnessNode ) {
282+
283+ t .Run ("with UI password" , func (t * testing.T ) {
284+ test (ctx , net , t , false , 1 )
285+ })
286+
287+ // Restart the node without the ui password and disable the UI.
288+ err := net .RestartNode (
289+ node , nil , []LitArgOption {
290+ WithoutLitArg ("uipassword" ),
291+ WithLitArg ("disableui" , "" ),
292+ },
293+ )
294+ require .NoError (t , err )
295+
296+ if ! node .Cfg .RemoteMode {
297+ // Reconnect Alice and Bob so that tests can continue to assert
298+ // that the nodes each have one peer at start up. This is only
299+ // required if the node is running in integrated mode since in
300+ // remote mode, the peers would never have disconnected.
301+ net .ConnectNodes (t , net .Alice , net .Bob )
302+ }
303+
304+ t .Run ("without UI password" , func (t * testing.T ) {
305+ test (ctx , net , t , true , 2 )
306+ })
307+ }
308+
273309// testModeIntegrated makes sure that in integrated mode all daemons work
274- // correctly.
310+ // correctly. It tests the full integrated mode test suite with the ui password
311+ // set and then again with no ui password and a disabled UI.
275312func testModeIntegrated (ctx context.Context , net * NetworkHarness ,
276313 t * harnessTest ) {
277314
315+ testWithAndWithoutUIPassword (
316+ ctx , net , t .t , integratedTestSuite , net .Alice ,
317+ )
318+ }
319+
320+ // integratedTestSuite makes sure that in integrated mode all daemons work
321+ // correctly.
322+ func integratedTestSuite (ctx context.Context , net * NetworkHarness , t * testing.T ,
323+ withoutUIPassword bool , runNum int ) {
324+
278325 // Some very basic functionality tests to make sure lnd is working fine
279326 // in integrated mode.
280- net .SendCoins (t . t , btcutil .SatoshiPerBitcoin , net .Alice )
327+ net .SendCoins (t , btcutil .SatoshiPerBitcoin , net .Alice )
281328
282329 // We expect a non-empty alias (truncated node ID) to be returned.
283330 resp , err := net .Alice .GetInfo (ctx , & lnrpc.GetInfoRequest {})
284- require .NoError (t . t , err )
285- require .NotEmpty (t . t , resp .Alias )
286- require .Contains (t . t , resp .Alias , "0" )
331+ require .NoError (t , err )
332+ require .NotEmpty (t , resp .Alias )
333+ require .Contains (t , resp .Alias , "0" )
287334
288- t .t . Run ("certificate check" , func (tt * testing.T ) {
335+ t .Run ("certificate check" , func (tt * testing.T ) {
289336 runCertificateCheck (tt , net .Alice )
290337 })
291- t .t . Run ("gRPC macaroon auth check" , func (tt * testing.T ) {
338+ t .Run ("gRPC macaroon auth check" , func (tt * testing.T ) {
292339 cfg := net .Alice .Cfg
293340
294341 for _ , endpoint := range endpoints {
@@ -313,7 +360,7 @@ func testModeIntegrated(ctx context.Context, net *NetworkHarness,
313360 }
314361 })
315362
316- t .t . Run ("UI password auth check" , func (tt * testing.T ) {
363+ t .Run ("UI password auth check" , func (tt * testing.T ) {
317364 cfg := net .Alice .Cfg
318365
319366 for _ , endpoint := range endpoints {
@@ -327,20 +374,28 @@ func testModeIntegrated(ctx context.Context, net *NetworkHarness,
327374 })
328375
329376 tt .Run (endpoint .name + " lit port" , func (ttt * testing.T ) {
377+ shouldFailWithoutMacaroon := false
378+ if withoutUIPassword {
379+ shouldFailWithoutMacaroon = true
380+ }
381+
330382 runUIPasswordCheck (
331383 ttt , cfg .LitAddr (), cfg .LitTLSCertPath ,
332384 cfg .UIPassword , endpoint .requestFn ,
333- false , endpoint .successPattern ,
385+ shouldFailWithoutMacaroon ,
386+ endpoint .successPattern ,
334387 )
335388 })
336389 }
337390 })
338391
339- t .t .Run ("UI index page fallback" , func (tt * testing.T ) {
340- runIndexPageCheck (tt , net .Alice .Cfg .LitAddr ())
392+ t .Run ("UI index page fallback" , func (tt * testing.T ) {
393+ runIndexPageCheck (
394+ tt , net .Alice .Cfg .LitAddr (), withoutUIPassword ,
395+ )
341396 })
342397
343- t .t . Run ("grpc-web auth" , func (tt * testing.T ) {
398+ t .Run ("grpc-web auth" , func (tt * testing.T ) {
344399 cfg := net .Alice .Cfg
345400
346401 for _ , endpoint := range endpoints {
@@ -349,12 +404,13 @@ func testModeIntegrated(ctx context.Context, net *NetworkHarness,
349404 runGRPCWebAuthTest (
350405 ttt , cfg .LitAddr (), cfg .UIPassword ,
351406 endpoint .grpcWebURI ,
407+ withoutUIPassword ,
352408 )
353409 })
354410 }
355411 })
356412
357- t .t . Run ("gRPC super macaroon auth check" , func (tt * testing.T ) {
413+ t .Run ("gRPC super macaroon auth check" , func (tt * testing.T ) {
358414 cfg := net .Alice .Cfg
359415
360416 superMacFile , err := bakeSuperMacaroon (cfg , true )
@@ -386,7 +442,7 @@ func testModeIntegrated(ctx context.Context, net *NetworkHarness,
386442 }
387443 })
388444
389- t .t . Run ("REST auth" , func (tt * testing.T ) {
445+ t .Run ("REST auth" , func (tt * testing.T ) {
390446 cfg := net .Alice .Cfg
391447
392448 for _ , endpoint := range endpoints {
@@ -403,20 +459,21 @@ func testModeIntegrated(ctx context.Context, net *NetworkHarness,
403459 endpoint .restWebURI ,
404460 endpoint .successPattern ,
405461 endpoint .restPOST ,
462+ withoutUIPassword ,
406463 )
407464 })
408465 }
409466 })
410467
411- t .t . Run ("lnc auth" , func (tt * testing.T ) {
468+ t .Run ("lnc auth" , func (tt * testing.T ) {
412469 cfg := net .Alice .Cfg
413470
414471 ctx := context .Background ()
415472 ctxt , cancel := context .WithTimeout (ctx , defaultTimeout )
416473 defer cancel ()
417474
418475 rawLNCConn := setUpLNCConn (
419- ctxt , t . t , cfg .LitAddr (), cfg .LitTLSCertPath ,
476+ ctxt , t , cfg .LitAddr (), cfg .LitTLSCertPath ,
420477 cfg .LitMacPath ,
421478 litrpc .SessionType_TYPE_MACAROON_READONLY , nil ,
422479 )
@@ -435,7 +492,7 @@ func testModeIntegrated(ctx context.Context, net *NetworkHarness,
435492 }
436493 })
437494
438- t .t . Run ("gRPC super macaroon account system test" , func (tt * testing.T ) {
495+ t .Run ("gRPC super macaroon account system test" , func (tt * testing.T ) {
439496 cfg := net .Alice .Cfg
440497
441498 superMacFile , err := bakeSuperMacaroon (cfg , false )
@@ -448,15 +505,15 @@ func testModeIntegrated(ctx context.Context, net *NetworkHarness,
448505 ht := newHarnessTest (tt , net )
449506 runAccountSystemTest (
450507 ht , net .Alice , cfg .LitAddr (), cfg .LitTLSCertPath ,
451- superMacFile , 1 ,
508+ superMacFile , ( runNum * 2 ) - 1 ,
452509 )
453510 runAccountSystemTest (
454511 ht , net .Alice , cfg .LitAddr (), cfg .LitTLSCertPath ,
455- superMacFile , 2 ,
512+ superMacFile , runNum * 2 ,
456513 )
457514 })
458515
459- t .t . Run ("lnc auth custom mac perms" , func (tt * testing.T ) {
516+ t .Run ("lnc auth custom mac perms" , func (tt * testing.T ) {
460517 cfg := net .Alice .Cfg
461518
462519 ctx := context .Background ()
@@ -478,7 +535,7 @@ func testModeIntegrated(ctx context.Context, net *NetworkHarness,
478535 }
479536
480537 rawLNCConn := setUpLNCConn (
481- ctxt , t . t , cfg .LitAddr (), cfg .LitTLSCertPath ,
538+ ctxt , t , cfg .LitAddr (), cfg .LitTLSCertPath ,
482539 cfg .LitMacPath ,
483540 litrpc .SessionType_TYPE_MACAROON_CUSTOM , customPerms ,
484541 )
@@ -665,21 +722,28 @@ func runUIPasswordCheck(t *testing.T, hostPort, tlsCertPath, uiPassword string,
665722}
666723
667724// runIndexPageCheck makes sure the index page is returned correctly.
668- func runIndexPageCheck (t * testing.T , hostPort string ) {
725+ func runIndexPageCheck (t * testing.T , hostPort string , uiDisabled bool ) {
726+ expect := indexHtmlMarker
727+ if uiDisabled {
728+ expect = ""
729+ }
730+
669731 body , err := getURL (fmt .Sprintf ("https://%s/index.html" , hostPort ))
670732 require .NoError (t , err )
671- require .Contains (t , body , indexHtmlMarker )
733+ require .Contains (t , body , expect )
672734
673735 // The UI implements "virtual" pages by using the browser history API.
674736 // Any URL that looks like a directory should fall back to the main
675737 // index.html file as well.
676738 body , err = getURL (fmt .Sprintf ("https://%s/loop" , hostPort ))
677739 require .NoError (t , err )
678- require .Contains (t , body , indexHtmlMarker )
740+ require .Contains (t , body , expect )
679741}
680742
681743// runGRPCWebAuthTest tests authentication of the given gRPC interface.
682- func runGRPCWebAuthTest (t * testing.T , hostPort , uiPassword , grpcWebURI string ) {
744+ func runGRPCWebAuthTest (t * testing.T , hostPort , uiPassword , grpcWebURI string ,
745+ shouldFailWithUIPassword bool ) {
746+
683747 basicAuth := base64 .StdEncoding .EncodeToString (
684748 []byte (fmt .Sprintf ("%s:%s" , uiPassword , uiPassword )),
685749 )
@@ -709,6 +773,18 @@ func runGRPCWebAuthTest(t *testing.T, hostPort, uiPassword, grpcWebURI string) {
709773 body , responseHeader , err := postURL (url , emptyGrpcWebRequest , header )
710774 require .NoError (t , err )
711775
776+ if shouldFailWithUIPassword {
777+ require .Equal (
778+ t , "expected 1 macaroon, got 0" ,
779+ responseHeader .Get ("grpc-message" ),
780+ )
781+ require .Equal (
782+ t , fmt .Sprintf ("%d" , codes .Unknown ),
783+ responseHeader .Get ("grpc-status" ),
784+ )
785+ return
786+ }
787+
712788 require .Empty (t , responseHeader .Get ("grpc-message" ))
713789 require .Empty (t , responseHeader .Get ("grpc-status" ))
714790
@@ -718,7 +794,7 @@ func runGRPCWebAuthTest(t *testing.T, hostPort, uiPassword, grpcWebURI string) {
718794
719795// runRESTAuthTest tests authentication of the given REST interface.
720796func runRESTAuthTest (t * testing.T , hostPort , uiPassword , macaroonPath , restURI ,
721- successPattern string , usePOST bool ) {
797+ successPattern string , usePOST , shouldFailWithUIPassword bool ) {
722798
723799 basicAuth := base64 .StdEncoding .EncodeToString (
724800 []byte (fmt .Sprintf ("%s:%s" , uiPassword , uiPassword )),
@@ -756,7 +832,15 @@ func runRESTAuthTest(t *testing.T, hostPort, uiPassword, macaroonPath, restURI,
756832 url , method , nil , basicAuthHeader , false ,
757833 )
758834 require .NoError (t , err )
759- require .Contains (t , body , successPattern )
835+
836+ if shouldFailWithUIPassword {
837+ require .Contains (
838+ t , body ,
839+ "expected 1 macaroon, got 0" ,
840+ )
841+ } else {
842+ require .Contains (t , body , successPattern )
843+ }
760844
761845 // And finally, try with the given macaroon.
762846 macBytes , err := ioutil .ReadFile (macaroonPath )
0 commit comments