Files
gocryptotrader/cmd/apichecker/apicheck_test.go
Ryan O'Hara-Reid 4e135c9590 logger: reduce go routine generation (#992)
* logger: reduce go routine generation

* logger: shift most of processing and prep work to the worker pool, add pool for fields because each log we are pushing the struct to the heap, has better segregation now and includes a buffer in scope instead of relying on a pool

* logger: shift fmt package calls to worker pool

* logger: conform tests to new design

* linter: fix issues

* Update log/logger_test.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* Update log/logger_test.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* UN-GLORIOUS: nits

* logger: Handle config variable

* logger: NITERINOS BY GLORIOUS CODE

* logger: revert

* glorious: nits

* Panic at the disco: fix

* Panic at the disco: fix

* logger: make sure logger closed and job channel emptied on start up error

* fix tests

* logger: reduce globals

* logger: finished reduces globals, reduce workers to one too keep everything in line.

* logger: remove comments

* logger/exhchange: linter issues

* db/test: fix linter

* logger: add tests shift wait before unlock

* logger: consolidate worker code; fix linter issue and make sure we can sustain writing for external testing.

* logger: fix race and warn for conflict in config

* logger: fix name and add to tests

* logger: remove zero value field

* glorious: panic fix and removal of code

* logger: reinstate channels in close

* logger: shift reinstate processing to SetupGlobalLogger

* logger: segregate config.json from internal log.Config

* logger: fix silly mistake that is silly

* engine: Add protection for nil issues and implement new constructor in tests

* logger: Force singular mutex usage throughout package, throw away funcs that are not used outside of this package, unexport a bunch. Fix tests.

* logger: actually set advanced settings

* Update log/loggers.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* Update log/loggers.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* Update log/loggers.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* Update log/loggers.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* Update log/logger_multiwriter.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* glorious: nits

* logger: test issue when not purging temp file and contents

* loggertest: add more protections for the panics

* linter: fix

* glorious: nits

* cleanup

* logger: linter fix

* linter: fix(?) :/

* linter: revert change

* linter: fix

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>
Co-authored-by: Ryan O'Hara-Reid <ryan.oharareid@thrasher.io>
2022-10-24 11:46:18 +11:00

690 lines
15 KiB
Go

package main
import (
"encoding/json"
"os"
"reflect"
"testing"
gctfile "github.com/thrasher-corp/gocryptotrader/common/file"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/log"
)
var (
testAPIKey = ""
testAPIToken = ""
testChecklistID = ""
testCardID = ""
testListID = ""
testBoardID = ""
testBoardName = ""
canTestMainFile = false
)
func TestMain(m *testing.M) {
setTestVars()
err := log.SetGlobalLogConfig(log.GenDefaultSettings())
if err != nil {
log.Error(log.Global, err)
os.Exit(1)
}
log.Infoln(log.Global, "set verbose to true for more detailed output")
configData, err = readFileData(jsonFile)
if err != nil {
log.Error(log.Global, err)
os.Exit(1)
}
testConfigData, err = readFileData(testJSONFile)
if err != nil {
log.Error(log.Global, err)
os.Exit(1)
}
usageData = testConfigData
setTestVars()
testExitCode := m.Run()
err = removeTestFileVars()
if err != nil {
log.Error(log.Global, err)
os.Exit(1)
}
os.Exit(testExitCode)
}
func areTestAPIKeysSet() bool {
return (testAPIKey != "" && testAPIToken != "")
}
func setTestVars() {
if !canUpdateTrello() {
apiKey = testAPIKey
apiToken = testAPIToken
trelloChecklistID = testChecklistID
trelloCardID = testCardID
trelloListID = testListID
trelloBoardID = testBoardID
trelloBoardName = testBoardName
return
}
}
func removeTestFileVars() error {
a, err := readFileData(testJSONFile)
if err != nil {
return err
}
a.BoardID = ""
a.CardID = ""
a.ChecklistID = ""
a.Key = ""
a.ListID = ""
a.Token = ""
file, err := json.MarshalIndent(&a, "", " ")
if err != nil {
return err
}
return os.WriteFile(testJSONFile, file, gctfile.DefaultPermissionOctal)
}
func canTestTrello() bool {
if testAPIKey != "" && testAPIToken != "" && testChecklistID != "" && testCardID != "" && testListID != "" && (testBoardID != "" || testBoardName != "") {
return true
}
return false
}
func TestCheckUpdates(t *testing.T) {
if !canUpdateTrello() || !canTestTrello() {
t.Skip()
}
err := checkUpdates(testJSONFile)
if err != nil {
t.Fatal(err)
}
}
func TestUpdateFile(t *testing.T) {
realConf, err := readFileData(jsonFile)
if err != nil {
t.Fatal(err)
}
configData = realConf
err = updateFile(testJSONFile)
if err != nil {
t.Fatal(err)
}
testConf, err := readFileData(testJSONFile)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(realConf, testConf) {
t.Error("test file update failed")
}
}
func TestCheckExistingExchanges(t *testing.T) {
t.Parallel()
if !checkExistingExchanges("Kraken") {
t.Fatal("Kraken data not found")
}
}
func TestCheckChangeLog(t *testing.T) {
t.Parallel()
data := HTMLScrapingData{TokenData: "h1",
Key: "id",
Val: "revision-history",
TokenDataEnd: "table",
TextTokenData: "td",
DateFormat: "2006/01/02",
RegExp: `^20(\d){2}/(\d){2}/(\d){2}$`,
Path: "https://docs.gemini.com/rest-api/#revision-history"}
if _, err := checkChangeLog(&data); err != nil {
t.Error(err)
}
}
func TestAdd(t *testing.T) {
t.Parallel()
data2 := HTMLScrapingData{
TokenData: "h1",
Key: "id",
Val: "change-log",
TextTokenData: "strong",
TokenDataEnd: "p",
Path: "incorrectpath",
}
err := addExch("FalseName", htmlScrape, data2, false)
if err == nil {
t.Error("expected an error due to invalid path being parsed in")
}
}
func TestHTMLScrapeGemini(t *testing.T) {
t.Parallel()
data := HTMLScrapingData{TokenData: "h1",
Key: "id",
Val: "revision-history",
TokenDataEnd: "table",
TextTokenData: "td",
DateFormat: "2006/01/02",
RegExp: "^20(\\d){2}/(\\d){2}/(\\d){2}$",
CheckString: "2019/11/15",
Path: "https://docs.gemini.com/rest-api/#revision-history"}
_, err := htmlScrapeDefault(&data)
if err != nil {
t.Error(err)
}
}
func TestHTMLScrapeHuobi(t *testing.T) {
t.Parallel()
data := HTMLScrapingData{TokenData: "h1",
Key: "id",
Val: "change-log",
TokenDataEnd: "h2",
TextTokenData: "td",
DateFormat: "2006.01.02 15:04",
RegExp: "^20(\\d){2}.(\\d){2}.(\\d){2} (\\d){2}:(\\d){2}$",
CheckString: "2019.12.27 19:00",
Path: "https://huobiapi.github.io/docs/spot/v1/en/#change-log"}
_, err := htmlScrapeDefault(&data)
if err != nil {
t.Error(err)
}
}
func TestHTMLScrapeCoinbasepro(t *testing.T) {
t.Parallel()
data := HTMLScrapingData{TokenData: "h1",
Key: "id",
Val: "changelog",
TokenDataEnd: "ul",
TextTokenData: "strong",
DateFormat: "01/02/06",
RegExp: "^(\\d){1,2}/(\\d){1,2}/(\\d){2}$",
CheckString: "12/16/19",
Path: "https://docs.pro.coinbase.com/#changelog"}
_, err := htmlScrapeDefault(&data)
if err != nil {
t.Error(err)
}
}
func TestHTMLScrapeBitfinex(t *testing.T) {
t.Parallel()
data := HTMLScrapingData{DateFormat: "2006-01-02",
RegExp: `section-v-(2\d{3}-\d{1,2}-\d{1,2})`,
Path: "https://docs.bitfinex.com/docs/changelog"}
_, err := htmlScrapeBitfinex(&data)
if err != nil {
t.Error(err)
}
}
func TestHTMLScrapeBitmex(t *testing.T) {
t.Parallel()
data := HTMLScrapingData{TokenData: "h4",
Key: "id",
Val: "",
TokenDataEnd: "",
TextTokenData: "",
DateFormat: "Jan-2-2006",
RegExp: `([A-Z]{1}[a-z]{2}-\d{1,2}-2\d{3})`,
Path: "https://www.bitmex.com/static/md/en-US/apiChangelog"}
if _, err := htmlScrapeBitmex(&data); err != nil {
t.Error(err)
}
}
func TestHTMLScrapeHitBTC(t *testing.T) {
t.Parallel()
data := HTMLScrapingData{RegExp: `newest version \d{1}.\d{1}`,
Path: "https://api.hitbtc.com/"}
if _, err := htmlScrapeHitBTC(&data); err != nil {
t.Error(err)
}
}
func TestHTMLScrapeDefault(t *testing.T) {
t.Parallel()
data := HTMLScrapingData{TokenData: "h3",
Key: "id",
Val: "change-change",
TokenDataEnd: "section",
TextTokenData: "p",
DateFormat: "2006-01-02",
RegExp: "(2\\d{3}-\\d{1,2}-\\d{1,2})",
CheckString: "2019-04-28",
Path: "https://www.okcoin.com/docs/en/#change-change"}
_, err := htmlScrapeDefault(&data)
if err != nil {
t.Error(err)
}
}
func TestHTMLScrapeBTSE(t *testing.T) {
t.Parallel()
data := HTMLScrapingData{RegExp: `^version: \d{1}.\d{1}.\d{1}`,
Path: "https://api.btcmarkets.net/openapi/info/index.yaml"}
if _, err := htmlScrapeBTSE(&data); err != nil {
t.Error(err)
}
}
func TestHTMLScrapeBTCMarkets(t *testing.T) {
t.Parallel()
data := HTMLScrapingData{RegExp: `^version: \d{1}.\d{1}.\d{1}`,
Path: "https://api.btcmarkets.net/openapi/info/index.yaml"}
if _, err := htmlScrapeBTCMarkets(&data); err != nil {
t.Error(err)
}
}
func TestHTMLScrapeBitflyer(t *testing.T) {
t.Parallel()
data := HTMLScrapingData{TokenData: "p",
TokenDataEnd: "h3",
TextTokenData: "code",
RegExp: `^https://api.bitflyer.com/v\d{1}/$`,
Path: "https://lightning.bitflyer.com/docs?lang=en"}
if _, err := htmlScrapeBitflyer(&data); err != nil {
t.Error(err)
}
}
func TestHTMLScrapeANX(t *testing.T) {
t.Parallel()
data := HTMLScrapingData{RegExp: `ANX Exchange API v\d{1}`,
Path: "https://anxv3.docs.apiary.io/#reference/quickstart-catalog"}
if _, err := htmlScrapeANX(&data); err != nil {
t.Error(err)
}
}
func TestHTMLPoloniex(t *testing.T) {
t.Parallel()
data := HTMLScrapingData{TokenData: "h1",
Key: "id",
Val: "changelog",
TokenDataEnd: "div",
TextTokenData: "h2",
DateFormat: "2006-01-02",
RegExp: `(2\d{3}-\d{1,2}-\d{1,2})`,
Path: "https://docs.poloniex.com/#changelog"}
if _, err := htmlScrapePoloniex(&data); err != nil {
t.Error(err)
}
}
func TestHTMLItBit(t *testing.T) {
t.Parallel()
data := HTMLScrapingData{TokenData: "a",
Key: "href",
Val: "changelog",
TokenDataEnd: "div",
TextTokenData: "h2",
DateFormat: "2006-01-02",
RegExp: `^https://api.itbit.com/v\d{1}/$`,
Path: "https://api.itbit.com/docs"}
if _, err := htmlScrapeItBit(&data); err != nil {
t.Error(err)
}
}
func TestHTMLScrapeExmo(t *testing.T) {
t.Parallel()
data := HTMLScrapingData{RegExp: `Last updated on [\s\S]*, 20\d{2}`,
Path: "https://exmo.com/en/api/"}
if _, err := htmlScrapeExmo(&data); err != nil {
t.Error(err)
}
}
func TestHTMLBitstamp(t *testing.T) {
t.Parallel()
data := HTMLScrapingData{RegExp: `refer to the v\d{1} API for future references.`,
Path: "https://www.bitstamp.net/api/"}
if _, err := htmlScrapeBitstamp(&data); err != nil {
t.Error(err)
}
}
func TestHTMLKraken(t *testing.T) {
t.Parallel()
data := HTMLScrapingData{TokenData: "h3",
TokenDataEnd: "p",
TextTokenData: "p",
RegExp: `URL: https://api.kraken.com/\d{1}/private/Balance`,
Path: "https://www.kraken.com/features/api"}
if _, err := htmlScrapeKraken(&data); err != nil {
t.Error(err)
}
}
func TestHTMLAlphaPoint(t *testing.T) {
t.Parallel()
data := HTMLScrapingData{TokenData: "h1",
Key: "id",
Val: "introduction",
TokenDataEnd: "blockquote",
TextTokenData: "h3",
RegExp: `revised-calls-\d{1}-\d{1}-\d{1}-gt-\d{1}-\d{1}-\d{1}`,
Path: "https://alphapoint.github.io/slate/#introduction"}
if _, err := htmlScrapeAlphaPoint(&data); err != nil {
t.Error(err)
}
}
func TestHTMLYobit(t *testing.T) {
t.Parallel()
data := HTMLScrapingData{TokenData: "h2",
Key: "id",
Path: "https://www.yobit.net/en/api/"}
if _, err := htmlScrapeYobit(&data); err != nil {
t.Error(err)
}
}
func TestHTMLScrapeLocalBitcoins(t *testing.T) {
t.Parallel()
data := HTMLScrapingData{TokenData: "div",
RegExp: `col-md-12([\s\S]*?)clearfix`,
Path: "https://localbitcoins.com/api-docs/"}
if _, err := htmlScrapeLocalBitcoins(&data); err != nil {
t.Error(err)
}
}
func TestHTMLScrapeOk(t *testing.T) {
t.Parallel()
data := HTMLScrapingData{TokenData: "a",
Key: "href",
Val: "./#change-change",
TokenDataEnd: "./#change-",
RegExp: `./#change-\d{8}`,
Path: "https://www.okex.com/docs/en/"}
if _, err := htmlScrapeOk(&data); err != nil {
t.Error(err)
}
}
func TestUpdate(t *testing.T) {
t.Parallel()
var exchCheck, updatedExch HTMLScrapingData
for x := range configData.Exchanges {
if configData.Exchanges[x].Name == "Exmo" {
exchCheck = *configData.Exchanges[x].Data.HTMLData
}
}
info := ExchangeInfo{Name: "Exmo",
CheckType: "HTML String Check",
Data: &CheckData{HTMLData: &HTMLScrapingData{RegExp: `Last updated on [\s\S]*, 20\d{2}`,
Path: "https://exmo.com/en/api/"},
},
}
updatedExchs := update("Exmo", configData.Exchanges, info)
for y := range updatedExchs {
if updatedExchs[y].Name == "Exmo" {
updatedExch = *updatedExchs[y].Data.HTMLData
}
}
if updatedExch == exchCheck {
t.Fatal("update failed")
}
}
func TestCheckMissingExchanges(t *testing.T) {
t.Parallel()
if a := checkMissingExchanges(); len(a) > len(exchange.Exchanges) {
t.Fatal("invalid response")
}
}
func TestNameUpdates(t *testing.T) {
t.Parallel()
tester := []struct {
Name string
Status string
ExpectedName string
ErrorExpected bool
}{
{
Name: "incorrectname",
Status: "incomplete",
ErrorExpected: true,
},
{
Name: "Gemini 2 2",
Status: "incomplete",
ErrorExpected: false,
},
{
Name: " Gemini 23",
Status: "incomplete",
ErrorExpected: true,
},
{
Name: "Gemini 123",
Status: "complete",
ExpectedName: "Gemini 1",
ErrorExpected: false,
},
{
Name: "Gemini",
Status: "complete",
ExpectedName: "Gemini 1",
ErrorExpected: false,
},
{
Name: "Gemini 24 ",
Status: "incomplete",
ErrorExpected: false,
},
}
for x := range tester {
r, err := nameStateChanges(tester[x].Name, tester[x].Status)
if r != tester[x].ExpectedName && err != nil && !tester[x].ErrorExpected {
t.Errorf("%d failed, expected %v, %v, got: %v, %v\n", x,
tester[x].ExpectedName,
tester[x].ErrorExpected,
r,
err)
}
}
}
func TestReadFileData(t *testing.T) {
t.Parallel()
_, err := readFileData(testJSONFile)
if err != nil {
t.Error(err)
}
}
func TestGetSha(t *testing.T) {
t.Parallel()
_, err := getSha("binance-exchange/binance-official-api-docs")
if err != nil {
t.Error(err)
}
}
func TestCheckBoardID(t *testing.T) {
if !areTestAPIKeysSet() {
t.Skip()
}
a, err := trelloCheckBoardID()
if err != nil {
t.Error(err)
}
if a != true {
t.Error("no match found for the given boardID")
}
}
func TestTrelloGetLists(t *testing.T) {
if !areTestAPIKeysSet() {
t.Skip()
}
if _, err := trelloGetLists(); err != nil {
t.Error(err)
}
}
func TestGetAllCards(t *testing.T) {
if !areTestAPIKeysSet() {
t.Skip()
}
if _, err := trelloGetAllCards(); err != nil {
t.Error(err)
}
}
func TestGetAllChecklists(t *testing.T) {
if !areTestAPIKeysSet() {
t.Skip()
}
if _, err := trelloGetAllChecklists(); err != nil {
t.Error(err)
}
}
func TestTrelloGetAllBoards(t *testing.T) {
if !areTestAPIKeysSet() {
t.Skip()
}
if trelloBoardID != "" || testBoardName != "" {
t.Skip()
}
if _, err := trelloGetBoardID(); err != nil {
t.Error(err)
}
}
func TestCreateNewList(t *testing.T) {
if !areTestAPIKeysSet() {
t.Skip()
}
if err := trelloCreateNewList(); err != nil {
t.Error(err)
}
}
func TestTrelloCreateNewCard(t *testing.T) {
if !areTestAPIKeysSet() {
t.Skip()
}
if err := trelloCreateNewCard(); err != nil {
t.Error(err)
}
}
func TestCreateNewChecklist(t *testing.T) {
if !areTestAPIKeysSet() {
t.Skip()
}
if err := trelloCreateNewChecklist(); err != nil {
t.Error(err)
}
}
func TestWriteAuthVars(t *testing.T) {
if canTestMainFile {
trelloCardID = "jdsfl"
if err := writeAuthVars(testMode); err != nil {
t.Error(err)
}
}
}
func TestCreateNewCheck(t *testing.T) {
if !canTestTrello() {
t.Skip()
}
err := trelloCreateNewCheck("Gemini")
if err != nil {
t.Error(err)
}
}
func TestUpdateCheckItem(t *testing.T) {
if !canTestTrello() {
t.Skip()
}
a, err := trelloGetChecklistItems()
if err != nil {
t.Error(err)
}
var checkID string
for x := range a.CheckItems {
if a.CheckItems[x].Name == "Gemini 1" {
checkID = a.CheckItems[x].ID
}
}
err = trelloUpdateCheckItem(checkID, "Gemini 1", "incomplete")
if err != nil {
t.Error(err)
}
}
func TestGetChecklistItems(t *testing.T) {
if !canTestTrello() {
t.Skip()
}
_, err := trelloGetChecklistItems()
if err != nil {
t.Error(err)
}
}
func TestSetAuthVars(t *testing.T) {
t.Parallel()
apiKey = ""
configData.Key = ""
apiToken = ""
configData.Token = ""
setAuthVars()
if usageData.Key != "" && usageData.Token != "" {
t.Errorf("incorrect key and token values")
}
}
func TestTrelloDeleteCheckItems(t *testing.T) {
if !areTestAPIKeysSet() {
t.Skip()
}
err := trelloDeleteCheckItem("")
if err != nil {
t.Error(err)
}
}
func TestHTMLScrapeFTX(t *testing.T) {
data := HTMLScrapingData{
TokenData: "span",
Key: "class",
Val: "css-truncate css-truncate-target d-block width-fit",
TokenDataEnd: "svg",
Path: "https://github.com/ftexchange/ftx"}
a, err := htmlScrapeFTX(&data)
if err != nil || len(a) != 1 {
t.Error(err)
}
}
func TestHTMLScrapeBinance(t *testing.T) {
data := HTMLScrapingData{
TokenData: "h1",
Key: "id",
Val: "change-log",
TextTokenData: "strong",
TokenDataEnd: "p",
Path: "https://binance-docs.github.io/apidocs/spot/en/#change-log",
}
_, err := htmlScrapeBinance(&data)
if err != nil {
t.Error(err)
}
}