blob: ec09bd7e00727459f6902128b97b0f99451bf3b8 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package privacy
import (
"config"
"testing"
"github.com/golang/glog"
)
// The try-bots expect glog to be imported, but we do not use it.
var _ = glog.Info
var metric = config.MetricDefinition{
EventCodeBufferMax: 5,
}
func TestEstimateWithEpsilon(t *testing.T) {
privacyParamsCalculator, err := NewPrivacyEncodingParamsCalculatorForTesting(testParamRecords)
if err != nil {
t.Fatal("Failed to create PrivacyEncodingParamsCalculator")
}
errorCalculator := NewErrorCalculator(*privacyParamsCalculator)
testMetric := config.MetricDefinition{
MetricName: "Occurrence",
MetricType: config.MetricDefinition_OCCURRENCE,
}
uniqueDeviceCount := config.ReportDefinition{
ReportName: "UniqueDeviceCounts",
ReportType: config.ReportDefinition_UNIQUE_DEVICE_COUNTS,
LocalAggregationProcedure: config.ReportDefinition_SELECT_FIRST,
}
uniqueDeviceHistogram := config.ReportDefinition{
ReportName: "UniqueDeviceHistograms",
ReportType: config.ReportDefinition_UNIQUE_DEVICE_HISTOGRAMS,
LocalAggregationProcedure: config.ReportDefinition_SELECT_FIRST,
}
hourlyValueHistogram := config.ReportDefinition{
ReportName: "HourlyValueHistograms",
ReportType: config.ReportDefinition_HOURLY_VALUE_HISTOGRAMS,
LocalAggregationProcedure: config.ReportDefinition_SELECT_FIRST,
}
fleetwideOccurrenceCount := config.ReportDefinition{
ReportName: "FleetwideOccurrenceCounts",
ReportType: config.ReportDefinition_FLEETWIDE_OCCURRENCE_COUNTS,
LocalAggregationProcedure: config.ReportDefinition_SELECT_FIRST,
MaxCount: 1,
}
fleetwideOccurrenceCountHighMax := config.ReportDefinition{
ReportName: "FleetwideOccurrenceCountsWithHighMaxCount",
ReportType: config.ReportDefinition_FLEETWIDE_OCCURRENCE_COUNTS,
LocalAggregationProcedure: config.ReportDefinition_SELECT_FIRST,
MaxCount: 4,
}
fleetwideHistogram := config.ReportDefinition{
ReportName: "FleetwideHistograms",
ReportType: config.ReportDefinition_FLEETWIDE_HISTOGRAMS,
LocalAggregationProcedure: config.ReportDefinition_SELECT_FIRST,
}
unsupportedReport := config.ReportDefinition{
ReportName: "FleetwideMeans",
ReportType: config.ReportDefinition_FLEETWIDE_MEANS,
}
type args struct {
metric *config.MetricDefinition
report *config.ReportDefinition
epsilon float64
population uint64
}
var tests = []struct {
input args
valid bool
expected float64
}{
// Single contribution reports
{args{&testMetric, &uniqueDeviceCount, 1, 10000}, true, 4.935511431266572},
{args{&testMetric, &uniqueDeviceCount, 10, 10000}, true, 3.014414887122711},
{args{&testMetric, &uniqueDeviceCount, 1, 20000}, true, 6.979867203344631},
{args{&testMetric, &uniqueDeviceHistogram, 1, 10000}, true, 4.935511431266572},
{args{&testMetric, &uniqueDeviceHistogram, 10, 10000}, true, 3.014414887122711},
{args{&testMetric, &uniqueDeviceHistogram, 1, 20000}, true, 6.979867203344631},
{args{&testMetric, &hourlyValueHistogram, 1, 10000}, true, 24.178969252553177},
{args{&testMetric, &hourlyValueHistogram, 10, 10000}, true, 14.767556692999985},
{args{&testMetric, &hourlyValueHistogram, 1, 20000}, true, 34.19422624116276},
// Multi-contribution reports
{args{&testMetric, &fleetwideOccurrenceCount, 1, 10000}, true, 10.796886170985388},
{args{&testMetric, &fleetwideOccurrenceCount, 10, 10000}, true, 7.640513872793125},
{args{&testMetric, &fleetwideOccurrenceCount, 1, 20000}, true, 15.269102854406052},
{args{&testMetric, &fleetwideOccurrenceCountHighMax, 1, 10000}, true, 43.18754468394155},
{args{&testMetric, &fleetwideHistogram, 1, 10000}, true, 10.796886170985388},
{args{&testMetric, &fleetwideHistogram, 10, 10000}, true, 7.640513872793125},
{args{&testMetric, &fleetwideHistogram, 1, 20000}, true, 15.269102854406052},
// Invalid input:
// This report type is not currently supported.
{args{&testMetric, &unsupportedReport, 1, 10000}, false, 1.0},
}
for _, test := range tests {
result, err := errorCalculator.Estimate(test.input.metric, test.input.report, test.input.epsilon, test.input.population)
if test.valid && err != nil {
t.Errorf("Estimate failed for report %v: %v", test.input.report.ReportName, err)
} else if !test.valid && err == nil {
t.Errorf("Estimate accepted invalid report: %v", test.input.report.ReportName)
} else if test.valid && result != test.expected {
t.Errorf("Estimate for report %v (epsilon: %v, population: %v): expected %v, got %v", test.input.report.ReportName, test.input.epsilon, test.input.population, test.expected, result)
}
}
}