Skip to content

Commit e3566b8

Browse files
authored
Merge pull request #22 from cpuguy83/windows_everywhere
Move windows matcher logic so all platforms can use
2 parents 9ada2e3 + 7c58292 commit e3566b8

8 files changed

+331
-367
lines changed

defaults_test.go

+204
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
/*
2+
Copyright The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package platforms
18+
19+
import (
20+
"reflect"
21+
"runtime"
22+
"sort"
23+
"testing"
24+
25+
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
26+
)
27+
28+
// TestMatchComparerMatch_ABICheckWCOW checks windows platform matcher
29+
// behavior for stable ABI and non-stable ABI compliant versions
30+
func TestMatchComparerMatch_ABICheckWCOW(t *testing.T) {
31+
platformNoVersion := imagespec.Platform{
32+
Architecture: "amd64",
33+
OS: "windows",
34+
}
35+
platformWS2019 := imagespec.Platform{
36+
Architecture: "amd64",
37+
OS: "windows",
38+
OSVersion: "10.0.17763",
39+
}
40+
platformWS2022 := imagespec.Platform{
41+
Architecture: "amd64",
42+
OS: "windows",
43+
OSVersion: "10.0.20348",
44+
}
45+
platformWindows11 := imagespec.Platform{
46+
Architecture: "amd64",
47+
OS: "windows",
48+
OSVersion: "10.0.22621",
49+
}
50+
51+
for _, test := range []struct {
52+
hostPlatform imagespec.Platform
53+
testPlatform imagespec.Platform
54+
match bool
55+
}{
56+
{
57+
hostPlatform: platformWS2019,
58+
testPlatform: imagespec.Platform{
59+
Architecture: "amd64",
60+
OS: "windows",
61+
OSVersion: "10.0.17763",
62+
},
63+
match: true,
64+
},
65+
{
66+
hostPlatform: platformWS2019,
67+
testPlatform: imagespec.Platform{
68+
Architecture: "amd64",
69+
OS: "windows",
70+
OSVersion: "10.0.20348",
71+
},
72+
match: false,
73+
},
74+
{
75+
hostPlatform: platformWS2022,
76+
testPlatform: imagespec.Platform{
77+
Architecture: "amd64",
78+
OS: "windows",
79+
OSVersion: "10.0.17763",
80+
},
81+
match: false,
82+
},
83+
{
84+
hostPlatform: platformWS2022,
85+
testPlatform: imagespec.Platform{
86+
Architecture: "amd64",
87+
OS: "windows",
88+
OSVersion: "10.0.20348",
89+
},
90+
match: true,
91+
},
92+
{
93+
hostPlatform: platformWindows11,
94+
testPlatform: imagespec.Platform{
95+
Architecture: "amd64",
96+
OS: "windows",
97+
OSVersion: "10.0.17763",
98+
},
99+
match: false,
100+
},
101+
{
102+
hostPlatform: platformWindows11,
103+
testPlatform: imagespec.Platform{
104+
Architecture: "amd64",
105+
OS: "windows",
106+
OSVersion: "10.0.20348",
107+
},
108+
match: true,
109+
},
110+
{
111+
hostPlatform: platformNoVersion,
112+
testPlatform: platformWS2019,
113+
match: true,
114+
},
115+
{
116+
hostPlatform: platformNoVersion,
117+
testPlatform: platformNoVersion,
118+
match: true,
119+
},
120+
{
121+
hostPlatform: platformNoVersion,
122+
testPlatform: platformWindows11,
123+
match: true,
124+
},
125+
} {
126+
matcher := NewMatcher(test.hostPlatform)
127+
if actual := matcher.Match(test.testPlatform); actual != test.match {
128+
t.Errorf("should match: %t, test(%s) to host(%s)", test.match, test.hostPlatform, test.testPlatform)
129+
}
130+
}
131+
}
132+
133+
func TestWindowsMatchComparerLess(t *testing.T) {
134+
p := imagespec.Platform{
135+
Architecture: "amd64",
136+
OS: "windows",
137+
OSVersion: "10.0.17763.1",
138+
}
139+
140+
m := NewMatcher(p)
141+
if runtime.GOOS != "windows" {
142+
// By default NewMatcher only returns the MatchComparer interface on Windows (which is only for backwards compatibility).
143+
// On other platforms, we need to wrap the matcher in a windowsMatchComparer since the test is using it.
144+
m = &windowsMatchComparer{m}
145+
}
146+
platforms := []imagespec.Platform{
147+
{
148+
Architecture: "amd64",
149+
OS: "windows",
150+
OSVersion: "10.0.17764.1",
151+
},
152+
{
153+
Architecture: "amd64",
154+
OS: "windows",
155+
},
156+
{
157+
Architecture: "amd64",
158+
OS: "windows",
159+
OSVersion: "10.0.17763.1",
160+
},
161+
{
162+
Architecture: "amd64",
163+
OS: "windows",
164+
OSVersion: "10.0.17763.2",
165+
},
166+
{
167+
Architecture: "amd64",
168+
OS: "windows",
169+
OSVersion: "10.0.17762.1",
170+
},
171+
}
172+
expected := []imagespec.Platform{
173+
{
174+
Architecture: "amd64",
175+
OS: "windows",
176+
OSVersion: "10.0.17763.2",
177+
},
178+
{
179+
Architecture: "amd64",
180+
OS: "windows",
181+
OSVersion: "10.0.17763.1",
182+
},
183+
{
184+
Architecture: "amd64",
185+
OS: "windows",
186+
},
187+
{
188+
Architecture: "amd64",
189+
OS: "windows",
190+
OSVersion: "10.0.17764.1",
191+
},
192+
{
193+
Architecture: "amd64",
194+
OS: "windows",
195+
OSVersion: "10.0.17762.1",
196+
},
197+
}
198+
sort.SliceStable(platforms, func(i, j int) bool {
199+
return m.(MatchComparer).Less(platforms[i], platforms[j])
200+
})
201+
if !reflect.DeepEqual(platforms, expected) {
202+
t.Errorf("expected: %s\nactual : %s", expected, platforms)
203+
}
204+
}

defaults_windows.go

-76
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ package platforms
1919
import (
2020
"fmt"
2121
"runtime"
22-
"strconv"
23-
"strings"
2422

2523
specs "github.com/opencontainers/image-spec/specs-go/v1"
2624
"golang.org/x/sys/windows"
@@ -38,80 +36,6 @@ func DefaultSpec() specs.Platform {
3836
}
3937
}
4038

41-
type windowsmatcher struct {
42-
specs.Platform
43-
osVersionPrefix string
44-
defaultMatcher Matcher
45-
}
46-
47-
// Match matches platform with the same windows major, minor
48-
// and build version.
49-
func (m windowsmatcher) Match(p specs.Platform) bool {
50-
match := m.defaultMatcher.Match(p)
51-
52-
if match && m.OS == "windows" {
53-
// HPC containers do not have OS version filled
54-
if m.OSVersion == "" || p.OSVersion == "" {
55-
return true
56-
}
57-
58-
hostOsVersion := getOSVersion(m.osVersionPrefix)
59-
ctrOsVersion := getOSVersion(p.OSVersion)
60-
return checkHostAndContainerCompat(hostOsVersion, ctrOsVersion)
61-
}
62-
63-
return match
64-
}
65-
66-
func getOSVersion(osVersionPrefix string) osVersion {
67-
parts := strings.Split(osVersionPrefix, ".")
68-
if len(parts) < 3 {
69-
return osVersion{}
70-
}
71-
72-
majorVersion, _ := strconv.ParseUint(parts[0], 10, 8)
73-
minorVersion, _ := strconv.ParseUint(parts[1], 10, 8)
74-
buildNumber, _ := strconv.ParseUint(parts[2], 10, 16)
75-
76-
return osVersion{
77-
MajorVersion: uint8(majorVersion),
78-
MinorVersion: uint8(minorVersion),
79-
Build: uint16(buildNumber),
80-
}
81-
}
82-
83-
// Less sorts matched platforms in front of other platforms.
84-
// For matched platforms, it puts platforms with larger revision
85-
// number in front.
86-
func (m windowsmatcher) Less(p1, p2 specs.Platform) bool {
87-
m1, m2 := m.Match(p1), m.Match(p2)
88-
if m1 && m2 {
89-
r1, r2 := revision(p1.OSVersion), revision(p2.OSVersion)
90-
return r1 > r2
91-
}
92-
return m1 && !m2
93-
}
94-
95-
func revision(v string) int {
96-
parts := strings.Split(v, ".")
97-
if len(parts) < 4 {
98-
return 0
99-
}
100-
r, err := strconv.Atoi(parts[3])
101-
if err != nil {
102-
return 0
103-
}
104-
return r
105-
}
106-
107-
func prefix(v string) string {
108-
parts := strings.Split(v, ".")
109-
if len(parts) < 4 {
110-
return v
111-
}
112-
return strings.Join(parts[0:3], ".")
113-
}
114-
11539
// Default returns the current platform's default platform specification.
11640
func Default() MatchComparer {
11741
return Only(DefaultSpec())

0 commit comments

Comments
 (0)