-
Notifications
You must be signed in to change notification settings - Fork 848
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[azcore] Add ETag type to Core (#15207)
* add type def for ETag * adding etag specific files and more functionality * testing weak * testing for etag equality * weak tag comparisons * adding docstrings * addressing richard and jeffs feedback. split equals to strong and weak, using more HasValue throughout * fixing one test * adding EOL * adding note about the difference between nil and empty etags * more feedback * fix spelling, remove comment about nil * format check
- Loading branch information
1 parent
6742bfa
commit b977244
Showing
4 changed files
with
186 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// +build go1.13 | ||
|
||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
package azcore | ||
|
||
import ( | ||
"strings" | ||
) | ||
|
||
// ETag is a property used for optimistic concurrency during updates | ||
// ETag is a validator based on https://tools.ietf.org/html/rfc7232#section-2.3.2 | ||
// An ETag can be empty (""). | ||
type ETag string | ||
|
||
// ETagAny is an ETag that represents everything, the value is "*" | ||
const ETagAny ETag = "*" | ||
|
||
// Equals does a strong comparison of two ETags. Equals returns true when both | ||
// ETags are not weak and the values of the underlying strings are equal. | ||
func (e ETag) Equals(other ETag) bool { | ||
return !e.IsWeak() && !other.IsWeak() && e == other | ||
} | ||
|
||
// WeakEquals does a weak comparison of two ETags. Two ETags are equivalent if their opaque-tags match | ||
// character-by-character, regardless of either or both being tagged as "weak". | ||
func (e ETag) WeakEquals(other ETag) bool { | ||
getStart := func(e1 ETag) int { | ||
if e1.IsWeak() { | ||
return 2 | ||
} | ||
return 0 | ||
} | ||
aStart := getStart(e) | ||
bStart := getStart(other) | ||
|
||
aVal := e[aStart:] | ||
bVal := other[bStart:] | ||
|
||
return aVal == bVal | ||
} | ||
|
||
// IsWeak specifies whether the ETag is strong or weak. | ||
func (e ETag) IsWeak() bool { | ||
return len(e) >= 4 && strings.HasPrefix(string(e), "W/\"") && strings.HasSuffix(string(e), "\"") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
// +build go1.13 | ||
|
||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
package azcore | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func createETag(s string) ETag { | ||
return ETag(s) | ||
} | ||
|
||
func TestETagEquals(t *testing.T) { | ||
e1 := createETag("tag") | ||
require.Equal(t, string(e1), "tag") | ||
|
||
e2 := createETag("\"tag\"") | ||
require.Equal(t, string(e2), "\"tag\"") | ||
|
||
e3 := createETag("W/\"weakETag\"") | ||
require.Equal(t, string(e3), "W/\"weakETag\"") | ||
require.Truef(t, e3.IsWeak(), "ETag is expected to be weak") | ||
|
||
strongETag := createETag("\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\"") | ||
require.Equal(t, string(strongETag), "\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\"") | ||
|
||
require.Falsef(t, ETagAny.IsWeak(), "ETagAny should not be weak") | ||
} | ||
|
||
func TestETagWeak(t *testing.T) { | ||
et1 := createETag("tag") | ||
require.Falsef(t, et1.IsWeak(), "expected etag to be strong") | ||
|
||
et2 := createETag("\"tag\"") | ||
require.Falsef(t, et2.IsWeak(), "expected etag to be strong") | ||
|
||
et3 := createETag("W/\"weakETag\"") | ||
require.Truef(t, et3.IsWeak(), "expected etag to be weak") | ||
|
||
et4 := createETag("W/\"\"") | ||
require.Truef(t, et4.IsWeak(), "expected etag to be weak") | ||
|
||
et5 := ETagAny | ||
require.Falsef(t, et5.IsWeak(), "expected etag to be strong") | ||
} | ||
|
||
func TestETagEquality(t *testing.T) { | ||
weakTag := createETag("W/\"\"") | ||
weakTag1 := createETag("W/\"1\"") | ||
weakTag2 := createETag("W/\"Two\"") | ||
strongTag1 := createETag("\"1\"") | ||
strongTag2 := createETag("\"Two\"") | ||
strongTagValidChars := createETag("\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\"") | ||
weakTagValidChars := createETag("W/\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\"") | ||
|
||
require.Falsef(t, weakTag.Equals(weakTag), "Expected etags to not be equal") | ||
require.Falsef(t, weakTag1.Equals(weakTag1), "Expected etags to not be equal") | ||
require.Falsef(t, weakTag2.Equals(weakTag2), "Expected etags to not be equal") | ||
require.Falsef(t, weakTagValidChars.Equals(weakTagValidChars), "Expected etags to not be equal") | ||
|
||
require.Truef(t, strongTag1.Equals(strongTag1), "Expected etags to be equal") | ||
require.Truef(t, strongTag2.Equals(strongTag2), "Expected etags to be equal") | ||
require.Truef(t, strongTagValidChars.Equals(strongTagValidChars), "Expected etags to be equal") | ||
|
||
require.Falsef(t, weakTag1.Equals(weakTag), "Expected etags to not be equal") | ||
require.Falsef(t, strongTagValidChars.Equals(weakTagValidChars), "Expected etags to not be equal") | ||
require.Falsef(t, weakTag2.Equals(weakTag1), "Expected etags to not be equal") | ||
require.Falsef(t, strongTag1.Equals(weakTag1), "Expected etags to not be equal") | ||
require.Falsef(t, strongTag2.Equals(weakTag2), "Expected etags to not be equal") | ||
} | ||
|
||
func TestEtagAny(t *testing.T) { | ||
anyETag := ETagAny | ||
star := createETag("*") | ||
weakStar := createETag("W\"*\"") | ||
quotedStar := createETag("\"*\"") | ||
|
||
require.Truef(t, anyETag.Equals(anyETag), "Expected etags to be equal") | ||
require.Truef(t, ETagAny.Equals(anyETag), "Expected etags to be equal") | ||
|
||
require.Truef(t, star.Equals(star), "Expected etags to be equal") | ||
require.Truef(t, ETagAny.Equals(star), "Expected etags to be equal") | ||
require.Truef(t, anyETag.Equals(star), "Expected etags to be equal") | ||
|
||
require.Falsef(t, star.Equals(weakStar), "Expected etags to be equal") | ||
require.Falsef(t, ETagAny.Equals(weakStar), "Expected etags to be equal") | ||
require.Falsef(t, weakStar.Equals(quotedStar), "Expected etags to be equal") | ||
|
||
require.Falsef(t, quotedStar.Equals(star), "Expected etags to be equal") | ||
|
||
require.Truef(t, star.Equals(ETagAny), "Expected etags to be equal") | ||
} | ||
|
||
func TestETagWeakComparison(t *testing.T) { | ||
// W/"" | ||
weakTag := createETag("W/\"\"") | ||
// W/"1" | ||
weakTag1 := createETag("W/\"1\"") | ||
// W/"Two" | ||
weakTagTwo := createETag("W/\"Two\"") | ||
// W/"two" | ||
weakTagtwo := createETag("W/\"two\"") | ||
// "1" | ||
strongTag1 := createETag("\"1\"") | ||
// "Two" | ||
strongTagTwo := createETag("\"Two\"") | ||
// "two" | ||
strongTagtwo := createETag("\"two\"") | ||
|
||
require.Truef(t, weakTag.WeakEquals(weakTag), "expected etags to be equal") | ||
require.Truef(t, weakTag1.WeakEquals(weakTag1), "expected etags to be equal") | ||
require.Truef(t, weakTagTwo.WeakEquals(weakTagTwo), "expected etags to be equal") | ||
require.Truef(t, weakTagtwo.WeakEquals(weakTagtwo), "expected etags to be equal") | ||
require.Truef(t, strongTag1.WeakEquals(strongTag1), "expected etags to be equal") | ||
require.Truef(t, strongTagTwo.WeakEquals(strongTagTwo), "expected etags to be equal") | ||
require.Truef(t, strongTagtwo.WeakEquals(strongTagtwo), "expected etags to be equal") | ||
|
||
require.Falsef(t, weakTag1.WeakEquals(weakTag), "Expected etags to not be equal") | ||
require.Falsef(t, weakTagTwo.WeakEquals(weakTag1), "Expected etags to not be equal") | ||
|
||
require.Truef(t, strongTag1.WeakEquals(weakTag1), "expected etags to be equal") | ||
require.Truef(t, strongTagTwo.WeakEquals(weakTagTwo), "expected etags to be equal") | ||
|
||
require.Falsef(t, weakTag1.WeakEquals(strongTagTwo), "Expected etags to not be equal") | ||
require.Falsef(t, weakTagtwo.WeakEquals(strongTagTwo), "Expected etags to not be equal") | ||
|
||
require.Falsef(t, strongTagtwo.WeakEquals(strongTagTwo), "Expected etags to not be equal") | ||
require.Falsef(t, weakTagtwo.WeakEquals(weakTagTwo), "Expected etags to not be equal") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters