def test_sum_local_noise_shares(self, local_scale, num_records):
    """Test the noise level of the sum of discrete Gaussians applied locally.

    The sum of discrete Gaussians is not a discrete Gaussian, but it will be
    extremely close for sigma >= 2. We will thus compare the aggregated noise
    to a central discrete Gaussian noise with appropriately scaled stddev with
    some reasonable tolerance.

    Args:
      local_scale: The stddev of the local discrete Gaussian noise.
      num_records: The number of records to be aggregated.
    """
    # Aggregated local noises.
    num_trials = 1000
    record = tf.zeros([num_trials], dtype=tf.int32)
    sample = [record] * num_records
    query = ddg_sum_query(l2_norm_bound=10.0, local_scale=local_scale)
    query_result, _ = test_utils.run_query(query, sample)

    # Central discrete Gaussian noise.
    central_scale = np.sqrt(num_records) * local_scale
    central_noise = discrete_gaussian_utils.sample_discrete_gaussian(
        scale=tf.cast(tf.round(central_scale), record.dtype),
        shape=tf.shape(record),
        dtype=record.dtype)

    agg_noise, central_noise = self.evaluate([query_result, central_noise])

    mean_stddev = central_scale * np.sqrt(num_trials) / num_trials
    atol = 3.5 * mean_stddev

    # Use the atol for mean as a rough default atol for stddev/percentile.
    self.assertAllClose(np.mean(agg_noise), np.mean(central_noise), atol=atol)
    self.assertAllClose(np.std(agg_noise), np.std(central_noise), atol=atol)
    self.assertAllClose(
        np.percentile(agg_noise, [25, 50, 75]),
        np.percentile(central_noise, [25, 50, 75]),
        atol=atol)