func TestSynLowId(t *testing.T) {
	t.Parallel()

	local, remote := newFakeConnPair()

	// don't need the remote output
	remote.Discard()

	// true for a client session
	s := NewSession(local, fakeStreamFactory, true, []Extension{})

	// Start a stream
	f := frame.NewWStreamSyn()
	f.Set(302, 0, 0, false)

	// send the frame into the session
	trans := frame.NewBasicTransport(remote)
	trans.WriteFrame(f)

	// accept it
	s.Accept()

	// Start a closed stream at a lower id number
	f.Set(300, 0, 0, false)

	// send the frame into the session
	trans.WriteFrame(f)

	code, err, _ := s.Wait()
	if code != frame.ProtocolError {
		t.Errorf("Session not terminated with protocol error, got %d expected %d. Error: %v", code, frame.ProtocolError, err)
	}
}
func TestWrongServerParity(t *testing.T) {
	t.Parallel()

	local, remote := newFakeConnPair()

	// true for a client session
	s := NewSession(local, fakeStreamFactory, true, []Extension{})

	// don't need the remote output
	remote.Discard()

	// 300 is even, and only servers send even stream ids
	f := frame.NewWStreamSyn()
	f.Set(301, 0, 0, false)

	// send the frame into the session
	trans := frame.NewBasicTransport(remote)
	trans.WriteFrame(f)

	// wait for failure
	code, err, _ := s.Wait()

	if code != frame.ProtocolError {
		t.Errorf("Session not terminated with protocol error. Got %d, expected %d. Session error: %v", code, frame.ProtocolError, err)
	}

	if !local.closed {
		t.Errorf("Session transport not closed after protocol failure.")
	}
}
func TestDataAfterRst(t *testing.T) {
	local, remote := newFakeConnPair()

	_ = NewSession(local, NewStream, false, []Extension{})
	trans := frame.NewBasicTransport(remote)

	// make sure that we get an RST STREAM_CLOSED
	done := make(chan int)
	go func() {
		defer func() { done <- 1 }()

		f, err := trans.ReadFrame()
		if err != nil {
			t.Errorf("Failed to read frame sent from session: %v", err)
			return
		}

		fr, ok := f.(*frame.RStreamRst)
		if !ok {
			t.Errorf("Frame is not STREAM_RST: %v", f)
			return
		}

		if fr.ErrorCode() != frame.StreamClosed {
			t.Errorf("Error code on STREAM_RST is not STREAM_CLOSED. Got %d, expected %d", fr.ErrorCode(), frame.StreamClosed)
			return
		}
	}()

	fSyn := frame.NewWStreamSyn()
	if err := fSyn.Set(301, 0, 0, false); err != nil {
		t.Fatalf("Failed to make syn frame: %v", err)
	}

	if err := trans.WriteFrame(fSyn); err != nil {
		t.Fatalf("Failed to send syn: %v", err)
	}

	fRst := frame.NewWStreamRst()
	if err := fRst.Set(301, frame.Cancel); err != nil {
		t.Fatal("Failed to make rst frame: %v", err)
	}

	if err := trans.WriteFrame(fRst); err != nil {
		t.Fatalf("Failed to write rst frame: %v", err)
	}

	fData := frame.NewWStreamData()
	if err := fData.Set(301, []byte{0xa, 0xFF}, false); err != nil {
		t.Fatalf("Failed to set data frame")
	}

	trans.WriteFrame(fData)

	<-done
}
func TestFlowControlError(t *testing.T) {
	local, remote := newFakeConnPair()

	s := NewSession(local, NewStream, false, []Extension{})
	s.(*Session).defaultWindowSize = 10
	trans := frame.NewBasicTransport(remote)

	// make sure that we get an RST FLOW_CONTROL_ERROR
	done := make(chan int)
	go func() {
		defer func() { done <- 1 }()

		f, err := trans.ReadFrame()
		if err != nil {
			t.Errorf("Failed to read frame sent from session: %v", err)
			return
		}

		fr, ok := f.(*frame.RStreamRst)
		if !ok {
			t.Errorf("Frame is not STREAM_RST: %v", f)
			return
		}

		if fr.ErrorCode() != frame.FlowControlError {
			t.Errorf("Error code on STREAM_RST is not FLOW_CONTROL_ERROR. Got %d, expected %d", fr.ErrorCode(), frame.FlowControlError)
			return
		}
	}()

	fSyn := frame.NewWStreamSyn()
	if err := fSyn.Set(301, 0, 0, false); err != nil {
		t.Fatalf("Failed to make syn frame: %v", err)
	}

	if err := trans.WriteFrame(fSyn); err != nil {
		t.Fatalf("Failed to send syn: %v", err)
	}

	fData := frame.NewWStreamData()
	if err := fData.Set(301, make([]byte, 11), false); err != nil {
		t.Fatalf("Failed to set data frame")
	}

	trans.WriteFrame(fData)

	<-done
}
func TestAcceptStream(t *testing.T) {
	t.Parallel()

	local, remote := newFakeConnPair()

	// don't need the remote output
	remote.Discard()

	// true for a client session
	s := NewSession(local, NewStream, true, []Extension{})
	defer s.Close()

	f := frame.NewWStreamSyn()
	f.Set(300, 0, 0, false)

	// send the frame into the session
	trans := frame.NewBasicTransport(remote)
	trans.WriteFrame(f)

	done := make(chan int)
	go func() {
		defer func() { done <- 1 }()

		// wait for accept
		str, err := s.Accept()

		if err != nil {
			t.Errorf("Error accepting stream: %v", err)
			return
		}

		if str.Id() != frame.StreamId(300) {
			t.Errorf("Stream has wrong id. Expected %d, got %d", str.Id(), 300)
		}
	}()

	select {
	case <-time.After(time.Second):
		t.Fatalf("Timed out!")
	case <-done:
	}
}