rdb publish: upload the updated eqc_category_expression to BQ
Dependent CLs:
- https://crrev.com/c/6249144
- https://crrev.com/c/6248741
LED: http://ci.chromium.org/b/8723080997439984897/infra
BQ data: http://screen/7b43fS7W63v9JD7.png
Bug: b:395760082, b:379801095
Test: Unit tests and LED
Change-Id: Ie6f67ad7f707a3aa649ae4dc902bf6ccabe01325
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/dev-util/+/6261828
Reviewed-by: Jason Kusuma <jkusuma@google.com>
Tested-by: Allen Xie <zhihuixie@google.com>
Reviewed-by: Tom Handakas <thandakas@chromium.org>
Commit-Queue: Allen Xie <zhihuixie@google.com>
diff --git a/src/go.chromium.org/chromiumos/test/publish/cmd/rdb-publish/service/eqc_service.go b/src/go.chromium.org/chromiumos/test/publish/cmd/rdb-publish/service/eqc_service.go
index f0b545a..8f038b0 100644
--- a/src/go.chromium.org/chromiumos/test/publish/cmd/rdb-publish/service/eqc_service.go
+++ b/src/go.chromium.org/chromiumos/test/publish/cmd/rdb-publish/service/eqc_service.go
@@ -44,11 +44,10 @@
// EQCRow represents a row in the EqC info BigQuery table.
type EQCRow struct {
- EQCHash string
- EQCName string
- // TODO: b/395760082 - Add the EqcCategoryExpression back once its type
- // is updated to JSON from string.
- EQCDimensions map[string]string
+ EQCHash string
+ EQCName string
+ EQCCategoryExpression map[string]string
+ EQCDimensions map[string]string
}
// NewEQCPublishService create a new EqC publish service to interact with
@@ -112,11 +111,10 @@
// Inserts the EqC info because it doesn't exist in the BQ table.
eqcRow := &EQCRow{
- EQCHash: eqcInfo.EqcHash,
- EQCName: eqcInfo.EqcName,
- // TODO: b/395760082 - Add the EqcCategoryExpression back once its type
- // is updated to JSON from string.
- EQCDimensions: eqcInfo.EqcDimensions,
+ EQCHash: eqcInfo.EqcHash,
+ EQCName: eqcInfo.EqcName,
+ EQCCategoryExpression: eqcInfo.EqcCategoryExpression,
+ EQCDimensions: eqcInfo.EqcDimensions,
}
inserter := eps.bqClient.Dataset(TestInfoDataset).Table(EQCInfoTable).Inserter()
@@ -173,6 +171,15 @@
// Save implements the ValueSaver interface for the EQCRow struct.
func (e *EQCRow) Save() (map[string]bigquery.Value, string, error) {
+ if e.EQCCategoryExpression == nil {
+ e.EQCCategoryExpression = make(map[string]string)
+ }
+
+ categoryExpression, err := json.Marshal(e.EQCCategoryExpression)
+ if err != nil {
+ return nil, "", fmt.Errorf("marshalling the EqC category expression: %w", err)
+ }
+
if e.EQCDimensions == nil {
e.EQCDimensions = make(map[string]string)
}
@@ -183,11 +190,10 @@
}
return map[string]bigquery.Value{
- "eqc_hash": e.EQCHash,
- "eqc_name": e.EQCName,
- // TODO: b/395760082 - Add the EqcCategoryExpression back once its type
- // is updated to JSON from string.
- "eqc_dimensions": string(dimensions),
+ "eqc_hash": e.EQCHash,
+ "eqc_name": e.EQCName,
+ "eqc_category_expression": string(categoryExpression),
+ "eqc_dimensions": string(dimensions),
}, e.EQCHash, nil
}
@@ -213,20 +219,45 @@
}
eqcInfo := &artifact.EqcInfo{
- EqcHash: eqcInfoMap["eqcHash"],
- EqcName: eqcInfoMap["eqcName"],
- // TODO: b/395760082 - Add the EqcCategoryExpression back once its type
- // is updated to JSON from string.
+ EqcHash: eqcInfoMap["eqcHash"],
+ EqcName: eqcInfoMap["eqcName"],
+ EqcCategoryExpression: make(map[string]string),
+ EqcDimensions: make(map[string]string),
+ }
+
+ // The content of the "eqcCategoryExpression" field is aligned with the
+ // CategoryExpression proto in "/ttcp/protos/ttcp/syntax/syntax.proto".
+ if categoryExpressionJSON, ok := eqcInfoMap["eqcCategoryExpression"]; ok {
+ categoryExpressionMap := make(map[string]interface{})
+ if err := json.Unmarshal([]byte(categoryExpressionJSON), &categoryExpressionMap); err != nil {
+ return nil, fmt.Errorf("unmarshalling the EqC category expression: %w", err)
+ }
+
+ for k, v := range categoryExpressionMap {
+ switch value := v.(type) {
+ case string:
+ // Corresponds to the name field which indicates the name of the
+ // predefined category. Most of the time (> 99.99%) it will be
+ // mapped to this string type.
+ eqcInfo.EqcCategoryExpression[k] = fmt.Sprintf("%v", value)
+ default:
+ // Corresponds to the category proto field which explicitly
+ // specifies the category contents.
+ jsonString, err := json.Marshal(value)
+ if err != nil {
+ log.Printf("Failed to marshal the category expression key: %s", k)
+ continue
+ }
+ eqcInfo.EqcCategoryExpression[k] = string(jsonString)
+ }
+
+ }
}
if dimensionsJSON, ok := eqcInfoMap["eqcDimensions"]; ok {
- dimensionsMap := make(map[string]string)
- if err := json.Unmarshal([]byte(dimensionsJSON), &dimensionsMap); err != nil {
+ if err := json.Unmarshal([]byte(dimensionsJSON), &eqcInfo.EqcDimensions); err != nil {
return nil, fmt.Errorf("unmarshalling the EqC dimensions: %w", err)
}
- eqcInfo.EqcDimensions = dimensionsMap
- } else {
- eqcInfo.EqcDimensions = make(map[string]string)
}
log.Printf("Successfully extracted the EqC info: %#v", eqcInfo)
diff --git a/src/go.chromium.org/chromiumos/test/publish/cmd/rdb-publish/service/eqc_service_test.go b/src/go.chromium.org/chromiumos/test/publish/cmd/rdb-publish/service/eqc_service_test.go
index 0a43e12..d2c5c0f 100644
--- a/src/go.chromium.org/chromiumos/test/publish/cmd/rdb-publish/service/eqc_service_test.go
+++ b/src/go.chromium.org/chromiumos/test/publish/cmd/rdb-publish/service/eqc_service_test.go
@@ -27,6 +27,9 @@
wantEQCInfo := &artifact.EqcInfo{
EqcHash: "9073744604696850342",
EqcName: "Cometlake-U__INTEL_HRP2_AX201__5.15",
+ EqcCategoryExpression: map[string]string{
+ "name": "WifiBtChipset_Soc_Kernel_Intel",
+ },
EqcDimensions: map[string]string{
"dlm:soc": "Cometlake-U",
"image:_kernel_version": "5.15",
@@ -34,9 +37,10 @@
},
}
eqcInfoMap := map[string]string{
- "eqcDimensions": "{\"dlm:soc\":\"Cometlake-U\",\"image:_kernel_version\":\"5.15\",\"wireless_field\":\"INTEL_HRP2_AX201\"}",
- "eqcHash": "9073744604696850342",
- "eqcName": "Cometlake-U__INTEL_HRP2_AX201__5.15",
+ "eqcCategoryExpression": "{\"name\": \"WifiBtChipset_Soc_Kernel_Intel\"}",
+ "eqcDimensions": "{\"dlm:soc\":\"Cometlake-U\",\"image:_kernel_version\":\"5.15\",\"wireless_field\":\"INTEL_HRP2_AX201\"}",
+ "eqcHash": "9073744604696850342",
+ "eqcName": "Cometlake-U__INTEL_HRP2_AX201__5.15",
}
rdbMetadata := &metadata.PublishRdbMetadata{
PublishKeys: []*api.PublishKey{
@@ -105,6 +109,9 @@
entry := &EQCRow{
EQCHash: eqcHash,
EQCName: eqcName,
+ EQCCategoryExpression: map[string]string{
+ "name": "WifiBtChipset_Soc_Kernel_Intel",
+ },
EQCDimensions: map[string]string{
"soc": "value1",
"wifiChip": "value2",
@@ -112,9 +119,10 @@
}
wantValue := map[string]bigquery.Value{
- "eqc_hash": eqcHash,
- "eqc_name": eqcName,
- "eqc_dimensions": `{"soc":"value1","wifiChip":"value2"}`, // Note: order may vary
+ "eqc_hash": eqcHash,
+ "eqc_name": eqcName,
+ "eqc_category_expression": `{"name": "WifiBtChipset_Soc_Kernel_Intel"}`,
+ "eqc_dimensions": `{"soc":"value1","wifiChip":"value2"}`, // Note: order may vary
}
gotValue, gotInsertID, err := entry.Save()
@@ -124,6 +132,17 @@
So(gotValue["eqc_hash"], ShouldEqual, wantValue["eqc_hash"])
So(gotValue["eqc_name"], ShouldEqual, eqcName)
+ // Compare maps, ignoring key order in eqc_category_expression.
+ gotCategoryExpression := gotValue["eqc_category_expression"]
+ wantCategoryExpression := wantValue["eqc_category_expression"]
+
+ var gotCategoryExprMap, wantCategoryExprMap map[string]string
+ err = json.Unmarshal([]byte(gotCategoryExpression.(string)), &gotCategoryExprMap)
+ So(err, ShouldBeNil)
+ err = json.Unmarshal([]byte(wantCategoryExpression.(string)), &wantCategoryExprMap)
+ So(err, ShouldBeNil)
+ So(gotCategoryExprMap, ShouldResemble, wantCategoryExprMap)
+
// Compare maps, ignoring key order in eqc_dimensions.
gotDimensions := gotValue["eqc_dimensions"]
wantDimensions := wantValue["eqc_dimensions"]
@@ -139,15 +158,17 @@
Convey("Empty dimensions", func() {
entry := &EQCRow{
- EQCHash: eqcHash,
- EQCName: eqcName,
- EQCDimensions: make(map[string]string), // Empty map
+ EQCHash: eqcHash,
+ EQCName: eqcName,
+ EQCCategoryExpression: make(map[string]string), // Empty map
+ EQCDimensions: make(map[string]string), // Empty map
}
wantValue := map[string]bigquery.Value{
- "eqc_hash": eqcHash,
- "eqc_name": eqcName,
- "eqc_dimensions": `{}`,
+ "eqc_hash": eqcHash,
+ "eqc_name": eqcName,
+ "eqc_category_expression": `{}`,
+ "eqc_dimensions": `{}`,
}
gotValue, _, err := entry.Save()
@@ -158,15 +179,17 @@
Convey("Nil dimensions", func() {
entry := &EQCRow{
- EQCHash: eqcHash,
- EQCName: eqcName,
- EQCDimensions: nil,
+ EQCHash: eqcHash,
+ EQCName: eqcName,
+ EQCCategoryExpression: nil,
+ EQCDimensions: nil,
}
wantValue := map[string]bigquery.Value{
- "eqc_hash": eqcHash,
- "eqc_name": eqcName,
- "eqc_dimensions": `{}`, // Should be treated as an empty map
+ "eqc_hash": eqcHash,
+ "eqc_name": eqcName,
+ "eqc_category_expression": `{}`,
+ "eqc_dimensions": `{}`, // Should be treated as an empty map
}
gotValue, _, err := entry.Save()
@@ -185,6 +208,9 @@
wantEQCInfo := &artifact.EqcInfo{
EqcHash: "9073744604696850342",
EqcName: "Cometlake-U__INTEL_HRP2_AX201__5.15",
+ EqcCategoryExpression: map[string]string{
+ "value": "{\"combinatorial\":{\"subcategories\":[{\"value\":{\"enumerated\":{\"classes\":[{\"value\":{\"expression\":{\"property\":{\"propertyPath\":\"swarming:label-wifi_state\",\"strEqual\":\"NORMAL\"}},\"name\":\"swarming:label-wifi_state:NORMAL\"}}]}}},{\"name\":\"WifiBtChipset_Soc_Kernel\"}]}}",
+ },
EqcDimensions: map[string]string{
"dlm:soc": "Cometlake-U",
"image:_kernel_version": "5.15",
@@ -192,9 +218,10 @@
},
}
eqcInfoMap := map[string]string{
- "eqcDimensions": "{\"dlm:soc\":\"Cometlake-U\",\"image:_kernel_version\":\"5.15\",\"wireless_field\":\"INTEL_HRP2_AX201\"}",
- "eqcHash": "9073744604696850342",
- "eqcName": "Cometlake-U__INTEL_HRP2_AX201__5.15",
+ "eqcCategoryExpression": "{\"value\":{\"combinatorial\":{\"subcategories\":[{\"value\":{\"enumerated\":{\"classes\":[{\"value\":{\"name\":\"swarming:label-wifi_state:NORMAL\",\"expression\":{\"property\":{\"propertyPath\":\"swarming:label-wifi_state\",\"strEqual\":\"NORMAL\"}}}}]}}},{\"name\":\"WifiBtChipset_Soc_Kernel\"}]}}}",
+ "eqcDimensions": "{\"dlm:soc\":\"Cometlake-U\",\"image:_kernel_version\":\"5.15\",\"wireless_field\":\"INTEL_HRP2_AX201\"}",
+ "eqcHash": "9073744604696850342",
+ "eqcName": "Cometlake-U__INTEL_HRP2_AX201__5.15",
}
rdbMetadata := &metadata.PublishRdbMetadata{
PublishKeys: []*api.PublishKey{