Skip to content

Commit

Permalink
Backend(Tests): extra safety measures against null
Browse files Browse the repository at this point in the history
This is the 3rd and last part of the bugfix for bug 242, which
makes sure that Type.GetType() won't return null again, or if
it does, that we will have enough info (or innerEx with info)
to find culprits and make better decisions later.
  • Loading branch information
knocte committed Jan 15, 2024
1 parent bd94cb7 commit 662596a
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 12 deletions.
11 changes: 7 additions & 4 deletions src/GWallet.Backend.Tests/MetaMarshalling.fs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ type MetaMarshalling() =
Assert.That(json, Is.Not.Null)
Assert.That(json, Is.Not.Empty)

let wrapperTypeString = Marshalling.ExtractStringType json
Assert.That(wrapperTypeString, Is.Not.Null)
Assert.That(wrapperTypeString, Is.Not.Empty)
let wrapper = Marshalling.ExtractWrapper json
Assert.That(wrapper, Is.Not.Null)
Assert.That(wrapper.TypeName, Is.Not.Null)
Assert.That(wrapper.TypeName, Is.Not.Empty)
Assert.That(wrapper.Version, Is.Not.Null)
Assert.That(wrapper.Version, Is.Not.Empty)

Assert.That(wrapperTypeString, Does.Not.Contain "Version=")
Assert.That(wrapper.TypeName, Does.Not.Contain "Version=")
38 changes: 30 additions & 8 deletions src/GWallet.Backend/Marshalling.fs
Original file line number Diff line number Diff line change
Expand Up @@ -145,21 +145,43 @@ module Marshalling =

let private currentVersion = VersionHelper.CURRENT_VERSION

let ExtractStringType(json: string): string =
let ExtractWrapper(json: string): MarshallingWrapper<obj> =
if String.IsNullOrEmpty json then
raise <| ArgumentNullException "json"
let wrapper = JsonConvert.DeserializeObject<MarshallingWrapper<obj>> json
if Object.ReferenceEquals(wrapper, null) then
failwith <| SPrintF1 "Failed to extract type from JSON (null check): %s" json
wrapper.TypeName
if String.IsNullOrEmpty wrapper.TypeName then
failwith <| SPrintF1 "Failed to extract type from JSON (inner null check 1): %s" json
if String.IsNullOrEmpty wrapper.Version then
failwith <| SPrintF1 "Failed to extract type from JSON (inner null check 2): %s" json
wrapper

let ExtractType(json: string): Type =
let typeName = ExtractStringType json
try
Type.GetType typeName
with
| :? NullReferenceException as _nre ->
failwith <| SPrintF1 "Failed to extract type from JSON (NRE): %s" json
let wrapper = ExtractWrapper json

let res =
try
// we prefer an ex with innerException than an NRE caused by the
// consumer of this function
let throwOnError = true

Type.GetType(wrapper.TypeName, throwOnError)
with
| :? NullReferenceException as _nre ->
failwith <| SPrintF1 "Failed to extract type from JSON (NRE): %s" json
| ex ->
let errMsg =
sprintf "Problem when trying to find type '%s' (version '%s')"
wrapper.TypeName
wrapper.Version
raise <| Exception(errMsg, ex)
if isNull res then
failwithf "Could not find type '%s' (version '%s')"
wrapper.TypeName
wrapper.Version
res


// FIXME: should we rather use JContainer.Parse? it seems JObject.Parse wouldn't detect error in this: {A:{"B": 1}}
// (for more info see replies of https://stackoverflow.com/questions/6903477/need-a-string-json-validator )
Expand Down

0 comments on commit 662596a

Please sign in to comment.