func TestSubscribeConsecutively(t *testing.T) {
	maybeSkipIntegrationTest(t)
	s, err := NewSession()
	if err != nil {
		t.Fatalf("Failed to create session: %v", err)
	}
	defer s.Close()
	if err := s.Subscribe("ike-updown", "child-updown"); err != nil {
		t.Fatalf("Unexpected error subscribing for events: %v", err)
	}
	if !reflect.DeepEqual(s.el.events, []string{"ike-updown", "child-updown"}) {
		t.Fatalf("Expected to find ike-updown and child-updown registered, got: %v", s.el.events)
	}
	if err := s.Subscribe("child-updown", "log", "ike-updown"); err != nil {
		t.Fatalf("Unexpected error subscribing for additional events: %v", err)
	}
	if !reflect.DeepEqual(s.el.events, []string{"ike-updown", "child-updown", "log"}) {
		t.Fatalf("Expected to find ike-updown and child-updown registered, got: %v", s.el.events)
	}
}
TestSubscribeConsecutively ensures that consecutive calls to subscribe
registers only NEW events to the event listener.
package vici
import (
	"context"
	"flag"
	"log"
	"net"
	"os/exec"
	"reflect"
	"testing"
	"time"
)
func mockCharon(ctx context.Context) net.Conn {
	client, srvr := net.Pipe()
	go func() {
		defer func() {
			srvr.Close()
		}()
		tr := &transport{conn: srvr}
		for {
			select {
			case <-ctx.Done():
				return
			default:
				break
			}
			p, err := tr.recv()
			if err != nil {
				return
			}
			switch p.ptype {
			case pktEventRegister, pktEventUnregister:
				var ack *packet
				if p.name != "test-event" {
					ack = newPacket(pktEventUnknown, "", nil)
				} else {
					ack = newPacket(pktEventConfirm, "", nil)
				}
				err := tr.send(ack)
				if err != nil {
					return
				}
				if p.ptype == pktEventRegister && ack.ptype == pktEventConfirm {
					msg := NewMessage()
					err := msg.Set("test", "hello world!")
					if err != nil {
						log.Printf("Failed to set message field: %v", err)
					}
					event := newPacket(pktEvent, "test-event", msg)
					err = tr.send(event)
					if err != nil {
						log.Printf("Failed to send test-event message: %v", err)
					}
				}
			default:
				continue
			}
		}
	}()
	return client
}
func TestSubscribeAndCloseSession(t *testing.T) {
	dctx, dcancel := context.WithCancel(context.Background())
	defer dcancel()
	conn := mockCharon(dctx)
	s, err := NewSession(withTestConn(conn))
	if err != nil {
		t.Fatalf("Failed to create session: %v", err)
	}
	defer s.Close()
	err = s.Subscribe("test-event")
	if err != nil {
		t.Fatalf("Failed to start event listener: %v", err)
	}
	e, err := s.NextEvent(context.TODO())
	if err != nil {
		t.Fatalf("Unexpected error on NextEvent: %v", err)
	}
	if e.Message.Get("test") != "hello world!" {
		t.Fatalf("Unexpected message: %v", e)
	}
	s.Close()
	e, err = s.NextEvent(context.TODO())
	if err == nil {
		t.Fatalf("Expected error after closing listener, got message: %v", e)
	}
}
func TestSessionClose(t *testing.T) {
	conn, _ := net.Pipe()
	s, err := NewSession(withTestConn(conn))
	if err != nil {
		t.Fatalf("Failed to create session: %v", err)
	}
	if err := s.Close(); err != nil {
		t.Fatalf("Unpexected error when closing Session: %v", err)
	}
}
func TestIdempotentSessionClose(t *testing.T) {
	conn, _ := net.Pipe()
	s, err := NewSession(withTestConn(conn))
	if err != nil {
		t.Fatalf("Failed to create session: %v", err)
	}
	if err := s.Close(); err != nil {
		t.Fatalf("Unpexected error when closing Session (first close): %v", err)
	}
	if err := s.Close(); err != nil {
		t.Fatalf("Unpexected error when closing Session (second close): %v", err)
	}
}
var (
	doIntegrationTests = flag.Bool("integration", false, "Run integration tests that require charon")
)
func maybeSkipIntegrationTest(t *testing.T) {
	if !*doIntegrationTests {
		t.Skip("Skipping integration test.")
	}
}
func TestCommandRequest(t *testing.T) {
	maybeSkipIntegrationTest(t)
	s, err := NewSession()
	if err != nil {
		t.Fatalf("Failed to create a session: %v", err)
	}
	defer s.Close()
	resp, err := s.CommandRequest("version", nil)
	if err != nil {
		t.Fatalf("Failed to get charon version information: %v", err)
	}
	if d := resp.Get("daemon"); d == "" {
		t.Fatal("Expected non-empty value at key 'daemon'")
	}
}
func TestStreamedCommandRequest(t *testing.T) {
	maybeSkipIntegrationTest(t)
	s, err := NewSession()
	if err != nil {
		t.Fatalf("Failed to create a session: %v", err)
	}
	defer s.Close()
	ms, err := s.StreamedCommandRequest("list-authorities", "list-authority", nil)
	if err != nil {
		t.Fatalf("Failed to list authorities: %v", err)
	}
	for i, m := range ms.Messages() {
		if m.Err() != nil {
			t.Fatalf("Got error in message #%d: %v", i+1, m.Err())
		}
	}
}
func TestSubscribeWhenAlreadyActive(t *testing.T) {
	maybeSkipIntegrationTest(t)
	s, err := NewSession()
	if err != nil {
		t.Fatalf("Failed to create session: %v", err)
	}
	defer s.Close()
	if err := s.Subscribe("control-log"); err != nil {
		t.Fatalf("Failed to start event listener: %v", err)
	}
	if err := s.Subscribe("log"); err != nil {
		t.Fatalf("Failed to subscribe to additional events: %v", err)
	}
}
func TestCloseWithActiveNextEvent(t *testing.T) {
	maybeSkipIntegrationTest(t)
	s, err := NewSession()
	if err != nil {
		t.Fatalf("Failed to create session: %v", err)
	}
	if err := s.Subscribe("ike-updown"); err != nil {
		t.Fatalf("Failed to start event listener: %v", err)
	}
	done := make(chan struct{}, 1)
	go func() {
		defer close(done)
		_, err := s.NextEvent(context.TODO())
		if err == nil {
			t.Errorf("Expected error when reading event from closed listener")
		}
	}()
	<-time.After(3 * time.Second)
	if err := s.Close(); err != nil {
		t.Fatalf("Unexpected error closing session: %v", err)
	}
	<-done
}
func TestEventNameIsSet(t *testing.T) {
	maybeSkipIntegrationTest(t)
	s, err := NewSession()
	if err != nil {
		t.Fatalf("Failed to create session: %v", err)
	}
	defer s.Close()
	if err := s.Subscribe("log"); err != nil {
		t.Fatalf("Failed to start event listener: %v", err)
	}
	if _, err := s.CommandRequest("reload-settings", nil); err != nil {
		t.Fatalf("Failed to send 'reload-settings' command: %v", err)
	}
	e, err := s.NextEvent(context.TODO())
	if err != nil {
		t.Fatalf("Unexpected error waiting for event: %v", err)
	}
	if e.Name != "log" {
		t.Fatalf("Expected to receive 'log' event, got %s", e.Name)
	}
}
func TestNextEventCancel(t *testing.T) {
	maybeSkipIntegrationTest(t)
	s, err := NewSession()
	if err != nil {
		t.Fatalf("Failed to create session: %v", err)
	}
	defer s.Close()
	if err := s.Subscribe("ike-updown"); err != nil {
		t.Fatalf("Failed to start event listener: %v", err)
	}
	ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
	defer cancel()
	_, err = s.NextEvent(ctx)
	if err != ctx.Err() {
		t.Fatalf("Expected to get context's timeout error after not receiving event, got: %v", err)
	}
}