github.com/anycable/anycable-go@v1.5.1/streams/controller_test.go (about)

     1  package streams
     2  
     3  import (
     4  	"fmt"
     5  	"log/slog"
     6  	"testing"
     7  
     8  	"github.com/anycable/anycable-go/common"
     9  	"github.com/stretchr/testify/assert"
    10  	"github.com/stretchr/testify/require"
    11  )
    12  
    13  const (
    14  	key = "s3Krit"
    15  	// Turbo.signed_stream_verifier_key = 's3Krit'
    16  	// Turbo::StreamsChannel.signed_stream_name([:chat, "2021"])
    17  	stream = "ImNoYXQ6MjAyMSI=--f9ee45dbccb1da04d8ceb99cc820207804370ba0d06b46fc3b8b373af1315628"
    18  )
    19  
    20  func TestNewController(t *testing.T) {
    21  	t.Run("No stream name", func(t *testing.T) {
    22  		resolver := func(string) (*SubscribeRequest, error) {
    23  			return &SubscribeRequest{}, nil
    24  		}
    25  
    26  		subject := NewController(key, resolver, slog.Default())
    27  
    28  		require.NotNil(t, subject)
    29  
    30  		res, err := subject.Subscribe("42", nil, "name=jack", "")
    31  
    32  		require.Error(t, err)
    33  		require.NotNil(t, res)
    34  
    35  		assert.Equal(t, common.FAILURE, res.Status)
    36  		assert.Equal(t, []string{common.RejectionMessage("")}, res.Transmissions)
    37  	})
    38  }
    39  
    40  func TestStreamsController(t *testing.T) {
    41  	t.Run("Subscribe - public", func(t *testing.T) {
    42  		conf := NewConfig()
    43  		conf.Public = true
    44  		subject := NewStreamsController(&conf, slog.Default())
    45  
    46  		require.NotNil(t, subject)
    47  
    48  		res, err := subject.Subscribe("42", nil, "name=jack", `{"channel":"$pubsub","stream_name":"chat:2024"}`)
    49  
    50  		require.NoError(t, err)
    51  		require.NotNil(t, res)
    52  		require.Equal(t, common.SUCCESS, res.Status)
    53  		assert.Equal(t, []string{common.ConfirmationMessage(`{"channel":"$pubsub","stream_name":"chat:2024"}`)}, res.Transmissions)
    54  		assert.Equal(t, []string{"chat:2024"}, res.Streams)
    55  		assert.Equal(t, -1, res.DisconnectInterest)
    56  		assert.Equal(t, "chat:2024", res.IState[common.WHISPER_STREAM_STATE])
    57  	})
    58  
    59  	t.Run("Subscribe - no public allowed", func(t *testing.T) {
    60  		conf := NewConfig()
    61  		subject := NewStreamsController(&conf, slog.Default())
    62  
    63  		require.NotNil(t, subject)
    64  
    65  		res, err := subject.Subscribe("42", nil, "name=jack", `{"channel":"$pubsub","stream_name":"chat:2024"}`)
    66  
    67  		require.Error(t, err)
    68  		require.NotNil(t, res)
    69  		assert.Equal(t, []string{common.RejectionMessage(`{"channel":"$pubsub","stream_name":"chat:2024"}`)}, res.Transmissions)
    70  	})
    71  
    72  	t.Run("Subscribe - signed", func(t *testing.T) {
    73  		conf := NewConfig()
    74  		conf.Secret = key
    75  		subject := NewStreamsController(&conf, slog.Default())
    76  
    77  		require.NotNil(t, subject)
    78  
    79  		identifier := `{"channel":"$pubsub","signed_stream_name":"` + stream + `"}`
    80  
    81  		res, err := subject.Subscribe("42", nil, "name=jack", identifier)
    82  
    83  		require.NoError(t, err)
    84  		require.NotNil(t, res)
    85  		require.Equal(t, common.SUCCESS, res.Status)
    86  		assert.Equal(t, []string{common.ConfirmationMessage(identifier)}, res.Transmissions)
    87  		assert.Equal(t, []string{"chat:2021"}, res.Streams)
    88  		assert.Equal(t, -1, res.DisconnectInterest)
    89  		assert.Nil(t, res.IState)
    90  	})
    91  
    92  	t.Run("Subscribe - signed - whisper", func(t *testing.T) {
    93  		conf := NewConfig()
    94  		conf.Secret = key
    95  		conf.Whisper = true
    96  		subject := NewStreamsController(&conf, slog.Default())
    97  
    98  		require.NotNil(t, subject)
    99  
   100  		identifier := `{"channel":"$pubsub","signed_stream_name":"` + stream + `"}`
   101  
   102  		res, err := subject.Subscribe("42", nil, "name=jack", identifier)
   103  
   104  		require.NoError(t, err)
   105  		require.NotNil(t, res)
   106  		require.Equal(t, common.SUCCESS, res.Status)
   107  		assert.Equal(t, []string{common.ConfirmationMessage(identifier)}, res.Transmissions)
   108  		assert.Equal(t, []string{"chat:2021"}, res.Streams)
   109  		assert.Equal(t, -1, res.DisconnectInterest)
   110  		assert.Equal(t, "chat:2021", res.IState[common.WHISPER_STREAM_STATE])
   111  	})
   112  }
   113  
   114  func TestTurboController(t *testing.T) {
   115  	env := common.NewSessionEnv("ws://demo.anycable.io/cable", &map[string]string{"cookie": "val=1;"})
   116  	subject := NewTurboController(key, slog.Default())
   117  
   118  	t.Run("Subscribe (success)", func(t *testing.T) {
   119  		channel := fmt.Sprintf("{\"channel\":\"Turbo::StreamsChannel\",\"signed_stream_name\":\"%s\"}", stream)
   120  
   121  		res, err := subject.Subscribe("42", env, "name=jack", channel)
   122  
   123  		require.NoError(t, err)
   124  		require.NotNil(t, res)
   125  		require.Equal(t, common.SUCCESS, res.Status)
   126  		assert.Equal(t, []string{common.ConfirmationMessage(channel)}, res.Transmissions)
   127  		assert.Equal(t, []string{"chat:2021"}, res.Streams)
   128  		assert.Equal(t, -1, res.DisconnectInterest)
   129  	})
   130  
   131  	t.Run("Subscribe (failure)", func(t *testing.T) {
   132  		channel := fmt.Sprintf("{\"channel\":\"Turbo::StreamsChannel\",\"signed_stream_name\":\"%s\"}", "fake_id")
   133  
   134  		res, err := subject.Subscribe("42", env, "name=jack", channel)
   135  
   136  		require.NoError(t, err)
   137  		require.NotNil(t, res)
   138  		require.Equal(t, common.FAILURE, res.Status)
   139  		assert.Equal(t, []string{common.RejectionMessage(channel)}, res.Transmissions)
   140  	})
   141  
   142  	t.Run("Subscribe (failure + not a string)", func(t *testing.T) {
   143  		signed := "WyJjaGF0LzIwMjMiLDE2ODUwMjQwMTdd--5b6661024d4c463c4936cd1542bc9a7672dd8039ac407d0b6c901697190e8aeb"
   144  		channel := fmt.Sprintf("{\"channel\":\"Turbo::StreamsChannel\",\"signed_stream_name\":\"%s\"}", signed)
   145  
   146  		res, err := subject.Subscribe("42", env, "name=jack", channel)
   147  
   148  		require.NoError(t, err)
   149  		require.NotNil(t, res)
   150  		require.Equal(t, common.FAILURE, res.Status)
   151  		assert.Equal(t, []string{common.RejectionMessage(channel)}, res.Transmissions)
   152  	})
   153  
   154  	t.Run("Unsubscribe", func(t *testing.T) {
   155  		channel := fmt.Sprintf("{\"channel\":\"Turbo::StreamsChannel\",\"signed_stream_name\":\"%s\"}", stream)
   156  
   157  		res, err := subject.Unsubscribe("42", env, "name=jack", channel)
   158  
   159  		require.NoError(t, err)
   160  		require.NotNil(t, res)
   161  		require.Equal(t, common.SUCCESS, res.Status)
   162  		assert.Equal(t, []string{}, res.Transmissions)
   163  		assert.Equal(t, []string{}, res.Streams)
   164  		assert.Equal(t, true, res.StopAllStreams)
   165  	})
   166  }
   167  
   168  func TestCableReadyController(t *testing.T) {
   169  	env := common.NewSessionEnv("ws://demo.anycable.io/cable", &map[string]string{"cookie": "val=1;"})
   170  	subject := NewCableReadyController(key, slog.Default())
   171  
   172  	t.Run("Subscribe (success)", func(t *testing.T) {
   173  		channel := fmt.Sprintf("{\"channel\":\"CableReady::Stream\",\"identifier\":\"%s\"}", stream)
   174  
   175  		res, err := subject.Subscribe("42", env, "name=jack", channel)
   176  
   177  		require.NoError(t, err)
   178  		require.NotNil(t, res)
   179  		require.Equal(t, common.SUCCESS, res.Status)
   180  		assert.Equal(t, []string{common.ConfirmationMessage(channel)}, res.Transmissions)
   181  		assert.Equal(t, []string{"chat:2021"}, res.Streams)
   182  		assert.Equal(t, -1, res.DisconnectInterest)
   183  	})
   184  
   185  	t.Run("Subscribe (failure)", func(t *testing.T) {
   186  		channel := fmt.Sprintf("{\"channel\":\"CableReady::Stream\",\"identifier\":\"%s\"}", "fake_id")
   187  
   188  		res, err := subject.Subscribe("42", env, "name=jack", channel)
   189  
   190  		require.NoError(t, err)
   191  		require.NotNil(t, res)
   192  		require.Equal(t, common.FAILURE, res.Status)
   193  		assert.Equal(t, []string{common.RejectionMessage(channel)}, res.Transmissions)
   194  	})
   195  
   196  	t.Run("Subscribe (failure + not a string)", func(t *testing.T) {
   197  		signed := "WyJjaGF0LzIwMjMiLDE2ODUwMjQwMTdd--5b6661024d4c463c4936cd1542bc9a7672dd8039ac407d0b6c901697190e8aeb"
   198  		channel := fmt.Sprintf("{\"channel\":\"CableReady::Stream\",\"identifier\":\"%s\"}", signed)
   199  
   200  		res, err := subject.Subscribe("42", env, "name=jack", channel)
   201  
   202  		require.NoError(t, err)
   203  		require.NotNil(t, res)
   204  		require.Equal(t, common.FAILURE, res.Status)
   205  		assert.Equal(t, []string{common.RejectionMessage(channel)}, res.Transmissions)
   206  	})
   207  
   208  	t.Run("Unsubscribe", func(t *testing.T) {
   209  		channel := fmt.Sprintf("{\"channel\":\"CableReady::Stream\",\"identifier\":\"%s\"}", stream)
   210  
   211  		res, err := subject.Unsubscribe("42", env, "name=jack", channel)
   212  
   213  		require.NoError(t, err)
   214  		require.NotNil(t, res)
   215  		require.Equal(t, common.SUCCESS, res.Status)
   216  		assert.Equal(t, []string{}, res.Transmissions)
   217  		assert.Equal(t, []string{}, res.Streams)
   218  		assert.Equal(t, true, res.StopAllStreams)
   219  	})
   220  }