Update to go1.24.0
This commit is contained in:
@@ -5,12 +5,16 @@
|
||||
package slog
|
||||
|
||||
import (
|
||||
"internal/asan"
|
||||
"internal/testenv"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestAttrNoAlloc(t *testing.T) {
|
||||
if asan.Enabled {
|
||||
t.Skip("test allocates with -asan")
|
||||
}
|
||||
testenv.SkipIfOptimizationOff(t)
|
||||
// Assign values just to make sure the compiler doesn't optimize away the statements.
|
||||
var (
|
||||
|
||||
27
src/log/slog/example_discard_test.go
Normal file
27
src/log/slog/example_discard_test.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package slog_test
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"log/slog/internal/slogtest"
|
||||
"os"
|
||||
)
|
||||
|
||||
func Example_discardHandler() {
|
||||
// A slog.TextHandler can output log messages.
|
||||
logger1 := slog.New(slog.NewTextHandler(
|
||||
os.Stdout,
|
||||
&slog.HandlerOptions{ReplaceAttr: slogtest.RemoveTime},
|
||||
))
|
||||
logger1.Info("message 1")
|
||||
|
||||
// A slog.DiscardHandler will discard all messages.
|
||||
logger2 := slog.New(slog.DiscardHandler)
|
||||
logger2.Info("message 2")
|
||||
|
||||
// Output:
|
||||
// level=INFO msg="message 1"
|
||||
}
|
||||
@@ -602,3 +602,14 @@ func appendRFC3339Millis(b []byte, t time.Time) []byte {
|
||||
b = append(b[:n+prefixLen], b[n+prefixLen+1:]...) // drop the 4th digit
|
||||
return b
|
||||
}
|
||||
|
||||
// DiscardHandler discards all log output.
|
||||
// DiscardHandler.Enabled returns false for all Levels.
|
||||
var DiscardHandler Handler = discardHandler{}
|
||||
|
||||
type discardHandler struct{}
|
||||
|
||||
func (dh discardHandler) Enabled(context.Context, Level) bool { return false }
|
||||
func (dh discardHandler) Handle(context.Context, Record) error { return nil }
|
||||
func (dh discardHandler) WithAttrs(attrs []Attr) Handler { return dh }
|
||||
func (dh discardHandler) WithGroup(name string) Handler { return dh }
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strconv"
|
||||
@@ -711,3 +712,23 @@ func BenchmarkWriteTime(b *testing.B) {
|
||||
buf = appendRFC3339Millis(buf[:0], tm)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDiscardHandler(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
stdout, stderr := os.Stdout, os.Stderr
|
||||
os.Stdout, os.Stderr = nil, nil // panic on write
|
||||
t.Cleanup(func() {
|
||||
os.Stdout, os.Stderr = stdout, stderr
|
||||
})
|
||||
|
||||
// Just ensure nothing panics during normal usage
|
||||
l := New(DiscardHandler)
|
||||
l.Info("msg", "a", 1, "b", 2)
|
||||
l.Debug("bg", Int("a", 1), "b", 2)
|
||||
l.Warn("w", Duration("dur", 3*time.Second))
|
||||
l.Error("bad", "a", 1)
|
||||
l.Log(ctx, LevelWarn+1, "w", Int("a", 1), String("b", "two"))
|
||||
l.LogAttrs(ctx, LevelInfo+1, "a b c", Int("a", 1), String("b", "two"))
|
||||
l.Info("info", "a", []Attr{Int("i", 1)})
|
||||
l.Info("info", "a", GroupValue(Int("i", 1)))
|
||||
}
|
||||
|
||||
@@ -98,10 +98,16 @@ func (l *Level) UnmarshalJSON(data []byte) error {
|
||||
return l.parse(s)
|
||||
}
|
||||
|
||||
// MarshalText implements [encoding.TextMarshaler]
|
||||
// AppendText implements [encoding.TextAppender]
|
||||
// by calling [Level.String].
|
||||
func (l Level) AppendText(b []byte) ([]byte, error) {
|
||||
return append(b, l.String()...), nil
|
||||
}
|
||||
|
||||
// MarshalText implements [encoding.TextMarshaler]
|
||||
// by calling [Level.AppendText].
|
||||
func (l Level) MarshalText() ([]byte, error) {
|
||||
return []byte(l.String()), nil
|
||||
return l.AppendText(nil)
|
||||
}
|
||||
|
||||
// UnmarshalText implements [encoding.TextUnmarshaler].
|
||||
@@ -172,10 +178,16 @@ func (v *LevelVar) String() string {
|
||||
return fmt.Sprintf("LevelVar(%s)", v.Level())
|
||||
}
|
||||
|
||||
// AppendText implements [encoding.TextAppender]
|
||||
// by calling [Level.AppendText].
|
||||
func (v *LevelVar) AppendText(b []byte) ([]byte, error) {
|
||||
return v.Level().AppendText(b)
|
||||
}
|
||||
|
||||
// MarshalText implements [encoding.TextMarshaler]
|
||||
// by calling [Level.MarshalText].
|
||||
// by calling [LevelVar.AppendText].
|
||||
func (v *LevelVar) MarshalText() ([]byte, error) {
|
||||
return v.Level().MarshalText()
|
||||
return v.AppendText(nil)
|
||||
}
|
||||
|
||||
// UnmarshalText implements [encoding.TextUnmarshaler]
|
||||
|
||||
@@ -89,6 +89,19 @@ func TestLevelMarshalText(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLevelAppendText(t *testing.T) {
|
||||
buf := make([]byte, 4, 16)
|
||||
want := LevelWarn - 3
|
||||
wantData := []byte("\x00\x00\x00\x00INFO+1")
|
||||
data, err := want.AppendText(buf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(data, wantData) {
|
||||
t.Errorf("got %s, want %s", string(data), string(wantData))
|
||||
}
|
||||
}
|
||||
|
||||
func TestLevelParse(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
in string
|
||||
@@ -162,6 +175,23 @@ func TestLevelVarMarshalText(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLevelVarAppendText(t *testing.T) {
|
||||
var v LevelVar
|
||||
v.Set(LevelWarn)
|
||||
buf := make([]byte, 4, 16)
|
||||
data, err := v.AppendText(buf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var v2 LevelVar
|
||||
if err := v2.UnmarshalText(data[4:]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if g, w := v2.Level(), LevelWarn; g != w {
|
||||
t.Errorf("got %s, want %s", g, w)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLevelVarFlag(t *testing.T) {
|
||||
fs := flag.NewFlagSet("test", flag.ContinueOnError)
|
||||
v := &LevelVar{}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package slog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"log"
|
||||
loginternal "log/internal"
|
||||
@@ -96,9 +97,7 @@ func (w *handlerWriter) Write(buf []byte) (int, error) {
|
||||
|
||||
// Remove final newline.
|
||||
origLen := len(buf) // Report that the entire buf was written.
|
||||
if len(buf) > 0 && buf[len(buf)-1] == '\n' {
|
||||
buf = buf[:len(buf)-1]
|
||||
}
|
||||
buf = bytes.TrimSuffix(buf, []byte{'\n'})
|
||||
r := NewRecord(time.Now(), level, string(buf), pc)
|
||||
return origLen, w.h.Handle(context.Background(), r)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ package slog
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"internal/asan"
|
||||
"internal/msan"
|
||||
"internal/race"
|
||||
"internal/testenv"
|
||||
"io"
|
||||
@@ -229,7 +231,7 @@ func TestCallDepth(t *testing.T) {
|
||||
|
||||
func TestAlloc(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
dl := New(discardHandler{})
|
||||
dl := New(discardTestHandler{})
|
||||
defer SetDefault(Default()) // restore
|
||||
SetDefault(dl)
|
||||
|
||||
@@ -256,7 +258,7 @@ func TestAlloc(t *testing.T) {
|
||||
})
|
||||
})
|
||||
t.Run("2 pairs disabled inline", func(t *testing.T) {
|
||||
l := New(discardHandler{disabled: true})
|
||||
l := New(DiscardHandler)
|
||||
s := "abc"
|
||||
i := 2000
|
||||
wantAllocs(t, 2, func() {
|
||||
@@ -267,7 +269,7 @@ func TestAlloc(t *testing.T) {
|
||||
})
|
||||
})
|
||||
t.Run("2 pairs disabled", func(t *testing.T) {
|
||||
l := New(discardHandler{disabled: true})
|
||||
l := New(DiscardHandler)
|
||||
s := "abc"
|
||||
i := 2000
|
||||
wantAllocs(t, 0, func() {
|
||||
@@ -303,7 +305,7 @@ func TestAlloc(t *testing.T) {
|
||||
})
|
||||
})
|
||||
t.Run("attrs3 disabled", func(t *testing.T) {
|
||||
logger := New(discardHandler{disabled: true})
|
||||
logger := New(DiscardHandler)
|
||||
wantAllocs(t, 0, func() {
|
||||
logger.LogAttrs(ctx, LevelInfo, "hello", Int("a", 1), String("b", "two"), Duration("c", time.Second))
|
||||
})
|
||||
@@ -566,18 +568,17 @@ func (c *captureHandler) clear() {
|
||||
c.r = Record{}
|
||||
}
|
||||
|
||||
type discardHandler struct {
|
||||
disabled bool
|
||||
attrs []Attr
|
||||
type discardTestHandler struct {
|
||||
attrs []Attr
|
||||
}
|
||||
|
||||
func (d discardHandler) Enabled(context.Context, Level) bool { return !d.disabled }
|
||||
func (discardHandler) Handle(context.Context, Record) error { return nil }
|
||||
func (d discardHandler) WithAttrs(as []Attr) Handler {
|
||||
func (d discardTestHandler) Enabled(context.Context, Level) bool { return true }
|
||||
func (discardTestHandler) Handle(context.Context, Record) error { return nil }
|
||||
func (d discardTestHandler) WithAttrs(as []Attr) Handler {
|
||||
d.attrs = concat(d.attrs, as)
|
||||
return d
|
||||
}
|
||||
func (h discardHandler) WithGroup(name string) Handler {
|
||||
func (h discardTestHandler) WithGroup(name string) Handler {
|
||||
return h
|
||||
}
|
||||
|
||||
@@ -644,8 +645,8 @@ func callerPC(depth int) uintptr {
|
||||
}
|
||||
|
||||
func wantAllocs(t *testing.T, want int, f func()) {
|
||||
if race.Enabled {
|
||||
t.Skip("skipping test in race mode")
|
||||
if race.Enabled || asan.Enabled || msan.Enabled {
|
||||
t.Skip("skipping test in race, asan, and msan modes")
|
||||
}
|
||||
testenv.SkipIfOptimizationOff(t)
|
||||
t.Helper()
|
||||
|
||||
@@ -6,6 +6,7 @@ package slog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"internal/asan"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -86,6 +87,10 @@ func TestValueString(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestValueNoAlloc(t *testing.T) {
|
||||
if asan.Enabled {
|
||||
t.Skip("test allocates more with -asan; see #70079")
|
||||
}
|
||||
|
||||
// Assign values just to make sure the compiler doesn't optimize away the statements.
|
||||
var (
|
||||
i int64
|
||||
|
||||
Reference in New Issue
Block a user