Skip to content

Commit

Permalink
Switch test-suite to use pretty-show and yaml for the output capture …
Browse files Browse the repository at this point in the history
…for easier diffs
  • Loading branch information
alexbiehl committed Feb 6, 2024
1 parent cc6f64a commit 3a05cd1
Show file tree
Hide file tree
Showing 70 changed files with 414 additions and 279 deletions.
1 change: 1 addition & 0 deletions scarf-gateway.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ test-suite scarf-gateway-test
, internal
, manifest
, network-uri
, pretty-show
, scarf-gateway
, tasty
, tasty-golden
Expand Down
4 changes: 2 additions & 2 deletions src/Scarf/Gateway/Rule.hs
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,10 @@ data RedirectOrProxy
| -- | Respond with bytes directly.
RespondBytes
!RuleCapture
-- | Headers we might want sent back
!ResponseHeaders
-- ^ Headers we might want sent back
-- | Response body
!LBS.ByteString
-- ^ Response body
| -- | Respond OK with no data
RespondOk
!RuleCapture
Expand Down
5 changes: 2 additions & 3 deletions src/Scarf/Gateway/Rule/Capture.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import Data.Aeson (Value)
import Data.ByteString (ByteString)
import Data.HashMap.Strict (HashMap)
import Data.Text (Text)
import Data.Text qualified as Text
import Data.Time (UTCTime)
import Data.UUID (UUID)
import Data.UUID.V4 qualified as UUID
Expand Down Expand Up @@ -78,7 +77,7 @@ newRequestId = RequestId <$> UUID.nextRandom
-- scarf-server.
--
-- TODO Switch to e.g. thrift encoding using Schema
newtype CapturedRequest = CapturedRequest Text
newtype CapturedRequest = CapturedRequest (Maybe RuleCapture)
deriving newtype (Show)

-- | Captures all the relevant information for further processing.
Expand All @@ -102,4 +101,4 @@ captureRequest ::
Maybe RuleCapture ->
CapturedRequest
captureRequest _time _requestId _request _responseStatus mcapture =
CapturedRequest $ Text.pack $ maybe "" show mcapture
CapturedRequest $ mcapture
6 changes: 4 additions & 2 deletions src/Scarf/Lib/Tracing.hs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,8 @@ withRootTracer manager msamplingRate action = do
not (null pushEndpoint) = do
let options =
zipkinOptions manager endpoint
& zoEndpoint .~ pushEndpoint
& zoEndpoint
.~ pushEndpoint

close zipkin =
closeZipkin zipkin `catch` \(_ :: BlockedIndefinitelyOnSTM) ->
Expand All @@ -207,7 +208,8 @@ withRootTracer manager msamplingRate action = do
Just port <- readMaybe (unpack port') = do
let options =
jaegerAgentOptions serviceName
& jaoAddr .~ UDPAddr (unpack hostname) port
& jaoAddr
.~ UDPAddr (unpack hostname) port
withJaegerAgent options $ \agent -> do
let batchOpts =
batchOptions (traverse_ (jaegerAgentReporter agent))
Expand Down
82 changes: 36 additions & 46 deletions test/Scarf/Gateway/Golden.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,24 @@ import Data.Aeson
( FromJSON (..),
ToJSON (..),
Value (Null),
decode,
encode,
object,
withObject,
(.!=),
(.:),
(.:?),
(.=),
)
import Data.Aeson.Encode.Pretty (confCompare, defConfig, encodePretty')
import Data.Aeson.Encoding (dict, int, pair, pairs, text, unsafeToEncoding)
import Data.Bifunctor (Bifunctor (bimap), first)
import Data.ByteString qualified as ByteString
import Data.ByteString.Builder (stringUtf8)
import Data.ByteString.Lazy qualified
import Data.CaseInsensitive qualified as CaseInsensitive
import Data.HashMap.Strict qualified as HashMap
import Data.IORef (newIORef, readIORef, writeIORef)
import Data.List (sort)
import Data.Map.Strict qualified as Map
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import Data.Text.Encoding (decodeUtf8, encodeUtf8)
import Data.Yaml (decodeFileThrow)
import Data.Yaml (decodeFileThrow, encode)
import Network.Wai
( Request
( rawQueryString,
Expand Down Expand Up @@ -75,10 +70,11 @@ import Scarf.Gateway.Rule.Capture
)
import Scarf.Lib.Tracing (nullTracer)
import Scarf.Manifest (Manifest, manifestToRules)
import System.FilePath (replaceExtension)
import System.FilePath (replaceExtension, takeExtensions)
import System.IO.Unsafe (unsafeInterleaveIO)
import Test.Tasty (TestTree)
import Test.Tasty.Golden (findByExtension, goldenVsStringDiff)
import Text.Show.Pretty qualified

-- | Input values for Golden tests.
data Input = Input
Expand Down Expand Up @@ -141,7 +137,15 @@ test_gateway_golden = goldenTests "test/golden"

goldenTests :: FilePath -> IO [TestTree]
goldenTests testsDirectory = do
inputFiles <- findByExtension [".yaml"] testsDirectory
inputFiles' <- findByExtension [".yaml"] testsDirectory

-- The glob above also includes the .output.yaml files. Ensure
-- we only take the input files.
let inputFiles =
filter
(\file -> takeExtensions file == ".yaml")
inputFiles'

when (null inputFiles) $
error "No golden tests!"
flip foldMap inputFiles $ \inputFile -> do
Expand Down Expand Up @@ -198,32 +202,27 @@ goldenTests testsDirectory = do
}
(request, capture) <- takeMVar chan

-- We want to have clear and deterministic diffs. For that we have to run the produced
-- JSON through aeson-pretty.
let json :: Value
json =
fromMaybe (error "impossible") $
decode $
encode $
Output
{ outputQueryString =
decodeUtf8 (rawQueryString request),
outputStatus =
fromEnum simpleStatus,
outputHeaders =
fmap (bimap (decodeUtf8 . CaseInsensitive.original) decodeUtf8) simpleHeaders,
outputCapture =
capture
}
pure (encodePretty' (defConfig {confCompare = compare}) json, simpleBody)
let output =
Output
{ outputQueryString =
decodeUtf8 (rawQueryString request),
outputStatus =
fromEnum simpleStatus,
outputHeaders =
fmap (bimap (decodeUtf8 . CaseInsensitive.original) decodeUtf8) simpleHeaders,
outputCapture =
capture
}

pure (Data.ByteString.Lazy.fromStrict (Data.Yaml.encode output), simpleBody)

let compareFiles = \ref new -> ["diff", "-u", ref, new]

pure
[ goldenVsStringDiff
inputFile
compareFiles
(replaceExtension inputFile "output.json")
(replaceExtension inputFile "output.yaml")
(pure (fst testResult)),
goldenVsStringDiff
(inputFile <> " body")
Expand Down Expand Up @@ -256,21 +255,12 @@ instance FromJSON Input where
<*> o .: "manifest"

instance ToJSON Output where
toJSON =
error "Unimplemented due to CapturedRequest not having a ToJSON instance for performance reasons"

toEncoding Output {..} =
pairs $
pair "status" (int outputStatus)
<> pair
"headers"
(dict text text Map.foldrWithKey (Map.fromList outputHeaders))
<> pair
"capture"
( unsafeToEncoding
( stringUtf8 $ show outputCapture
)
)
<> if outputQueryString /= ""
then pair "query" (text outputQueryString)
else mempty
toJSON Output {..} =
object $
[ "status" .= outputStatus,
"headers" .= Map.fromList outputHeaders,
"capture" .= Text.Show.Pretty.ppShow outputCapture
]
<> [ "query" .= outputQueryString
| outputQueryString /= ""
]
8 changes: 0 additions & 8 deletions test/golden/auto-creation-rules-1.output.json

This file was deleted.

13 changes: 13 additions & 0 deletions test/golden/auto-creation-rules-1.output.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
capture: |-
Just
DockerCapture
{ dockerCaptureImage = [ "library" , "proxy" ]
, dockerCaptureReference = "latest"
, dockerCaptureBackendRegistry = "ghcr.io"
, dockerCapturePackage = Nothing
, dockerCaptureAutoCreate = Just "rule-123"
}
headers:
Location: https://ghcr.io/v2/library/proxy/manifests/latest
X-This-Request-Was-Proxied: '1'
status: 307
Empty file.
14 changes: 14 additions & 0 deletions test/golden/auto-creation-rules-2.output.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
capture: |-
Just
DockerCapture
{ dockerCaptureImage = [ "library" , "hello-world" ]
, dockerCaptureReference = "latest"
, dockerCaptureBackendRegistry = "ghcr.io"
, dockerCapturePackage =
Just "8717953c-3452-4ef7-9a14-b64dc19163b4"
, dockerCaptureAutoCreate = Nothing
}
headers:
Location: https://ghcr.io/v2/library/hello-world/manifests/latest
X-This-Request-Was-Proxied: '1'
status: 307
15 changes: 15 additions & 0 deletions test/golden/auto-creation-rules-2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
path: /v2/library/hello-world/manifests/latest
headers:
Host: cr.test.io
manifest:
rules:
- type: docker-v1
repository-name: library/hello-world
domain: cr.test.io
registry: ghcr.io
package-id: "8717953c-3452-4ef7-9a14-b64dc19163b4"
- type: docker-v2
domain: cr.test.io
registry: ghcr.io
rule-id: rule-123
pattern: "library/hello-world"
8 changes: 0 additions & 8 deletions test/golden/docker-test-1.output.json

This file was deleted.

14 changes: 14 additions & 0 deletions test/golden/docker-test-1.output.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
capture: |-
Just
DockerCapture
{ dockerCaptureImage = [ "library" , "proxy" ]
, dockerCaptureReference = "latest"
, dockerCaptureBackendRegistry = "ghcr.io"
, dockerCapturePackage =
Just "8717953c-3452-4ef7-9a14-b64dc19163b4"
, dockerCaptureAutoCreate = Nothing
}
headers:
Location: https://ghcr.io/v2/library/proxy/manifests/latest
X-This-Request-Was-Proxied: '1'
status: 307

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
capture: |-
Just
FlatfileCapture
{ fileAbsoluteUrl = Nothing
, fileVariables =
fromList
[ ( "somevar" , "very-nice" ) , ( "somevar2" , "really-nice" ) ]
, filePackage = "21c24cd1-73fa-4970-8a6a-bc570e55b91e"
}
headers: {}
status: 200

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
capture: Nothing
headers: {}
status: 404

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
capture: Nothing
headers: {}
status: 404
5 changes: 0 additions & 5 deletions test/golden/file-package-with-no-outgoing-url.output.json

This file was deleted.

9 changes: 9 additions & 0 deletions test/golden/file-package-with-no-outgoing-url.output.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
capture: |-
Just
FlatfileCapture
{ fileAbsoluteUrl = Nothing
, fileVariables = fromList []
, filePackage = "a3941b62-12ff-4c39-a263-4342495f4b8b"
}
headers: {}
status: 200
8 changes: 0 additions & 8 deletions test/golden/file-package-with-variables-1.output.json

This file was deleted.

15 changes: 15 additions & 0 deletions test/golden/file-package-with-variables-1.output.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
capture: |-
Just
FlatfileCapture
{ fileAbsoluteUrl =
Just
"https://datausa.io/api/data?drilldowns=Nation&measures=Population"
, fileVariables =
fromList
[ ( "drilldowns" , "Nation" ) , ( "measures" , "Population" ) ]
, filePackage = "a1b331fa-1539-49e5-bdc4-dc8a48e586d1"
}
headers:
Location: https://datausa.io/api/data?drilldowns=Nation&measures=Population
query: ?drilldowns=Nation&measures=Population
status: 302
8 changes: 0 additions & 8 deletions test/golden/file-package-with-variables-2.output.json

This file was deleted.

15 changes: 15 additions & 0 deletions test/golden/file-package-with-variables-2.output.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
capture: |-
Just
FlatfileCapture
{ fileAbsoluteUrl =
Just
"https://datausa.io/api/data?drilldowns=Nation&measures=Population"
, fileVariables =
fromList
[ ( "drilldowns" , "Nation" ) , ( "measures" , "Population" ) ]
, filePackage = "a1b331fa-1539-49e5-bdc4-dc8a48e586d1"
}
headers:
Location: https://datausa.io/api/data?drilldowns=Nation&measures=Population
query: ?measures=Population
status: 302
Loading

0 comments on commit 3a05cd1

Please sign in to comment.