Skip to content

Commit

Permalink
feat!: use FormatException instead of custom ValidationException
Browse files Browse the repository at this point in the history
  • Loading branch information
JKRhb committed Jun 2, 2024
1 parent 4d47ee5 commit f7ee480
Show file tree
Hide file tree
Showing 19 changed files with 38 additions and 85 deletions.
2 changes: 1 addition & 1 deletion lib/src/binding_coap/coap_extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ extension CoapFormExtension on AugmentedForm {
return BlockSize.fromDecodedValue(value);
// ignore: avoid_catching_errors
} on ArgumentError {
throw ValidationException(
throw FormatException(
"Encountered invalid blocksize $value in CoAP form",
);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/src/binding_mqtt/mqtt_extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ extension MqttFormExtension on AugmentedForm {

// TODO: This validation should maybe already happen earlier.
if (qosValue != null) {
throw ValidationException(
throw FormatException(
"Encountered unknown QoS value $qosValue. "
"in form with href $href of Thing Description with Identifier "
"$tdIdentifier.",
Expand Down
10 changes: 4 additions & 6 deletions lib/src/core/definitions/context.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import "package:collection/collection.dart";
import "package:curie/curie.dart";
import "package:meta/meta.dart";

import "../exceptions.dart";

const _tdVersion10ContextUrl = "https://www.w3.org/2019/wot/td/v1";
const _tdVersion11ContextUrl = "https://www.w3.org/2022/wot/td/v1.1";

Expand All @@ -30,14 +28,14 @@ final class Context {
final firstContextEntry = contextEntries.firstOrNull;

if (firstContextEntry is! SingleContextEntry) {
throw const ValidationException("Missing TD context URL.");
throw const FormatException("Missing TD context URL.");
}

final firstContextValue = firstContextEntry.value;

if (![_tdVersion10ContextUrl, _tdVersion11ContextUrl]
.contains(firstContextValue)) {
throw ValidationException(
throw FormatException(
"Encountered invalid TD context URL $firstContextEntry",
);
}
Expand Down Expand Up @@ -142,12 +140,12 @@ final class SingleContextEntry extends ContextEntry {
/// Creates a new [SingleContextEntry] from a [string] that represents a URI.
///
/// If the [string] should not be a valid URI, this factory constructor will
/// throw a [ValidationException].
/// throw a [FormatException].
factory SingleContextEntry.fromString(String string) {
final parsedUri = Uri.tryParse(string);

if (parsedUri == null) {
throw ValidationException("Encountered invalid URI $string");
throw FormatException("Encountered invalid URI $string");
}

return SingleContextEntry(parsedUri);
Expand Down
13 changes: 6 additions & 7 deletions lib/src/core/definitions/extensions/json_parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

import "package:curie/curie.dart";

import "../../exceptions.dart";
import "../additional_expected_response.dart";
import "../context.dart";
import "../data_schema.dart";
Expand Down Expand Up @@ -96,7 +95,7 @@ extension ParseField on Map<String, dynamic> {
}

/// Parses a single field with a given [name] and throws a
/// [ValidationException] if the field is not present or does not have the
/// [FormatException] if the field is not present or does not have the
/// type [T].
///
/// Like [parseField], it adds the field [name] to the set of [parsedFields],
Expand All @@ -105,7 +104,7 @@ extension ParseField on Map<String, dynamic> {
final fieldValue = parseField(name, parsedFields);

if (fieldValue is! T) {
throw ValidationException(
throw FormatException(
"Value for field $name has wrong data type or is missing. "
"Expected ${T.runtimeType}, got ${fieldValue.runtimeType}.",
);
Expand All @@ -115,7 +114,7 @@ extension ParseField on Map<String, dynamic> {
}

/// Parses a single field with a given [name] as a [Uri] and throws a
/// [ValidationException] if the field is not present or cannot be parsed.
/// [FormatException] if the field is not present or cannot be parsed.
///
/// If a [Set] of [parsedFields] is passed to this function, the field [name]
/// will added. This can be used for filtering when parsing additional fields.
Expand Down Expand Up @@ -284,7 +283,7 @@ extension ParseField on Map<String, dynamic> {
return forms;
}

throw const ValidationException(
throw const FormatException(
'Missing "forms" member in InteractionAffordance',
);
}
Expand Down Expand Up @@ -610,7 +609,7 @@ Iterable<ContextEntry> _parseContextEntries(dynamic json) sync* {
final value = entry.value;

if (value is! String) {
throw ValidationException(
throw FormatException(
"Expected $value to be a String or a Map<String, String> "
"as @context entry, got ${value.runtimeType} instead.");
}
Expand All @@ -625,7 +624,7 @@ Iterable<ContextEntry> _parseContextEntries(dynamic json) sync* {
});
}
default:
throw ValidationException(
throw FormatException(
"Expected the @context entry $json to "
"either be a String or a Map<String, String>, "
"got ${json.runtimeType} instead.",
Expand Down
3 changes: 1 addition & 2 deletions lib/src/core/definitions/operation_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
//
// SPDX-License-Identifier: BSD-3-Clause

import "../exceptions.dart";
import "interaction_affordances/interaction_affordance.dart";

/// Enumeration for the possible WoT operation types.
Expand Down Expand Up @@ -55,7 +54,7 @@ enum OperationType {
final operationType = OperationType._registry[stringValue];

if (operationType == null) {
throw ValidationException(
throw FormatException(
"Encountered unknown OperationType $stringValue.",
);
}
Expand Down
3 changes: 1 addition & 2 deletions lib/src/core/definitions/thing_description.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import "package:curie/curie.dart";
import "package:meta/meta.dart";

import "../exceptions.dart";
import "additional_expected_response.dart";
import "context.dart";
import "data_schema.dart";
Expand Down Expand Up @@ -60,7 +59,7 @@ class ThingDescription {
if (validate) {
final validationResult = thingDescriptionSchema.validate(json);
if (!validationResult.isValid) {
throw ValidationException(
throw FormatException(
"Validation of Thing Description failed.",
validationResult.errors,
);
Expand Down
28 changes: 0 additions & 28 deletions lib/src/core/exceptions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,34 +24,6 @@ base class DartWotException implements Exception {
String toString() => "$exceptionType: $message";
}

/// An [Exception] that is thrown when the validation of a definition fails.
base class ValidationException extends DartWotException {
/// Constructor.
const ValidationException(super.message, [this._validationErrors]);

final List<Object>? _validationErrors;

@override
String get exceptionType => "ValidationException";

@override
String toString() {
final String formattedValidationErrors;

final validationErrors = _validationErrors;
if (validationErrors != null) {
formattedValidationErrors = [
"\n\nErrors:\n",
...validationErrors,
].join("\n");
} else {
formattedValidationErrors = "";
}

return "$exceptionType: $message$formattedValidationErrors";
}
}

/// Custom [Exception] that is thrown when the discovery process fails.
final class DiscoveryException extends DartWotException {
/// Creates a new [DiscoveryException] with the specified error [message].
Expand Down
5 changes: 2 additions & 3 deletions lib/src/core/implementation/augmented_form.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import "package:meta/meta.dart";
import "package:uri/uri.dart";

import "../definitions.dart";
import "../exceptions.dart";

/// A [Form] augmented with information from its associated [_thingDescription]
/// and [_interactionAffordance].
Expand Down Expand Up @@ -140,7 +139,7 @@ final class AugmentedForm implements Form {
.where((element) => !affordanceUriVariables.containsKey(element));

if (uncoveredHrefUriVariables.isNotEmpty) {
throw ValidationException(
throw FormatException(
"The following URI template variables defined in the form's href "
"but are not covered by a uriVariable entry at the TD or affordance "
"level: ${uncoveredHrefUriVariables.join(", ")}.");
Expand All @@ -162,7 +161,7 @@ final class AugmentedForm implements Form {
final result = schema.validate(userProvidedValue);

if (!result.isValid) {
throw ValidationException("Invalid type for URI variable $key");
throw FormatException("Invalid type for URI variable $key");
}
}
}
Expand Down
5 changes: 2 additions & 3 deletions lib/src/core/implementation/content_serdes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import "package:http_parser/http_parser.dart";
import "package:json_schema/json_schema.dart";

import "../definitions/data_schema.dart";
import "../exceptions.dart";
import "../scripting_api/data_schema_value.dart";
import "codecs/cbor_codec.dart";
import "codecs/codec_media_type.dart";
Expand Down Expand Up @@ -145,15 +144,15 @@ class ContentSerdes {
}

if (dataSchemaValue == null) {
throw const ValidationException("Expected a defined dataSchemaValue");
throw const FormatException("Expected a defined dataSchemaValue");
}

final schema = JsonSchema.create(
Map.fromEntries(filteredDataSchemaJson),
schemaVersion: SchemaVersion.draft7,
);
if (!schema.validate(dataSchemaValue.value).isValid) {
throw const ValidationException("JSON Schema validation failed.");
throw const FormatException("JSON Schema validation failed.");
}
}

Expand Down
2 changes: 1 addition & 1 deletion lib/src/core/implementation/thing_discovery.dart
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ class ThingDiscovery extends Stream<ThingDescription>
return dataSchemaValue.value.toThingDescription();
}

throw ValidationException(
throw FormatException(
"Encountered wrong datatype ${dataSchemaValue.runtimeType} that cannot "
"be processed as a Thing Description.",
);
Expand Down
4 changes: 2 additions & 2 deletions test/binding_coap/coap_definitions_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,11 @@ void main() {
);
expect(
() => invalidForm.block1Size,
throwsA(isA<ValidationException>()),
throwsA(isA<FormatException>()),
);
expect(
() => invalidForm.block2Size,
throwsA(isA<ValidationException>()),
throwsA(isA<FormatException>()),
);
});
});
Expand Down
2 changes: 1 addition & 1 deletion test/binding_mqtt/mqtt_extension_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ void main() {

expect(
() => augmentedForm.qualityOfService,
throwsA(isA<ValidationException>()),
throwsA(isA<FormatException>()),
);
});
});
Expand Down
4 changes: 2 additions & 2 deletions test/core/augmented_form_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ void main() {

expect(
() => augmentedForm4.resolvedHref,
throwsA(isA<ValidationException>()),
throwsA(isA<FormatException>()),
);

final augmentedForm5 = AugmentedForm(
Expand All @@ -209,7 +209,7 @@ void main() {

expect(
() => augmentedForm5.resolvedHref,
throwsA(isA<ValidationException>()),
throwsA(isA<FormatException>()),
);

final augmentedForm6 = AugmentedForm(
Expand Down
2 changes: 1 addition & 1 deletion test/core/consumed_thing_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ void main() {
"status2",
uriVariables: uriVariables,
),
throwsA(const TypeMatcher<ValidationException>()),
throwsA(const TypeMatcher<FormatException>()),
);

await servient.shutdown();
Expand Down
7 changes: 3 additions & 4 deletions test/core/content_serdes_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

import "package:curie/curie.dart";
import "package:dart_wot/src/core/definitions/data_schema.dart";
import "package:dart_wot/src/core/exceptions.dart";
import "package:dart_wot/src/core/implementation/codecs/json_codec.dart";
import "package:dart_wot/src/core/implementation/content.dart";
import "package:dart_wot/src/core/implementation/content_serdes.dart";
Expand Down Expand Up @@ -41,15 +40,15 @@ void main() {

expect(
contentSerdes.contentToValue(testContent2, failingSchema),
throwsA(const TypeMatcher<ValidationException>()),
throwsA(const TypeMatcher<FormatException>()),
);

expect(
() => contentSerdes.valueToContent(
DataSchemaValue.tryParse(42),
failingSchema,
),
throwsA(const TypeMatcher<ValidationException>()),
throwsA(const TypeMatcher<FormatException>()),
);

final testContent3 = _getTestContent("");
Expand Down Expand Up @@ -150,7 +149,7 @@ void main() {
// FIXME(JKRhb): Should not be necessary to use fromJson here
DataSchema.fromJson(const {"type": "object"}, PrefixMapping()),
),
throwsA(isA<ValidationException>()),
throwsA(isA<FormatException>()),
);
});

Expand Down
5 changes: 2 additions & 3 deletions test/core/context_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
//
// SPDX-License-Identifier: BSD-3-Clause

import "package:dart_wot/core.dart";
import "package:dart_wot/src/core/definitions/context.dart";
import "package:dart_wot/src/core/definitions/extensions/json_parser.dart";
import "package:test/test.dart";
Expand All @@ -17,7 +16,7 @@ void main() {

expect(
() => Context([illegalSingleContextEntry]),
throwsA(isA<ValidationException>()),
throwsA(isA<FormatException>()),
);
});

Expand Down Expand Up @@ -90,7 +89,7 @@ void main() {
test("only be valid when created from a valid URI", () {
expect(
() => SingleContextEntry.fromString("::foobar::"),
throwsA(isA<ValidationException>()),
throwsA(isA<FormatException>()),
);
});

Expand Down
Loading

0 comments on commit f7ee480

Please sign in to comment.