Repository: smithy-lang/smithy
Pull request #2467 (2024-11-15 21:35:00)

Update blob defaults for protocol tests
### Description 
Updates the blob defaults in a few protocol tests to conform with expected values.

Also adds documentation on the expected constraints on default blob values and a validator to warn on incorrect values. A warning is used instead of an error as this could otherwise be a breaking change for consumers 

---
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.



Patch:
diff --git a/docs/source-2.0/spec/type-refinement-traits.rst b/docs/source-2.0/spec/type-refinement-traits.rst
index e14c8a42e..7ebbb4d52 100644
--- a/docs/source-2.0/spec/type-refinement-traits.rst
+++ b/docs/source-2.0/spec/type-refinement-traits.rst
@@ -105,6 +105,7 @@ numeric types MUST be numbers that fit within the targeted type and match any
 
 The following shapes have restrictions on their default values:
 
+* blob: can be set to any valid base64-encoded string.
 * enum: can be set to any valid string *value* of the enum.
 * intEnum: can be set to any valid integer *value* of the enum.
 * document: can be set to ``null``, ```true``, ``false``, string, numbers,
diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/DefaultTraitValidator.java b/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/DefaultTraitValidator.java
index ff0bd2922..ae95a9012 100644
--- a/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/DefaultTraitValidator.java
+++ b/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/DefaultTraitValidator.java
@@ -15,7 +15,9 @@
 
 package software.amazon.smithy.model.validation.validators;
 
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
+import java.util.Base64;
 import java.util.List;
 import software.amazon.smithy.model.Model;
 import software.amazon.smithy.model.knowledge.NeighborProviderIndex;
@@ -109,6 +111,15 @@ public final class DefaultTraitValidator extends AbstractValidator {
         events.addAll(shape.accept(visitor));
 
         switch (shapeTarget.getType()) {
+            case BLOB:
+                try {
+                    value.asStringNode().ifPresent(val -> {
+                        Base64.getDecoder().decode(val.getValue().getBytes(StandardCharsets.UTF_8));
+                    });
+                } catch (IllegalArgumentException exc) {
+                    events.add(warning(shape, trait, "The @default value of a blob should be a valid base64 string."));
+                }
+                break;
             case MAP:
                 value.asObjectNode().ifPresent(obj -> {
                     if (!obj.isEmpty()) {


Test patch:
diff --git a/smithy-aws-protocol-tests/model/awsJson1_0/required.smithy b/smithy-aws-protocol-tests/model/awsJson1_0/required.smithy
index 036bf45e9..7d281a7a6 100644
--- a/smithy-aws-protocol-tests/model/awsJson1_0/required.smithy
+++ b/smithy-aws-protocol-tests/model/awsJson1_0/required.smithy
@@ -54,7 +54,7 @@ apply OperationWithRequiredMembersWithDefaults @httpResponseTests([
             requiredBoolean: true
             requiredList: []
             requiredTimestamp: 1
-            requiredBlob: "{}"
+            requiredBlob: "blob"
             requiredByte: 1
             requiredShort: 1
             requiredInteger: 10
@@ -127,7 +127,7 @@ structure RequiredMembersWithDefaultsMixin {
     requiredTimestamp: Timestamp = 1
 
     @required
-    requiredBlob: Blob = "{}"
+    requiredBlob: Blob = "YmxvYg=="
 
     @required
     requiredByte: Byte = 1
diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/defaults/default-with-invalid-blob.errors b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/defaults/default-with-invalid-blob.errors
new file mode 100644
index 000000000..2db4d8441
--- /dev/null
+++ b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/defaults/default-with-invalid-blob.errors
@@ -0,0 +1,2 @@
+[WARNING] smithy.example#Foo$invalidBlob: The @default value of a blob should be a valid base64 string. | DefaultTrait
+[WARNING] smithy.example#InvalidBlob: The @default value of a blob should be a valid base64 string. | DefaultTrait
diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/defaults/default-with-invalid-blob.smithy b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/defaults/default-with-invalid-blob.smithy
new file mode 100644
index 000000000..6271edef4
--- /dev/null
+++ b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/defaults/default-with-invalid-blob.smithy
@@ -0,0 +1,10 @@
+$version: "2.0"
+
+namespace smithy.example
+
+structure Foo {
+    invalidBlob: Blob = "{}"
+}
+
+@default("{}") // invalid default value
+blob InvalidBlob
diff --git a/smithy-protocol-tests/model/rpcv2Cbor/defaults.smithy b/smithy-protocol-tests/model/rpcv2Cbor/defaults.smithy
index 53df9a2c3..1dce66736 100644
--- a/smithy-protocol-tests/model/rpcv2Cbor/defaults.smithy
+++ b/smithy-protocol-tests/model/rpcv2Cbor/defaults.smithy
@@ -314,7 +314,7 @@ structure DefaultsMixin {
     defaultBoolean: Boolean = true
     defaultList: TestStringList = []
     defaultTimestamp: Timestamp = 0
-    defaultBlob: Blob = "abc"
+    defaultBlob: Blob = "YWJj"
     defaultByte: Byte = 1
     defaultShort: Short = 1
     defaultInteger: Integer = 10