func TestRealtimeChannel_Publish(t *testing.T) {
	t.Parallel()
	app, client := testutil.ProvisionRealtime(nil, nil)
	defer safeclose(t, client, app)

	channel := client.Channels.Get("test")
	if err := wait(channel.Publish("hello", "world")); err != nil {
		t.Fatalf("Publish()=%v", err)
	}
}
func TestRealtimeConn_AlreadyConnected(t *testing.T) {
	app, client := testutil.ProvisionRealtime(nil, &ably.ClientOptions{NoConnect: true})
	defer safeclose(t, client, app)

	if err := wait(client.Connection.Connect()); err != nil {
		t.Fatalf("Connect=%s", err)
	}
	if err := wait(client.Connection.Connect()); err != nil {
		t.Fatalf("Connect=%s", err)
	}
}
func TestRealtimeChannel_Close(t *testing.T) {
	rec := ably.NewStateRecorder(8)
	app, client := testutil.ProvisionRealtime(nil, &ably.ClientOptions{Listener: rec.Channel()})
	defer safeclose(t, client, app)

	channel := client.Channels.Get("test")
	sub, err := channel.Subscribe()
	if err != nil {
		t.Fatalf("channel.Subscribe()=%v", err)
	}
	defer sub.Close()
	if err := wait(channel.Publish("hello", "world")); err != nil {
		t.Fatalf("channel.Publish()=%v", err)
	}
	done := make(chan error)
	go func() {
		msg, ok := <-sub.MessageChannel()
		if !ok {
			done <- errors.New("did not receive published message")
		}
		if msg.Name != "hello" || msg.Data != "world" {
			done <- fmt.Errorf(`want name="hello", data="world"; got %s, %s`, msg.Name, msg.Data)
		}
		if _, ok = <-sub.MessageChannel(); ok {
			done <- fmt.Errorf("expected channel to be closed")
		}
		done <- nil
	}()
	if err := channel.Close(); err != nil {
		t.Fatalf("channel.Close()=%v", err)
	}
	if err := client.Close(); err != nil {
		t.Fatalf("client.Close()=%v", err)
	}
	select {
	case err := <-done:
		if err != nil {
			t.Fatalf("waiting on subscribed channel close failed: err=%s", err)
		}
	case <-time.After(timeout):
		t.Fatalf("waiting on subscribed channel close timed out after %v", timeout)
	}
	rec.Stop()
	states := rec.States()
	for _, expected := range chanCloseTransitions {
		if reflect.DeepEqual(states, expected) {
			return
		}
	}
	t.Fatalf("unexpected state transitions %v", states)
}
func TestRealtimeConn_Connect(t *testing.T) {
	rec := ably.NewStateRecorder(4)
	app, client := testutil.ProvisionRealtime(nil, &ably.ClientOptions{Listener: rec.Channel()})
	defer safeclose(t, client, app)

	if err := await(client.Connection.State, ably.StateConnConnected); err != nil {
		t.Fatal(err)
	}
	if err := client.Close(); err != nil {
		t.Fatalf("client.Close()=%v", err)
	}
	rec.Stop()
	if states := rec.States(); !reflect.DeepEqual(states, connTransitions) {
		t.Errorf("expected states=%v; got %v", connTransitions, states)
	}
}
func TestRealtimeChannel_Subscribe(t *testing.T) {
	t.Parallel()
	app, client1 := testutil.ProvisionRealtime(nil, nil)
	defer safeclose(t, client1, app)
	client2, err := ably.NewRealtimeClient(app.Options(&ably.ClientOptions{NoEcho: true}))
	if err != nil {
		t.Fatalf("client2: NewRealtimeClient()=%v", err)
	}
	defer safeclose(t, client2)

	channel1 := client1.Channels.Get("test")
	sub1, err := channel1.Subscribe()
	if err != nil {
		t.Fatalf("client1: Subscribe()=%v", err)
	}
	defer sub1.Close()

	channel2 := client2.Channels.Get("test")
	sub2, err := channel2.Subscribe()
	if err != nil {
		t.Fatalf("client2: Subscribe()=%v", err)
	}
	defer sub2.Close()

	if err := wait(channel1.Publish("hello", "client1")); err != nil {
		t.Fatalf("client1: Publish()=%v", err)
	}
	if err := wait(channel2.Publish("hello", "client2")); err != nil {
		t.Fatalf("client2: Publish()=%v", err)
	}

	timeout := 15 * time.Second

	if err := expectMsg(sub1.MessageChannel(), "hello", "client1", timeout, true); err != nil {
		t.Fatal(err)
	}
	if err := expectMsg(sub1.MessageChannel(), "hello", "client2", timeout, true); err != nil {
		t.Fatal(err)
	}
	if err := expectMsg(sub2.MessageChannel(), "hello", "client1", timeout, true); err != nil {
		t.Fatal(err)
	}
	if err := expectMsg(sub2.MessageChannel(), "hello", "client2", timeout, false); err != nil {
		t.Fatal(err)
	}
}