blob: 926362c6b001e9eafab20681e2e59dcd9917cf28 [file] [log] [blame]
// Copyright 2018 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 config_validator
import (
"config"
"testing"
)
// makeValidReport returns a valid instance of config.ReportDefinition which
// can be modified to fail various validation checks for testing purposes.
func makeValidReport() config.ReportDefinition {
return makeValidReportWithName("the_report_name")
}
func makeValidReportWithName(name string) config.ReportDefinition {
return config.ReportDefinition{
Id: 10,
ReportName: name,
ReportType: config.ReportDefinition_EVENT_COMPONENT_OCCURRENCE_COUNT,
}
}
// Test that makeValidReport returns a valid report.
func TestValidateMakeValidReport(t *testing.T) {
r := makeValidReport()
if err := validateReportDefinition(r); err != nil {
t.Errorf("Rejected valid report: %v", err)
}
}
func TestDifferentReportId(t *testing.T) {
r := makeValidReport()
r.Id += 1
if err := validateReportDefinition(r); err != nil {
t.Error("Reject report with different report id.")
}
}
func TestValidateInvalidName(t *testing.T) {
r := makeValidReportWithName("_invalid_name")
if err := validateReportDefinition(r); err == nil {
t.Error("Accepted report with invalid name.")
}
}
func TestValidateZeroReportId(t *testing.T) {
r := makeValidReportWithName("NRaMinLNcqiYmgEypLLVGnXymNpxJzqabtbbjLycCMEohvVzZtAYpah")
r.Id = 0
if err := validateReportDefinition(r); err == nil {
t.Error("Accepted report with 0 id.")
}
}
func TestValidateUnsetReportType(t *testing.T) {
if err := validateReportType(config.MetricDefinition_EVENT_OCCURRED, config.ReportDefinition_REPORT_TYPE_UNSET); err == nil {
t.Error("Accepted report with no report type set.")
}
}
// Test that validateLocalPrivacyNoiseLevel accepts a ReportDefinition if and only if it has a local_privacy_noise_level field.
func TestValidateLocalPrivacyNoiseLevel(t *testing.T) {
r := makeValidReport()
if err := validateLocalPrivacyNoiseLevel(r); err == nil {
t.Error("Accepted report definition with local_privacy_noise_level unset.")
}
r.LocalPrivacyNoiseLevel = config.ReportDefinition_SMALL
if err := validateLocalPrivacyNoiseLevel(r); err != nil {
t.Errorf("Rejected report definition with local_privacy_noise_level set: %v", err)
}
}
// Test that validateWindowSize rejects a ReportDefinition with no window_size field, and a ReportDefinition with a
// window_size field where one of the window sizes is UNSET.
func TestValidateWindowSize(t *testing.T) {
r := makeValidReport()
if err := validateWindowSize(r); err == nil {
t.Error("Accepted report definition without window_size field.")
}
r.WindowSize = []config.WindowSize{config.WindowSize_WINDOW_1_DAY, config.WindowSize_UNSET}
if err := validateWindowSize(r); err == nil {
t.Error("Accepted report definition with an UNSET window size.")
}
r.WindowSize = []config.WindowSize{config.WindowSize_WINDOW_1_DAY, config.WindowSize_WINDOW_7_DAYS}
if err := validateWindowSize(r); err != nil {
t.Errorf("Rejected report definition with valid window_size field: %v", err)
}
}
// Test that local_privacy_noise_level must be set if the report type is SIMPLE_OCCURRENCE_COUNT.
func TestValidateReportDefinitionForSimpleOccurrenceCount(t *testing.T) {
r := makeValidReport()
r.ReportType = config.ReportDefinition_SIMPLE_OCCURRENCE_COUNT
if err := validateReportDefinition(r); err == nil {
t.Error("Accepted report definition of type SIMPLE_OCCURRENCE_COUNT with local_privacy_noise_level unset.")
}
}
// Test that local_privacy_noise_level and window_size must be set if the report type is UNIQUE_N_DAY_ACTIVES.
func TestValidateReportDefinitionForUniqueActives(t *testing.T) {
r := makeValidReport()
r.ReportType = config.ReportDefinition_UNIQUE_N_DAY_ACTIVES
// Add a valid window_size, but not a local_privacy_noise_level.
r.WindowSize = []config.WindowSize{config.WindowSize_WINDOW_1_DAY}
if err := validateReportDefinition(r); err == nil {
t.Error("Accepted report definition of type UNIQUE_N_DAY_ACTIVES with local_privacy_noise_level unset.")
}
// Remove window_size and add a local_privacy_noise_level.
r.WindowSize = []config.WindowSize{}
r.LocalPrivacyNoiseLevel = config.ReportDefinition_SMALL
if err := validateReportDefinition(r); err == nil {
t.Error("Accepted report definition of type UNIQUE_N_DAY_ACTIVES without window_size field.")
}
// Add a valid window size to window_size, but also add an UNSET window size.
r.WindowSize = []config.WindowSize{config.WindowSize_WINDOW_1_DAY, config.WindowSize_UNSET}
if err := validateReportDefinition(r); err == nil {
t.Error("Accepted report definition of type UNIQUE_N_DAY_ACTIVES with window_size field containing an UNSET window size.")
}
}
// Test that window_size must be set if the report type is PER_DEVICE_NUMERIC_STATS.
func TestValidateReportDefinitionForPerDeviceNumericStats(t *testing.T) {
r := makeValidReport()
r.ReportType = config.ReportDefinition_PER_DEVICE_NUMERIC_STATS
if err := validateReportDefinition(r); err == nil {
t.Error("Accepted report definition of type PER_DEVICE_NUMERIC_STATS without window_size field.")
}
// Add a valid window size to window_size, but also add an UNSET window size.
r.WindowSize = []config.WindowSize{config.WindowSize_WINDOW_1_DAY, config.WindowSize_UNSET}
if err := validateReportDefinition(r); err == nil {
t.Error("Accepted report definition of type PER_DEVICE_NUMERIC_STATS with window_size field containing an UNSET window size.")
}
}
// Test that window_size must be set if the report type is PER_DEVICE_HISTOGRAM.
func TestValidateReportDefinitionForPerDeviceHistogram(t *testing.T) {
r := makeValidReport()
r.ReportType = config.ReportDefinition_PER_DEVICE_HISTOGRAM
if err := validateReportDefinition(r); err == nil {
t.Error("No int_buckets specified for report of type PER_DEVICE_HISTOGRAM.")
}
r.IntBuckets = &config.IntegerBuckets{}
if err := validateReportDefinition(r); err == nil {
t.Error("Accepted report definition of type PER_DEVICE_HISTOGRAM without window_size field.")
}
// Add a valid window size to window_size, but also add an UNSET window size.
r.WindowSize = []config.WindowSize{config.WindowSize_WINDOW_1_DAY, config.WindowSize_UNSET}
if err := validateReportDefinition(r); err == nil {
t.Error("Accepted report definition of type PER_DEVICE_HISTOGRAM with window_size field containing an UNSET window size.")
}
}
// Test percentiles range for NUMERIC_AGGREGATION report types.
func TestValidateReportDefinitionForNumericAggregation(t *testing.T) {
r := makeValidReport()
r.ReportType = config.ReportDefinition_NUMERIC_AGGREGATION
// Test that percentiles are optional.
if err := validateReportDefinition(r); err != nil {
t.Error("Rejected report definition of type NUMERIC_AGGREGATION with no percentiles set.")
}
// Test that percentiles between 0 and 100 are accepted.
r.Percentiles = []uint32{0, 25, 50, 75, 90, 99, 100}
if err := validateReportDefinition(r); err != nil {
t.Error("Rejected report definition of type NUMERIC_AGGREGATION with valid percentiles.")
}
// Test that out of bounds percentiles are rejected.
r.Percentiles = []uint32{0, 25, 50, 75, 100, 101}
if err := validateReportDefinition(r); err == nil {
t.Error("Accepted report definition of type NUMERIC_AGGREGATION with invalid percentiles.")
}
}