1*b7c941bbSAndroid Build Coastguard Worker// Copyright (C) 2024 The Android Open Source Project 2*b7c941bbSAndroid Build Coastguard Worker// 3*b7c941bbSAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*b7c941bbSAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*b7c941bbSAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*b7c941bbSAndroid Build Coastguard Worker// 7*b7c941bbSAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*b7c941bbSAndroid Build Coastguard Worker// 9*b7c941bbSAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*b7c941bbSAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*b7c941bbSAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*b7c941bbSAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*b7c941bbSAndroid Build Coastguard Worker// limitations under the License. 14*b7c941bbSAndroid Build Coastguard Worker 15*b7c941bbSAndroid Build Coastguard Workerpackage requirementsdata_test 16*b7c941bbSAndroid Build Coastguard Worker 17*b7c941bbSAndroid Build Coastguard Workerimport ( 18*b7c941bbSAndroid Build Coastguard Worker "slices" 19*b7c941bbSAndroid Build Coastguard Worker "testing" 20*b7c941bbSAndroid Build Coastguard Worker 21*b7c941bbSAndroid Build Coastguard Worker "google.golang.org/protobuf/proto" 22*b7c941bbSAndroid Build Coastguard Worker 23*b7c941bbSAndroid Build Coastguard Worker "google3/third_party/android/mediapc_requirements/requirements" 24*b7c941bbSAndroid Build Coastguard Worker pb "cts/test/mediapc/requirements/requirements_go_proto" 25*b7c941bbSAndroid Build Coastguard Worker "github.com/google/go-cmp/cmp" 26*b7c941bbSAndroid Build Coastguard Worker "github.com/google/go-cmp/cmp/cmpopts" 27*b7c941bbSAndroid Build Coastguard Worker 28*b7c941bbSAndroid Build Coastguard Worker _ "embed" 29*b7c941bbSAndroid Build Coastguard Worker) 30*b7c941bbSAndroid Build Coastguard Worker 31*b7c941bbSAndroid Build Coastguard Worker// MPC Requirements data from requirements.txtpb 32*b7c941bbSAndroid Build Coastguard Worker// 33*b7c941bbSAndroid Build Coastguard Worker//go:embed requirements.binbp 34*b7c941bbSAndroid Build Coastguard Workervar reqBinary []byte 35*b7c941bbSAndroid Build Coastguard Worker 36*b7c941bbSAndroid Build Coastguard Workerfunc TestUniqueRequirementIDs(t *testing.T) { 37*b7c941bbSAndroid Build Coastguard Worker reqList := mustUnmarshalRequirementList(t) 38*b7c941bbSAndroid Build Coastguard Worker 39*b7c941bbSAndroid Build Coastguard Worker // Requirement ids must be unique 40*b7c941bbSAndroid Build Coastguard Worker ids := make(map[string]bool) 41*b7c941bbSAndroid Build Coastguard Worker for _, req := range reqList.GetRequirements() { 42*b7c941bbSAndroid Build Coastguard Worker id := req.GetId() 43*b7c941bbSAndroid Build Coastguard Worker if ids[id] { 44*b7c941bbSAndroid Build Coastguard Worker t.Errorf("requirement [%s] is a duplicate", id) 45*b7c941bbSAndroid Build Coastguard Worker } 46*b7c941bbSAndroid Build Coastguard Worker ids[id] = true 47*b7c941bbSAndroid Build Coastguard Worker } 48*b7c941bbSAndroid Build Coastguard Worker} 49*b7c941bbSAndroid Build Coastguard Worker 50*b7c941bbSAndroid Build Coastguard Workerfunc TestUniqueRequirementNames(t *testing.T) { 51*b7c941bbSAndroid Build Coastguard Worker reqList := mustUnmarshalRequirementList(t) 52*b7c941bbSAndroid Build Coastguard Worker 53*b7c941bbSAndroid Build Coastguard Worker // Requirement names must be unique 54*b7c941bbSAndroid Build Coastguard Worker nameToID := make(map[string]string) // name to id 55*b7c941bbSAndroid Build Coastguard Worker for _, req := range reqList.GetRequirements() { 56*b7c941bbSAndroid Build Coastguard Worker if req.HasName() { 57*b7c941bbSAndroid Build Coastguard Worker name := req.GetName() 58*b7c941bbSAndroid Build Coastguard Worker if nameToID[name] != "" { 59*b7c941bbSAndroid Build Coastguard Worker t.Errorf("the name %q of requirement [%s] is a duplicate of requirement [%s]'s name", req.GetId(), name, nameToID[name]) 60*b7c941bbSAndroid Build Coastguard Worker } 61*b7c941bbSAndroid Build Coastguard Worker nameToID[name] = req.GetId() 62*b7c941bbSAndroid Build Coastguard Worker } 63*b7c941bbSAndroid Build Coastguard Worker } 64*b7c941bbSAndroid Build Coastguard Worker 65*b7c941bbSAndroid Build Coastguard Worker} 66*b7c941bbSAndroid Build Coastguard Worker 67*b7c941bbSAndroid Build Coastguard Workerfunc TestAllTestConfigsSpecifiedAndUsed(t *testing.T) { 68*b7c941bbSAndroid Build Coastguard Worker reqList := mustUnmarshalRequirementList(t) 69*b7c941bbSAndroid Build Coastguard Worker 70*b7c941bbSAndroid Build Coastguard Worker for _, req := range reqList.GetRequirements() { 71*b7c941bbSAndroid Build Coastguard Worker if !req.HasName() { 72*b7c941bbSAndroid Build Coastguard Worker continue // Do not check requirements that are not implemented yet 73*b7c941bbSAndroid Build Coastguard Worker } 74*b7c941bbSAndroid Build Coastguard Worker 75*b7c941bbSAndroid Build Coastguard Worker t.Run(req.GetName(), func(t *testing.T) { 76*b7c941bbSAndroid Build Coastguard Worker 77*b7c941bbSAndroid Build Coastguard Worker specifiedTestConfigs := []string{} 78*b7c941bbSAndroid Build Coastguard Worker for id := range req.GetTestConfigs() { 79*b7c941bbSAndroid Build Coastguard Worker specifiedTestConfigs = append(specifiedTestConfigs, id) 80*b7c941bbSAndroid Build Coastguard Worker } 81*b7c941bbSAndroid Build Coastguard Worker 82*b7c941bbSAndroid Build Coastguard Worker usedTestConfigs := []string{} 83*b7c941bbSAndroid Build Coastguard Worker for _, spec := range req.GetSpecs() { 84*b7c941bbSAndroid Build Coastguard Worker if !slices.Contains(usedTestConfigs, spec.GetTestConfigId()) { 85*b7c941bbSAndroid Build Coastguard Worker usedTestConfigs = append(usedTestConfigs, spec.GetTestConfigId()) 86*b7c941bbSAndroid Build Coastguard Worker } 87*b7c941bbSAndroid Build Coastguard Worker } 88*b7c941bbSAndroid Build Coastguard Worker 89*b7c941bbSAndroid Build Coastguard Worker if diff := cmp.Diff(specifiedTestConfigs, usedTestConfigs, cmpopts.SortSlices( 90*b7c941bbSAndroid Build Coastguard Worker func(a, b string) bool { return a < b })); diff != "" { 91*b7c941bbSAndroid Build Coastguard Worker t.Errorf("Specified test configs do not match used test configs (-want +got):\n%s", diff) 92*b7c941bbSAndroid Build Coastguard Worker } 93*b7c941bbSAndroid Build Coastguard Worker }) 94*b7c941bbSAndroid Build Coastguard Worker } 95*b7c941bbSAndroid Build Coastguard Worker} 96*b7c941bbSAndroid Build Coastguard Worker 97*b7c941bbSAndroid Build Coastguard Workerfunc TestConfigMeasurementsValid(t *testing.T) { 98*b7c941bbSAndroid Build Coastguard Worker reqList := mustUnmarshalRequirementList(t) 99*b7c941bbSAndroid Build Coastguard Worker 100*b7c941bbSAndroid Build Coastguard Worker for _, req := range reqList.GetRequirements() { 101*b7c941bbSAndroid Build Coastguard Worker if !req.HasName() { 102*b7c941bbSAndroid Build Coastguard Worker continue // Do not check requirements that are not implemented yet 103*b7c941bbSAndroid Build Coastguard Worker } 104*b7c941bbSAndroid Build Coastguard Worker 105*b7c941bbSAndroid Build Coastguard Worker t.Run(req.GetName(), func(t *testing.T) { 106*b7c941bbSAndroid Build Coastguard Worker for measurementName, measurement := range req.GetMeasurements() { 107*b7c941bbSAndroid Build Coastguard Worker if measurement.GetComparison() != pb.Comparison_COMPARISON_CONFIG { 108*b7c941bbSAndroid Build Coastguard Worker continue // Do not check measurements that are not config measurements 109*b7c941bbSAndroid Build Coastguard Worker } 110*b7c941bbSAndroid Build Coastguard Worker 111*b7c941bbSAndroid Build Coastguard Worker t.Run(measurementName, func(t *testing.T) { 112*b7c941bbSAndroid Build Coastguard Worker measurementValues := make(map[string]*pb.RequiredValue) 113*b7c941bbSAndroid Build Coastguard Worker for _, spec := range req.GetSpecs() { 114*b7c941bbSAndroid Build Coastguard Worker val, ok := measurementValues[spec.GetTestConfigId()] 115*b7c941bbSAndroid Build Coastguard Worker if !ok { 116*b7c941bbSAndroid Build Coastguard Worker measurementValues[spec.GetTestConfigId()] = spec.GetRequiredValues()[measurementName] 117*b7c941bbSAndroid Build Coastguard Worker } else if !proto.Equal(val, spec.GetRequiredValues()[measurementName]) { 118*b7c941bbSAndroid Build Coastguard Worker t.Errorf("Test config [%s] has multiple different values for measurement [%s]: [%v] and [%v]", spec.GetTestConfigId(), measurementName, spec.GetRequiredValues()[measurementName], val) 119*b7c941bbSAndroid Build Coastguard Worker } 120*b7c941bbSAndroid Build Coastguard Worker } 121*b7c941bbSAndroid Build Coastguard Worker }) 122*b7c941bbSAndroid Build Coastguard Worker } 123*b7c941bbSAndroid Build Coastguard Worker 124*b7c941bbSAndroid Build Coastguard Worker }) 125*b7c941bbSAndroid Build Coastguard Worker } 126*b7c941bbSAndroid Build Coastguard Worker} 127*b7c941bbSAndroid Build Coastguard Worker 128*b7c941bbSAndroid Build Coastguard Workerfunc TestConfigVariantsValid(t *testing.T) { 129*b7c941bbSAndroid Build Coastguard Worker reqList := mustUnmarshalRequirementList(t) 130*b7c941bbSAndroid Build Coastguard Worker 131*b7c941bbSAndroid Build Coastguard Worker for _, req := range reqList.GetRequirements() { 132*b7c941bbSAndroid Build Coastguard Worker if !req.HasName() { 133*b7c941bbSAndroid Build Coastguard Worker continue // Do not check requirements that are not implemented yet 134*b7c941bbSAndroid Build Coastguard Worker } 135*b7c941bbSAndroid Build Coastguard Worker 136*b7c941bbSAndroid Build Coastguard Worker t.Run(req.GetName(), func(t *testing.T) { 137*b7c941bbSAndroid Build Coastguard Worker for configID := range req.GetTestConfigs() { 138*b7c941bbSAndroid Build Coastguard Worker 139*b7c941bbSAndroid Build Coastguard Worker // Check that all test configs have the same variants 140*b7c941bbSAndroid Build Coastguard Worker t.Run(configID, func(t *testing.T) { 141*b7c941bbSAndroid Build Coastguard Worker specToVariants := make(map[int64][]string) 142*b7c941bbSAndroid Build Coastguard Worker for mpc, spec := range req.GetSpecs() { 143*b7c941bbSAndroid Build Coastguard Worker if spec.GetTestConfigId() == configID { 144*b7c941bbSAndroid Build Coastguard Worker specToVariants[mpc] = []string{} 145*b7c941bbSAndroid Build Coastguard Worker for variantID := range spec.GetVariantSpecs() { 146*b7c941bbSAndroid Build Coastguard Worker specToVariants[mpc] = append(specToVariants[mpc], variantID) 147*b7c941bbSAndroid Build Coastguard Worker } 148*b7c941bbSAndroid Build Coastguard Worker } 149*b7c941bbSAndroid Build Coastguard Worker } 150*b7c941bbSAndroid Build Coastguard Worker 151*b7c941bbSAndroid Build Coastguard Worker prev := []string{} 152*b7c941bbSAndroid Build Coastguard Worker for _, variants := range specToVariants { 153*b7c941bbSAndroid Build Coastguard Worker if len(prev) > 0 { 154*b7c941bbSAndroid Build Coastguard Worker if diff := cmp.Diff(prev, variants, cmpopts.SortSlices( 155*b7c941bbSAndroid Build Coastguard Worker func(a, b string) bool { return a < b })); diff != "" { 156*b7c941bbSAndroid Build Coastguard Worker t.Errorf("Test config [%s] missing variants (-want +got):\n%s", configID, diff) 157*b7c941bbSAndroid Build Coastguard Worker } 158*b7c941bbSAndroid Build Coastguard Worker } 159*b7c941bbSAndroid Build Coastguard Worker prev = variants 160*b7c941bbSAndroid Build Coastguard Worker } 161*b7c941bbSAndroid Build Coastguard Worker }) 162*b7c941bbSAndroid Build Coastguard Worker } 163*b7c941bbSAndroid Build Coastguard Worker }) 164*b7c941bbSAndroid Build Coastguard Worker } 165*b7c941bbSAndroid Build Coastguard Worker} 166*b7c941bbSAndroid Build Coastguard Worker 167*b7c941bbSAndroid Build Coastguard Workerfunc TestProtoFieldNumbersAreUniqueAndValid(t *testing.T) { 168*b7c941bbSAndroid Build Coastguard Worker reqList := mustUnmarshalRequirementList(t) 169*b7c941bbSAndroid Build Coastguard Worker 170*b7c941bbSAndroid Build Coastguard Worker usedReqNumbers := make(map[int32]bool) 171*b7c941bbSAndroid Build Coastguard Worker for _, req := range reqList.GetRequirements() { 172*b7c941bbSAndroid Build Coastguard Worker for testConfigID, testConfig := range req.GetTestConfigs() { 173*b7c941bbSAndroid Build Coastguard Worker if !testConfig.HasProtoFieldNumber() { 174*b7c941bbSAndroid Build Coastguard Worker continue 175*b7c941bbSAndroid Build Coastguard Worker } 176*b7c941bbSAndroid Build Coastguard Worker 177*b7c941bbSAndroid Build Coastguard Worker if usedReqNumbers[testConfig.GetProtoFieldNumber()] { 178*b7c941bbSAndroid Build Coastguard Worker t.Errorf("Test config [%s] has the same proto field number [%d] as another test config", testConfigID, testConfig.GetProtoFieldNumber()) 179*b7c941bbSAndroid Build Coastguard Worker } else if testConfig.GetProtoFieldNumber() <= 0 { 180*b7c941bbSAndroid Build Coastguard Worker t.Errorf("Test config [%s] has an invalid proto field number [%d]", testConfigID, testConfig.GetProtoFieldNumber()) 181*b7c941bbSAndroid Build Coastguard Worker } else { 182*b7c941bbSAndroid Build Coastguard Worker usedReqNumbers[testConfig.GetProtoFieldNumber()] = true 183*b7c941bbSAndroid Build Coastguard Worker } 184*b7c941bbSAndroid Build Coastguard Worker } 185*b7c941bbSAndroid Build Coastguard Worker 186*b7c941bbSAndroid Build Coastguard Worker t.Run(req.GetId(), func(t *testing.T) { 187*b7c941bbSAndroid Build Coastguard Worker usedMeasurementNumbers := make(map[int32]bool) 188*b7c941bbSAndroid Build Coastguard Worker 189*b7c941bbSAndroid Build Coastguard Worker for _, measurement := range req.GetMeasurements() { 190*b7c941bbSAndroid Build Coastguard Worker if !measurement.HasProtoFieldNumber() { 191*b7c941bbSAndroid Build Coastguard Worker continue 192*b7c941bbSAndroid Build Coastguard Worker } 193*b7c941bbSAndroid Build Coastguard Worker 194*b7c941bbSAndroid Build Coastguard Worker if usedMeasurementNumbers[measurement.GetProtoFieldNumber()] { 195*b7c941bbSAndroid Build Coastguard Worker t.Errorf("Measurement [%s] has the same proto field number [%d] as another measurement", measurement.GetId(), measurement.GetProtoFieldNumber()) 196*b7c941bbSAndroid Build Coastguard Worker } else if measurement.GetProtoFieldNumber() <= 2 { 197*b7c941bbSAndroid Build Coastguard Worker t.Errorf("Measurement [%s] has an invalid proto field number [%d]", measurement.GetId(), measurement.GetProtoFieldNumber()) 198*b7c941bbSAndroid Build Coastguard Worker } else { 199*b7c941bbSAndroid Build Coastguard Worker usedMeasurementNumbers[measurement.GetProtoFieldNumber()] = true 200*b7c941bbSAndroid Build Coastguard Worker } 201*b7c941bbSAndroid Build Coastguard Worker } 202*b7c941bbSAndroid Build Coastguard Worker }) 203*b7c941bbSAndroid Build Coastguard Worker } 204*b7c941bbSAndroid Build Coastguard Worker} 205*b7c941bbSAndroid Build Coastguard Worker 206*b7c941bbSAndroid Build Coastguard Workerfunc mustUnmarshalRequirementList(t *testing.T) *pb.RequirementList { 207*b7c941bbSAndroid Build Coastguard Worker t.Helper() 208*b7c941bbSAndroid Build Coastguard Worker reqList, err := requirements.UnmarshalRequirementList(reqBinary) 209*b7c941bbSAndroid Build Coastguard Worker if err != nil { 210*b7c941bbSAndroid Build Coastguard Worker t.Fatalf("failed to unmarshal reqBinary: %v", err) 211*b7c941bbSAndroid Build Coastguard Worker } 212*b7c941bbSAndroid Build Coastguard Worker return reqList 213*b7c941bbSAndroid Build Coastguard Worker} 214