runtimes/google/rt: bring back tests for runtime shutdown.

Change-Id: Idc01807d0beed6785d4916fb2c49d76655185359
diff --git a/lib/expect/expect.go b/lib/expect/expect.go
index 957f244..b9b8311 100644
--- a/lib/expect/expect.go
+++ b/lib/expect/expect.go
@@ -282,46 +282,75 @@
 	if s.Failed() {
 		return
 	}
+	if err := s.expectSetRE(len(expected), expected...); err != nil {
+		s.error(err)
+	}
+}
+
+// ExpectSetEventuallyRE is like ExpectSetRE except that it reads
+// all remaining output rather than just the next n lines and thus
+// can be used to look for a set of patterns that occur within that
+// output.
+func (s *Session) ExpectSetEventuallyRE(expected ...string) {
+	if s.Failed() {
+		return
+	}
+	if err := s.expectSetRE(-1, expected...); err != nil {
+		s.error(err)
+	}
+}
+
+// expectSetRE will look for the expected set of patterns in the next
+// numLines of output or in all remaining output.
+func (s *Session) expectSetRE(numLines int, expected ...string) error {
+
 	regexps := make([]*regexp.Regexp, len(expected))
 	for i, expRE := range expected {
 		re, err := regexp.Compile(expRE)
 		if err != nil {
-			s.error(err)
-			return
+			return err
 		}
 		regexps[i] = re
 	}
-	actual := make([]string, len(expected))
-	for i := 0; i < len(expected); i++ {
+	actual := []string{}
+	i := 0
+	for {
 		line, err := s.read(readLine)
 		line = strings.TrimRight(line, "\n")
 		s.log(err, "ExpectSetRE: %s", line)
 		if err != nil {
-			s.error(err)
-			return
+			if numLines >= 0 {
+				return err
+			}
+			break
 		}
-		actual[i] = line
+		actual = append(actual, line)
+		i++
+		if numLines > 0 && i >= numLines {
+			break
+		}
 	}
+
 	// Match each line against all regexp's and remove each regexp
 	// that matches.
 	for _, l := range actual {
-		found := false
 		for i, re := range regexps {
 			if re == nil {
 				continue
 			}
 			if re.MatchString(l) {
-				// We remove each RE that matches.
-				found = true
 				regexps[i] = nil
 				break
 			}
 		}
-		if !found {
-			s.error(fmt.Errorf("found no match for %q", l))
-			return
+	}
+	// It's an error if there are any unmatched regexps.
+	for _, re := range regexps {
+		if re != nil {
+			return fmt.Errorf("found no match for %q", re)
 		}
 	}
+	return nil
 }
 
 // ReadLine reads the next line, if any, from the input stream. It will set
diff --git a/lib/expect/expect_test.go b/lib/expect/expect_test.go
index 8fa62da..8e8424d 100644
--- a/lib/expect/expect_test.go
+++ b/lib/expect/expect_test.go
@@ -102,12 +102,42 @@
 	buffer.WriteString("ooh\n")
 	buffer.WriteString("aah\n")
 	s.ExpectSetRE("bar=.*", "def")
-	if got, want := s.Error(), "expect_test.go:104: found no match for \"ooh\""; got == nil || got.Error() != want {
+	if got, want := s.Error(), "expect_test.go:104: found no match for \"bar=.*\""; got == nil || got.Error() != want {
 		t.Errorf("got %v, want %q", got, want)
 	}
 	s.ExpectEOF()
 }
 
+func TestExpectSetEventuallyRE(t *testing.T) {
+	buf := []byte{}
+	buffer := bytes.NewBuffer(buf)
+	buffer.WriteString("bar=baz\n")
+	buffer.WriteString("abc\n")
+	buffer.WriteString("def\n")
+	buffer.WriteString("abc\n")
+	s := expect.NewSession(nil, bufio.NewReader(buffer), time.Minute)
+	s.SetVerbosity(testing.Verbose())
+	s.ExpectSetEventuallyRE("^bar=.*$", "def")
+	if s.Error() != nil {
+		t.Errorf("unexpected error: %s", s.Error())
+	}
+	s.ExpectSetEventuallyRE("abc")
+	if got, want := s.Error(), "expect_test.go:124: found no match for \"abc\""; got == nil || got.Error() != want {
+		t.Errorf("got %q, want %q", got, want)
+	}
+	// Need to clear the EOF from the previous ExpectSetEventuallyRE call
+	buf = []byte{}
+	buffer = bytes.NewBuffer(buf)
+	s = expect.NewSession(nil, bufio.NewReader(buffer), time.Minute)
+	buffer.WriteString("ooh\n")
+	buffer.WriteString("aah\n")
+	s.ExpectSetEventuallyRE("zzz")
+	if got, want := s.Error(), "expect_test.go:134: found no match for \"zzz\""; got == nil || got.Error() != want {
+		t.Errorf("got %q, want %q", got, want)
+	}
+	s.ExpectEOF()
+}
+
 func TestRead(t *testing.T) {
 	buf := []byte{}
 	buffer := bytes.NewBuffer(buf)
diff --git a/runtimes/google/rt/shutdown_servers_test.go b/runtimes/google/rt/shutdown_servers_test.go
new file mode 100644
index 0000000..3e3f730
--- /dev/null
+++ b/runtimes/google/rt/shutdown_servers_test.go
@@ -0,0 +1,271 @@
+package rt_test
+
+import (
+	"bufio"
+	"fmt"
+	"io"
+	"os"
+	"os/signal"
+	"sync"
+	"syscall"
+
+	"veyron.io/veyron/veyron2/ipc"
+	"veyron.io/veyron/veyron2/rt"
+	"veyron.io/veyron/veyron2/vlog"
+
+	"veyron.io/veyron/veyron/lib/modules"
+	"veyron.io/veyron/veyron/lib/signals"
+	"veyron.io/veyron/veyron/profiles"
+)
+
+func init() {
+	modules.RegisterChild("simpleServerProgram", "", simpleServerProgram)
+	modules.RegisterChild("complexServerProgram", "", complexServerProgram)
+}
+
+type dummy struct{}
+
+func (*dummy) Echo(ipc.ServerContext) error { return nil }
+
+// makeServer sets up a simple dummy server.
+func makeServer() ipc.Server {
+	server, err := rt.R().NewServer()
+	if err != nil {
+		vlog.Fatalf("r.NewServer error: %s", err)
+	}
+	if _, err := server.Listen(profiles.LocalListenSpec); err != nil {
+		vlog.Fatalf("server.Listen error: %s", err)
+	}
+	if err := server.Serve("", &dummy{}, nil); err != nil {
+		vlog.Fatalf("server.Serve error: %s", err)
+	}
+	return server
+}
+
+// remoteCmdLoop listens on stdin and interprets commands sent over stdin (from
+// the parent process).
+func remoteCmdLoop(stdin io.Reader) func() {
+	done := make(chan struct{})
+	go func() {
+		defer close(done)
+		scanner := bufio.NewScanner(stdin)
+		for scanner.Scan() {
+			switch scanner.Text() {
+			case "stop":
+				rt.R().AppCycle().Stop()
+			case "forcestop":
+				fmt.Println("straight exit")
+				rt.R().AppCycle().ForceStop()
+			case "close":
+				return
+			}
+		}
+	}()
+	return func() { <-done }
+}
+
+// complexServerProgram demonstrates the recommended way to write a more
+// complex server application (with several servers, a mix of interruptible
+// and blocking cleanup, and parallel and sequential cleanup execution).
+// For a more typical server, see simpleServerProgram.
+func complexServerProgram(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+	// Initialize the runtime.  This is boilerplate.
+	r := rt.Init()
+
+	// This is part of the test setup -- we need a way to accept
+	// commands from the parent process to simulate Stop and
+	// RemoteStop commands that would normally be issued from
+	// application code.
+	go remoteCmdLoop(stdin)()
+
+	// r.Cleanup is optional, but it's a good idea to clean up, especially
+	// since it takes care of flushing the logs before exiting.
+	defer r.Cleanup()
+
+	// Create a couple servers, and start serving.
+	server1 := makeServer()
+	server2 := makeServer()
+
+	// This is how to wait for a shutdown.  In this example, a shutdown
+	// comes from a signal or a stop command.
+	var done sync.WaitGroup
+	done.Add(1)
+
+	// This is how to configure signal handling to allow clean shutdown.
+	sigChan := make(chan os.Signal, 2)
+	signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT)
+
+	// This is how to configure handling of stop commands to allow clean
+	// shutdown.
+	stopChan := make(chan string, 2)
+	r.AppCycle().WaitForStop(stopChan)
+
+	// Blocking is used to prevent the process from exiting upon receiving a
+	// second signal or stop command while critical cleanup code is
+	// executing.
+	var blocking sync.WaitGroup
+	blockingCh := make(chan struct{})
+
+	// This is how to wait for a signal or stop command and initiate the
+	// clean shutdown steps.
+	go func() {
+		// First signal received.
+		select {
+		case sig := <-sigChan:
+			// If the developer wants to take different actions
+			// depending on the type of signal, they can do it here.
+			fmt.Fprintln(stdout, "Received signal", sig)
+		case stop := <-stopChan:
+			fmt.Fprintln(stdout, "Stop", stop)
+		}
+		// This commences the cleanup stage.
+		done.Done()
+		// Wait for a second signal or stop command, and force an exit,
+		// but only once all blocking cleanup code (if any) has
+		// completed.
+		select {
+		case <-sigChan:
+		case <-stopChan:
+		}
+		<-blockingCh
+		os.Exit(1)
+	}()
+
+	// This communicates to the parent test driver process in our unit test
+	// that this server is ready and waiting on signals or stop commands.
+	// It's purely an artifact of our test setup.
+	fmt.Fprintln(stdout, "Ready")
+
+	// Wait for shutdown.
+	done.Wait()
+
+	// Stop the servers.  In this example we stop them in goroutines to
+	// parallelize the wait, but if there was a dependency between the
+	// servers, the developer can simply stop them sequentially.
+	var waitServerStop sync.WaitGroup
+	waitServerStop.Add(2)
+	go func() {
+		server1.Stop()
+		waitServerStop.Done()
+	}()
+	go func() {
+		server2.Stop()
+		waitServerStop.Done()
+	}()
+	waitServerStop.Wait()
+
+	// This is where all cleanup code should go.  By placing it at the end,
+	// we make its purpose and order of execution clear.
+
+	// This is an example of how to mix parallel and sequential cleanup
+	// steps.  Most real-world servers will likely be simpler, with either
+	// just sequential or just parallel cleanup stages.
+
+	// parallelCleanup is used to wait for all goroutines executing cleanup
+	// code in parallel to finish.
+	var parallelCleanup sync.WaitGroup
+
+	// Simulate four parallel cleanup steps, two blocking and two
+	// interruptible.
+	parallelCleanup.Add(1)
+	blocking.Add(1)
+	go func() {
+		fmt.Fprintln(stdout, "Parallel blocking cleanup1")
+		blocking.Done()
+		parallelCleanup.Done()
+	}()
+
+	parallelCleanup.Add(1)
+	blocking.Add(1)
+	go func() {
+		fmt.Fprintln(stdout, "Parallel blocking cleanup2")
+		blocking.Done()
+		parallelCleanup.Done()
+	}()
+
+	parallelCleanup.Add(1)
+	go func() {
+		fmt.Fprintln(stdout, "Parallel interruptible cleanup1")
+		parallelCleanup.Done()
+	}()
+
+	parallelCleanup.Add(1)
+	go func() {
+		fmt.Fprintln(stdout, "Parallel interruptible cleanup2")
+		parallelCleanup.Done()
+	}()
+
+	// Simulate two sequential cleanup steps, one blocking and one
+	// interruptible.
+	fmt.Fprintln(stdout, "Sequential blocking cleanup")
+	blocking.Wait()
+	close(blockingCh)
+
+	fmt.Fprintln(stdout, "Sequential interruptible cleanup")
+
+	parallelCleanup.Wait()
+	return nil
+}
+
+// simpleServerProgram demonstrates the recommended way to write a typical
+// simple server application (with one server and a clean shutdown triggered by
+// a signal or a stop command).  For an example of something more involved, see
+// complexServerProgram.
+func simpleServerProgram(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+	// Initialize the runtime.  This is boilerplate.
+	r := rt.Init()
+
+	// This is part of the test setup -- we need a way to accept
+	// commands from the parent process to simulate Stop and
+	// RemoteStop commands that would normally be issued from
+	// application code.
+	go remoteCmdLoop(stdin)()
+
+	// r.Cleanup is optional, but it's a good idea to clean up, especially
+	// since it takes care of flushing the logs before exiting.
+	//
+	// We use defer to ensure this is the last thing in the program (to
+	// avoid shutting down the runtime while it may still be in use), and to
+	// allow it to execute even if a panic occurs down the road.
+	defer r.Cleanup()
+
+	// Create a server, and start serving.
+	server := makeServer()
+
+	// This is how to wait for a shutdown.  In this example, a shutdown
+	// comes from a signal or a stop command.
+	//
+	// Note, if the developer wants to exit immediately upon receiving a
+	// signal or stop command, they can skip this, in which case the default
+	// behavior is for the process to exit.
+	waiter := signals.ShutdownOnSignals()
+
+	// This communicates to the parent test driver process in our unit test
+	// that this server is ready and waiting on signals or stop commands.
+	// It's purely an artifact of our test setup.
+	fmt.Fprintln(stdout, "Ready")
+
+	// Use defer for anything that should still execute even if a panic
+	// occurs.
+	defer fmt.Fprintln(stdout, "Deferred cleanup")
+
+	// Wait for shutdown.
+	sig := <-waiter
+	// The developer could take different actions depending on the type of
+	// signal.
+	fmt.Fprintln(stdout, "Received signal", sig)
+
+	// Cleanup code starts here.  Alternatively, these steps could be
+	// invoked through defer, but we list them here to make the order of
+	// operations obvious.
+
+	// Stop the server.
+	server.Stop()
+
+	// Note, this will not execute in cases of forced shutdown
+	// (e.g. SIGSTOP), when the process calls os.Exit (e.g. via log.Fatal),
+	// or when a panic occurs.
+	fmt.Fprintln(stdout, "Interruptible cleanup")
+
+	return nil
+}
diff --git a/runtimes/google/rt/shutdown_test.go b/runtimes/google/rt/shutdown_test.go
new file mode 100644
index 0000000..f0a57aa
--- /dev/null
+++ b/runtimes/google/rt/shutdown_test.go
@@ -0,0 +1,228 @@
+package rt_test
+
+import (
+	"fmt"
+	"io"
+	"os"
+	"syscall"
+	"testing"
+	"time"
+
+	"veyron.io/veyron/veyron2"
+
+	"veyron.io/veyron/veyron/lib/expect"
+	"veyron.io/veyron/veyron/lib/modules"
+	"veyron.io/veyron/veyron/lib/signals"
+	"veyron.io/veyron/veyron/lib/testutil"
+)
+
+var cstderr io.Writer
+
+func init() {
+	testutil.Init()
+	if testing.Verbose() {
+		cstderr = os.Stderr
+	}
+}
+
+// TestSimpleServerSignal verifies that sending a signal to the simple server
+// causes it to exit cleanly.
+func TestSimpleServerSignal(t *testing.T) {
+	sh := modules.NewShell()
+	defer sh.Cleanup(os.Stdout, cstderr)
+	h, _ := sh.Start("simpleServerProgram", nil)
+	s := expect.NewSession(t, h.Stdout(), time.Minute)
+	s.Expect("Ready")
+	syscall.Kill(h.Pid(), syscall.SIGINT)
+	s.Expect("Received signal interrupt")
+	s.Expect("Interruptible cleanup")
+	s.Expect("Deferred cleanup")
+	fmt.Fprintln(h.Stdin(), "close")
+	s.ExpectEOF()
+}
+
+// TestSimpleServerLocalStop verifies that sending a local stop command to the
+// simple server causes it to exit cleanly.
+func TestSimpleServerLocalStop(t *testing.T) {
+	sh := modules.NewShell()
+	defer sh.Cleanup(os.Stdout, cstderr)
+	h, _ := sh.Start("simpleServerProgram", nil)
+	s := expect.NewSession(t, h.Stdout(), time.Minute)
+	s.Expect("Ready")
+	fmt.Fprintln(h.Stdin(), "stop")
+	s.Expect(fmt.Sprintf("Received signal %s", veyron2.LocalStop))
+	s.Expect("Interruptible cleanup")
+	s.Expect("Deferred cleanup")
+	fmt.Fprintln(h.Stdin(), "close")
+	s.ExpectEOF()
+}
+
+// TestSimpleServerDoubleSignal verifies that sending a succession of two
+// signals to the simple server causes it to initiate the cleanup sequence on
+// the first signal and then exit immediately on the second signal.
+func TestSimpleServerDoubleSignal(t *testing.T) {
+	sh := modules.NewShell()
+	defer sh.Cleanup(os.Stdout, cstderr)
+	h, _ := sh.Start("simpleServerProgram", nil)
+	s := expect.NewSession(t, h.Stdout(), time.Minute)
+	s.Expect("Ready")
+	syscall.Kill(h.Pid(), syscall.SIGINT)
+	s.Expect("Received signal interrupt")
+	syscall.Kill(h.Pid(), syscall.SIGINT)
+	err := h.Shutdown(os.Stdout, cstderr)
+	if err == nil {
+		t.Fatalf("expected an error")
+	}
+	if got, want := err.Error(), fmt.Sprintf("exit status %d", signals.DoubleStopExitCode); got != want {
+		t.Errorf("got %q, want %q", got, want)
+	}
+}
+
+// TestSimpleServerLocalForceStop verifies that sending a local ForceStop
+// command to the simple server causes it to exit immediately.
+func TestSimpleServerLocalForceStop(t *testing.T) {
+	sh := modules.NewShell()
+	defer sh.Cleanup(os.Stdout, cstderr)
+	h, _ := sh.Start("simpleServerProgram", nil)
+	s := expect.NewSession(t, h.Stdout(), time.Minute)
+	s.Expect("Ready")
+	fmt.Fprintln(h.Stdin(), "forcestop")
+	s.Expect("straight exit")
+	err := h.Shutdown(os.Stdout, cstderr)
+	if err == nil {
+		t.Fatalf("expected an error")
+	}
+	if got, want := err.Error(), fmt.Sprintf("exit status %d", veyron2.ForceStopExitCode); got != want {
+		t.Errorf("got %q, want %q", got, want)
+	}
+}
+
+// TestSimpleServerKill demonstrates that a SIGKILL still forces the server
+// to exit regardless of our signal handling.
+func TestSimpleServerKill(t *testing.T) {
+	sh := modules.NewShell()
+	defer sh.Cleanup(os.Stdout, cstderr)
+	h, _ := sh.Start("simpleServerProgram", nil)
+	s := expect.NewSession(t, h.Stdout(), time.Minute)
+	s.Expect("Ready")
+	syscall.Kill(h.Pid(), syscall.SIGKILL)
+	err := h.Shutdown(os.Stdout, cstderr)
+	if err == nil {
+		t.Fatalf("expected an error")
+	}
+	if got, want := err.Error(), "signal: killed"; got != want {
+		t.Errorf("got %q, want %q", got, want)
+	}
+}
+
+// TestComplexServerSignal verifies that sending a signal to the complex server
+// initiates the cleanup sequence in that server (we observe the printouts
+// corresponding to all the simulated sequential/parallel and
+// blocking/interruptible shutdown steps), and then exits cleanly.
+func TestComplexServerSignal(t *testing.T) {
+	sh := modules.NewShell()
+	defer sh.Cleanup(os.Stdout, cstderr)
+	h, _ := sh.Start("complexServerProgram", nil)
+	s := expect.NewSession(t, h.Stdout(), time.Minute)
+	s.Expect("Ready")
+	syscall.Kill(h.Pid(), syscall.SIGINT)
+	s.Expect("Received signal interrupt")
+	s.ExpectSetRE("Sequential blocking cleanup",
+		"Sequential interruptible cleanup",
+		"Parallel blocking cleanup1",
+		"Parallel blocking cleanup2",
+		"Parallel interruptible cleanup1",
+		"Parallel interruptible cleanup2")
+	fmt.Fprintln(h.Stdin(), "close")
+	s.ExpectEOF()
+}
+
+// TestComplexServerLocalStop verifies that sending a local stop command to the
+// complex server initiates the cleanup sequence in that server (we observe the
+// printouts corresponding to all the simulated sequential/parallel and
+// blocking/interruptible shutdown steps), and then exits cleanly.
+func TestComplexServerLocalStop(t *testing.T) {
+	sh := modules.NewShell()
+	defer sh.Cleanup(os.Stdout, cstderr)
+	h, _ := sh.Start("complexServerProgram", nil)
+	s := expect.NewSession(t, h.Stdout(), time.Minute)
+	s.Expect("Ready")
+
+	fmt.Fprintln(h.Stdin(), "stop")
+	s.Expect(fmt.Sprintf("Stop %s", veyron2.LocalStop))
+	s.ExpectSetRE(
+		"Sequential blocking cleanup",
+		"Sequential interruptible cleanup",
+		"Parallel blocking cleanup1",
+		"Parallel blocking cleanup2",
+		"Parallel interruptible cleanup1",
+		"Parallel interruptible cleanup2",
+	)
+	fmt.Fprintln(h.Stdin(), "close")
+	s.ExpectEOF()
+}
+
+// TestComplexServerDoubleSignal verifies that sending a succession of two
+// signals to the complex server has the expected effect: the first signal
+// initiates the cleanup steps and the second signal kills the process, but only
+// after the blocking shutdown steps were allowed to complete (as observed by
+// the corresponding printouts from the server).  Note that we have no
+// expectations on whether or not the interruptible shutdown steps execute.
+func TestComplexServerDoubleSignal(t *testing.T) {
+	sh := modules.NewShell()
+	defer sh.Cleanup(os.Stdout, cstderr)
+	h, _ := sh.Start("complexServerProgram", nil)
+	s := expect.NewSession(t, h.Stdout(), time.Minute)
+	s.Expect("Ready")
+	syscall.Kill(h.Pid(), syscall.SIGINT)
+	s.Expect("Received signal interrupt")
+	syscall.Kill(h.Pid(), syscall.SIGINT)
+	s.ExpectSetEventuallyRE(
+		"Sequential blocking cleanup",
+		"Parallel blocking cleanup1",
+		"Parallel blocking cleanup2")
+	err := h.Shutdown(os.Stdout, cstderr)
+	if err == nil {
+		t.Fatalf("expected an error")
+	}
+	if got, want := err.Error(), fmt.Sprintf("exit status %d", signals.DoubleStopExitCode); got != want {
+		t.Errorf("got %q, want %q", got, want)
+	}
+}
+
+// TestComplexServerLocalForceStop verifies that sending a local ForceStop
+// command to the complex server forces it to exit immediately.
+func TestComplexServerLocalForceStop(t *testing.T) {
+	sh := modules.NewShell()
+	defer sh.Cleanup(os.Stdout, cstderr)
+	h, _ := sh.Start("complexServerProgram", nil)
+	s := expect.NewSession(t, h.Stdout(), time.Minute)
+	s.Expect("Ready")
+	fmt.Fprintln(h.Stdin(), "forcestop")
+	s.Expect("straight exit")
+	err := h.Shutdown(os.Stdout, cstderr)
+	if err == nil {
+		t.Fatalf("expected an error")
+	}
+	if got, want := err.Error(), fmt.Sprintf("exit status %d", veyron2.ForceStopExitCode); got != want {
+		t.Errorf("got %q, want %q", got, want)
+	}
+}
+
+// TestComplexServerKill demonstrates that a SIGKILL still forces the server to
+// exit regardless of our signal handling.
+func TestComplexServerKill(t *testing.T) {
+	sh := modules.NewShell()
+	defer sh.Cleanup(os.Stdout, cstderr)
+	h, _ := sh.Start("complexServerProgram", nil)
+	s := expect.NewSession(t, h.Stdout(), time.Minute)
+	s.Expect("Ready")
+	syscall.Kill(h.Pid(), syscall.SIGKILL)
+	err := h.Shutdown(os.Stdout, cstderr)
+	if err == nil {
+		t.Fatalf("expected an error")
+	}
+	if got, want := err.Error(), "signal: killed"; got != want {
+		t.Errorf("got %q, want %q", got, want)
+	}
+}
diff --git a/runtimes/google/rt/signal.go b/runtimes/google/rt/signal.go
index fc13847..0e5d607 100644
--- a/runtimes/google/rt/signal.go
+++ b/runtimes/google/rt/signal.go
@@ -4,6 +4,7 @@
 	"os"
 	"os/signal"
 	"syscall"
+
 	"veyron.io/veyron/veyron2/vlog"
 )
 
diff --git a/security/testdata/blessingstore.sig b/security/testdata/blessingstore.sig
index 2f2a57c..1040fb8 100644
--- a/security/testdata/blessingstore.sig
+++ b/security/testdata/blessingstore.sig
Binary files differ