...

Source file src/oss.terrastruct.com/util-go/cmdlog/cmdlog_test.go

Documentation: oss.terrastruct.com/util-go/cmdlog

     1  package cmdlog_test
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"fmt"
     7  	"io"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/creack/pty"
    12  
    13  	"oss.terrastruct.com/util-go/assert"
    14  	"oss.terrastruct.com/util-go/cmdlog"
    15  	"oss.terrastruct.com/util-go/xos"
    16  )
    17  
    18  func TestLogger(t *testing.T) {
    19  	t.Parallel()
    20  
    21  	var tca = []struct {
    22  		name string
    23  		run  func(t *testing.T, ctx context.Context, env *xos.Env)
    24  	}{
    25  		{
    26  			name: "COLOR=1",
    27  			run: func(t *testing.T, ctx context.Context, env *xos.Env) {
    28  				b := &bytes.Buffer{}
    29  				env.Setenv("COLOR", "1")
    30  				l := cmdlog.New(env, b)
    31  
    32  				testLogger(l)
    33  
    34  				t.Log(b.String())
    35  				assert.TestdataJSON(t, b.String())
    36  			},
    37  		},
    38  		{
    39  			name: "COLOR=",
    40  			run: func(t *testing.T, ctx context.Context, env *xos.Env) {
    41  				b := &bytes.Buffer{}
    42  				l := cmdlog.New(env, b)
    43  
    44  				testLogger(l)
    45  
    46  				t.Log(b.String())
    47  				assert.TestdataJSON(t, b.String())
    48  			},
    49  		},
    50  		{
    51  			name: "tty",
    52  			run: func(t *testing.T, ctx context.Context, env *xos.Env) {
    53  				ptmx, tty, err := pty.Open()
    54  				if err != nil {
    55  					t.Fatalf("failed to open pty: %v", err)
    56  				}
    57  				defer assert.Close(t, ptmx)
    58  				defer assert.Close(t, tty)
    59  
    60  				l := cmdlog.New(env, tty)
    61  				testLogger(l)
    62  
    63  				timer := time.AfterFunc(time.Second*5, func() {
    64  					// For some reason ptmx.SetDeadline() does not work.
    65  					// tty has to be closed for a read on ptmx to unblock.
    66  					tty.Close()
    67  					t.Error("read took too long, update expLen")
    68  				})
    69  				defer timer.Stop()
    70  				// If the expected output changes, increase this to 9999, rerun and then update
    71  				// for new length.
    72  				const expLen = 415
    73  				out, err := io.ReadAll(io.LimitReader(ptmx, expLen))
    74  				if err != nil {
    75  					t.Fatalf("failed to read log output: %v", err)
    76  				}
    77  				t.Log(len(out), string(out))
    78  				assert.TestdataJSON(t, string(out))
    79  			},
    80  		},
    81  		{
    82  			name: "testing.TB",
    83  			run: func(t *testing.T, ctx context.Context, env *xos.Env) {
    84  				ft := &fakeTB{
    85  					TB: t,
    86  					logf: func(f string, v ...interface{}) {
    87  						t.Helper()
    88  						assert.String(t, "info: what's up\n", fmt.Sprintf(f, v...))
    89  					},
    90  				}
    91  
    92  				env.Setenv("COLOR", "0")
    93  				l := cmdlog.NewTB(env, ft)
    94  				l.Info.Printf("what's up")
    95  			},
    96  		},
    97  		{
    98  			name: "WithPrefix",
    99  			run: func(t *testing.T, ctx context.Context, env *xos.Env) {
   100  				b := &bytes.Buffer{}
   101  				env.Setenv("COLOR", "1")
   102  				l := cmdlog.New(env, b)
   103  
   104  				l2 := l.WithCCPrefix("lochness")
   105  				if l2 == l {
   106  					t.Fatalf("expected l and l2 to be different loggers")
   107  				}
   108  				l2 = l2.WithCCPrefix("imgbundler")
   109  				l2 = l2.WithCCPrefix("cache")
   110  
   111  				testLogger(l)
   112  				testLogger(l2)
   113  
   114  				t.Log(b.String())
   115  				assert.TestdataJSON(t, b.String())
   116  			},
   117  		},
   118  		{
   119  			name: "multiline",
   120  			run: func(t *testing.T, ctx context.Context, env *xos.Env) {
   121  				b := &bytes.Buffer{}
   122  				env.Setenv("COLOR", "1")
   123  				l := cmdlog.New(env, b)
   124  
   125  				l.NoLevel.Print("")
   126  				l.SetTS(true)
   127  				l.NoLevel.Print("")
   128  				l.SetTS(false)
   129  
   130  				l2 := l.WithCCPrefix("lochness")
   131  				l2 = l2.WithCCPrefix("imgbundler")
   132  				l2 = l2.WithCCPrefix("cache")
   133  
   134  				l2.Warn.Print(``)
   135  				l2.Warn.Print("\n\n\n")
   136  				l2.SetTS(true)
   137  				l2.Warn.Printf(`yes %d
   138  yes %d`, 3, 4)
   139  
   140  				t.Log(b.String())
   141  				assert.TestdataJSON(t, b.String())
   142  			},
   143  		},
   144  	}
   145  
   146  	ctx := context.Background()
   147  	for _, tc := range tca {
   148  		tc := tc
   149  		t.Run(tc.name, func(t *testing.T) {
   150  			t.Parallel()
   151  
   152  			ctx, cancel := context.WithCancel(ctx)
   153  			defer cancel()
   154  
   155  			env := xos.NewEnv(nil)
   156  			tc.run(t, ctx, env)
   157  		})
   158  	}
   159  }
   160  
   161  func testLogger(l *cmdlog.Logger) {
   162  	l.NoLevel.Println("Somehow, the world always affects you more than you affect it.")
   163  
   164  	l.SetDebug(true)
   165  	l.Debug.Println("Man is a rational animal who always loses his temper when he is called upon.")
   166  
   167  	l.SetDebug(false)
   168  	l.Debug.Println("You can never trust a woman; she may be true to you.")
   169  
   170  	l.SetTS(true)
   171  	l.Success.Println("An alcoholic is someone you don't like who drinks as much as you do.")
   172  	l.Info.Println("There once was this swami who lived above a delicatessan.")
   173  
   174  	l.SetTSFormat(time.UnixDate)
   175  	l.Warn.Println("Telephone books are like dictionaries -- if you know the answer before.")
   176  
   177  	l.SetTS(false)
   178  	l.Error.Println("Nothing can be done in one trip.")
   179  	l.Error.Println(`Good day to let down old friends who need help.
   180  I believe in getting into hot water; it keeps you clean.`)
   181  }
   182  
   183  type fakeTB struct {
   184  	testing.TB
   185  	logf func(string, ...interface{})
   186  }
   187  
   188  func (ftb *fakeTB) Logf(f string, v ...interface{}) {
   189  	ftb.TB.Helper()
   190  	ftb.logf(f, v...)
   191  }
   192  

View as plain text