Skip to content

Commit

Permalink
Merge #681
Browse files Browse the repository at this point in the history
681: More integration tests for external tx r=piotr-iohk a=piotr-iohk

# Issue Number

#627 
#628

# Overview

<!-- Detail in a few bullet points the work accomplished in this PR -->

- [ ] I have added more integration tests for tx external API endpoint and CLI


# Comments

<!-- Additional comments or screenshots to attach if any -->

<!-- 
Don't forget to:

 ✓ Self-review your changes to make sure nothing unexpected slipped through
 ✓ Assign yourself to the PR
 ✓ Assign one or several reviewer(s)
 ✓ Once created, link this PR to its corresponding ticket
 ✓ Acknowledge any changes required to the Wiki
-->


Co-authored-by: Piotr Stachyra <piotr.stachyra@iohk.io>
Co-authored-by: IOHK <devops+nix-tools@iohk.io>
  • Loading branch information
3 people committed Sep 6, 2019
2 parents 186ae0e + 45652b0 commit a57e665
Show file tree
Hide file tree
Showing 13 changed files with 277 additions and 19 deletions.
1 change: 1 addition & 0 deletions lib/core-integration/cardano-wallet-core-integration.cabal
Expand Up @@ -52,6 +52,7 @@ library
, retry
, time
, template-haskell
, temporary
, text
, text-class
, time
Expand Down
100 changes: 98 additions & 2 deletions lib/core-integration/src/Test/Integration/Framework/DSL.hs
Expand Up @@ -72,6 +72,7 @@ module Test.Integration.Framework.DSL
, emptyWalletWith
, getFromResponse
, getFromResponseList
, getJormungandrBlock0H
, json
, listAddresses
, listTransactions
Expand All @@ -89,6 +90,7 @@ module Test.Integration.Framework.DSL
, for
, toQueryString
, utcIso8601ToText
, prepExternalTxViaJcli

-- * Endpoints
, getWalletEp
Expand All @@ -102,6 +104,8 @@ module Test.Integration.Framework.DSL
, updateWalletPassEp

-- * CLI
, runJcli
, command
, cardanoWalletCLI
, generateMnemonicsViaCLI
, createWalletViaCLI
Expand Down Expand Up @@ -196,7 +200,7 @@ import Data.Generics.Product.Fields
import Data.Generics.Product.Typed
( HasType, typed )
import Data.List
( (!!) )
( elemIndex, (!!) )
import Data.List.NonEmpty
( NonEmpty )
import Data.Maybe
Expand Down Expand Up @@ -230,13 +234,15 @@ import Numeric.Natural
import Prelude hiding
( fail )
import System.Command
( CmdResult, Stderr, Stdout, command )
( CmdResult, Stderr, Stdout (..), command )
import System.Directory
( doesPathExist )
import System.Exit
( ExitCode (..) )
import System.IO
( BufferMode (..), Handle, hClose, hFlush, hPutStr, hSetBuffering )
import System.IO.Temp
( withSystemTempDirectory )
import System.Process
( CreateProcess (..)
, ProcessHandle
Expand Down Expand Up @@ -1047,6 +1053,12 @@ updateWalletPassEp w =
--- CLI
---

runJcli
:: CmdResult r
=> [String]
-> IO r
runJcli = command [] "jcli"

-- | A class to select the right command for a given 'Context t'
class KnownCommand t where
commandName :: String
Expand Down Expand Up @@ -1316,3 +1328,87 @@ groupsOf n xs = take n xs : groupsOf n (drop n xs)
-- | 'map' flipped.
for :: [a] -> (a -> b) -> [b]
for = flip map

withTempDir :: (FilePath -> IO a) -> IO a
withTempDir = withSystemTempDirectory "external-tx"

getJormungandrBlock0H :: IO String
getJormungandrBlock0H = do
let block0File = "./test/data/jormungandr/block0.bin"
Stdout block0H <- runJcli ["genesis", "hash", "--input", block0File]
return (T.unpack . T.strip . T.pack $ block0H)

-- | Prepare externally signed Tx for Jormungandr
prepExternalTxViaJcli :: Text -> Natural -> IO Text
prepExternalTxViaJcli addrStr amt = do
withTempDir $ \d -> do
let strip = T.unpack . T.strip . T.pack
let txFile = d <> "/trans.tx"
let witnessFile = d <> "/witness"
let keyFile = "./test/data/jormungandr/key.prv"
let faucetAddr =
"ca1swl53wlqt5dnl63e0gnf8vpazgt6g5mq384dmz72329eh4m8z7e5un8q6lg"

-- get inputFunds, inputIndex and inputTxId associated with faucetAddr
-- from Jormungandr utxo
Stdout u <- runJcli
[ "rest", "v0", "utxo", "get"
, "-h", "http://127.0.0.1:8080/api" ]

let utxo = T.splitOn "\n" (T.pack u)
let (Just i) =
elemIndex ( "- address: " ++ faucetAddr ) (T.unpack <$> utxo)
let inputFunds = T.replace " associated_fund: " "" (utxo !! (i + 1))
let inputIndex = T.replace " index_in_transaction: " "" (utxo !! (i + 2))
let inputTxId = T.replace " transaction_id: " "" (utxo !! (i + 3))

-- prepare tx using `jcli`
runJcli ["transaction", "new", "--staging", txFile ]
>>= (`shouldBe` ExitSuccess)
runJcli
[ "transaction"
, "add-input"
, T.unpack inputTxId
, T.unpack inputIndex
, T.unpack inputFunds
, "--staging", txFile ]
>>= (`shouldBe` ExitSuccess)
runJcli
[ "transaction"
, "add-output"
, T.unpack addrStr
, show amt
, "--staging", txFile ]
>>= (`shouldBe` ExitSuccess)
runJcli
[ "transaction"
, "finalize"
, faucetAddr
, "--fee-constant", "42"
, "--fee-coefficient", "0"
, "--staging", txFile ]
>>= (`shouldBe` ExitSuccess)
Stdout txId <- runJcli ["transaction", "id", "--staging", txFile]
block0H <- getJormungandrBlock0H
runJcli
[ "transaction"
, "make-witness"
, strip txId
, "--genesis-block-hash", block0H
, "--type", "utxo"
, witnessFile
, keyFile ]
>>= (`shouldBe` ExitSuccess)
runJcli
[ "transaction"
, "add-witness"
, witnessFile
, "--staging", txFile ]
>>= (`shouldBe` ExitSuccess)
runJcli ["transaction", "seal", "--staging", txFile ]
>>= (`shouldBe` ExitSuccess)
Stdout txMess <- runJcli
[ "transaction"
, "to-message"
, "--staging", txFile ]
return (T.strip . T.pack $ txMess)
10 changes: 6 additions & 4 deletions lib/core-integration/src/Test/Integration/Framework/TestData.hs
Expand Up @@ -319,10 +319,12 @@ errMsg406 = "It seems as though you don't accept 'application/json', but\
\ 'Accept' request header and make sure it's set to 'application/json'"

errMsg415 :: String
errMsg415 = "I'm really sorry but I only understand 'application/json'. I need\
\ you to tell me what language you're speaking in order for me to understand\
\ your message. Please double-check your 'Content-Type' request header and\
\ make sure it's set to 'application/json'"
errMsg415 = "I'm really sorry but I only understand 'application/json'\
\ or 'application/octet-stream'. I need you to tell me what language you're\
\ speaking in order for me to understand your message. Please double-check\
\ your 'Content-Type' request header and make sure it's set to\
\ 'application/json' or 'application/octet-stream' (depending on the\
\ endpoint you want to request)."

errMsg500 :: String
errMsg500 = "That's embarrassing. It looks like I've created an invalid\
Expand Down
11 changes: 6 additions & 5 deletions lib/core/src/Cardano/Wallet/Api/Server.hs
Expand Up @@ -786,11 +786,12 @@ instance LiftHandler ServantErr where
, "set to 'application/json'."
]
415 -> apiError err' UnsupportedMediaType $ mconcat
[ "I'm really sorry but I only understand 'application/json'. I "
, "need you to tell me what language you're speaking in order for "
, "me to understand your message. Please double-check your "
, "'Content-Type' request header and make sure it's set to "
, "'application/json'."
[ "I'm really sorry but I only understand 'application/json' or "
, "'application/octet-stream'. I need you to tell me what language "
, "you're speaking in order for me to understand your message. "
, "Please double-check your 'Content-Type' request header and make "
, "sure it's set to 'application/json' or 'application/octet-stream' "
, "(depending on the endpoint you want to request)."
]
_ -> apiError err' UnexpectedError $ mconcat
[ "It looks like something unexpected went wrong. Unfortunately I "
Expand Down
Expand Up @@ -12,7 +12,7 @@ module Test.Integration.HttpBridge.Scenario.API.Transactions
import Prelude

import Cardano.Wallet.Api.Types
( ApiFee, ApiTransaction )
( ApiFee, ApiTransaction, ApiTxId )
import Cardano.Wallet.Primitive.Types
( DecodeAddress (..), EncodeAddress (..) )
import Control.Monad
Expand All @@ -35,6 +35,7 @@ import Test.Integration.Framework.DSL
, for
, json
, listAddresses
, postExternalTxEp
, postTxEp
, postTxFeeEp
, request
Expand All @@ -47,6 +48,16 @@ import qualified Network.HTTP.Types.Status as HTTP

spec :: forall t. (EncodeAddress t, DecodeAddress t) => SpecWith (Context t)
spec = do
it "TRANS_EXTERNAL_CREATE_05 - not supported for http-bridge" $ \ctx -> do
_ <- emptyWallet ctx
let headers = Headers [ ("Content-Type", "application/octet-stream") ]
r <- request @ApiTxId ctx postExternalTxEp headers Empty
verify r
[ expectResponseCode HTTP.status400
, expectErrorMessage "This endpoint is not supported by the backend\
\ currently in use. Please try a different backend."
]

it "TRANS_CREATE_09 - 0 amount transaction is forbidden on single output tx" $ \ctx -> do
(wSrc, payload) <- fixtureZeroAmtSingle ctx
r <- request @(ApiTransaction t) ctx (postTxEp wSrc) Default payload
Expand Down
Expand Up @@ -18,6 +18,8 @@ import Data.Generics.Internal.VL.Lens
( (^.) )
import Data.Proxy
( Proxy (..) )
import System.Command
( Exit (..), Stderr (..), Stdout (..) )
import System.Exit
( ExitCode (..) )
import Test.Hspec
Expand All @@ -30,6 +32,7 @@ import Test.Integration.Framework.DSL
, emptyWallet
, fixtureWallet
, listAddresses
, postExternalTransactionViaCLI
, postTransactionFeeViaCLI
, postTransactionViaCLI
, walletId
Expand All @@ -43,6 +46,14 @@ spec
:: forall t.(EncodeAddress t, DecodeAddress t, KnownCommand t)
=> SpecWith (Context t)
spec = do
it "TRANS_EXTERNAL_CREATE_05 - not supported for http-bridge" $ \ctx -> do
(Exit code, Stdout out, Stderr err) <-
postExternalTransactionViaCLI @t ctx ["1111"]
err `shouldBe` "This endpoint is not supported by the backend\
\ currently in use. Please try a different backend.\n"
out `shouldBe` mempty
code `shouldBe` ExitFailure 1

it "TRANS_CREATE_09 - 0 amount transaction is forbidden on single output tx" $ \ctx -> do
wSrc <- fixtureWallet ctx
wDest <- emptyWallet ctx
Expand Down
Binary file modified lib/jormungandr/test/data/jormungandr/block0.bin
Binary file not shown.
3 changes: 3 additions & 0 deletions lib/jormungandr/test/data/jormungandr/genesis.yaml
Expand Up @@ -3059,3 +3059,6 @@ initial:
- fund:
- address: ta1swaga8c5sjwsw86yprw5d3m44ktla3ymesn0rtwurer5pg9mmp24kznrwfg
value: 100000000000
- fund:
- address: ca1swl53wlqt5dnl63e0gnf8vpazgt6g5mq384dmz72329eh4m8z7e5un8q6lg
value: 100000000000
11 changes: 9 additions & 2 deletions lib/jormungandr/test/integration/Cardano/Faucet.hs
Expand Up @@ -3,6 +3,7 @@
module Cardano.Faucet
( initFaucet
, block0H
, block0HText
) where

import Prelude
Expand All @@ -15,18 +16,24 @@ import Cardano.Wallet.Unsafe
( unsafeFromHex, unsafeMkMnemonic )
import Control.Concurrent.MVar
( newMVar )
import Data.Text
( Text )
import Test.Integration.Faucet
( Faucet (..) )

import qualified Data.Text.Encoding as T

-- | Initialize a bunch of faucet wallets and make them available for the
-- integration tests scenarios.
initFaucet :: IO Faucet
initFaucet = do
Faucet <$> newMVar mnemonics

block0H :: Hash "Genesis"
block0H = Hash $ unsafeFromHex
"301b1c634aa7b586da7243dd66a61bde904bc1755e9a20a9b5b1b0064e70d904"
block0H = Hash $ unsafeFromHex (T.encodeUtf8 block0HText)

block0HText :: Text
block0HText = "657233631a44a0ffc49dfeb645fc2014e6e1de7e150148ff681c6884f1dcf97e"
-- ^ jcli genesis hash --input test/data/jormungandr/block0.bin

mnemonics :: [Mnemonic 15]
Expand Down

0 comments on commit a57e665

Please sign in to comment.