mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-02 19:17:10 +00:00
Merge branch 'web-logs-reach-the-spec' into correctness-and-spec-skills
This commit is contained in:
commit
36caf6916f
7 files changed
+329
-13
No files matched your search
@@ -70,23 +70,27 @@ func New() *Driver {
|
||||
}
|
||||
var parts []string
|
||||
for _, arg := range e.Args {
|
||||
if arg.Value != nil {
|
||||
var s string
|
||||
if err := json.Unmarshal(arg.Value, &s); err == nil {
|
||||
parts = append(parts, s)
|
||||
} else {
|
||||
parts = append(parts, string(arg.Value))
|
||||
// An object argument, which is what console.error(err) passes,
|
||||
// carries no value at all: CDP sends a description instead. Reading
|
||||
// only the value logged those calls with an empty message, so the
|
||||
// entry named a level and nothing a reader could act on.
|
||||
if arg.Value == nil {
|
||||
if arg.Description != "" {
|
||||
parts = append(parts, arg.Description)
|
||||
}
|
||||
continue
|
||||
}
|
||||
var s string
|
||||
if err := json.Unmarshal(arg.Value, &s); err == nil {
|
||||
parts = append(parts, s)
|
||||
} else {
|
||||
parts = append(parts, string(arg.Value))
|
||||
}
|
||||
}
|
||||
level := strings.ToUpper(string(e.Type))
|
||||
if level == "LOG" {
|
||||
level = "I"
|
||||
}
|
||||
d.logsMu.Lock()
|
||||
d.logs = append(d.logs, driver.LogEntry{
|
||||
UnixMillis: int64(e.Timestamp.Time().UnixMilli()),
|
||||
Level: level,
|
||||
Level: consoleLevel(e.Type),
|
||||
Tag: "console",
|
||||
Message: strings.Join(parts, " "),
|
||||
})
|
||||
@@ -712,9 +716,33 @@ func (d *Driver) Metrics(ctx context.Context, _ string) (driver.Metrics, error)
|
||||
}, nil
|
||||
}
|
||||
|
||||
// consoleLevel places a console call on driver.LogEntry's logcat scale. The
|
||||
// verbs a spec acts on are all named here; the rest are info rather than "E"
|
||||
// because promoting them would convict an app of an error it never logged.
|
||||
func consoleLevel(apiType runtime.APIType) string {
|
||||
switch apiType {
|
||||
case runtime.APITypeError, runtime.APITypeAssert:
|
||||
return "E"
|
||||
case runtime.APITypeWarning:
|
||||
return "W"
|
||||
case runtime.APITypeDebug:
|
||||
return "D"
|
||||
default:
|
||||
return "I"
|
||||
}
|
||||
}
|
||||
|
||||
// meetsLevel keeps an entry whose level the scale cannot rank. Ranking an
|
||||
// unknown level below every threshold drops it, and a dropped entry is
|
||||
// indistinguishable from a quiet app: the caller sees silence and reports it as
|
||||
// health.
|
||||
func meetsLevel(level, minLevel string) bool {
|
||||
order := map[string]int{"V": 0, "D": 1, "I": 2, "W": 3, "E": 4, "F": 5}
|
||||
return order[level] >= order[minLevel]
|
||||
rank, ranked := order[level]
|
||||
if !ranked {
|
||||
return true
|
||||
}
|
||||
return rank >= order[minLevel]
|
||||
}
|
||||
|
||||
func pngDimensions(png []byte) (int, int) {
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package chrome
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/chromedp/cdproto/runtime"
|
||||
)
|
||||
|
||||
// Every console verb has to land on the logcat scale driver.LogEntry declares:
|
||||
// the runner fetches at "E" and the default properties count entries whose
|
||||
// level equals "E", so a level spelled any other way is an error the spec never
|
||||
// sees. A verb with no mapping is info, which is honest about severity without
|
||||
// fabricating an error the page never logged.
|
||||
func TestConsoleLevel(t *testing.T) {
|
||||
cases := map[runtime.APIType]string{
|
||||
runtime.APITypeError: "E",
|
||||
runtime.APITypeAssert: "E",
|
||||
runtime.APITypeWarning: "W",
|
||||
runtime.APITypeDebug: "D",
|
||||
runtime.APITypeLog: "I",
|
||||
runtime.APITypeInfo: "I",
|
||||
runtime.APITypeTable: "I",
|
||||
runtime.APIType("countReset"): "I",
|
||||
}
|
||||
for apiType, want := range cases {
|
||||
if got := consoleLevel(apiType); got != want {
|
||||
t.Errorf("consoleLevel(%q) = %q, want %q", apiType, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A level the scale does not name is unknown, not verbose. Ranking it below
|
||||
// every threshold is what silently emptied the web log channel: the entries
|
||||
// existed, the filter dropped them, and the run reported nothing. Evidence the
|
||||
// filter cannot rank has to reach the caller, who can at least see it.
|
||||
func TestMeetsLevel(t *testing.T) {
|
||||
cases := []struct {
|
||||
level string
|
||||
minLevel string
|
||||
want bool
|
||||
}{
|
||||
{"E", "E", true},
|
||||
{"F", "E", true},
|
||||
{"W", "E", false},
|
||||
{"I", "E", false},
|
||||
{"D", "E", false},
|
||||
{"V", "E", false},
|
||||
{"W", "W", true},
|
||||
{"I", "W", false},
|
||||
{"D", "V", true},
|
||||
{"ERROR", "E", true},
|
||||
{"WARNING", "E", true},
|
||||
{"", "E", true},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
if got := meetsLevel(tc.level, tc.minLevel); got != tc.want {
|
||||
t.Errorf("meetsLevel(%q, %q) = %v, want %v", tc.level, tc.minLevel, got, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,6 +82,12 @@ type FocusedWindowChecker interface {
|
||||
FocusedWindowApp(ctx context.Context) (string, error)
|
||||
}
|
||||
|
||||
// LogEntry is one line of device log. Level is logcat's single-letter scale on
|
||||
// every platform: "V", "D", "I", "W", "E", "F", ordered as written. The runner
|
||||
// fetches at "E" and the default properties count entries whose level equals
|
||||
// "E", so a driver that spells a level any other way empties the channel
|
||||
// without failing anything: the entries never arrive and every property reading
|
||||
// state.logs holds vacuously.
|
||||
type LogEntry struct {
|
||||
UnixMillis int64
|
||||
Level string
|
||||
|
||||
@@ -1084,7 +1084,10 @@ func (d *Driver) WaitForIdle(ctx context.Context, _ time.Duration) error {
|
||||
}
|
||||
|
||||
// RecentLogs returns no entries: the companion log RPC is a follow-up, so v1
|
||||
// reports an empty slice rather than failing.
|
||||
// reports an empty slice rather than failing. Every property reading state.logs
|
||||
// therefore holds vacuously on iOS and nothing says so; closing it means
|
||||
// tailing idb's streaming log RPC and mapping os_log levels onto the
|
||||
// single-letter scale driver.LogEntry declares.
|
||||
func (d *Driver) RecentLogs(_ context.Context, _ time.Time, _ string) ([]driver.LogEntry, error) {
|
||||
return []driver.LogEntry{}, nil
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user