//  [python]
def test_GPyTorchPosterior(self) -> None:
        for dtype in (torch.float, torch.double):
            n = 3
            mean = torch.rand(n, dtype=dtype, device=self.device)
            variance = 1 + torch.rand(n, dtype=dtype, device=self.device)
            covar = variance.diag()
            mvn = MultivariateNormal(mean, to_linear_operator(covar))
            posterior = GPyTorchPosterior(distribution=mvn)
            # basics
            self.assertEqual(posterior.device.type, self.device.type)
            self.assertTrue(posterior.dtype == dtype)
            self.assertEqual(posterior._extended_shape(), torch.Size([n, 1]))
            self.assertTrue(torch.equal(posterior.mean, mean.unsqueeze(-1)))
            self.assertTrue(torch.equal(posterior.variance, variance.unsqueeze(-1)))
            # rsample
            samples = posterior.rsample()
            self.assertEqual(samples.shape, torch.Size([1, n, 1]))
            for sample_shape in ([4], [4, 2]):
                samples = posterior.rsample(sample_shape=torch.Size(sample_shape))
                self.assertEqual(samples.shape, torch.Size(sample_shape + [n, 1]))
            # check enabling of approximate root decomposition
            with ExitStack() as es:
                mock_func = es.enter_context(
                    mock.patch(
                        ROOT_DECOMP_PATH, return_value=torch.linalg.cholesky(covar)
                    )
                )
                es.enter_context(gpt_settings.max_cholesky_size(0))
                es.enter_context(
                    gpt_settings.fast_computations(covar_root_decomposition=True)
                )
                # need to clear cache, cannot re-use previous objects
                mvn = MultivariateNormal(mean, to_linear_operator(covar))
                posterior = GPyTorchPosterior(distribution=mvn)
                posterior.rsample(sample_shape=torch.Size([4]))
                mock_func.assert_called_once()

            # rsample w/ base samples
            base_samples = torch.randn(4, 3, device=self.device, dtype=dtype)
            # incompatible shapes
            with self.assertRaisesRegex(RuntimeError, "sample_shape"):
                posterior.rsample_from_base_samples(
                    sample_shape=torch.Size([3]), base_samples=base_samples
                )
            # ensure consistent result
            for sample_shape in ([4], [4, 2]):
                base_samples = torch.randn(
                    *sample_shape, 3, device=self.device, dtype=dtype
                )
                samples = [
                    posterior.rsample_from_base_samples(
                        sample_shape=torch.Size(sample_shape), base_samples=base_samples
                    )
                    for _ in range(2)
                ]
                self.assertAllClose(*samples)
            # Quantile & Density.
            marginal = Normal(
                loc=mean.unsqueeze(-1), scale=variance.unsqueeze(-1).sqrt()
            )
            q_val = torch.rand(2, dtype=dtype, device=self.device)
            quantile = posterior.quantile(q_val)
            self.assertEqual(quantile.shape, posterior._extended_shape(torch.Size([2])))
            expected = torch.stack([marginal.icdf(q) for q in q_val], dim=0)
            self.assertAllClose(quantile, expected)
            density = posterior.density(q_val)
            self.assertEqual(density.shape, posterior._extended_shape(torch.Size([2])))
            expected = torch.stack([marginal.log_prob(q).exp() for q in q_val], dim=0)
            self.assertAllClose(density, expected)