github.com/google/osv-scalibr@v0.4.1/semantic/parse_test.go (about) 1 // Copyright 2025 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package semantic_test 16 17 import ( 18 "errors" 19 "testing" 20 21 "github.com/google/osv-scalibr/semantic" 22 ) 23 24 var ecosystems = []string{ 25 "AlmaLinux", 26 "Alpaquita", 27 "Alpine", 28 "BellSoft Hardened Containers", 29 "Bioconductor", 30 "Bitnami", 31 "Chainguard", 32 "ConanCenter", 33 "CRAN", 34 "crates.io", 35 "Debian", 36 "GHC", 37 "Go", 38 "Hex", 39 "Julia", 40 "Mageia", 41 "Maven", 42 "MinimOS", 43 "npm", 44 "NuGet", 45 "openEuler", 46 "openSUSE", 47 "Packagist", 48 "Pub", 49 "PyPI", 50 "Rocky Linux", 51 "RubyGems", 52 "SUSE", 53 "SwiftURL", 54 "Ubuntu", 55 "Wolfi", 56 } 57 58 func TestParse(t *testing.T) { 59 for _, ecosystem := range ecosystems { 60 _, err := semantic.Parse("", ecosystem) 61 62 if errors.Is(err, semantic.ErrUnsupportedEcosystem) { 63 t.Errorf("'%s' is not a supported ecosystem", ecosystem) 64 } 65 } 66 } 67 68 func TestParse_EcosystemWithSuffix(t *testing.T) { 69 ecosystems := []string{ 70 "Debian:13", 71 "Alpine:v3.9", 72 "Red Hat:ansible_automation_platform:2.0::el8", 73 "Ubuntu:Pro:24.04:LTS", 74 } 75 for _, ecosystem := range ecosystems { 76 _, err := semantic.Parse("", ecosystem) 77 78 if errors.Is(err, semantic.ErrUnsupportedEcosystem) { 79 t.Errorf("'%s' is not a supported ecosystem", ecosystem) 80 } 81 } 82 } 83 84 func TestParse_InvalidVersions(t *testing.T) { 85 type args struct { 86 versions []string 87 ecosystem string 88 } 89 tests := []struct { 90 name string 91 args args 92 }{ 93 { 94 name: "invalid_cran_versions", 95 args: args{ 96 versions: []string{"!", "?", "1.a.2", "z.c.3"}, 97 ecosystem: "CRAN", 98 }, 99 }, 100 { 101 name: "invalid_debian_versions", 102 args: args{ 103 versions: []string{"1.2.3-not-a-debian:version!@#$"}, 104 ecosystem: "Debian", 105 }, 106 }, 107 { 108 name: "invalid_hackage_versions", 109 args: args{ 110 versions: []string{"1.2.3.4.5-notallowed"}, 111 ecosystem: "Hackage", 112 }, 113 }, 114 } 115 for _, tt := range tests { 116 t.Run(tt.name, func(t *testing.T) { 117 for _, version := range tt.args.versions { 118 _, err := semantic.Parse(version, tt.args.ecosystem) 119 120 if err == nil { 121 t.Errorf("expected error for '%s', got nil", version) 122 123 continue 124 } 125 126 if !errors.Is(err, semantic.ErrInvalidVersion) { 127 t.Errorf("expected ErrInvalidVersion for '%s', got '%v'", version, err) 128 } 129 } 130 }) 131 } 132 } 133 134 func TestMustParse(t *testing.T) { 135 defer func() { 136 if r := recover(); r != nil { 137 t.Errorf("unexpected panic - '%s'", r) 138 } 139 }() 140 141 for _, ecosystem := range ecosystems { 142 semantic.MustParse("", ecosystem) 143 } 144 } 145 146 func TestMustParse_InvalidVersions(t *testing.T) { 147 type args struct { 148 versions []string 149 ecosystem string 150 } 151 tests := []struct { 152 name string 153 args args 154 }{ 155 { 156 name: "invalid_ecosystem", 157 args: args{ 158 versions: []string{""}, 159 ecosystem: "<unknown>", 160 }, 161 }, 162 { 163 name: "invalid_cran_versions", 164 args: args{ 165 versions: []string{"!", "?", "1.a.2", "z.c.3"}, 166 ecosystem: "CRAN", 167 }, 168 }, 169 { 170 name: "invalid_debian_versions", 171 args: args{ 172 versions: []string{"1.2.3-not-a-debian:version!@#$"}, 173 ecosystem: "Debian", 174 }, 175 }, 176 { 177 name: "invalid_hackage_versions", 178 args: args{ 179 versions: []string{"1.2.3.4.5-notallowed"}, 180 ecosystem: "Hackage", 181 }, 182 }, 183 } 184 for _, tt := range tests { 185 t.Run(tt.name, func(t *testing.T) { 186 defer func() { 187 if r := recover(); r == nil { 188 t.Errorf("expected panic, got nil") 189 } 190 }() 191 192 for _, version := range tt.args.versions { 193 semantic.MustParse(version, tt.args.ecosystem) 194 195 // if we reached here, then we can't have panicked 196 t.Errorf("function did not panic when given invalid version '%s'", version) 197 } 198 }) 199 } 200 }