mirror of
https://github.com/Start9Labs/registry.git
synced 2026-03-30 19:54:47 +00:00
more robust testing
This commit is contained in:
@@ -1,9 +0,0 @@
|
|||||||
bitcoind:
|
|
||||||
title: "Bitcoin Core"
|
|
||||||
description:
|
|
||||||
short: "A Bitcoin Full Node"
|
|
||||||
long: "The bitcoin full node implementation by Bitcoin Core."
|
|
||||||
version-info:
|
|
||||||
- version: 0.18.1
|
|
||||||
release-notes: "Some stuff"
|
|
||||||
icon-type: png
|
|
||||||
@@ -62,6 +62,7 @@ dependencies:
|
|||||||
- yesod-core >=1.6 && <1.7
|
- yesod-core >=1.6 && <1.7
|
||||||
- yesod-static
|
- yesod-static
|
||||||
- yesod-persistent >= 1.6 && < 1.7
|
- yesod-persistent >= 1.6 && < 1.7
|
||||||
|
- shakespeare >=2.0 && <2.1
|
||||||
|
|
||||||
library:
|
library:
|
||||||
source-dirs: src
|
source-dirs: src
|
||||||
|
|||||||
@@ -6,4 +6,17 @@ bitcoind:
|
|||||||
version-info:
|
version-info:
|
||||||
- version: 0.18.1
|
- version: 0.18.1
|
||||||
release-notes: "Some stuff"
|
release-notes: "Some stuff"
|
||||||
|
- version: 0.18.2
|
||||||
|
release-notes: "Some more stuff"
|
||||||
|
icon-type: png
|
||||||
|
cups:
|
||||||
|
title: "Cups Messenger"
|
||||||
|
description:
|
||||||
|
short: "P2P Encrypted messaging"
|
||||||
|
long: "Peer-to-peer encrypted messaging platform that operates over tor."
|
||||||
|
version-info:
|
||||||
|
- version: 0.2.1
|
||||||
|
release-notes: "Some stuff"
|
||||||
|
- version: 0.2.2
|
||||||
|
release-notes: "Some more stuff"
|
||||||
icon-type: png
|
icon-type: png
|
||||||
@@ -10,24 +10,24 @@ import Database.Persist.Sql
|
|||||||
import Model
|
import Model
|
||||||
import Settings
|
import Settings
|
||||||
|
|
||||||
fetchApp :: MonadIO m => AppIdentifier -> AppVersion -> ReaderT SqlBackend m (Maybe (Entity App))
|
fetchApp :: MonadIO m => AppIdentifier -> AppVersion -> ReaderT SqlBackend m (Maybe (Entity SApp))
|
||||||
fetchApp appId appVersion = selectFirst [AppAppId ==. appId, AppSemver ==. appVersion] []
|
fetchApp appId appVersion = selectFirst [SAppAppId ==. appId, SAppVersion ==. appVersion] []
|
||||||
|
|
||||||
createApp :: MonadIO m => AppIdentifier -> AppSeed -> ReaderT SqlBackend m (Maybe (Key App))
|
createApp :: MonadIO m => AppIdentifier -> AppSeed -> ReaderT SqlBackend m (Maybe (Key SApp))
|
||||||
createApp appId AppSeed{..} = do
|
createApp appId AppSeed{..} = do
|
||||||
time <- liftIO $ getCurrentTime
|
time <- liftIO $ getCurrentTime
|
||||||
insertUnique $ App
|
insertUnique $ SApp
|
||||||
time
|
time
|
||||||
Nothing
|
Nothing
|
||||||
title
|
appSeedTitle
|
||||||
appId
|
appId
|
||||||
descShort
|
appSeedDescShort
|
||||||
descLong
|
appSeedDescLong
|
||||||
appVersion
|
appSeedVersion
|
||||||
releaseNotes'
|
appSeedReleaseNotes
|
||||||
iconType
|
appSeedIconType
|
||||||
|
|
||||||
createMetric :: MonadIO m => Maybe (Key App) -> AppIdentifier -> ReaderT SqlBackend m ()
|
createMetric :: MonadIO m => Maybe (Key SApp) -> AppIdentifier -> ReaderT SqlBackend m ()
|
||||||
createMetric appId event = do
|
createMetric appId event = do
|
||||||
time <- liftIO $ getCurrentTime
|
time <- liftIO $ getCurrentTime
|
||||||
insert_ $ Metric
|
insert_ $ Metric
|
||||||
@@ -41,15 +41,15 @@ createAllAppVersions app appId = do
|
|||||||
-- inseryt new records and replace existing records (matching any unique constraint)
|
-- inseryt new records and replace existing records (matching any unique constraint)
|
||||||
putMany $ toList $ storeAppToSeed time appId app
|
putMany $ toList $ storeAppToSeed time appId app
|
||||||
|
|
||||||
storeAppToSeed :: UTCTime -> AppIdentifier -> StoreApp -> NonEmpty App
|
storeAppToSeed :: UTCTime -> AppIdentifier -> StoreApp -> NonEmpty SApp
|
||||||
storeAppToSeed time appId StoreApp{..} = map (\b -> App
|
storeAppToSeed time appId StoreApp{..} = map (\b -> SApp
|
||||||
time
|
time
|
||||||
Nothing
|
Nothing
|
||||||
storeAppTitle
|
storeAppTitle
|
||||||
appId
|
appId
|
||||||
storeAppDescShort
|
storeAppDescShort
|
||||||
storeAppDescLong
|
storeAppDescLong
|
||||||
(semver b)
|
(version' b)
|
||||||
(releaseNotes b)
|
(releaseNotes' b)
|
||||||
storeAppIconType
|
storeAppIconType
|
||||||
) storeAppSemver
|
) storeAppVersionInfo
|
||||||
|
|||||||
@@ -83,22 +83,22 @@ getApp rootDir ext@(Extension appId) = do
|
|||||||
Nothing -> sendResponseStatus status400 ("App not present in manifest" :: Text)
|
Nothing -> sendResponseStatus status400 ("App not present in manifest" :: Text)
|
||||||
Just StoreApp{..} -> do
|
Just StoreApp{..} -> do
|
||||||
-- look up at specfic version
|
-- look up at specfic version
|
||||||
VersionInfo{..} <- case NE.filter (\v -> appVersion == semver v) storeAppSemver of
|
VersionInfo{..} <- case NE.filter (\v -> appVersion == version' v) storeAppVersionInfo of
|
||||||
[] -> sendResponseStatus status400 ("App version not present in manifest" :: Text)
|
[] -> sendResponseStatus status400 ("App version not present in manifest" :: Text)
|
||||||
x : _ -> pure x
|
x : _ -> pure x
|
||||||
pure $ AppSeed
|
pure $ AppSeed
|
||||||
{ title = storeAppTitle
|
{ appSeedTitle = storeAppTitle
|
||||||
, descShort = storeAppDescShort
|
, appSeedDescShort = storeAppDescShort
|
||||||
, descLong = storeAppDescLong
|
, appSeedDescLong = storeAppDescLong
|
||||||
, appVersion = semver
|
, appSeedVersion = version'
|
||||||
, releaseNotes' = releaseNotes
|
, appSeedReleaseNotes = releaseNotes'
|
||||||
, iconType = storeAppIconType
|
, appSeedIconType = storeAppIconType
|
||||||
}
|
}
|
||||||
-- create metric based off these app details
|
|
||||||
appKey <- runDB $ createApp appId' deets
|
appKey <- runDB $ createApp appId' deets
|
||||||
case appKey of
|
case appKey of
|
||||||
Nothing -> $logWarn $ "app at this version already exists in db, no need to insert"
|
Nothing -> $logWarn $ "app at this version already exists in db, no need to insert" -- unreachable
|
||||||
Just k -> runDB $ createMetric (Just k) appId' -- log app download
|
-- log app download
|
||||||
|
Just k -> runDB $ createMetric (Just k) appId'
|
||||||
Just a -> runDB $ createMetric (Just $ entityKey a) appId'
|
Just a -> runDB $ createMetric (Just $ entityKey a) appId'
|
||||||
sz <- liftIO $ fileSize <$> getFileStatus filePath
|
sz <- liftIO $ fileSize <$> getFileStatus filePath
|
||||||
addHeader "Content-Length" (show sz)
|
addHeader "Content-Length" (show sz)
|
||||||
|
|||||||
@@ -12,23 +12,23 @@ import Lib.Types.Semver
|
|||||||
|
|
||||||
|
|
||||||
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
|
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
|
||||||
App
|
SApp
|
||||||
createdAt UTCTime
|
createdAt UTCTime
|
||||||
updatedAt UTCTime Maybe
|
updatedAt UTCTime Maybe
|
||||||
title Text
|
title Text
|
||||||
appId Text
|
appId Text
|
||||||
descShort Text
|
descShort Text
|
||||||
descLong Text
|
descLong Text
|
||||||
semver AppVersion
|
version AppVersion
|
||||||
releaseNotes Text
|
releaseNotes Text
|
||||||
iconType Text
|
iconType Text
|
||||||
UniqueSemver semver
|
UniqueVersion version
|
||||||
deriving Eq
|
deriving Eq
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
Metric
|
Metric
|
||||||
createdAt UTCTime
|
createdAt UTCTime
|
||||||
appId AppId Maybe default=null
|
appId SAppId Maybe default=null
|
||||||
event Text
|
event Text
|
||||||
deriving Eq
|
deriving Eq
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|||||||
@@ -96,19 +96,19 @@ getAppManifest resourcesDir = do
|
|||||||
|
|
||||||
type AppIdentifier = Text
|
type AppIdentifier = Text
|
||||||
data AppSeed = AppSeed
|
data AppSeed = AppSeed
|
||||||
{ title :: Text
|
{ appSeedTitle :: Text
|
||||||
, descShort :: Text
|
, appSeedDescShort :: Text
|
||||||
, descLong :: Text
|
, appSeedDescLong :: Text
|
||||||
, appVersion :: AppVersion
|
, appSeedVersion :: AppVersion
|
||||||
, releaseNotes' :: Text
|
, appSeedReleaseNotes :: Text
|
||||||
, iconType :: Text
|
, appSeedIconType :: Text
|
||||||
} deriving (Show)
|
} deriving (Show)
|
||||||
|
|
||||||
data StoreApp = StoreApp
|
data StoreApp = StoreApp
|
||||||
{ storeAppTitle :: Text
|
{ storeAppTitle :: Text
|
||||||
, storeAppDescShort :: Text
|
, storeAppDescShort :: Text
|
||||||
, storeAppDescLong :: Text
|
, storeAppDescLong :: Text
|
||||||
, storeAppSemver :: NonEmpty VersionInfo -- TODO rename
|
, storeAppVersionInfo :: NonEmpty VersionInfo
|
||||||
, storeAppIconType :: Text
|
, storeAppIconType :: Text
|
||||||
} deriving (Show)
|
} deriving (Show)
|
||||||
|
|
||||||
@@ -124,19 +124,19 @@ instance FromJSON AppManifest where
|
|||||||
storeAppIconType <- config .: "icon-type"
|
storeAppIconType <- config .: "icon-type"
|
||||||
storeAppDescShort <- config .: "description" >>= (.: "short")
|
storeAppDescShort <- config .: "description" >>= (.: "short")
|
||||||
storeAppDescLong <- config .: "description" >>= (.: "long")
|
storeAppDescLong <- config .: "description" >>= (.: "long")
|
||||||
storeAppSemver <- config .: "version-info" >>= \case
|
storeAppVersionInfo <- config .: "version-info" >>= \case
|
||||||
[] -> fail "No Valid Version Info"
|
[] -> fail "No Valid Version Info"
|
||||||
(x:xs) -> pure $ x :| xs
|
(x:xs) -> pure $ x :| xs
|
||||||
return $ (appId, StoreApp {..})
|
return $ (appId, StoreApp {..})
|
||||||
return $ AppManifest (HM.fromList apps)
|
return $ AppManifest (HM.fromList apps)
|
||||||
|
|
||||||
data VersionInfo = VersionInfo
|
data VersionInfo = VersionInfo
|
||||||
{ semver :: AppVersion
|
{ version' :: AppVersion
|
||||||
, releaseNotes :: Text
|
, releaseNotes' :: Text
|
||||||
} deriving (Eq, Ord, Show)
|
} deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
instance FromJSON VersionInfo where
|
instance FromJSON VersionInfo where
|
||||||
parseJSON = withObject "version info" $ \o -> do
|
parseJSON = withObject "version info" $ \o -> do
|
||||||
semver <- o .: "version"
|
version' <- o .: "version"
|
||||||
releaseNotes <- o .: "release-notes"
|
releaseNotes' <- o .: "release-notes"
|
||||||
pure VersionInfo {..}
|
pure VersionInfo {..}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ module Handler.AppSpec (spec) where
|
|||||||
|
|
||||||
import Startlude
|
import Startlude
|
||||||
import TestImport
|
import TestImport
|
||||||
|
import Database.Persist.Sql
|
||||||
|
import Model
|
||||||
|
|
||||||
spec :: Spec
|
spec :: Spec
|
||||||
spec = do
|
spec = do
|
||||||
@@ -15,15 +17,29 @@ spec = do
|
|||||||
bodyContains "bitcoind"
|
bodyContains "bitcoind"
|
||||||
bodyContains "version: 0.18.1"
|
bodyContains "version: 0.18.1"
|
||||||
statusIs 200
|
statusIs 200
|
||||||
describe "GET /apps/:appId" $
|
describe "GET /apps/:appId with unknown version spec for bitcoin" $
|
||||||
withApp $ it "fails to get unknown app" $ do
|
withApp $ it "fails to get unknown app" $ do
|
||||||
request $ do
|
request $ do
|
||||||
setMethod "GET"
|
setMethod "GET"
|
||||||
setUrl ("/apps/bitcoind.s9pk?spec=0.18.2" :: Text)
|
setUrl ("/apps/bitcoind.s9pk?spec=0.18.3" :: Text)
|
||||||
statusIs 404
|
statusIs 404
|
||||||
describe "GET /apps/:appId" $
|
describe "GET /apps/:appId with existing version spec for bitcoin" $
|
||||||
withApp $ it "makes da records" $ do
|
withApp $ it "creates app and metric records" $ do
|
||||||
request $ do
|
request $ do
|
||||||
setMethod "GET"
|
setMethod "GET"
|
||||||
setUrl ("/apps/bitcoind.s9pk?spec=0.18.1" :: Text)
|
setUrl ("/apps/bitcoind.s9pk?spec=0.18.1" :: Text)
|
||||||
statusIs 200
|
statusIs 200
|
||||||
|
apps <- runDBtest $ selectList [SAppAppId ==. "bitcoind"] []
|
||||||
|
metrics <- runDBtest $ selectList [MetricEvent ==. "bitcoind"] []
|
||||||
|
assertEq "app should exist" (length apps) 1
|
||||||
|
assertEq "metric should exist" (length metrics) 1
|
||||||
|
describe "GET /apps/:appId with existing version spec for cups" $
|
||||||
|
withApp $ it "creates app and metric records" $ do
|
||||||
|
request $ do
|
||||||
|
setMethod "GET"
|
||||||
|
setUrl ("/apps/cups.s9pk?spec=0.2.1" :: Text)
|
||||||
|
statusIs 200
|
||||||
|
apps <- runDBtest $ selectList [SAppAppId ==. "cups"] []
|
||||||
|
metrics <- runDBtest $ selectList [MetricEvent ==. "cups"] []
|
||||||
|
assertEq "app should exist" (length apps) 1
|
||||||
|
assertEq "metric should exist" (length metrics) 1
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
{-# LANGUAGE QuasiQuotes #-}
|
{-# LANGUAGE QuasiQuotes #-}
|
||||||
|
{-# LANGUAGE RankNTypes #-}
|
||||||
|
{-# LANGUAGE KindSignatures #-}
|
||||||
|
|
||||||
module TestImport
|
module TestImport
|
||||||
( module TestImport
|
( module TestImport
|
||||||
@@ -12,6 +14,10 @@ import Test.Hspec as X
|
|||||||
import Yesod.Default.Config2 (useEnv, loadYamlSettings)
|
import Yesod.Default.Config2 (useEnv, loadYamlSettings)
|
||||||
import Yesod.Test as X
|
import Yesod.Test as X
|
||||||
import Yesod.Core.Unsafe (fakeHandlerGetLogger)
|
import Yesod.Core.Unsafe (fakeHandlerGetLogger)
|
||||||
|
import Database.Persist.Sql
|
||||||
|
import Text.Shakespeare.Text (st)
|
||||||
|
import Yesod.Core
|
||||||
|
import qualified Data.Text as T
|
||||||
|
|
||||||
runHandler :: Handler a -> YesodExample AgentCtx a
|
runHandler :: Handler a -> YesodExample AgentCtx a
|
||||||
runHandler handler = do
|
runHandler handler = do
|
||||||
@@ -25,5 +31,38 @@ withApp = before $ do
|
|||||||
[]
|
[]
|
||||||
useEnv
|
useEnv
|
||||||
foundation <- makeFoundation settings
|
foundation <- makeFoundation settings
|
||||||
|
wipeDB foundation
|
||||||
logWare <- liftIO $ makeLogWare foundation
|
logWare <- liftIO $ makeLogWare foundation
|
||||||
return (foundation, logWare)
|
return (foundation, logWare)
|
||||||
|
|
||||||
|
getTables :: DB [Text]
|
||||||
|
getTables = do
|
||||||
|
tables <- rawSql [st|
|
||||||
|
SELECT table_name
|
||||||
|
FROM information_schema.tables
|
||||||
|
WHERE table_schema = 'public'
|
||||||
|
AND table_type = 'BASE TABLE';
|
||||||
|
|] []
|
||||||
|
|
||||||
|
return $ map unSingle tables
|
||||||
|
|
||||||
|
wipeDB :: AgentCtx -> IO ()
|
||||||
|
wipeDB app = runDBWithApp app $ do
|
||||||
|
tables <- getTables
|
||||||
|
sqlBackend <- ask
|
||||||
|
|
||||||
|
let escapedTables = map (T.unpack . connEscapeName sqlBackend . DBName) tables
|
||||||
|
query = "TRUNCATE TABLE " ++ (intercalate ", " $ escapedTables)
|
||||||
|
rawExecute (T.pack query) []
|
||||||
|
|
||||||
|
runDBtest :: SqlPersistM a -> YesodExample AgentCtx a
|
||||||
|
runDBtest query = do
|
||||||
|
app <- getTestYesod
|
||||||
|
liftIO $ runDBWithApp app query
|
||||||
|
|
||||||
|
runDBWithApp :: AgentCtx -> SqlPersistM a -> IO a
|
||||||
|
runDBWithApp app query = runSqlPersistMPool query (appConnPool app)
|
||||||
|
|
||||||
|
-- A convenient synonym for database access functions.
|
||||||
|
type DB a = forall (m :: * -> *).
|
||||||
|
(MonadUnliftIO m) => ReaderT SqlBackend m a
|
||||||
|
|||||||
Reference in New Issue
Block a user