@ -6,41 +6,55 @@ package cli
import (
"bytes"
"context"
"encoding/json"
"fmt"
"os"
"path/filepath"
"reflect"
"runtime"
"strconv"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/peterbourgon/ff/v3/ffcli"
"tailscale.com/ipn"
"tailscale.com/ipn/ipnstate"
"tailscale.com/types/logger"
)
func TestServeDevConfigMutations ( t * testing . T ) {
// Stateful mutations, starting from an empty config.
// step is a stateful mutation within a group
type step struct {
command [ ] string // serve args; nil means no command to run (only reset)
reset bool // if true, reset all ServeConfig state
want * ipn . ServeConfig // non-nil means we want a save of this value
wantErr func ( error ) ( badErrMsg string ) // nil means no error is wanted
line int // line number of addStep call, for error messages
before func ( t * testing . T )
}
debugBreak func ( )
// group is a group of steps that share the same
// config mutation, but always starts from an empty config
type group struct {
name string
steps [ ] step
}
// creaet a temporary directory for path-based destinations
td := t . TempDir ( )
writeFile := func ( suffix , contents string ) {
if err := os . WriteFile ( filepath . Join ( td , suffix ) , [ ] byte ( contents ) , 0600 ) ; err != nil {
t . Fatal ( err )
}
var steps [ ] step
add := func ( s step ) {
_ , _ , s . line , _ = runtime . Caller ( 1 )
steps = append ( steps , s )
}
writeFile ( "foo" , "this is foo" )
err := os . MkdirAll ( filepath . Join ( td , "subdir" ) , 0700 )
if err != nil {
t . Fatal ( err )
}
writeFile ( "subdir/file-a" , "this is subdir" )
// using port number
add ( step { reset : true } )
add ( step {
groups := [ ... ] group {
{
name : "using_port_number" ,
steps : [ ] step { {
command : cmd ( "funnel --bg 3000" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } } ,
@ -51,11 +65,11 @@ func TestServeDevConfigMutations(t *testing.T) {
} ,
AllowFunnel : map [ ipn . HostPort ] bool { "foo.test.ts.net:443" : true } ,
} ,
} )
// funnel background
add ( step { reset : true } )
add ( step {
} } ,
} ,
{
name : "funnel_background" ,
steps : [ ] step { {
command : cmd ( "funnel --bg localhost:3000" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } } ,
@ -66,11 +80,11 @@ func TestServeDevConfigMutations(t *testing.T) {
} ,
AllowFunnel : map [ ipn . HostPort ] bool { "foo.test.ts.net:443" : true } ,
} ,
} )
// serve background
add ( step { reset : true } )
add ( step {
} } ,
} ,
{
name : "serve_background" ,
steps : [ ] step { {
command : cmd ( "serve --bg localhost:3000" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } } ,
@ -80,12 +94,12 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
// --set-path runs in background
add ( step { reset : true } )
add ( step {
command : cmd ( "serve -- bg -- set-path=/ localhost:3000") ,
} } ,
} ,
{
name : "set_path_bg" ,
steps : [ ] step { {
command : cmd ( "serve -- set-path=/ --bg localhost:3000") ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } } ,
Web : map [ ipn . HostPort ] * ipn . WebServerConfig {
@ -94,11 +108,11 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
// using http listener
add ( step { reset : true } )
add ( step {
} } ,
} ,
{
name : "http_listener" ,
steps : [ ] step { {
command : cmd ( "serve --bg --http=80 localhost:3000" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 80 : { HTTP : true } } ,
@ -108,11 +122,11 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
// using https listener with a valid port
add ( step { reset : true } )
add ( step {
} } ,
} ,
{
name : "https_listener_valid_port" ,
steps : [ ] step { {
command : cmd ( "serve --bg --https=8443 localhost:3000" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 8443 : { HTTPS : true } } ,
@ -122,11 +136,12 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
// https
add ( step { reset : true } )
add ( step { // allow omitting port (default to 80)
} } ,
} ,
{
name : "multiple_http_with_off" ,
steps : [ ] step {
{
command : cmd ( "serve --http=80 --bg http://localhost:3000" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 80 : { HTTP : true } } ,
@ -136,9 +151,9 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step { // support non Funnel port
command : cmd ( "serve -- http=9999 --bg --set-path=/abc http://localhost:3001") ,
} ,
{ // support non Funnel port
command : cmd ( "serve -- bg -- http=9999 --set-path=/abc http://localhost:3001") ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 80 : { HTTP : true } , 9999 : { HTTP : true } } ,
Web : map [ ipn . HostPort ] * ipn . WebServerConfig {
@ -150,9 +165,9 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step {
command : cmd ( "serve -- http=9999 --bg --set-path=/abc off") ,
} ,
{ // turn off one handler
command : cmd ( "serve -- bg -- http=9999 --set-path=/abc off") ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 80 : { HTTP : true } } ,
Web : map [ ipn . HostPort ] * ipn . WebServerConfig {
@ -161,9 +176,9 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step {
command : cmd ( "serve -- http=8080 --bg --set-path=/abc http://127.0.0.1:3001") ,
} ,
{ // add another handler
command : cmd ( "serve -- bg -- http=8080 --set-path=/abc http://127.0.0.1:3001") ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 80 : { HTTP : true } , 8080 : { HTTP : true } } ,
Web : map [ ipn . HostPort ] * ipn . WebServerConfig {
@ -175,28 +190,42 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
// // https
add ( step { reset : true } )
add ( step {
} ,
} ,
} ,
{
name : "invalid_port_too_low" ,
steps : [ ] step { {
command : cmd ( "serve --https=443 --bg http://localhost:0" ) , // invalid port, too low
wantErr : anyErr ( ) ,
} )
add ( step {
} } ,
} ,
{
name : "invalid_port_too_high" ,
steps : [ ] step { {
command : cmd ( "serve --https=443 --bg http://localhost:65536" ) , // invalid port, too high
wantErr : anyErr ( ) ,
} )
add ( step {
} } ,
} ,
{
name : "invalid_host" ,
steps : [ ] step { {
command : cmd ( "serve --https=443 --bg http://somehost:3000" ) , // invalid host
wantErr : anyErr ( ) ,
} )
add ( step {
} } ,
} ,
{
name : "invalid_scheme" ,
steps : [ ] step { {
command : cmd ( "serve --https=443 --bg httpz://127.0.0.1" ) , // invalid scheme
wantErr : anyErr ( ) ,
} )
add ( step { // allow omitting port (default to 443)
command : cmd ( "serve --https=443 --bg http://localhost:3000" ) ,
} } ,
} ,
{
name : "turn_off_https" ,
steps : [ ] step {
{
command : cmd ( "serve --bg --https=443 http://localhost:3000" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } } ,
Web : map [ ipn . HostPort ] * ipn . WebServerConfig {
@ -205,9 +234,9 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step { // support non Funnel port
command : cmd ( "serve -- https=9999 --bg --set-path=/abc http://localhost:3001") ,
} ,
{
command : cmd ( "serve -- bg -- https=9999 --set-path=/abc http://localhost:3001") ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } , 9999 : { HTTPS : true } } ,
Web : map [ ipn . HostPort ] * ipn . WebServerConfig {
@ -219,9 +248,9 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step {
command : cmd ( "serve -- https=9999 --bg --set-path=/abc off") ,
} ,
{
command : cmd ( "serve -- bg -- https=9999 --set-path=/abc off") ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } } ,
Web : map [ ipn . HostPort ] * ipn . WebServerConfig {
@ -230,9 +259,9 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step {
command : cmd ( "serve -- https=8443 --bg --set-path=/abc http://127.0.0.1:3001") ,
} ,
{
command : cmd ( "serve -- bg -- https=8443 --set-path=/abc http://127.0.0.1:3001") ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } , 8443 : { HTTPS : true } } ,
Web : map [ ipn . HostPort ] * ipn . WebServerConfig {
@ -244,61 +273,50 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step {
command : cmd ( "serve --https=10000 --bg text:hi" ) ,
} ,
} ,
} ,
{
name : "https_text_bg" ,
steps : [ ] step { {
command : cmd ( "serve --bg --https=10000 text:hi" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler {
443 : { HTTPS : true } , 8443 : { HTTPS : true } , 10000 : { HTTPS : true } } ,
TCP : map [ uint16 ] * ipn . TCPPortHandler { 10000 : { HTTPS : true } } ,
Web : map [ ipn . HostPort ] * ipn . WebServerConfig {
"foo.test.ts.net:443" : { Handlers : map [ string ] * ipn . HTTPHandler {
"/" : { Proxy : "http://127.0.0.1:3000" } ,
} } ,
"foo.test.ts.net:8443" : { Handlers : map [ string ] * ipn . HTTPHandler {
"/abc" : { Proxy : "http://127.0.0.1:3001" } ,
} } ,
"foo.test.ts.net:10000" : { Handlers : map [ string ] * ipn . HTTPHandler {
"/" : { Text : "hi" } ,
} } ,
} ,
} ,
} )
add ( step {
command : cmd ( "serve --https=443 --bg --set-path=/foo off" ) ,
} } ,
} ,
{
name : "handler_not_found" ,
steps : [ ] step { {
command : cmd ( "serve --https=443 --set-path=/foo off" ) ,
want : nil , // nothing to save
wantErr : anyErr ( ) ,
} ) // handler doesn't exist, so we get an error
add ( step {
command : cmd ( "serve --https=10000 off" ) ,
} } ,
} ,
{
name : "clean_mount" , // "bar" becomes "/bar"
steps : [ ] step { {
command : cmd ( "serve --bg --https=443 --set-path=bar https://127.0.0.1:8443" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } , 8443 : { HTTPS : true } } ,
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443: { HTTPS : true } } ,
Web : map [ ipn . HostPort ] * ipn . WebServerConfig {
"foo.test.ts.net:443" : { Handlers : map [ string ] * ipn . HTTPHandler {
"/" : { Proxy : "http://127.0.0.1:3000" } ,
} } ,
"foo.test.ts.net:8443" : { Handlers : map [ string ] * ipn . HTTPHandler {
"/abc" : { Proxy : "http://127.0.0.1:3001" } ,
"/bar" : { Proxy : "https://127.0.0.1:8443" } ,
} } ,
} ,
} ,
} )
add ( step {
command : cmd ( "serve --https=443 off" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 8443 : { HTTPS : true } } ,
Web : map [ ipn . HostPort ] * ipn . WebServerConfig {
"foo.test.ts.net:8443" : { Handlers : map [ string ] * ipn . HTTPHandler {
"/abc" : { Proxy : "http://127.0.0.1:3001" } ,
} } ,
} ,
} ,
} )
add ( step {
command : cmd ( "serve --https=8443 --bg --set-path=/abc off" ) ,
want : & ipn . ServeConfig { } ,
} )
add ( step { // clean mount: "bar" becomes "/bar"
command : cmd ( "serve --https=443 --bg --set-path=bar https://127.0.0.1:8443" ) ,
{
name : "serve_reset" ,
steps : [ ] step {
{
command : cmd ( "serve --bg --https=443 --set-path=bar https://127.0.0.1:8443" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } } ,
Web : map [ ipn . HostPort ] * ipn . WebServerConfig {
@ -307,17 +325,17 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
// add(step{
// command: cmd("serve --https=443 --set-path=bar https://127.0.0.1:8443"),
// want: nil, // nothing to save
// })
add ( step { // try resetting using reset command
} ,
{
command : cmd ( "serve reset" ) ,
want : & ipn . ServeConfig { } ,
} )
add ( step {
command : cmd ( "serve --https=443 --bg https+insecure://127.0.0.1:3001" ) ,
} ,
} ,
} ,
{
name : "https_insecure" ,
steps : [ ] step { {
command : cmd ( "serve --bg --https=443 https+insecure://127.0.0.1:3001" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } } ,
Web : map [ ipn . HostPort ] * ipn . WebServerConfig {
@ -326,10 +344,13 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step { reset : true } )
add ( step {
command : cmd ( "serve --https=443 --bg --set-path=/foo localhost:3000" ) ,
} } ,
} ,
{
name : "two_ports_same_dest" ,
steps : [ ] step {
{
command : cmd ( "serve --bg --https=443 --set-path=/foo localhost:3000" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } } ,
Web : map [ ipn . HostPort ] * ipn . WebServerConfig {
@ -338,9 +359,9 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step { // test a second handler on the same port
command : cmd ( "serve -- https=8443 --bg --set-path=/foo localhost:3000") ,
} ,
{
command : cmd ( "serve -- bg -- https=8443 --set-path=/foo localhost:3000") ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } , 8443 : { HTTPS : true } } ,
Web : map [ ipn . HostPort ] * ipn . WebServerConfig {
@ -352,10 +373,13 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step { reset : true } )
add ( step { // support path in proxy
command : cmd ( "serve --https=443 --bg http://127.0.0.1:3000/foo/bar" ) ,
} ,
} ,
} ,
{
name : "path_in_dest" ,
steps : [ ] step { {
command : cmd ( "serve --bg --https=443 http://127.0.0.1:3000/foo/bar" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } } ,
Web : map [ ipn . HostPort ] * ipn . WebServerConfig {
@ -364,23 +388,32 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
// // tcp
add ( step { reset : true } )
add ( step { // !somehost, must be localhost or 127.0.0.1
} } ,
} ,
{
name : "unknown_host_tcp" ,
steps : [ ] step { {
command : cmd ( "serve --tls-terminated-tcp=443 --bg tcp://somehost:5432" ) ,
wantErr : exactErrMsg ( errHelp ) ,
} )
add ( step { // bad target port, too low
} } ,
} ,
{
name : "tcp_port_too_low" ,
steps : [ ] step { {
command : cmd ( "serve --tls-terminated-tcp=443 --bg tcp://somehost:0" ) ,
wantErr : exactErrMsg ( errHelp ) ,
} )
add ( step { // bad target port, too high
} } ,
} ,
{
name : "tcp_port_too_high" ,
steps : [ ] step { {
command : cmd ( "serve --tls-terminated-tcp=443 --bg tcp://somehost:65536" ) ,
wantErr : exactErrMsg ( errHelp ) ,
} )
add ( step { // support shorthand
} } ,
} ,
{
name : "tcp_shorthand" ,
steps : [ ] step { {
command : cmd ( "serve --tls-terminated-tcp=443 --bg 5432" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler {
@ -390,9 +423,12 @@ func TestServeDevConfigMutations(t *testing.T) {
} ,
} ,
} ,
} )
add ( step { reset : true } )
add ( step {
} } ,
} ,
{
name : "tls_terminated_tcp" ,
steps : [ ] step {
{
command : cmd ( "serve --tls-terminated-tcp=443 --bg tcp://localhost:5432" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler {
@ -402,8 +438,8 @@ func TestServeDevConfigMutations(t *testing.T) {
} ,
} ,
} ,
} )
add ( step {
} ,
{
command : cmd ( "serve --tls-terminated-tcp=443 --bg tcp://127.0.0.1:8443" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler {
@ -413,31 +449,13 @@ func TestServeDevConfigMutations(t *testing.T) {
} ,
} ,
} ,
} )
add ( step {
command : cmd ( "serve --tls-terminated-tcp=443 --bg tcp://localhost:8444" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler {
443 : {
TCPForward : "127.0.0.1:8444" ,
TerminateTLS : "foo.test.ts.net" ,
} ,
} ,
} ,
} )
add ( step {
command : cmd ( "serve --tls-terminated-tcp=443 --bg tcp://127.0.0.1:8445" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler {
443 : {
TCPForward : "127.0.0.1:8445" ,
TerminateTLS : "foo.test.ts.net" ,
} ,
} ,
} ,
} )
add ( step { reset : true } )
add ( step {
{
name : "tcp_off" ,
steps : [ ] step {
{
command : cmd ( "serve --tls-terminated-tcp=443 --bg tcp://localhost:123" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler {
@ -447,19 +465,20 @@ func TestServeDevConfigMutations(t *testing.T) {
} ,
} ,
} ,
} )
add ( step { // handler doesn't exist, so we get an error
} ,
{ // handler doesn't exist
command : cmd ( "serve --tls-terminated-tcp=8443 off" ) ,
wantErr : anyErr ( ) ,
} )
add ( step {
} ,
{
command : cmd ( "serve --tls-terminated-tcp=443 off" ) ,
want : & ipn . ServeConfig { } ,
} )
// // text
add ( step { reset : true } )
add ( step {
} ,
} ,
} ,
{
name : "text" ,
steps : [ ] step { {
command : cmd ( "serve --https=443 --bg text:hello" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } } ,
@ -469,19 +488,12 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
// path
td := t . TempDir ( )
writeFile := func ( suffix , contents string ) {
if err := os . WriteFile ( filepath . Join ( td , suffix ) , [ ] byte ( contents ) , 0600 ) ; err != nil {
t . Fatal ( err )
}
}
add ( step { reset : true } )
writeFile ( "foo" , "this is foo" )
add ( step {
} } ,
} ,
{
name : "path" ,
steps : [ ] step {
{
command : cmd ( "serve --https=443 --bg " + filepath . Join ( td , "foo" ) ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } } ,
@ -491,11 +503,9 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
os . MkdirAll ( filepath . Join ( td , "subdir" ) , 0700 )
writeFile ( "subdir/file-a" , "this is A" )
add ( step {
command : cmd ( "serve --https=443 --bg --set-path=/some/where " + filepath . Join ( td , "subdir/file-a" ) ) ,
} ,
{
command : cmd ( "serve --bg --https=443 --set-path=/some/where " + filepath . Join ( td , "subdir/file-a" ) ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } } ,
Web : map [ ipn . HostPort ] * ipn . WebServerConfig {
@ -505,14 +515,21 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step { // bad path
command : cmd ( "serve --https=443 --bg bad/path" ) ,
} ,
} ,
} ,
{
name : "bad_path" ,
steps : [ ] step { {
command : cmd ( "serve --bg --https=443 bad/path" ) ,
wantErr : exactErrMsg ( errHelp ) ,
} )
add ( step { reset : true } )
add ( step {
command : cmd ( "serve --https=443 --bg " + filepath . Join ( td , "subdir" ) ) ,
} } ,
} ,
{
name : "path_off" ,
steps : [ ] step {
{
command : cmd ( "serve --bg --https=443 " + filepath . Join ( td , "subdir" ) ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } } ,
Web : map [ ipn . HostPort ] * ipn . WebServerConfig {
@ -521,15 +538,17 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step {
command : cmd ( "serve --https=443 off") ,
} ,
{
command : cmd ( "serve --bg --https=443 off") ,
want : & ipn . ServeConfig { } ,
} )
// // combos
add ( step { reset : true } )
add ( step {
} ,
} ,
} ,
{
name : "combos" ,
steps : [ ] step {
{
command : cmd ( "serve --bg localhost:3000" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } } ,
@ -539,8 +558,8 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step { // enable funnel for primary port
} ,
{ // enable funnel for primary port
command : cmd ( "funnel --bg localhost:3000" ) ,
want : & ipn . ServeConfig {
AllowFunnel : map [ ipn . HostPort ] bool { "foo.test.ts.net:443" : true } ,
@ -551,9 +570,9 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step { // serving on secondary port doesn't change funnel on primary port
command : cmd ( "serve -- https=8443 --bg --set-path=/bar localhost:3001") ,
} ,
{ // serving on secondary port doesn't change funnel on primary port
command : cmd ( "serve -- bg -- https=8443 --set-path=/bar localhost:3001") ,
want : & ipn . ServeConfig {
AllowFunnel : map [ ipn . HostPort ] bool { "foo.test.ts.net:443" : true } ,
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } , 8443 : { HTTPS : true } } ,
@ -566,9 +585,9 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step { // turn funnel on for secondary port
command : cmd ( "funnel -- https=8443 --bg --set-path=/bar localhost:3001") ,
} ,
{ // turn funnel on for secondary port
command : cmd ( "funnel -- bg -- https=8443 --set-path=/bar localhost:3001") ,
want : & ipn . ServeConfig {
AllowFunnel : map [ ipn . HostPort ] bool { "foo.test.ts.net:443" : true , "foo.test.ts.net:8443" : true } ,
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } , 8443 : { HTTPS : true } } ,
@ -581,8 +600,8 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step { // turn funnel off for primary port 443
} ,
{ // turn funnel off for primary port 443
command : cmd ( "serve --bg localhost:3000" ) ,
want : & ipn . ServeConfig {
AllowFunnel : map [ ipn . HostPort ] bool { "foo.test.ts.net:8443" : true } ,
@ -596,9 +615,9 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step { // remove secondary port
command : cmd ( "serve --https=8443 --set-path=/bar off") ,
} ,
{ // remove secondary port
command : cmd ( "serve --bg --https=8443 --set-path=/bar off") ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } } ,
Web : map [ ipn . HostPort ] * ipn . WebServerConfig {
@ -607,8 +626,8 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step { // start a tcp forwarder on 8443
} ,
{ // start a tcp forwarder on 8443
command : cmd ( "serve --bg --tcp=8443 tcp://localhost:5432" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } , 8443 : { TCPForward : "127.0.0.1:5432" } } ,
@ -618,22 +637,24 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step { // remove primary port http handler
} ,
{ // remove primary port http handler
command : cmd ( "serve off" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 8443 : { TCPForward : "127.0.0.1:5432" } } ,
} ,
} )
add ( step { // remove tcp forwarder
} ,
{ // remove tcp forwarder
command : cmd ( "serve --tls-terminated-tcp=8443 off" ) ,
want : & ipn . ServeConfig { } ,
} )
// tricky steps
add ( step { reset : true } )
add ( step { // a directory with a trailing slash mount point
command : cmd ( "serve --https=443 --bg --set-path=/dir " + filepath . Join ( td , "subdir" ) ) ,
} ,
} ,
} ,
{
name : "tricky_steps" ,
steps : [ ] step {
{ // a directory with a trailing slash mount point
command : cmd ( "serve --bg --https=443 --set-path=/dir " + filepath . Join ( td , "subdir" ) ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } } ,
Web : map [ ipn . HostPort ] * ipn . WebServerConfig {
@ -642,9 +663,9 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step { // this should overwrite the previous one
command : cmd ( "serve -- https=443 --bg --set-path=/dir " + filepath . Join ( td , "foo" ) ) ,
} ,
{ // this should overwrite the previous one
command : cmd ( "serve -- bg -- https=443 --set-path=/dir " + filepath . Join ( td , "foo" ) ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } } ,
Web : map [ ipn . HostPort ] * ipn . WebServerConfig {
@ -653,10 +674,13 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step { reset : true } ) // reset and do the opposite
add ( step { // a file without a trailing slash mount point
command : cmd ( "serve --https=443 --bg --set-path=/dir " + filepath . Join ( td , "foo" ) ) ,
} ,
{ // reset and do opposite
command : cmd ( "serve reset" ) ,
want : & ipn . ServeConfig { } ,
} ,
{ // a file without a trailing slash mount point
command : cmd ( "serve --bg --https=443 --set-path=/dir " + filepath . Join ( td , "foo" ) ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } } ,
Web : map [ ipn . HostPort ] * ipn . WebServerConfig {
@ -665,9 +689,9 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step { // this should overwrite the previous one
command : cmd ( "serve -- https=443 --bg --set-path=/dir " + filepath . Join ( td , "subdir" ) ) ,
} ,
{ // this should overwrite the previous one
command : cmd ( "serve -- bg -- https=443 --set-path=/dir " + filepath . Join ( td , "subdir" ) ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } } ,
Web : map [ ipn . HostPort ] * ipn . WebServerConfig {
@ -676,11 +700,13 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
// // error states
add ( step { reset : true } )
add ( step { // tcp forward 5432 on serve port 443
} ,
} ,
} ,
{
name : "cannot_override_tcp_with_http" ,
steps : [ ] step {
{ // tcp forward 5432 on serve port 443
command : cmd ( "serve --tls-terminated-tcp=443 --bg tcp://localhost:5432" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler {
@ -690,13 +716,17 @@ func TestServeDevConfigMutations(t *testing.T) {
} ,
} ,
} ,
} )
add ( step { // try to start a web handler on the same port
} ,
{
command : cmd ( "serve --https=443 --bg localhost:3000" ) ,
wantErr : anyErr ( ) ,
} )
add ( step { reset : true } )
add ( step { // start a web handler on port 443
} ,
} ,
} ,
{
name : "cannot_override_http_with_tcp" ,
steps : [ ] step {
{
command : cmd ( "serve --https=443 --bg localhost:3000" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 443 : { HTTPS : true } } ,
@ -706,19 +736,17 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step { // try to start a tcp forwarder on the same serve port
} ,
{ // try to start a tcp forwarder on the same serve port
command : cmd ( "serve --tls-terminated-tcp=443 --bg tcp://localhost:5432" ) ,
wantErr : anyErr ( ) ,
} )
add ( step {
command : cmd ( "serve reset" ) ,
want : & ipn . ServeConfig { } ,
} )
// start two handlers and turn them off in one command
add ( step {
} ,
} ,
} ,
{
name : "turn_off_multiple_handlers" ,
steps : [ ] step {
{
command : cmd ( "serve --https=4545 --set-path=/foo --bg localhost:3000" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 4545 : { HTTPS : true } } ,
@ -728,8 +756,8 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step {
} ,
{
command : cmd ( "serve --https=4545 --set-path=/bar --bg localhost:3000" ) ,
want : & ipn . ServeConfig {
TCP : map [ uint16 ] * ipn . TCPPortHandler { 4545 : { HTTPS : true } } ,
@ -740,33 +768,27 @@ func TestServeDevConfigMutations(t *testing.T) {
} } ,
} ,
} ,
} )
add ( step {
} ,
{
command : cmd ( "serve --https=4545 --bg --yes localhost:3000 off" ) ,
want : & ipn . ServeConfig { } ,
} )
lc := & fakeLocalServeClient { }
// And now run the steps above.
for i , st := range steps {
if st . debugBreak != nil {
st . debugBreak ( )
}
if st . reset {
t . Logf ( "Executing step #%d, line %v: [reset]" , i , st . line )
lc . config = nil
}
if st . command == nil {
continue
} ,
} ,
} ,
}
t . Logf ( "Executing step #%d, line %v: %q ... " , i , st . line , st . command )
for _ , group := range groups {
t . Run ( group . name , func ( t * testing . T ) {
lc := & fakeLocalServeClient { }
for i , st := range group . steps {
var stderr bytes . Buffer
var stdout bytes . Buffer
var flagOut bytes . Buffer
e := & serveEnv {
lc : lc ,
testFlagOut : & flagOut ,
testStdout : & stdout ,
testStderr : & stderr ,
}
lastCount := lc . setCount
var cmd * ffcli . Command
@ -785,29 +807,29 @@ func TestServeDevConfigMutations(t *testing.T) {
}
if err != nil {
if st . wantErr == nil {
t . Fatalf ( "step #%d , line %v : unexpected error: %v", i , st . line , err )
t . Fatalf ( "step #%d : unexpected error: %v", i , err )
}
if bad := st . wantErr ( err ) ; bad != "" {
t . Fatalf ( "step #%d , line %v : unexpected error: %v", i , st . line , bad )
t . Fatalf ( "step #%d : unexpected error: %v", i , bad )
}
continue
}
if st . wantErr != nil {
t . Fatalf ( "step #%d , line %v : got success (saved=%v), but wanted an error", i , st . line , lc . config != nil )
t . Fatalf ( "step #%d : got success (saved=%v), but wanted an error", i , lc . config != nil )
}
var got * ipn . ServeConfig = nil
if lc . setCount > lastCount {
got = lc . config
}
if ! reflect . DeepEqual ( got , st . want ) {
t . Fatalf ( "[%d] %v: bad state. got:\n%v\n\nwant:\n%v\n" ,
i , st . command , logger . AsJSON ( got ) , logger . AsJSON ( st . want ) )
// NOTE: asJSON will omit empty fields, which might make
// result in bad state got/want diffs being the same, even
// though the actual state is different. Use below to debug:
// t.Fatalf("[%d] %v: bad state. got:\n%+v\n\nwant:\n%+v\n",
// i, st.command, got, st.want)
gotbts , _ := json . MarshalIndent ( got , "" , "\t" )
wantbts , _ := json . MarshalIndent ( st . want , "" , "\t" )
t . Fatalf ( "step: %d, cmd: %v, diff:\n%s" , i , st . command , cmp . Diff ( string ( gotbts ) , string ( wantbts ) ) )
}
}
} )
}
}