Hacker Public Radio

HPR3489: Equality of structured errors


Listen Later

Equality of structured errors
Background
In previous episode, I built a system where error codes weren't defined in one huge type. This made compilation times faster and maintenance quite a bit more easier.
Problem
I wanted to write a test to see that parameters passed to validatePatchApiPersonR are validated correctly. patchApiPersonR is used by client to do partial updates on a Person entity. There's three different cases I wanted to check:
trying to change life focus too soon (there's 5 year cooldown)
trying to select same life focus that has already been selected
trying to modify somebody else's avatar
Code is shown below and the last 2 lines are the interesting ones. There I'm using equality to compare if a given error exists in a list of errors created by validatePatchApiPersonR.
spec :: Spec
spec = do
describe "people" $ do
describe "life focus" $ do
describe "Validating requests" $ do
it "All errors are reported" $ do
forAll anyCompletelyFaultyRequest $
(userE, personE, msg, date) ->
let res = validatePatchApiPersonR (userE ^. entityKeyL, userE ^. entityValL, personE, msg, date)
newFocus = msg ^? patchPersonRequestLifeFocus . _Just . _Just
in
case res of
V.Success _ ->
expectationFailure "Invalid request was not detected"
V.Failure errs -> do
errs `shouldSatisfy` (xs -> any (x -> "CanNotChangeLifeFocusSoSoon" `isInfixOf` (pack $ show x)) xs)
errs `shouldContain` [ canNotReselectSameLifeFocus newFocus ]
errs `shouldContain` [ insufficientRights ]
Detour on equality
Equality in Haskell works slightly differently compared to for example C#. There is no built in, default implementation that gets used when the programmer hasn't written their own. If you want to compare equality, there needs to be implementation specific to your data types. This is done by making an instance of type class Eq (https://hackage.haskell.org/package/base-4.15.0.0/docs/Data-Eq.html).
class Eq a where
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
There's two functions: == for equality and /= for inequality. You need to implement either one.
Back to problem
ECode is our structured error code type and defined as follows (this is short recap of previous episode):
data ECode where
ECode :: (ErrorCodeClass a, ToJSON a, Eq a, Show a) => a -> ECode
It can wrap anything that has correct type class instances and you will always get ECode as a result. It hides the specific type of thing being wrapped and only functions defined in type classes are available.
First try
Peel away ECode and compare what's inside and compare wrapped values:
instance Eq ECode where
ECode a == ECode b =
a == b
This will lead into a error "Couldn't match expected type ‘a’ with actual type ‘a1’. ‘a1’ is a rigid type variable bound by a pattern with constructor...". This is because ECode can wrap man
...more
View all episodesView all episodes
Download on the App Store

Hacker Public RadioBy Hacker Public Radio

  • 4.2
  • 4.2
  • 4.2
  • 4.2
  • 4.2

4.2

34 ratings


More shows like Hacker Public Radio

View all
The Changelog: Software Development, Open Source by Changelog Media

The Changelog: Software Development, Open Source

290 Listeners

Defensive Security Podcast - Malware, Hacking, Cyber Security & Infosec by Jerry Bell and Andrew Kalat

Defensive Security Podcast - Malware, Hacking, Cyber Security & Infosec

372 Listeners

LINUX Unplugged by Jupiter Broadcasting

LINUX Unplugged

268 Listeners

SANS Internet Stormcenter Daily Cyber Security Podcast (Stormcast) by Johannes B. Ullrich

SANS Internet Stormcenter Daily Cyber Security Podcast (Stormcast)

651 Listeners

Curious Cases by BBC Radio 4

Curious Cases

821 Listeners

The Strong Towns Podcast by Strong Towns

The Strong Towns Podcast

423 Listeners

Late Night Linux by The Late Night Linux Family

Late Night Linux

164 Listeners

Darknet Diaries by Jack Rhysider

Darknet Diaries

8,059 Listeners

Cybersecurity Today by Jim Love

Cybersecurity Today

179 Listeners

CISO Series Podcast by David Spark, Mike Johnson, and Andy Ellis

CISO Series Podcast

189 Listeners

TechCrunch Daily Crunch by TechCrunch

TechCrunch Daily Crunch

42 Listeners

Strict Scrutiny by Crooked Media

Strict Scrutiny

5,800 Listeners

2.5 Admins by The Late Night Linux Family

2.5 Admins

98 Listeners

Cyber Security Headlines by CISO Series

Cyber Security Headlines

139 Listeners

What the Hack? by DeleteMe

What the Hack?

228 Listeners