cmd/hakurei/print: use new store interface
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				Test / Create distribution (push) Successful in 35s
				
			
		
			
				
	
				Test / Sandbox (push) Successful in 2m15s
				
			
		
			
				
	
				Test / Hakurei (push) Successful in 3m11s
				
			
		
			
				
	
				Test / Hpkg (push) Successful in 4m2s
				
			
		
			
				
	
				Test / Sandbox (race detector) (push) Successful in 4m11s
				
			
		
			
				
	
				Test / Hakurei (race detector) (push) Successful in 5m3s
				
			
		
			
				
	
				Test / Flake checks (push) Successful in 1m40s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Test / Create distribution (push) Successful in 35s
				
			Test / Sandbox (push) Successful in 2m15s
				
			Test / Hakurei (push) Successful in 3m11s
				
			Test / Hpkg (push) Successful in 4m2s
				
			Test / Sandbox (race detector) (push) Successful in 4m11s
				
			Test / Hakurei (race detector) (push) Successful in 5m3s
				
			Test / Flake checks (push) Successful in 1m40s
				
			This removes the final uses of the compat interfaces. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
		
							parent
							
								
									0edcb7c1d3
								
							
						
					
					
						commit
						1c168babf2
					
				@ -20,7 +20,6 @@ import (
 | 
				
			|||||||
	"hakurei.app/internal"
 | 
						"hakurei.app/internal"
 | 
				
			||||||
	"hakurei.app/internal/env"
 | 
						"hakurei.app/internal/env"
 | 
				
			||||||
	"hakurei.app/internal/outcome"
 | 
						"hakurei.app/internal/outcome"
 | 
				
			||||||
	"hakurei.app/internal/store"
 | 
					 | 
				
			||||||
	"hakurei.app/message"
 | 
						"hakurei.app/message"
 | 
				
			||||||
	"hakurei.app/system/dbus"
 | 
						"hakurei.app/system/dbus"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@ -340,7 +339,7 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
 | 
				
			|||||||
		c.NewCommand("ps", "List active instances", func(args []string) error {
 | 
							c.NewCommand("ps", "List active instances", func(args []string) error {
 | 
				
			||||||
			var sc hst.Paths
 | 
								var sc hst.Paths
 | 
				
			||||||
			env.CopyPaths().Copy(&sc, new(outcome.Hsu).MustID(nil))
 | 
								env.CopyPaths().Copy(&sc, new(outcome.Hsu).MustID(nil))
 | 
				
			||||||
			printPs(os.Stdout, time.Now().UTC(), store.NewMulti(msg, sc.SharePath), flagShort, flagJSON)
 | 
								printPs(msg, os.Stdout, time.Now().UTC(), outcome.NewStore(&sc), flagShort, flagJSON)
 | 
				
			||||||
			return errSuccess
 | 
								return errSuccess
 | 
				
			||||||
		}).Flag(&flagShort, "short", command.BoolFlag(false), "Print instance id")
 | 
							}).Flag(&flagShort, "short", command.BoolFlag(false), "Print instance id")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,6 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
	"maps"
 | 
					 | 
				
			||||||
	"slices"
 | 
						"slices"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
@ -170,52 +169,52 @@ func printShowInstance(
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// printPs writes a representation of active instances to output.
 | 
					// printPs writes a representation of active instances to output.
 | 
				
			||||||
func printPs(output io.Writer, now time.Time, s store.Compat, short, flagJSON bool) {
 | 
					func printPs(msg message.Msg, output io.Writer, now time.Time, s *store.Store, short, flagJSON bool) {
 | 
				
			||||||
	var entries map[hst.ID]*hst.State
 | 
						f := func(a func(eh *store.EntryHandle)) {
 | 
				
			||||||
	if e, err := store.Join(s); err != nil {
 | 
							entries, copyError := s.All()
 | 
				
			||||||
		log.Fatalf("cannot join store: %v", err)
 | 
							for eh := range entries {
 | 
				
			||||||
	} else {
 | 
								a(eh)
 | 
				
			||||||
		entries = e
 | 
							}
 | 
				
			||||||
 | 
							if err := copyError(); err != nil {
 | 
				
			||||||
 | 
								msg.GetLogger().Println(getMessage("cannot iterate over store:", err))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !short && flagJSON {
 | 
						if short { // short output requires identifier only
 | 
				
			||||||
		es := slices.Collect(maps.Values(entries))
 | 
							var identifiers []*hst.ID
 | 
				
			||||||
		slices.SortFunc(es, func(a, b *hst.State) int { return bytes.Compare(a.ID[:], b.ID[:]) })
 | 
							f(func(eh *store.EntryHandle) {
 | 
				
			||||||
		encodeJSON(log.Fatal, output, short, es)
 | 
								if _, err := eh.Load(nil); err != nil { // passes through decode error
 | 
				
			||||||
 | 
									msg.GetLogger().Println(getMessage("cannot validate state entry header:", err))
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								identifiers = append(identifiers, &eh.ID)
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							slices.SortFunc(identifiers, func(a, b *hst.ID) int { return bytes.Compare(a[:], b[:]) })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if flagJSON {
 | 
				
			||||||
 | 
								encodeJSON(log.Fatal, output, short, identifiers)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								for _, id := range identifiers {
 | 
				
			||||||
 | 
									mustPrintln(output, shortIdentifier(id))
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// sort state entries by id string to ensure consistency between runs
 | 
						// long output requires full instance state
 | 
				
			||||||
	exp := make([]*expandedStateEntry, 0, len(entries))
 | 
						var instances []*hst.State
 | 
				
			||||||
	for id, instance := range entries {
 | 
						f(func(eh *store.EntryHandle) {
 | 
				
			||||||
		// gracefully skip nil states
 | 
							var state hst.State
 | 
				
			||||||
		if instance == nil {
 | 
							if _, err := eh.Load(&state); err != nil { // passes through decode error
 | 
				
			||||||
			log.Printf("got invalid state entry %s", id.String())
 | 
								msg.GetLogger().Println(getMessage("cannot load state entry:", err))
 | 
				
			||||||
			continue
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							instances = append(instances, &state)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						slices.SortFunc(instances, func(a, b *hst.State) int { return bytes.Compare(a.ID[:], b.ID[:]) })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// gracefully skip inconsistent states
 | 
						if flagJSON {
 | 
				
			||||||
		if id != instance.ID {
 | 
							encodeJSON(log.Fatal, output, short, instances)
 | 
				
			||||||
			log.Printf("possible store corruption: entry %s has id %s",
 | 
					 | 
				
			||||||
				id.String(), instance.ID.String())
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		exp = append(exp, &expandedStateEntry{s: id.String(), State: instance})
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	slices.SortFunc(exp, func(a, b *expandedStateEntry) int { return a.Time.Compare(b.Time) })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if short {
 | 
					 | 
				
			||||||
		if flagJSON {
 | 
					 | 
				
			||||||
			v := make([]string, len(exp))
 | 
					 | 
				
			||||||
			for i, e := range exp {
 | 
					 | 
				
			||||||
				v[i] = e.s
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			encodeJSON(log.Fatal, output, short, v)
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			for _, e := range exp {
 | 
					 | 
				
			||||||
				mustPrintln(output, shortIdentifierString(e.s))
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -223,33 +222,21 @@ func printPs(output io.Writer, now time.Time, s store.Compat, short, flagJSON bo
 | 
				
			|||||||
	defer t.MustFlush()
 | 
						defer t.MustFlush()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	t.Println("\tInstance\tPID\tApplication\tUptime")
 | 
						t.Println("\tInstance\tPID\tApplication\tUptime")
 | 
				
			||||||
	for _, e := range exp {
 | 
						for _, instance := range instances {
 | 
				
			||||||
		if len(e.s) != 1<<5 {
 | 
					 | 
				
			||||||
			// unreachable
 | 
					 | 
				
			||||||
			log.Printf("possible store corruption: invalid instance string %s", e.s)
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		as := "(No configuration information)"
 | 
							as := "(No configuration information)"
 | 
				
			||||||
		if e.Config != nil {
 | 
							if instance.Config != nil {
 | 
				
			||||||
			as = strconv.Itoa(e.Config.Identity)
 | 
								as = strconv.Itoa(instance.Config.Identity)
 | 
				
			||||||
			id := e.Config.ID
 | 
								id := instance.Config.ID
 | 
				
			||||||
			if id == "" {
 | 
								if id == "" {
 | 
				
			||||||
				id = "app.hakurei." + shortIdentifierString(e.s)
 | 
									id = "app.hakurei." + shortIdentifier(&instance.ID)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			as += " (" + id + ")"
 | 
								as += " (" + id + ")"
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		t.Printf("\t%s\t%d\t%s\t%s\n",
 | 
							t.Printf("\t%s\t%d\t%s\t%s\n",
 | 
				
			||||||
			shortIdentifierString(e.s), e.PID, as, now.Sub(e.Time).Round(time.Second).String())
 | 
								shortIdentifier(&instance.ID), instance.PID, as, now.Sub(instance.Time).Round(time.Second).String())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// expandedStateEntry stores [hst.State] alongside a string representation of its [hst.ID].
 | 
					 | 
				
			||||||
type expandedStateEntry struct {
 | 
					 | 
				
			||||||
	s string
 | 
					 | 
				
			||||||
	*hst.State
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// newPrinter returns a configured, wrapped [tabwriter.Writer].
 | 
					// newPrinter returns a configured, wrapped [tabwriter.Writer].
 | 
				
			||||||
func newPrinter(output io.Writer) *tp { return &tp{tabwriter.NewWriter(output, 0, 1, 4, ' ', 0)} }
 | 
					func newPrinter(output io.Writer) *tp { return &tp{tabwriter.NewWriter(output, 0, 1, 4, ' ', 0)} }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@ package main
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
@ -9,6 +10,7 @@ import (
 | 
				
			|||||||
	"hakurei.app/container/check"
 | 
						"hakurei.app/container/check"
 | 
				
			||||||
	"hakurei.app/hst"
 | 
						"hakurei.app/hst"
 | 
				
			||||||
	"hakurei.app/internal/store"
 | 
						"hakurei.app/internal/store"
 | 
				
			||||||
 | 
						"hakurei.app/message"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
@ -18,13 +20,30 @@ var (
 | 
				
			|||||||
		0x4c, 0xf0, 0x73, 0xbd,
 | 
							0x4c, 0xf0, 0x73, 0xbd,
 | 
				
			||||||
		0xb4, 0x6e, 0xb5, 0xc1,
 | 
							0xb4, 0x6e, 0xb5, 0xc1,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	testState = &hst.State{
 | 
						testState = hst.State{
 | 
				
			||||||
		ID:      testID,
 | 
							ID:      testID,
 | 
				
			||||||
		PID:     0xcafebabe,
 | 
							PID:     0xcafebabe,
 | 
				
			||||||
		ShimPID: 0xdeadbeef,
 | 
							ShimPID: 0xdeadbeef,
 | 
				
			||||||
		Config:  hst.Template(),
 | 
							Config:  hst.Template(),
 | 
				
			||||||
		Time:    testAppTime,
 | 
							Time:    testAppTime,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						testStateSmall = hst.State{
 | 
				
			||||||
 | 
							ID:      (hst.ID)(bytes.Repeat([]byte{0xaa}, len(hst.ID{}))),
 | 
				
			||||||
 | 
							PID:     0xbeef,
 | 
				
			||||||
 | 
							ShimPID: 0xcafe,
 | 
				
			||||||
 | 
							Config: &hst.Config{
 | 
				
			||||||
 | 
								Enablements: hst.NewEnablements(hst.EWayland | hst.EPulse),
 | 
				
			||||||
 | 
								Identity:    1,
 | 
				
			||||||
 | 
								Container: &hst.ContainerConfig{
 | 
				
			||||||
 | 
									Shell: check.MustAbs("/bin/sh"),
 | 
				
			||||||
 | 
									Home:  check.MustAbs("/data/data/uk.gensokyo.cat"),
 | 
				
			||||||
 | 
									Path:  check.MustAbs("/usr/bin/cat"),
 | 
				
			||||||
 | 
									Args:  []string{"cat"},
 | 
				
			||||||
 | 
									Flags: hst.FUserns,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							Time: time.Unix(0, 0xdeadbeef).UTC(),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	testTime    = time.Unix(3752, 1).UTC()
 | 
						testTime    = time.Unix(3752, 1).UTC()
 | 
				
			||||||
	testAppTime = time.Unix(0, 9).UTC()
 | 
						testAppTime = time.Unix(0, 9).UTC()
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@ -133,7 +152,7 @@ Session bus
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
`, false},
 | 
					`, false},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		{"instance", testState, hst.Template(), false, false, `State
 | 
							{"instance", &testState, hst.Template(), false, false, `State
 | 
				
			||||||
 Instance:    8e2c76b066dabe574cf073bdb46eb5c1 (3405691582 -> 3735928559)
 | 
					 Instance:    8e2c76b066dabe574cf073bdb46eb5c1 (3405691582 -> 3735928559)
 | 
				
			||||||
 Uptime:      1h2m32s
 | 
					 Uptime:      1h2m32s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -173,7 +192,7 @@ System bus
 | 
				
			|||||||
 Talk:      ["org.bluez" "org.freedesktop.Avahi" "org.freedesktop.UPower"]
 | 
					 Talk:      ["org.bluez" "org.freedesktop.Avahi" "org.freedesktop.UPower"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
`, true},
 | 
					`, true},
 | 
				
			||||||
		{"instance pd", testState, new(hst.Config), false, false, `Error: configuration missing container state!
 | 
							{"instance pd", &testState, new(hst.Config), false, false, `Error: configuration missing container state!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
State
 | 
					State
 | 
				
			||||||
 Instance:    8e2c76b066dabe574cf073bdb46eb5c1 (3405691582 -> 3735928559)
 | 
					 Instance:    8e2c76b066dabe574cf073bdb46eb5c1 (3405691582 -> 3735928559)
 | 
				
			||||||
@ -187,7 +206,7 @@ App
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		{"json nil", nil, nil, false, true, `null
 | 
							{"json nil", nil, nil, false, true, `null
 | 
				
			||||||
`, true},
 | 
					`, true},
 | 
				
			||||||
		{"json instance", testState, nil, false, true, `{
 | 
							{"json instance", &testState, nil, false, true, `{
 | 
				
			||||||
  "instance": "8e2c76b066dabe574cf073bdb46eb5c1",
 | 
					  "instance": "8e2c76b066dabe574cf073bdb46eb5c1",
 | 
				
			||||||
  "pid": 3405691582,
 | 
					  "pid": 3405691582,
 | 
				
			||||||
  "shim_pid": 3735928559,
 | 
					  "shim_pid": 3735928559,
 | 
				
			||||||
@ -515,41 +534,27 @@ func TestPrintPs(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	testCases := []struct {
 | 
						testCases := []struct {
 | 
				
			||||||
		name        string
 | 
							name        string
 | 
				
			||||||
		entries     map[hst.ID]*hst.State
 | 
							data        []hst.State
 | 
				
			||||||
		short, json bool
 | 
							short, json bool
 | 
				
			||||||
		want        string
 | 
							want, log   string
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		{"no entries", make(map[hst.ID]*hst.State), false, false, "    Instance    PID    Application    Uptime\n"},
 | 
							{"no entries", []hst.State{}, false, false, "    Instance    PID    Application    Uptime\n", ""},
 | 
				
			||||||
		{"no entries short", make(map[hst.ID]*hst.State), true, false, ""},
 | 
							{"no entries short", []hst.State{}, true, false, "", ""},
 | 
				
			||||||
		{"nil instance", map[hst.ID]*hst.State{testID: nil}, false, false, "    Instance    PID    Application    Uptime\n"},
 | 
					 | 
				
			||||||
		{"state corruption", map[hst.ID]*hst.State{hst.ID{}: testState}, false, false, "    Instance    PID    Application    Uptime\n"},
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		{"valid pd", map[hst.ID]*hst.State{testID: {ID: testID, PID: 1 << 8, Config: new(hst.Config), Time: testAppTime}}, false, false, `    Instance    PID    Application                 Uptime
 | 
							{"invalid config", []hst.State{{ID: testID, PID: 1 << 8, Config: new(hst.Config), Time: testAppTime}}, false, false, "    Instance    PID    Application    Uptime\n", "check: configuration missing container state\n"},
 | 
				
			||||||
    4cf073bd    256    0 (app.hakurei.4cf073bd)    1h2m32s
 | 
					 | 
				
			||||||
`},
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		{"valid", map[hst.ID]*hst.State{testID: testState}, false, false, `    Instance    PID           Application                  Uptime
 | 
							{"valid", []hst.State{testStateSmall, testState}, false, false, `    Instance    PID           Application                  Uptime
 | 
				
			||||||
    4cf073bd    3405691582    9 (org.chromium.Chromium)    1h2m32s
 | 
					    4cf073bd    3405691582    9 (org.chromium.Chromium)    1h2m32s
 | 
				
			||||||
`},
 | 
					    aaaaaaaa    48879         1 (app.hakurei.aaaaaaaa)     1h2m28s
 | 
				
			||||||
		{"valid short", map[hst.ID]*hst.State{testID: testState}, true, false, "4cf073bd\n"},
 | 
					`, ""},
 | 
				
			||||||
		{"valid json", map[hst.ID]*hst.State{testID: testState, (hst.ID)(bytes.Repeat([]byte{0xaa}, len(hst.ID{}))): {
 | 
							{"valid single", []hst.State{testState}, false, false, `    Instance    PID           Application                  Uptime
 | 
				
			||||||
			ID:      (hst.ID)(bytes.Repeat([]byte{0xaa}, len(hst.ID{}))),
 | 
					    4cf073bd    3405691582    9 (org.chromium.Chromium)    1h2m32s
 | 
				
			||||||
			PID:     0xbeef,
 | 
					`, ""},
 | 
				
			||||||
			ShimPID: 0xcafe,
 | 
					
 | 
				
			||||||
			Config: &hst.Config{
 | 
							{"valid short", []hst.State{testStateSmall, testState}, true, false, "4cf073bd\naaaaaaaa\n", ""},
 | 
				
			||||||
				ID:          "uk.gensokyo.cat",
 | 
							{"valid short single", []hst.State{testState}, true, false, "4cf073bd\n", ""},
 | 
				
			||||||
				Enablements: hst.NewEnablements(hst.EWayland | hst.EPulse),
 | 
					
 | 
				
			||||||
				Identity:    1,
 | 
							{"valid json", []hst.State{testState, testStateSmall}, false, true, `[
 | 
				
			||||||
				Container: &hst.ContainerConfig{
 | 
					 | 
				
			||||||
					Shell: check.MustAbs("/bin/sh"),
 | 
					 | 
				
			||||||
					Home:  check.MustAbs("/data/data/uk.gensokyo.cat"),
 | 
					 | 
				
			||||||
					Path:  check.MustAbs("/usr/bin/cat"),
 | 
					 | 
				
			||||||
					Args:  []string{"cat"},
 | 
					 | 
				
			||||||
					Flags: hst.FUserns,
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			Time: time.Unix(0, 0xdeadbeef).UTC(),
 | 
					 | 
				
			||||||
		}}, false, true, `[
 | 
					 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    "instance": "8e2c76b066dabe574cf073bdb46eb5c1",
 | 
					    "instance": "8e2c76b066dabe574cf073bdb46eb5c1",
 | 
				
			||||||
    "pid": 3405691582,
 | 
					    "pid": 3405691582,
 | 
				
			||||||
@ -707,7 +712,7 @@ func TestPrintPs(t *testing.T) {
 | 
				
			|||||||
    "instance": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
 | 
					    "instance": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
 | 
				
			||||||
    "pid": 48879,
 | 
					    "pid": 48879,
 | 
				
			||||||
    "shim_pid": 51966,
 | 
					    "shim_pid": 51966,
 | 
				
			||||||
    "id": "uk.gensokyo.cat",
 | 
					    "id": "",
 | 
				
			||||||
    "enablements": {
 | 
					    "enablements": {
 | 
				
			||||||
      "wayland": true,
 | 
					      "wayland": true,
 | 
				
			||||||
      "pulse": true
 | 
					      "pulse": true
 | 
				
			||||||
@ -729,30 +734,44 @@ func TestPrintPs(t *testing.T) {
 | 
				
			|||||||
    "time": "1970-01-01T00:00:03.735928559Z"
 | 
					    "time": "1970-01-01T00:00:03.735928559Z"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
`},
 | 
					`, ""},
 | 
				
			||||||
		{"valid short json", map[hst.ID]*hst.State{testID: testState}, true, true, `["8e2c76b066dabe574cf073bdb46eb5c1"]
 | 
							{"valid short json", []hst.State{testStateSmall, testState}, true, true, `["8e2c76b066dabe574cf073bdb46eb5c1","aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
 | 
				
			||||||
`},
 | 
					`, ""},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, tc := range testCases {
 | 
						for _, tc := range testCases {
 | 
				
			||||||
 | 
							s := store.New(check.MustAbs(t.TempDir()).Append("store"))
 | 
				
			||||||
 | 
							for i := range tc.data {
 | 
				
			||||||
 | 
								if h, err := s.Handle(tc.data[i].Identity); err != nil {
 | 
				
			||||||
 | 
									t.Fatalf("Handle: error = %v", err)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									var unlock func()
 | 
				
			||||||
 | 
									if unlock, err = h.Lock(); err != nil {
 | 
				
			||||||
 | 
										t.Fatalf("Lock: error = %v", err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									_, err = h.Save(&tc.data[i])
 | 
				
			||||||
 | 
									unlock()
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										t.Fatalf("Save: error = %v", err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// store must not be written to beyond this point
 | 
				
			||||||
		t.Run(tc.name, func(t *testing.T) {
 | 
							t.Run(tc.name, func(t *testing.T) {
 | 
				
			||||||
			t.Parallel()
 | 
								t.Parallel()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			output := new(strings.Builder)
 | 
								var printBuf, logBuf bytes.Buffer
 | 
				
			||||||
			printPs(output, testTime, stubStore(tc.entries), tc.short, tc.json)
 | 
								msg := message.NewMsg(log.New(&logBuf, "check: ", 0))
 | 
				
			||||||
			if got := output.String(); got != tc.want {
 | 
								msg.SwapVerbose(true)
 | 
				
			||||||
				t.Errorf("printPs: got\n%s\nwant\n%s",
 | 
								printPs(msg, &printBuf, testTime, s, tc.short, tc.json)
 | 
				
			||||||
					got, tc.want)
 | 
								if got := printBuf.String(); got != tc.want {
 | 
				
			||||||
 | 
									t.Errorf("printPs:\n%s\nwant\n%s", got, tc.want)
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								if got := logBuf.String(); got != tc.log {
 | 
				
			||||||
 | 
									t.Errorf("msg:\n%s\nwant\n%s", got, tc.log)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// stubStore implements [state.Store] and returns test samples via [state.Joiner].
 | 
					 | 
				
			||||||
type stubStore map[hst.ID]*hst.State
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s stubStore) Join() (map[hst.ID]*hst.State, error)       { return s, nil }
 | 
					 | 
				
			||||||
func (s stubStore) Do(int, func(c store.Cursor)) (bool, error) { panic("unreachable") }
 | 
					 | 
				
			||||||
func (s stubStore) List() ([]int, error)                       { panic("unreachable") }
 | 
					 | 
				
			||||||
func (s stubStore) Close() error                               { return nil }
 | 
					 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user