| // 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) |
| } |
| } |
| } |