log_test.go raw

   1  package lol
   2  
   3  import (
   4  	"bytes"
   5  	"errors"
   6  	"fmt"
   7  	"strings"
   8  	"testing"
   9  )
  10  
  11  func TestLogLevels(t *testing.T) {
  12  	// Test that log levels are correctly ordered
  13  	if !(Off < Fatal && Fatal < Error && Error < Warn && Warn < Info && Info < Debug && Debug < Trace) {
  14  		t.Error("Log levels are not correctly ordered")
  15  	}
  16  
  17  	// Test that LevelNames matches the constants
  18  	expectedLevelNames := []string{
  19  		"off", "fatal", "error", "warn", "info", "debug", "trace",
  20  	}
  21  	for i, name := range expectedLevelNames {
  22  		if LevelNames[i] != name {
  23  			t.Errorf("LevelNames[%d] = %s, want %s", i, LevelNames[i], name)
  24  		}
  25  	}
  26  }
  27  
  28  func TestGetLogLevel(t *testing.T) {
  29  	tests := []struct {
  30  		level    string
  31  		expected int
  32  	}{
  33  		{"off", Off},
  34  		{"fatal", Fatal},
  35  		{"error", Error},
  36  		{"warn", Warn},
  37  		{"info", Info},
  38  		{"debug", Debug},
  39  		{"trace", Trace},
  40  		{"unknown", Info}, // Default to Info for unknown levels
  41  	}
  42  
  43  	for _, test := range tests {
  44  		t.Run(
  45  			test.level, func(t *testing.T) {
  46  				result := GetLogLevel(test.level)
  47  				if result != test.expected {
  48  					t.Errorf(
  49  						"GetLogLevel(%q) = %d, want %d", test.level, result,
  50  						test.expected,
  51  					)
  52  				}
  53  			},
  54  		)
  55  	}
  56  }
  57  
  58  func TestSetLogLevel(t *testing.T) {
  59  	// Save original level
  60  	originalLevel := Level.Load()
  61  	defer SetLoggers(int(originalLevel)) // Restore original level after test
  62  
  63  	tests := []struct {
  64  		level    string
  65  		expected int32
  66  	}{
  67  		{"off", Off},
  68  		{"fatal", Fatal},
  69  		{"error", Error},
  70  		{"warn", Warn},
  71  		{"info", Info},
  72  		{"debug", Debug},
  73  		{"trace", Trace},
  74  		{"unknown", Trace}, // Should default to Trace for unknown levels
  75  	}
  76  
  77  	for _, test := range tests {
  78  		t.Run(
  79  			test.level, func(t *testing.T) {
  80  				SetLogLevel(test.level)
  81  				result := Level.Load()
  82  				if result != test.expected {
  83  					t.Errorf(
  84  						"After SetLogLevel(%q), Level = %d, want %d",
  85  						test.level, result, test.expected,
  86  					)
  87  				}
  88  			},
  89  		)
  90  	}
  91  }
  92  
  93  func TestJoinStrings(t *testing.T) {
  94  	tests := []struct {
  95  		args     []any
  96  		expected string
  97  	}{
  98  		{[]any{}, ""},
  99  		{[]any{"hello"}, "hello"},
 100  		{[]any{"hello", "world"}, "hello world"},
 101  		{[]any{1, 2, 3}, "1 2 3"},
 102  		{[]any{1, "hello", 3.14}, "1 hello 3.14"},
 103  	}
 104  
 105  	for i, test := range tests {
 106  		t.Run(
 107  			fmt.Sprintf("case_%d", i), func(t *testing.T) {
 108  				result := JoinStrings(test.args...)
 109  				if result != test.expected {
 110  					t.Errorf(
 111  						"JoinStrings(%v) = %q, want %q", test.args, result,
 112  						test.expected,
 113  					)
 114  				}
 115  			},
 116  		)
 117  	}
 118  }
 119  
 120  func TestGetLoc(t *testing.T) {
 121  	loc := GetLoc(1)
 122  	if !strings.Contains(loc, "log_test.go") {
 123  		t.Errorf("GetLoc(1) = %q, expected to contain 'log_test.go'", loc)
 124  	}
 125  }
 126  
 127  func TestGetPrinter(t *testing.T) {
 128  	// Create a buffer to capture output
 129  	var buf bytes.Buffer
 130  
 131  	// Set log level to Info
 132  	originalLevel := Level.Load()
 133  	Level.Store(int32(Info))
 134  	defer Level.Store(originalLevel) // Restore original level
 135  
 136  	// Create a printer for Debug level
 137  	printer := GetPrinter(int32(Debug), &buf, 1)
 138  
 139  	// Test Ln method - should not print because Debug > Info
 140  	buf.Reset()
 141  	printer.Ln("test message")
 142  	if buf.String() != "" {
 143  		t.Errorf(
 144  			"printer.Ln() printed when level is too high: %q", buf.String(),
 145  		)
 146  	}
 147  
 148  	// Set log level to Debug
 149  	Level.Store(int32(Debug))
 150  
 151  	// Test Ln method - should print now
 152  	buf.Reset()
 153  	printer.Ln("test message")
 154  	output := buf.String()
 155  	if output == "" {
 156  		t.Error("printer.Ln() did not print when it should have")
 157  	}
 158  	if !strings.Contains(output, "test message") {
 159  		t.Errorf(
 160  			"printer.Ln() output %q does not contain 'test message'", output,
 161  		)
 162  	}
 163  
 164  	// Test F method
 165  	buf.Reset()
 166  	printer.F("formatted %s", "message")
 167  	output = buf.String()
 168  	if !strings.Contains(output, "formatted message") {
 169  		t.Errorf(
 170  			"printer.F() output %q does not contain 'formatted message'",
 171  			output,
 172  		)
 173  	}
 174  
 175  	// Test S method
 176  	buf.Reset()
 177  	printer.S("spew message")
 178  	output = buf.String()
 179  	if !strings.Contains(output, "spew message") {
 180  		t.Errorf(
 181  			"printer.S() output %q does not contain 'spew message'", output,
 182  		)
 183  	}
 184  
 185  	// Test C method
 186  	buf.Reset()
 187  	printer.C(func() string { return "closure message" })
 188  	output = buf.String()
 189  	if !strings.Contains(output, "closure message") {
 190  		t.Errorf(
 191  			"printer.C() output %q does not contain 'closure message'", output,
 192  		)
 193  	}
 194  
 195  	// Test Chk method with nil error
 196  	buf.Reset()
 197  	result := printer.Chk(nil)
 198  	if result != false {
 199  		t.Error("printer.Chk(nil) returned true, expected false")
 200  	}
 201  	if buf.String() != "" {
 202  		t.Errorf("printer.Chk(nil) printed output: %q", buf.String())
 203  	}
 204  
 205  	// Test Chk method with error
 206  	buf.Reset()
 207  	testErr := errors.New("test error")
 208  	result = printer.Chk(testErr)
 209  	if result != true {
 210  		t.Error("printer.Chk(error) returned false, expected true")
 211  	}
 212  	if !strings.Contains(buf.String(), "test error") {
 213  		t.Errorf(
 214  			"printer.Chk(error) output %q does not contain 'test error'",
 215  			buf.String(),
 216  		)
 217  	}
 218  
 219  	// Test Err method
 220  	buf.Reset()
 221  	err := printer.Err("error %s", "message")
 222  	if err == nil {
 223  		t.Error("printer.Err() returned nil error")
 224  	}
 225  	if err.Error() != "error message" {
 226  		t.Errorf(
 227  			"printer.Err() returned error with message %q, expected 'error message'",
 228  			err.Error(),
 229  		)
 230  	}
 231  	// Check if the message was logged
 232  	if !strings.Contains(buf.String(), "error message") {
 233  		t.Errorf(
 234  			"printer.Err() output %q does not contain 'error message'",
 235  			buf.String(),
 236  		)
 237  	}
 238  }
 239  
 240  func TestGetNullPrinter(t *testing.T) {
 241  	printer := GetNullPrinter()
 242  
 243  	// Test that Ln, F, S, C methods don't panic
 244  	printer.Ln("test")
 245  	printer.F("test %s", "format")
 246  	printer.S("test")
 247  	printer.C(func() string { return "test" })
 248  
 249  	// Test Chk method
 250  	if !printer.Chk(errors.New("test")) {
 251  		t.Error("GetNullPrinter().Chk(error) returned false, expected true")
 252  	}
 253  	if printer.Chk(nil) {
 254  		t.Error("GetNullPrinter().Chk(nil) returned true, expected false")
 255  	}
 256  
 257  	// Test Err method
 258  	err := printer.Err("test %s", "error")
 259  	if err == nil {
 260  		t.Error("GetNullPrinter().Err() returned nil error")
 261  	}
 262  	if err.Error() != "test error" {
 263  		t.Errorf(
 264  			"GetNullPrinter().Err() returned error with message %q, expected 'test error'",
 265  			err.Error(),
 266  		)
 267  	}
 268  }
 269  
 270  func TestNew(t *testing.T) {
 271  	var buf bytes.Buffer
 272  	log, check, errorf := New(&buf, 1)
 273  
 274  	// Verify that all components are created
 275  	if log == nil {
 276  		t.Error("New() returned nil Log")
 277  	}
 278  	if check == nil {
 279  		t.Error("New() returned nil Check")
 280  	}
 281  	if errorf == nil {
 282  		t.Error("New() returned nil Errorf")
 283  	}
 284  
 285  	// Test that the log functions work
 286  	originalLevel := Level.Load()
 287  	Level.Store(int32(Debug))
 288  	defer Level.Store(originalLevel)
 289  
 290  	buf.Reset()
 291  	log.D.Ln("test message")
 292  	if !strings.Contains(buf.String(), "test message") {
 293  		t.Errorf(
 294  			"log.D.Ln() output %q doesn't contain 'test message'",
 295  			buf.String(),
 296  		)
 297  	}
 298  }
 299