Merge branch 'main' into 18842-arv-mount-disk-config
[arvados.git] / sdk / go / arvados / vocabulary_test.go
index 3099495a33da0bf2238cf95a2b96982b25e9a97a..f31a4f984b36f7c70aa9987017d9596900c91173 100644 (file)
@@ -6,6 +6,8 @@ package arvados
 
 import (
        "encoding/json"
+       "regexp"
+       "strings"
 
        check "gopkg.in/check.v1"
 )
@@ -56,7 +58,7 @@ func (s *VocabularySuite) SetUpTest(c *check.C) {
                        },
                },
        }
-       err := s.testVoc.validate()
+       _, err := s.testVoc.validate()
        c.Assert(err, check.IsNil)
 }
 
@@ -220,7 +222,8 @@ func (s *VocabularySuite) TestNewVocabulary(c *check.C) {
                                        "labels": [{"label": "Animal"}, {"label": "Creature"}],
                                        "values": {
                                                "IDVALANIMAL1":{"labels":[{"label":"Human"}, {"label":"Homo sapiens"}]},
-                                               "IDVALANIMAL2":{"labels":[{"label":"Elephant"}, {"label":"Loxodonta"}]}
+                                               "IDVALANIMAL2":{"labels":[{"label":"Elephant"}, {"label":"Loxodonta"}]},
+                                               "DOG":{"labels":[{"label":"Dog"}, {"label":"Canis lupus familiaris"}, {"label":"dOg"}]}
                                        }
                                }
                        }}`,
@@ -235,6 +238,8 @@ func (s *VocabularySuite) TestNewVocabulary(c *check.C) {
                                        "docker-image-repo-tag": true,
                                        "filters":               true,
                                        "container_request":     true,
+                                       "cwl_input":             true,
+                                       "cwl_output":            true,
                                },
                                StrictTags: false,
                                Tags: map[string]VocabularyTag{
@@ -248,20 +253,35 @@ func (s *VocabularySuite) TestNewVocabulary(c *check.C) {
                                                        "IDVALANIMAL2": {
                                                                Labels: []VocabularyLabel{{Label: "Elephant"}, {Label: "Loxodonta"}},
                                                        },
+                                                       "DOG": {
+                                                               Labels: []VocabularyLabel{{Label: "Dog"}, {Label: "Canis lupus familiaris"}, {Label: "dOg"}},
+                                                       },
                                                },
                                        },
                                },
                        },
                },
                {
-                       "Valid data, but uses reserved key",
+                       "Invalid JSON error with line & column numbers",
+                       `{"tags":{
+                               "aKey":{
+                                       "labels": [,{"label": "A label"}]
+                               }
+                       }}`,
+                       false, `invalid JSON format:.*\(line \d+, column \d+\)`, nil,
+               },
+               {
+                       "Invalid JSON with duplicate & reserved keys",
                        `{"tags":{
                                "type":{
                                        "strict": false,
-                                       "labels": [{"label": "Type"}]
+                                       "labels": [{"label": "Class", "label": "Type"}]
+                               },
+                               "type":{
+                                       "labels": []
                                }
                        }}`,
-                       false, "tag key.*is reserved", nil,
+                       false, "(?s).*duplicate JSON key \"tags.type.labels.0.label\"\nduplicate JSON key \"tags.type\"\ntag key \"type\" is reserved", nil,
                },
        }
 
@@ -284,14 +304,14 @@ func (s *VocabularySuite) TestValidationErrors(c *check.C) {
        tests := []struct {
                name       string
                voc        *Vocabulary
-               errMatches string
+               errMatches []string
        }{
                {
                        "Strict vocabulary, no keys",
                        &Vocabulary{
                                StrictTags: true,
                        },
-                       "vocabulary is strict but no tags are defined",
+                       []string{"vocabulary is strict but no tags are defined"},
                },
                {
                        "Collision between tag key and tag key label",
@@ -308,7 +328,7 @@ func (s *VocabularySuite) TestValidationErrors(c *check.C) {
                                        },
                                },
                        },
-                       "", // Depending on how the map is sorted, this could be one of two errors
+                       nil, // Depending on how the map is sorted, this could be one of two errors
                },
                {
                        "Collision between tag key and tag key label (case-insensitive)",
@@ -325,7 +345,7 @@ func (s *VocabularySuite) TestValidationErrors(c *check.C) {
                                        },
                                },
                        },
-                       "", // Depending on how the map is sorted, this could be one of two errors
+                       nil, // Depending on how the map is sorted, this could be one of two errors
                },
                {
                        "Collision between tag key labels",
@@ -342,7 +362,7 @@ func (s *VocabularySuite) TestValidationErrors(c *check.C) {
                                        },
                                },
                        },
-                       "tag label.*for key.*already seen.*",
+                       []string{"(?s).*tag label.*for key.*already seen.*"},
                },
                {
                        "Collision between tag value and tag value label",
@@ -363,7 +383,7 @@ func (s *VocabularySuite) TestValidationErrors(c *check.C) {
                                        },
                                },
                        },
-                       "", // Depending on how the map is sorted, this could be one of two errors
+                       nil, // Depending on how the map is sorted, this could be one of two errors
                },
                {
                        "Collision between tag value and tag value label (case-insensitive)",
@@ -384,7 +404,7 @@ func (s *VocabularySuite) TestValidationErrors(c *check.C) {
                                        },
                                },
                        },
-                       "", // Depending on how the map is sorted, this could be one of two errors
+                       nil, // Depending on how the map is sorted, this could be one of two errors
                },
                {
                        "Collision between tag value labels",
@@ -405,7 +425,28 @@ func (s *VocabularySuite) TestValidationErrors(c *check.C) {
                                        },
                                },
                        },
-                       "tag value label.*for pair.*already seen.*",
+                       []string{"(?s).*tag value label.*for pair.*already seen.*on value.*"},
+               },
+               {
+                       "Collision between tag value labels (case-insensitive)",
+                       &Vocabulary{
+                               StrictTags: false,
+                               Tags: map[string]VocabularyTag{
+                                       "IDTAGANIMALS": {
+                                               Strict: false,
+                                               Labels: []VocabularyLabel{{Label: "Animal"}, {Label: "Creature"}},
+                                               Values: map[string]VocabularyTagValue{
+                                                       "IDVALANIMAL1": {
+                                                               Labels: []VocabularyLabel{{Label: "Human"}, {Label: "Mammal"}},
+                                                       },
+                                                       "IDVALANIMAL2": {
+                                                               Labels: []VocabularyLabel{{Label: "Elephant"}, {Label: "mAMMAL"}},
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+                       []string{"(?s).*tag value label.*for pair.*already seen.*on value.*"},
                },
                {
                        "Strict tag key, with no values",
@@ -418,15 +459,47 @@ func (s *VocabularySuite) TestValidationErrors(c *check.C) {
                                        },
                                },
                        },
-                       "tag key.*is configured as strict but doesn't provide values",
+                       []string{"(?s).*tag key.*is configured as strict but doesn't provide values"},
+               },
+               {
+                       "Multiple errors reported",
+                       &Vocabulary{
+                               StrictTags: false,
+                               Tags: map[string]VocabularyTag{
+                                       "IDTAGANIMALS": {
+                                               Strict: true,
+                                               Labels: []VocabularyLabel{{Label: "Animal"}, {Label: "Creature"}},
+                                       },
+                                       "IDTAGSIZES": {
+                                               Labels: []VocabularyLabel{{Label: "Animal"}, {Label: "Size"}},
+                                       },
+                               },
+                       },
+                       []string{
+                               "(?s).*tag key.*is configured as strict but doesn't provide values.*",
+                               "(?s).*tag label.*for key.*already seen.*",
+                       },
                },
        }
        for _, tt := range tests {
                c.Log(c.TestName()+" ", tt.name)
-               err := tt.voc.validate()
+               validationErrs, err := tt.voc.validate()
                c.Assert(err, check.NotNil)
-               if tt.errMatches != "" {
-                       c.Assert(err, check.ErrorMatches, tt.errMatches)
+               for _, errMatch := range tt.errMatches {
+                       seen := false
+                       for _, validationErr := range validationErrs {
+                               if regexp.MustCompile(errMatch).MatchString(validationErr) {
+                                       seen = true
+                                       break
+                               }
+                       }
+                       if len(validationErrs) == 0 {
+                               c.Assert(err, check.ErrorMatches, errMatch)
+                       } else {
+                               c.Assert(seen, check.Equals, true,
+                                       check.Commentf("Expected to see error matching %q:\n%s",
+                                               errMatch, strings.Join(validationErrs, "\n")))
+                       }
                }
        }
 }