Exemplo n.º 1
0
 def test_upload_limits_provided_without_max_blob_size(self):
     # This just shows that the proto3 default value of 0 is reported as
     # usual, not handled as a special case.
     info = server_info_pb2.ServerInfoResponse()
     info.upload_limits.SetInParent()
     actual = server_info.max_blob_size(info)
     self.assertEqual(actual, 0)
Exemplo n.º 2
0
 def test_more_plugins(self):
     info = server_info_pb2.ServerInfoResponse()
     info.plugin_control.allowed_plugins.append("foo")
     info.plugin_control.allowed_plugins.append("bar")
     info.plugin_control.allowed_plugins.append("foo")
     actual = server_info.allowed_plugins(info)
     self.assertEqual(actual, frozenset(["foo", "bar"]))
    def testUploadIntentWithExperimentUrlCallback(self):
        """Test the upload intent with a callback."""
        server_info = server_info_pb2.ServerInfoResponse()
        server_info.url_format.template = "https://tensorboard.dev/x/{}"
        server_info.url_format.id_placeholder = "{}"

        stub = dry_run_stubs.DryRunTensorBoardWriterStub()
        stub.CreateExperiment = (
            lambda req, **__: write_service_pb2.CreateExperimentResponse(
                experiment_id="test_experiment_id", url="this URL is ignored"
            )
        )

        expected_url = "https://tensorboard.dev/x/test_experiment_id"

        with mock.patch.object(
            dry_run_stubs,
            "DryRunTensorBoardWriterStub",
            wraps=lambda: stub,
        ), mock.patch.object(sys.stdout, "write"):
            mock_channel = mock.Mock()
            mock_experiment_url_callback = mock.Mock()
            intent = uploader_subcommand.UploadIntent(
                self.get_temp_dir(),
                dry_run=True,
                one_shot=True,
                experiment_url_callback=mock_experiment_url_callback,
            )
            intent.execute(server_info, mock_channel)
        mock_experiment_url_callback.assert_called_once_with(expected_url)
Exemplo n.º 4
0
 def test_upload_limits_provided_without_max_tensor_point_size(self):
     # This just shows that the proto3 default value of 0 is reported as
     # usual, not handled as a special case.
     info = server_info_pb2.ServerInfoResponse()
     # Ensure upload_limits is set but do not explicitly set
     # max_tensor_point_size.
     info.upload_limits.max_blob_size = 42
     actual = server_info.max_tensor_point_size(info)
     self.assertEqual(actual, 0)
Exemplo n.º 5
0
    def test_missing_max_blob_size_in_upload_limits(self):
        # Test the one remaining field we did not test in
        # test_missing_fields_in_upload_limits.
        info = server_info_pb2.ServerInfoResponse()
        info.upload_limits.max_tensor_point_size = 22
        actual = server_info.upload_limits(info)

        self.assertEqual(actual.max_blob_size,
                         server_info._DEFAULT_MAX_BLOB_SIZE)
        self.assertEqual(actual.max_tensor_point_size, 22)
Exemplo n.º 6
0
 def app(request):
     body = request.get_data()
     request_pb = server_info_pb2.ServerInfoRequest.FromString(body)
     self.assertEqual(request_pb.version, version.VERSION)
     self.assertEqual(
         request_pb.plugin_specification.upload_plugins,
         ["plugin1", "plugin2"],
     )
     return wrappers.BaseResponse(
         server_info_pb2.ServerInfoResponse().SerializeToString())
Exemplo n.º 7
0
    def test_upload_limits_from_server_info(self):
        info_upload_limits = server_info_pb2.UploadLimits()
        info_upload_limits.max_scalar_request_size = 1
        info_upload_limits.max_tensor_request_size = 2
        info_upload_limits.max_blob_request_size = 3
        info_upload_limits.min_scalar_request_interval = 4
        info_upload_limits.min_tensor_request_interval = 5
        info_upload_limits.min_blob_request_interval = 6
        info_upload_limits.max_blob_size = 7
        info_upload_limits.max_tensor_point_size = 8

        info = server_info_pb2.ServerInfoResponse()
        info.upload_limits.CopyFrom(info_upload_limits)

        actual = server_info.upload_limits(info)
        self.assertEqual(actual, info_upload_limits)
Exemplo n.º 8
0
    def testDeleteIntentDeletesMultipleExperiments(self):
        # Setup: A uploader_lib which will report success (return `None`) on the
        #   deletion of an experiment.
        eid_1 = "1111"
        eid_2 = "22222"
        eid_3 = "333333"
        mock_delete_experiment = mock.MagicMock(return_value=None)
        mock_stdout_write = mock.MagicMock()

        # Execute: A _DeleteExperimentIntent on the list containing exactly
        #  three experiment_ids
        #
        # Mock three places:
        # 1. Writing to stdout, so we can inspect messages to the user.
        # 2. uploader_lib.delete_experiment itself, we will inspect invocations
        #    this method but do not want to actually delete anything.
        # 3. The creation of the grpc TensorBoardWriterServiceStub, which
        #    happens in intent, but we don't want to actually open a network
        #    communication.
        with mock.patch.object(
            sys.stdout, "write", mock_stdout_write
        ), mock.patch.object(
            uploader_lib, "delete_experiment", mock_delete_experiment
        ), mock.patch.object(
            write_service_pb2_grpc, "TensorBoardWriterServiceStub"
        ):
            # Set up an UploadIntent configured with one_shot and an empty temp
            # directory.
            intent = uploader_subcommand._DeleteExperimentIntent(
                experiment_id_list=[eid_1, eid_2, eid_3]
            )
            # Execute the intent.execute method.
            intent.execute(server_info_pb2.ServerInfoResponse(), None)

        # Expect that there are three calls to delete_experiment.
        self.assertEqual(mock_delete_experiment.call_count, 3)
        # Expect that ".*Deleted experiment.*" and the eid are among the things
        #    printed.
        out_msg = ",".join([x[0][0] for x in mock_stdout_write.call_args_list])
        self.assertRegex(out_msg, f".*Deleted experiment {eid_1}.*")
        self.assertRegex(out_msg, f".*Deleted experiment {eid_2}.*")
        self.assertRegex(out_msg, f".*Deleted experiment {eid_3}.*")
 def testUploadIntentOneShot(self):
     """Test the upload intent under the one-shot mode."""
     # Mock three places:
     # 1. The uploader itself, we will inspect invocations of its methods but
     #    do not want to actually uplaod anything.
     # 2. Writing to stdout, so we can inspect messages to the user.
     # 3. The creation of the grpc WriteServiceChannel, which happens in the
     #    non dry_run execution, but we don't want to actually open a network
     #    communication.        mock_uploader = mock.MagicMock()
     mock_uploader = mock.MagicMock()
     mock_uploader.create_experiment = mock.MagicMock(
         return_value="fake_experiment_id"
     )
     mock_stdout_write = mock.MagicMock()
     with mock.patch.object(
         sys.stdout, "write", mock_stdout_write
     ), mock.patch.object(
         uploader_lib, "TensorBoardUploader", return_value=mock_uploader
     ), mock.patch.object(
         write_service_pb2_grpc, "TensorBoardWriterServiceStub"
     ):
         # Set up an UploadIntent configured with one_shot and an empty temp
         # directory.
         intent = uploader_subcommand.UploadIntent(
             self.get_temp_dir(), one_shot=True
         )
         # Execute the intent.execute method.
         intent.execute(server_info_pb2.ServerInfoResponse(), None)
     # Expect that there is one call to create_experiment.
     self.assertEqual(mock_uploader.create_experiment.call_count, 1)
     # Expect that there is one call to start_uploading.
     self.assertEqual(mock_uploader.start_uploading.call_count, 1)
     # Expect that ".*Done scanning logdir.*" is among the things printed.
     stdout_writes = [x[0][0] for x in mock_stdout_write.call_args_list]
     self.assertRegex(
         ",".join(stdout_writes),
         ".*experiment created.*",
     )
     # Expect that the last thing written is the string "Done" and the
     # experiment_id.
     self.assertRegex(stdout_writes[-1], ".*Done.*")
     self.assertRegex(stdout_writes[-1], ".*fake_experiment_id.*")
Exemplo n.º 10
0
    def test_fetches_response(self):
        expected_result = server_info_pb2.ServerInfoResponse()
        expected_result.compatibility.verdict = server_info_pb2.VERDICT_OK
        expected_result.compatibility.details = "all clear"
        expected_result.api_server.endpoint = "api.example.com:443"
        expected_result.url_format.template = "http://localhost:8080/{{eid}}"
        expected_result.url_format.id_placeholder = "{{eid}}"

        @wrappers.BaseRequest.application
        def app(request):
            self.assertEqual(request.method, "POST")
            self.assertEqual(request.path, "/api/uploader")
            body = request.get_data()
            request_pb = server_info_pb2.ServerInfoRequest.FromString(body)
            self.assertEqual(request_pb.version, version.VERSION)
            return wrappers.BaseResponse(expected_result.SerializeToString())

        origin = self._start_server(app)
        result = server_info.fetch_server_info(origin)
        self.assertEqual(result, expected_result)
Exemplo n.º 11
0
def create_server_info(frontend_origin, api_endpoint):
  """Manually creates server info given a frontend and backend.

  Args:
    frontend_origin: The origin of the TensorBoard.dev frontend, like
      "https://tensorboard.dev" or "http://localhost:8000".
    api_endpoint: As to `server_info_pb2.ApiServer.endpoint`.

  Returns:
    A `server_info_pb2.ServerInfoResponse` message.
  """
  result = server_info_pb2.ServerInfoResponse()
  result.compatibility.verdict = server_info_pb2.VERDICT_OK
  result.api_server.endpoint = api_endpoint
  url_format = result.url_format
  placeholder = "{{EID}}"
  while placeholder in frontend_origin:
    placeholder = "{%s}" % placeholder
  url_format.template = "%s/experiment/%s/" % (frontend_origin, placeholder)
  url_format.id_placeholder = placeholder
  return result
Exemplo n.º 12
0
    def test_no_upload_limits_in_server_info(self):
        info = server_info_pb2.ServerInfoResponse()
        actual = server_info.upload_limits(info)

        expected = server_info_pb2.UploadLimits()
        expected.max_scalar_request_size = (
            server_info._DEFAULT_MAX_SCALAR_REQUEST_SIZE)
        expected.max_tensor_request_size = (
            server_info._DEFAULT_MAX_TENSOR_REQUEST_SIZE)
        expected.max_blob_request_size = (
            server_info._DEFAULT_MAX_BLOB_REQUEST_SIZE)
        expected.min_scalar_request_interval = (
            server_info._DEFAULT_MIN_SCALAR_REQUEST_INTERVAL)
        expected.min_tensor_request_interval = (
            server_info._DEFAULT_MIN_TENSOR_REQUEST_INTERVAL)
        expected.min_blob_request_interval = (
            server_info._DEFAULT_MIN_BLOB_REQUEST_INTERVAL)
        expected.max_blob_size = server_info._DEFAULT_MAX_BLOB_SIZE
        expected.max_tensor_point_size = (
            server_info._DEFAULT_MAX_TENSOR_POINT_SIZE)
        self.assertEqual(actual, expected)
Exemplo n.º 13
0
    def testUploadIntentOneShotEmptyDirectoryFails(self):
        """Test the upload intent under the one-shot mode with missing dir.

        In the case of a non-existent directoy, uploading should not
        create an experiment.
        """
        # Mock three places:
        # 1. The uploader itself, we will inspect invocations of its methods but
        #    do not want to actually uplaod anything.
        # 2. Writing to stdout, so we can inspect messages to the user.
        # 3. The creation of the grpc WriteServiceChannel, which happens in the
        #    non dry_run execution, but we don't want to actually open a network
        #    communication.
        mock_uploader = mock.MagicMock()
        mock_stdout_write = mock.MagicMock()
        with mock.patch.object(
            uploader_lib,
            "TensorBoardUploader",
            return_value=mock_uploader,
        ), mock.patch.object(
            sys.stdout, "write", mock_stdout_write
        ), mock.patch.object(
            write_service_pb2_grpc, "TensorBoardWriterServiceStub"
        ):
            # Set up an UploadIntent configured with one_shot and a
            # non-existent directory.
            intent = uploader_subcommand.UploadIntent(
                "/dev/null/non/existent/directory", one_shot=True
            )
            # Execute the intent.execute method.
            intent.execute(server_info_pb2.ServerInfoResponse(), None)
        # Expect that there is no call to create an experiment.
        self.assertEqual(mock_uploader.create_experiment.call_count, 0)
        # Expect a message to the user indicating no experiment was created.
        stdout_writes = [x[0][0] for x in mock_stdout_write.call_args_list]
        self.assertRegex(
            ",".join(stdout_writes),
            ".*Exiting without creating an experiment.*",
        )
Exemplo n.º 14
0
    def testDeleteIntentRaisesWhenAskedToDeleteZeroExperiments(self):
        mock_delete_experiment = mock.MagicMock(return_value=None)
        mock_stdout_write = mock.MagicMock()

        # Execute: A _DeleteExperimentIntent on the empty list.
        #
        # Mock three places:
        # 1. Writing to stdout, so we can inspect messages to the user.
        # 2. uploader_lib.delete_experiment itself, we will inspect invocations
        #    this method but do not want to actually delete anything.
        # 3. The creation of the grpc TensorBoardWriterServiceStub, which
        #    happens in intent, but we don't want to actually open a network
        #    communication.
        with mock.patch.object(
            sys.stdout, "write", mock_stdout_write
        ), mock.patch.object(
            uploader_lib, "delete_experiment", mock_delete_experiment
        ), mock.patch.object(
            write_service_pb2_grpc, "TensorBoardWriterServiceStub"
        ):
            # Set up an UploadIntent configured with one_shot and an empty temp
            # directory.
            intent = uploader_subcommand._DeleteExperimentIntent(
                experiment_id_list=[]
            )
            # Execute the intent.execute method.
            # Expect raises with appropriate message.
            with self.assertRaisesRegex(
                base_plugin.FlagsError,
                "Must specify at least one experiment ID to delete.*",
            ):
                intent.execute(server_info_pb2.ServerInfoResponse(), None)

        # Expect:
        # Expect that there are zero calls to delete_experiment.
        self.assertEqual(mock_delete_experiment.call_count, 0)
Exemplo n.º 15
0
 def test_old_server_no_upload_limits(self):
     info = server_info_pb2.ServerInfoResponse()
     actual = server_info.max_tensor_point_size(info)
     self.assertEqual(actual, server_info._DEFAULT_MAX_TENSOR_POINT_SIZE)
Exemplo n.º 16
0
    def testDeleteIntentHandlesUndeletableExperiemtns(self):
        # Setup: A uploader_lib which will emit scripted results for differen
        # eids.  See mock_delete_func for script.
        eid_1_ok = "1111"
        eid_2_empty = ""
        eid_3_ok = "3333"
        eid_4_missing = "4444"
        eid_5_ok = "5555"
        eid_6_permission_denied = "6666"
        eid_7_ok = "7777"
        eid_8_rate_limited = "8888"
        eid_9_ok = "9999"

        def mock_delete_func(_, eid):
            if eid == eid_4_missing:
                raise uploader_lib.ExperimentNotFoundError()
            if eid == eid_6_permission_denied:
                raise uploader_lib.PermissionDeniedError()
            if eid == eid_8_rate_limited:
                raise grpc.RpcError("Rate limited")
            return None

        mock_delete_experiment = mock.MagicMock(side_effect=mock_delete_func)
        mock_stdout_write = mock.MagicMock()
        mock_stderr_write = mock.MagicMock()
        mock_sys_exit = mock.MagicMock()

        # Execute: A _DeleteExperimentIntent on the motley list of
        #    experiments.
        #
        # Mock five places:
        # 1. Writing to stdout, so we can inspect messages to the user.
        # 2. Writing to stderr.
        # 3. uploader_lib.delete_experiment itself, we will inspect invocations
        #    this method but do not want to actually delete anything.
        # 4. The creation of the grpc TensorBoardWriterServiceStub, which
        #    happens in intent, but we don't want to actually open a network
        #    communication.
        # 5. Replace uploader_subcommand._die with something that wont
        #    actually kill the test.
        with mock.patch.object(
            sys.stdout, "write", mock_stdout_write
        ), mock.patch.object(
            sys.stderr, "write", mock_stderr_write
        ), mock.patch.object(
            uploader_lib, "delete_experiment", mock_delete_experiment
        ), mock.patch.object(
            write_service_pb2_grpc, "TensorBoardWriterServiceStub"
        ), mock.patch.object(
            sys, "exit", mock_sys_exit
        ):
            # Set up an UploadIntent configured with one_shot and an empty temp
            # directory.
            intent = uploader_subcommand._DeleteExperimentIntent(
                experiment_id_list=[
                    eid_1_ok,
                    eid_2_empty,
                    eid_3_ok,
                    eid_4_missing,
                    eid_5_ok,
                    eid_6_permission_denied,
                    eid_7_ok,
                    eid_8_rate_limited,
                    eid_9_ok,
                ]
            )
            # Execute the intent.execute method.
            intent.execute(server_info_pb2.ServerInfoResponse(), None)

        # Expect that there are eight calls to delete_experiment, one for each
        # experiment *except* the empty one.
        self.assertEqual(mock_delete_experiment.call_count, 8)
        # Expect that ".*Deleted experiment.*" and the eid are among the things
        #    printed to stdout
        stdout_msg = ",".join(
            [x[0][0] for x in mock_stdout_write.call_args_list]
        )
        self.assertRegex(stdout_msg, f".*Deleted experiment {eid_1_ok}.*")
        self.assertRegex(stdout_msg, f".*Deleted experiment {eid_3_ok}.*")
        self.assertRegex(stdout_msg, f".*Deleted experiment {eid_5_ok}.*")
        self.assertRegex(stdout_msg, f".*Deleted experiment {eid_7_ok}.*")
        self.assertRegex(stdout_msg, f".*Deleted experiment {eid_9_ok}.*")
        self.assertRegex(stdout_msg, ".*Skipping empty experiment_id.*")
        self.assertNotRegex(
            stdout_msg, f".*Deleted experiment {eid_4_missing}.*"
        )
        self.assertNotRegex(
            stdout_msg, f".*Deleted experiment {eid_6_permission_denied}.*"
        )
        self.assertNotRegex(
            stdout_msg, f".*Deleted experiment {eid_8_rate_limited}.*"
        )
        # Expect appropriate error messages sent to stderr
        stderr_msg = ",".join(
            [x[0][0] for x in mock_stderr_write.call_args_list]
        )
        self.assertRegex(stderr_msg, f".*No such experiment {eid_4_missing}.*")
        self.assertRegex(
            stderr_msg,
            f".*Cannot delete experiment {eid_6_permission_denied}.*",
        )
        self.assertRegex(
            stderr_msg,
            f".*Internal error deleting experiment {eid_8_rate_limited}.*",
        )
        # Expect a call to kill the process.
        self.assertEqual(mock_sys_exit.call_count, 1)
Exemplo n.º 17
0
 def test_scalars_only(self):
     info = server_info_pb2.ServerInfoResponse()
     info.plugin_control.allowed_plugins.append(
         scalars_metadata.PLUGIN_NAME)
     actual = server_info.allowed_plugins(info)
     self.assertEqual(actual, frozenset([scalars_metadata.PLUGIN_NAME]))
Exemplo n.º 18
0
 def test_provided_but_no_plugins(self):
     info = server_info_pb2.ServerInfoResponse()
     info.plugin_control.SetInParent()
     actual = server_info.allowed_plugins(info)
     self.assertEqual(actual, frozenset([]))
Exemplo n.º 19
0
 def test_old_server_no_plugins(self):
     info = server_info_pb2.ServerInfoResponse()
     actual = server_info.allowed_plugins(info)
     self.assertEqual(actual, frozenset([scalars_metadata.PLUGIN_NAME]))
Exemplo n.º 20
0
 def test(self):
     info = server_info_pb2.ServerInfoResponse()
     info.url_format.template = "https://unittest.tensorboard.dev/x/???"
     info.url_format.id_placeholder = "???"
     actual = server_info.experiment_url(info, "123")
     self.assertEqual(actual, "https://unittest.tensorboard.dev/x/123")
Exemplo n.º 21
0
 def app(request):
     result = server_info_pb2.ServerInfoResponse()
     result.compatibility.details = request.headers["User-Agent"]
     return wrappers.BaseResponse(result.SerializeToString())
Exemplo n.º 22
0
 def test_old_server_no_upload_limits(self):
     info = server_info_pb2.ServerInfoResponse()
     actual = server_info.max_blob_size(info)
     self.assertEqual(actual, server_info._DEFAULT_MAX_BLOB_SIZE)
Exemplo n.º 23
0
 def test_upload_limits_provided_with_max_blob_size(self):
     info = server_info_pb2.ServerInfoResponse()
     info.upload_limits.max_blob_size = 42
     actual = server_info.max_blob_size(info)
     self.assertEqual(actual, 42)