code: def test_websocket_origins(
      ManagedServerLoop, unused_tcp_port
  ) -> None:
      application = Application()
      with ManagedServerLoop(
          application, port=unused_tcp_port
      ) as server:
          assert server._tornado.websocket_origins == {
              f"localhost:{unused_tcp_port}"
          }
  
      # OK this is a bit of a confusing mess. The user-facing arg for server is
      # "allow_websocket_origin" which gets converted to "extra_websocket_origins"
      # for BokehTornado, which is exposed as a property "websocket_origins"...
      with ManagedServerLoop(
          application, allow_websocket_origin=["foo"]
      ) as server:
          assert server._tornado.websocket_origins == {"foo:80"}
  
      with ManagedServerLoop(
          application, allow_websocket_origin=["foo:8080"]
      ) as server:
          assert server._tornado.websocket_origins == {"foo:8080"}
  
      with ManagedServerLoop(
          application, allow_websocket_origin=["foo:8080", "bar"]
      ) as server:
          assert server._tornado.websocket_origins == {
              "foo:8080",
              "bar:80",
          }
  
imports: from __future__ import annotations
  import pytest
  import json
  import logging
  from _util_server import http_get, url
  from tornado.web import StaticFileHandler
  from bokeh.application import Application
  from bokeh.client import pull_session
  from bokeh.core.types import ID
  from bokeh.server.auth_provider import NullAuth
  from bokeh.server.views.static_handler import StaticHandler
  from bokeh.server.views.ws import WSHandler
  from tests.support.plugins.managed_server_loop import MSL
  from tests.support.util.env import envset
  import bokeh.server.tornado
label_desc: Use image node_id 10 for calling a global function with example usage: test_websocket_origins(ManagedServerLoop, unused_tcp_port) without return types