mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 23:16:45 +00:00
Engine: Scripting support (#383)
* WIP * updated appveyor and increased deadline 5 seconds due to increased linters being added * revert files to upstream/engine * WIP * WIP * mod file changes * added script manager * Added manager/and cli interfaces to scripting * Added script task handler * WIP - Added timer/repeat support and fleshed out wrapper further * autoload support added + WIP * WIP commit * added account balance info * btc markets temp work around * WIP - merged with upstream for new order package BTC Markets responses broken * Cancel order wrapper WIP * order wrapper update * Added test coverage for VM * moved to map for VM List shutdown of all VM now handled added gctcli commands for list and stop of running scripts * added override to load/execute for path * fixed incorrect channel shutdown added further test coverage and restructured gctcli commands into sub commands * increased test coverage for packages * Added docs cleaned up tests and example scripts * Test coverage increased for module/gct/exchange package * windows fixes * merged upstream/engine * WIP * logger fixes - removed pointer to bool check removed duplicate test check for logger * remove unused mutex * added inital upload support * fix linter issues for go-fmt * added zip support for uploading and added base for fund withdrawing * changed error return types and also log errors, fix zip path issue * improved error outputs and code flow * pairs response fix added protobuf defs for stop all and list all * added stop all running scripts general clean up and moved across to OrderManager * linter fixes (gofmt) * added list all command * rewrote zip handler to be cleaner also fixed file overwrite on upload * added query command reworked tests * added further error checking to compileandrun corrected use of pointers for accountinfo * bumped tengo version * Removed named returns reworded log messages removed unused falseptr * WIP * Added virutal machine limit improved config options * added model for script event added upload validation * script_event table has been completed, tests for wrapper functions implemented * README updates * reverted changes opened new PR to move withdraw struct outs * intial work on adding withdraw support after merger of withdraw package * started work on examples * Added crypto withdraw support * fix switch case assignment and gofmt project * Reworking Fiat withdraw request pending #402 * removed double pointer call * added withdraw support for fiat currencies * added tests for withdraw methods increased readme * removed local tengo require and also fix linter issues * Added default log size const added basic test for invalid script execution * First pass at moving wrapper to validator package to allow proper validation of uploaded scripts * Added script details to README added config test added test for no file extension * moved tests to const and fixed incorrect pathing * added test coverage to withdraw package * corrected file close handling * point to included configtest.json * extended validator support when a script is uploaded * Bug fix on bool logic * Added mutex * Don't create autit events on test execution * reverted common to master * moved file rename to unix timestamp format * converted logger enabled back to pointer as i need nilness check also moved scriptid to text over blob * started work on autoload add/remove support * First round of PR fixes (mostly commented exports) * Moved GCTScript load to last, removed unneeded error from cleanup() * Comment clairty for AuitEventID * added autoload add/remove command to cli * added tests for autoload * Test updates for Exchanges * linter fixes (gofmt) * Removed double check of engine pointer * remove possible nil pointer on GetSpecificTicker * Fixed not closing file handler on write that causes archive removal to fail * file handler Close clean ups * corrected spelling on error return and return invalid name n autoload * moved strings to cosnt moved bool pointer creation to convert package * new zip extractor added * Validation has been added to archive uploads * removed shadow var on err * added ok check to conversion * converted condition check * basic test for zip extract added * new zip handler * reverted back to old atomic loading system * removed shadow err * lets add a new line * added space to error return * command line toggle for script now works properly * readme updated * set configLoaded to true * check for configLoaded condition * added mutex to allow for multiple access on virtual machine increased test coverage disable script manager if scripting is disabled * linked up to enable/disablesubsystem commands * added start/stop example to readme * reworked logic on test as check should be done on Load() * updated to tengo v2 * linters * lower time on ntp client to stop slippage * remove all fails if any fail validtion from an archive * remove vm from list if timer is invalid * removed shadow on err * remove config creation from NTPCheck test * WIP testing DB changes * add unique constraint * WIP: created has many model * linters run * basic sqlite3 support added for new database format * linters run * Added test coverage for script repo * removed unused print * updated env vars for CI instances * updated env vars for CI instances * Updated test packages * Test updates for postgresql * removed invalid tests from postgres * remove duplication of struct and improved code flow * general cleanup * wording changes on log output * use databasemgr logger and add support for autoload without file extension * corrected test naming * return correct error * return correct error again version 82 * store scriptdata on creation * Hello * Errorln -> Errorf * Removed unused vars * Read me updates * testing without parallel * comment on exported type * added nil check against VM for test * add debugging information * gofmt * remove verbose and data sent to channel * Added debug information * linter fixes (gofmt) * remove unused CompileAndRun() call * test sleep to see if issue is timing related * semi-concurrent map fixes * one day i will run gofmt or setup precommit hooks * new line :D * increased test coverage * added correct sleep time * Moved over to sync map * linter fixes (gofmt) * goimports * moved VM related methods to vm.go * new line at end of file * trying increased timeout on golangci-lint for appveyor * add debugging information * removed timeout * reworked timeout logic * linter fixes (gofmt) * increased test coverage * increased test coverage * one day i will run gofmt or setup precommit hooks * removed unused exchange test * increased golangci-lint timeout * Added nil check on shutdown and test coverage for it lowered timeout back to 1:30 * reworked ID system * removed script hash as it was unused * added comments on exported methods and read me update * reorder code * removed to atomic.value for test execution flag * increased test coverage * move add further up execution * point to correct script file
This commit is contained in:
@@ -24,7 +24,8 @@ environment:
|
||||
PSQL_PASS: Password12!
|
||||
PSQL_DBNAME: gct_dev_ci
|
||||
PSQL_SSLMODE: disable
|
||||
|
||||
PSQL_SKIPSQLCMD: true
|
||||
PSQL_TESTDBNAME: gct_dev_ci
|
||||
stack: go 1.13.x
|
||||
|
||||
services:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
run:
|
||||
timeout: 1m0s
|
||||
timeout: 1m30s
|
||||
issues-exit-code: 1
|
||||
tests: true
|
||||
skip-dirs:
|
||||
|
||||
@@ -24,6 +24,8 @@ matrix:
|
||||
- PSQL_USER=postgres
|
||||
- PSQL_HOST=localhost
|
||||
- PSQL_DBNAME=gct_dev_ci
|
||||
- PSQL_SKIPSQLCMD=true
|
||||
- PSQL_TESTDBNAME=gct_dev_ci
|
||||
install: true
|
||||
cache:
|
||||
directories:
|
||||
@@ -48,6 +50,8 @@ matrix:
|
||||
- PSQL_USER=postgres
|
||||
- PSQL_HOST=localhost
|
||||
- PSQL_DBNAME=gct_dev_ci
|
||||
- PSQL_SKIPSQLCMD=true
|
||||
- PSQL_TESTDBNAME=gct_dev_ci
|
||||
install: true
|
||||
cache:
|
||||
directories:
|
||||
|
||||
@@ -72,6 +72,7 @@ We are aiming to support the top 20 highest volume exchanges based off the [Coin
|
||||
+ Packages for handling currency pairs, tickers and orderbooks.
|
||||
+ Portfolio management tool; fetches balances from supported exchanges and allows for custom address tracking.
|
||||
+ Basic event trigger system.
|
||||
+ Scripting support. See [gctscript](/gctscript/README.md)
|
||||
+ WebGUI (discontinued).
|
||||
|
||||
## Planned Features
|
||||
|
||||
@@ -4,8 +4,10 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -2915,3 +2917,436 @@ func getAuditEvent(c *cli.Context) error {
|
||||
jsonOutput(result)
|
||||
return nil
|
||||
}
|
||||
|
||||
var uuid, filename, path string
|
||||
var gctScriptCommand = cli.Command{
|
||||
Name: "gctscript",
|
||||
Usage: "execute gctscript command",
|
||||
ArgsUsage: "<command> <args>",
|
||||
Subcommands: []cli.Command{
|
||||
{
|
||||
Name: "execute",
|
||||
Usage: "execute script filename",
|
||||
ArgsUsage: "<filename> <path>",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "filename",
|
||||
Usage: "<filename>",
|
||||
Destination: &filename,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "path",
|
||||
Usage: "<script path>",
|
||||
Destination: &path,
|
||||
},
|
||||
},
|
||||
Action: gctScriptExecute,
|
||||
},
|
||||
{
|
||||
Name: "query",
|
||||
Usage: "query running virtual machine",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "uuid",
|
||||
Usage: "<uuid>",
|
||||
Destination: &uuid,
|
||||
},
|
||||
},
|
||||
Action: gctScriptQuery,
|
||||
},
|
||||
{
|
||||
Name: "read",
|
||||
Usage: "read script",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "name",
|
||||
Usage: "<name>",
|
||||
Destination: &uuid,
|
||||
},
|
||||
},
|
||||
Action: gctScriptRead,
|
||||
},
|
||||
{
|
||||
Name: "status",
|
||||
Usage: "get status of running scripts",
|
||||
Action: gctScriptStatus,
|
||||
},
|
||||
{
|
||||
Name: "list",
|
||||
Usage: "lists all scripts in default scriptpath",
|
||||
Action: gctScriptList,
|
||||
},
|
||||
{
|
||||
Name: "stop",
|
||||
Usage: "terminate running script",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "uuid",
|
||||
Usage: "<uuid>",
|
||||
Destination: &uuid,
|
||||
},
|
||||
},
|
||||
Action: gctScriptStop,
|
||||
},
|
||||
{
|
||||
Name: "stopall",
|
||||
Usage: "terminate running script",
|
||||
Action: gctScriptStopAll,
|
||||
},
|
||||
{
|
||||
Name: "upload",
|
||||
Usage: "upload a new script/archive",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "path",
|
||||
Usage: "<path> to single script or zip collection",
|
||||
Destination: &filename,
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "overwrite",
|
||||
Usage: "<true/false>",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "archived",
|
||||
Usage: "<true/false>",
|
||||
},
|
||||
},
|
||||
Action: gctScriptUpload,
|
||||
},
|
||||
{
|
||||
Name: "autoload",
|
||||
Usage: "add or remove script from autoload list",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "command",
|
||||
Usage: "<add/remove>",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "script",
|
||||
Usage: "<script name>",
|
||||
},
|
||||
},
|
||||
Action: gctScriptAutoload,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func gctScriptAutoload(c *cli.Context) error {
|
||||
if c.NArg() == 0 && c.NumFlags() == 0 {
|
||||
_ = cli.ShowSubcommandHelp(c)
|
||||
return nil
|
||||
}
|
||||
|
||||
var command, script string
|
||||
var status bool
|
||||
if !c.IsSet("command") {
|
||||
if c.Args().Get(0) != "" {
|
||||
command = c.Args().Get(0)
|
||||
}
|
||||
}
|
||||
|
||||
if !c.IsSet("script") {
|
||||
if c.Args().Get(1) != "" {
|
||||
script = c.Args().Get(1)
|
||||
}
|
||||
}
|
||||
|
||||
switch command {
|
||||
case "add":
|
||||
status = false
|
||||
case "remove":
|
||||
status = true
|
||||
default:
|
||||
_ = cli.ShowSubcommandHelp(c)
|
||||
return nil
|
||||
}
|
||||
|
||||
conn, err := setupClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
client := gctrpc.NewGoCryptoTraderClient(conn)
|
||||
|
||||
executeCommand, err := client.GCTScriptAutoLoadToggle(context.Background(),
|
||||
&gctrpc.GCTScriptAutoLoadRequest{
|
||||
Script: script,
|
||||
Status: status,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
jsonOutput(executeCommand)
|
||||
return nil
|
||||
}
|
||||
|
||||
func gctScriptExecute(c *cli.Context) error {
|
||||
if c.NArg() == 0 && c.NumFlags() == 0 {
|
||||
_ = cli.ShowSubcommandHelp(c)
|
||||
return nil
|
||||
}
|
||||
|
||||
if !c.IsSet("filename") {
|
||||
if c.Args().Get(0) != "" {
|
||||
filename = c.Args().Get(0)
|
||||
}
|
||||
}
|
||||
|
||||
if !c.IsSet("path") {
|
||||
if c.Args().Get(1) != "" {
|
||||
path = c.Args().Get(1)
|
||||
}
|
||||
}
|
||||
|
||||
conn, err := setupClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
client := gctrpc.NewGoCryptoTraderClient(conn)
|
||||
|
||||
executeCommand, err := client.GCTScriptExecute(context.Background(),
|
||||
&gctrpc.GCTScriptExecuteRequest{
|
||||
Script: &gctrpc.GCTScript{
|
||||
Name: filename,
|
||||
Path: path,
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
jsonOutput(executeCommand)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func gctScriptStatus(c *cli.Context) error {
|
||||
conn, err := setupClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
client := gctrpc.NewGoCryptoTraderClient(conn)
|
||||
|
||||
executeCommand, err := client.GCTScriptStatus(context.Background(),
|
||||
&gctrpc.GCTScriptStatusRequest{})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
jsonOutput(executeCommand)
|
||||
return nil
|
||||
}
|
||||
|
||||
func gctScriptList(c *cli.Context) error {
|
||||
conn, err := setupClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
client := gctrpc.NewGoCryptoTraderClient(conn)
|
||||
|
||||
executeCommand, err := client.GCTScriptListAll(context.Background(),
|
||||
&gctrpc.GCTScriptListAllRequest{})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
jsonOutput(executeCommand)
|
||||
return nil
|
||||
}
|
||||
|
||||
func gctScriptStop(c *cli.Context) error {
|
||||
if c.NArg() == 0 && c.NumFlags() == 0 {
|
||||
_ = cli.ShowSubcommandHelp(c)
|
||||
return nil
|
||||
}
|
||||
|
||||
if !c.IsSet("uuid") {
|
||||
if c.Args().Get(0) != "" {
|
||||
uuid = c.Args().Get(0)
|
||||
}
|
||||
}
|
||||
|
||||
conn, err := setupClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
client := gctrpc.NewGoCryptoTraderClient(conn)
|
||||
|
||||
executeCommand, err := client.GCTScriptStop(context.Background(),
|
||||
&gctrpc.GCTScriptStopRequest{
|
||||
Script: &gctrpc.GCTScript{UUID: uuid},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
jsonOutput(executeCommand)
|
||||
return nil
|
||||
}
|
||||
|
||||
func gctScriptStopAll(c *cli.Context) error {
|
||||
conn, err := setupClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
client := gctrpc.NewGoCryptoTraderClient(conn)
|
||||
|
||||
executeCommand, err := client.GCTScriptStopAll(context.Background(),
|
||||
&gctrpc.GCTScriptStopAllRequest{})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
jsonOutput(executeCommand)
|
||||
return nil
|
||||
}
|
||||
|
||||
func gctScriptRead(c *cli.Context) error {
|
||||
if c.NArg() == 0 && c.NumFlags() == 0 {
|
||||
_ = cli.ShowSubcommandHelp(c)
|
||||
return nil
|
||||
}
|
||||
|
||||
if !c.IsSet("name") {
|
||||
if c.Args().Get(0) != "" {
|
||||
uuid = c.Args().Get(0)
|
||||
}
|
||||
}
|
||||
|
||||
conn, err := setupClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
client := gctrpc.NewGoCryptoTraderClient(conn)
|
||||
|
||||
executeCommand, err := client.GCTScriptReadScript(context.Background(),
|
||||
&gctrpc.GCTScriptReadScriptRequest{
|
||||
Script: &gctrpc.GCTScript{
|
||||
Name: uuid,
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
jsonOutput(executeCommand)
|
||||
return nil
|
||||
}
|
||||
|
||||
func gctScriptQuery(c *cli.Context) error {
|
||||
if c.NArg() == 0 && c.NumFlags() == 0 {
|
||||
_ = cli.ShowSubcommandHelp(c)
|
||||
return nil
|
||||
}
|
||||
|
||||
if !c.IsSet("uuid") {
|
||||
if c.Args().Get(0) != "" {
|
||||
uuid = c.Args().Get(0)
|
||||
}
|
||||
}
|
||||
|
||||
conn, err := setupClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
client := gctrpc.NewGoCryptoTraderClient(conn)
|
||||
|
||||
executeCommand, err := client.GCTScriptQuery(context.Background(),
|
||||
&gctrpc.GCTScriptQueryRequest{
|
||||
Script: &gctrpc.GCTScript{
|
||||
UUID: uuid,
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
jsonOutput(executeCommand)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func gctScriptUpload(c *cli.Context) error {
|
||||
if c.NArg() == 0 && c.NumFlags() == 0 {
|
||||
_ = cli.ShowSubcommandHelp(c)
|
||||
return nil
|
||||
}
|
||||
|
||||
var overwrite bool
|
||||
var archived bool
|
||||
if !c.IsSet("path") {
|
||||
if c.Args().Get(0) != "" {
|
||||
filename = c.Args().Get(0)
|
||||
}
|
||||
}
|
||||
|
||||
if c.IsSet("overwrite") {
|
||||
overwrite = c.Bool("overwrite")
|
||||
} else {
|
||||
ow, err := strconv.ParseBool(c.Args().Get(1))
|
||||
if err == nil {
|
||||
overwrite = ow
|
||||
}
|
||||
}
|
||||
|
||||
if c.IsSet("archived") {
|
||||
archived = c.Bool("archived")
|
||||
} else {
|
||||
ow, err := strconv.ParseBool(c.Args().Get(1))
|
||||
if err == nil {
|
||||
archived = ow
|
||||
}
|
||||
}
|
||||
|
||||
if filepath.Ext(filename) != ".gct" && filepath.Ext(filename) != ".zip" {
|
||||
return errors.New("file type must be gct or zip")
|
||||
}
|
||||
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
conn, err := setupClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
client := gctrpc.NewGoCryptoTraderClient(conn)
|
||||
|
||||
data, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
uploadCommand, err := client.GCTScriptUpload(context.Background(),
|
||||
&gctrpc.GCTScriptUploadRequest{
|
||||
ScriptName: filepath.Base(file.Name()),
|
||||
Data: data,
|
||||
Archived: archived,
|
||||
Overwrite: overwrite,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
jsonOutput(uploadCommand)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -133,6 +133,7 @@ func main() {
|
||||
getTickerStreamCommand,
|
||||
getExchangeTickerStreamCommand,
|
||||
getAuditEventCommand,
|
||||
gctScriptCommand,
|
||||
}
|
||||
|
||||
err := app.Run(os.Args)
|
||||
|
||||
@@ -107,3 +107,9 @@ func SplitFloatDecimals(input float64) (baseNum, decimalNum int64, err error) {
|
||||
}
|
||||
return baseNum, decimalNum, nil
|
||||
}
|
||||
|
||||
// BoolPtr takes in boolen condition and returns pointer version of it
|
||||
func BoolPtr(condition bool) *bool {
|
||||
b := condition
|
||||
return &b
|
||||
}
|
||||
|
||||
@@ -205,3 +205,14 @@ func TestSplitFloatDecimals(t *testing.T) {
|
||||
t.Error("Conversion error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBoolPtr(t *testing.T) {
|
||||
y := BoolPtr(true)
|
||||
if !*y {
|
||||
t.Fatal("true expected received false")
|
||||
}
|
||||
z := BoolPtr(false)
|
||||
if *z {
|
||||
t.Fatal("false expected received true")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/currency/forexprovider/base"
|
||||
"github.com/thrasher-corp/gocryptotrader/database"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
gctscript "github.com/thrasher-corp/gocryptotrader/gctscript/vm"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
@@ -1187,10 +1188,8 @@ func (c *Config) CheckLoggerConfig() error {
|
||||
c.Logging = log.GenDefaultSettings()
|
||||
}
|
||||
|
||||
f := func(f bool) *bool { return &f }(false)
|
||||
|
||||
if c.Logging.AdvancedSettings.ShowLogSystemName == nil {
|
||||
c.Logging.AdvancedSettings.ShowLogSystemName = f
|
||||
c.Logging.AdvancedSettings.ShowLogSystemName = convert.BoolPtr(false)
|
||||
}
|
||||
|
||||
if c.Logging.LoggerFileConfig != nil {
|
||||
@@ -1198,10 +1197,11 @@ func (c *Config) CheckLoggerConfig() error {
|
||||
c.Logging.LoggerFileConfig.FileName = "log.txt"
|
||||
}
|
||||
if c.Logging.LoggerFileConfig.Rotate == nil {
|
||||
c.Logging.LoggerFileConfig.Rotate = f
|
||||
c.Logging.LoggerFileConfig.Rotate = convert.BoolPtr(false)
|
||||
}
|
||||
if c.Logging.LoggerFileConfig.MaxSize < 0 {
|
||||
c.Logging.LoggerFileConfig.MaxSize = 100
|
||||
if c.Logging.LoggerFileConfig.MaxSize <= 0 {
|
||||
log.Warnf(log.Global, "Logger rotation size invalid, defaulting to %v", log.DefaultMaxFileSize)
|
||||
c.Logging.LoggerFileConfig.MaxSize = log.DefaultMaxFileSize
|
||||
}
|
||||
log.FileLoggingConfiguredCorrectly = true
|
||||
}
|
||||
@@ -1218,6 +1218,30 @@ func (c *Config) CheckLoggerConfig() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) checkGCTScriptConfig() error {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
if c.GCTScript.ScriptTimeout <= 0 {
|
||||
c.GCTScript.ScriptTimeout = gctscript.DefaultTimeoutValue
|
||||
}
|
||||
|
||||
if c.GCTScript.MaxVirtualMachines == 0 {
|
||||
c.GCTScript.MaxVirtualMachines = gctscript.DefaultMaxVirtualMachines
|
||||
}
|
||||
|
||||
scriptPath := filepath.Join(common.GetDefaultDataDir(runtime.GOOS), "scripts")
|
||||
err := common.CreateDir(scriptPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gctscript.ScriptPath = scriptPath
|
||||
gctscript.GCTScriptConfig = &c.GCTScript
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) checkDatabaseConfig() error {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
@@ -1623,6 +1647,11 @@ func (c *Config) CheckConfig() error {
|
||||
return fmt.Errorf(ErrCheckingConfigValues, err)
|
||||
}
|
||||
|
||||
err = c.checkGCTScriptConfig()
|
||||
if err != nil {
|
||||
log.Errorf(log.Global, "Failed to configure gctscript, feature has been disabled: %s\n", err)
|
||||
}
|
||||
|
||||
c.CheckConnectionMonitorConfig()
|
||||
c.CheckCommunicationsConfig()
|
||||
c.CheckClientBankAccounts()
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/database"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
gctscript "github.com/thrasher-corp/gocryptotrader/gctscript/vm"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/ntpclient"
|
||||
)
|
||||
@@ -1760,25 +1761,12 @@ func TestCheckLoggerConfig(t *testing.T) {
|
||||
*c.Logging.AdvancedSettings.ShowLogSystemName {
|
||||
t.Error("unexpected result")
|
||||
}
|
||||
|
||||
err = c.LoadConfig(TestFile, true)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to load config: %v", err)
|
||||
}
|
||||
err = c.CheckLoggerConfig()
|
||||
if err != nil {
|
||||
t.Errorf("Failed to create logger with user settings: reason: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDisableNTPCheck(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
c := GetConfig()
|
||||
err := c.LoadConfig(TestFile, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var c Config
|
||||
|
||||
warn, err := c.DisableNTPCheck(strings.NewReader("w\n"))
|
||||
if err != nil {
|
||||
@@ -1804,6 +1792,23 @@ func TestDisableNTPCheck(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckGCTScriptConfig(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var c Config
|
||||
if err := c.checkGCTScriptConfig(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if c.GCTScript.ScriptTimeout != gctscript.DefaultTimeoutValue {
|
||||
t.Fatal("unexpected value return")
|
||||
}
|
||||
|
||||
if c.GCTScript.MaxVirtualMachines != gctscript.DefaultMaxVirtualMachines {
|
||||
t.Fatal("unexpected value return")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckDatabaseConfig(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/currency/forexprovider/base"
|
||||
"github.com/thrasher-corp/gocryptotrader/database"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
|
||||
gctscript "github.com/thrasher-corp/gocryptotrader/gctscript/vm"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/portfolio"
|
||||
)
|
||||
@@ -87,6 +88,7 @@ type Config struct {
|
||||
ConnectionMonitor ConnectionMonitorConfig `json:"connectionMonitor"`
|
||||
Profiler ProfilerConfig `json:"profiler"`
|
||||
NTPClient NTPClientConfig `json:"ntpclient"`
|
||||
GCTScript gctscript.Config `json:"gctscript"`
|
||||
Currency CurrencyConfig `json:"currencyConfig"`
|
||||
Communications CommunicationsConfig `json:"communications"`
|
||||
RemoteControl RemoteControlConfig `json:"remoteControl"`
|
||||
|
||||
@@ -61,6 +61,14 @@
|
||||
"allowedDifference": 50000000,
|
||||
"allowedNegativeDifference": 50000000
|
||||
},
|
||||
"gctscript": {
|
||||
"enabled": true,
|
||||
"timeout": 60000000000,
|
||||
"max_virtual_machines": 10,
|
||||
"allow_imports": true,
|
||||
"auto_load": [],
|
||||
"verbose": false
|
||||
},
|
||||
"currencyConfig": {
|
||||
"forexProviders": [
|
||||
{
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
-- +goose Up
|
||||
-- SQL in this section is executed when the migration is applied.
|
||||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
-- +goose Down
|
||||
-- SQL in this section is executed when the migration is rolled back.
|
||||
DROP EXTENSION IF EXISTS pgcrypto;
|
||||
@@ -0,0 +1,8 @@
|
||||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
SELECT 'up SQL query';
|
||||
-- +goose StatementEnd
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
SELECT 'down SQL query';
|
||||
-- +goose StatementEnd
|
||||
16
database/migrations/20191210124558_script/postgres.sql
Normal file
16
database/migrations/20191210124558_script/postgres.sql
Normal file
@@ -0,0 +1,16 @@
|
||||
-- +goose Up
|
||||
-- SQL in this section is executed when the migration is applied.
|
||||
CREATE TABLE IF NOT EXISTS script
|
||||
(
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
script_id text not null,
|
||||
script_name varchar not null,
|
||||
script_path varchar not null,
|
||||
script_data bytea null,
|
||||
last_executed_at TIMESTAMP DEFAULT (now() at time zone 'utc'),
|
||||
created_at TIMESTAMP DEFAULT (now() at time zone 'utc'),
|
||||
CONSTRAINT script_event_uniq UNIQUE (script_id)
|
||||
);
|
||||
-- +goose Down
|
||||
-- SQL in this section is executed when the migration is rolled back.
|
||||
DROP TABLE script;
|
||||
14
database/migrations/20191210124558_script/sqlite3.sql
Normal file
14
database/migrations/20191210124558_script/sqlite3.sql
Normal file
@@ -0,0 +1,14 @@
|
||||
-- +goose Up
|
||||
-- SQL in this section is executed when the migration is applied.
|
||||
CREATE TABLE "script" (
|
||||
id text not null primary key,
|
||||
script_id text not null,
|
||||
script_name text not null,
|
||||
script_path text not NULL,
|
||||
script_data blob null,
|
||||
last_executed_at timestamp not null default CURRENT_TIMESTAMP,
|
||||
created_at timestamp not null default CURRENT_TIMESTAMP
|
||||
);
|
||||
-- +goose Down
|
||||
-- SQL in this section is executed when the migration is rolled back.
|
||||
DROP TABLE "script";
|
||||
@@ -0,0 +1,13 @@
|
||||
-- +goose Up
|
||||
-- SQL in this section is executed when the migration is applied.
|
||||
CREATE TABLE IF NOT EXISTS script_execution
|
||||
(
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
script_id uuid REFERENCES script(id) ON DELETE CASCADE,
|
||||
execution_type varchar NOT NULL,
|
||||
execution_status varchar NOT NULL,
|
||||
execution_time TIMESTAMP NOT NULL DEFAULT (now() at time zone 'utc')
|
||||
);
|
||||
-- +goose Down
|
||||
-- SQL in this section is executed when the migration is rolled back.
|
||||
DROP TABLE script_execution;
|
||||
@@ -0,0 +1,14 @@
|
||||
-- +goose Up
|
||||
-- SQL in this section is executed when the migration is applied.
|
||||
CREATE TABLE IF NOT EXISTS "script_execution"
|
||||
(
|
||||
id integer not null primary key,
|
||||
script_id text not null,
|
||||
execution_type text NOT NULL,
|
||||
execution_status text NOT NULL,
|
||||
execution_time timestamp not null default CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY(script_id) REFERENCES script(id)
|
||||
);
|
||||
-- +goose Down
|
||||
-- SQL in this section is executed when the migration is rolled back.
|
||||
DROP TABLE script_execution;
|
||||
@@ -568,7 +568,7 @@ func testAuditEventsSelect(t *testing.T) {
|
||||
}
|
||||
|
||||
var (
|
||||
auditEventDBTypes = map[string]string{`ID`: `bigint`, `Type`: `character varying`, `Identifier`: `character varying`, `Message`: `text`, `CreatedAt`: `timestamp with time zone`}
|
||||
auditEventDBTypes = map[string]string{`ID`: `bigint`, `Type`: `character varying`, `Identifier`: `character varying`, `Message`: `text`, `CreatedAt`: `timestamp without time zone`}
|
||||
_ = bytes.MinRead
|
||||
)
|
||||
|
||||
|
||||
@@ -13,51 +13,64 @@ import "testing"
|
||||
// Separating the tests thusly grants avoidance of Postgres deadlocks.
|
||||
func TestParent(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEvents)
|
||||
t.Run("Scripts", testScripts)
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsDelete)
|
||||
t.Run("Scripts", testScriptsDelete)
|
||||
}
|
||||
|
||||
func TestQueryDeleteAll(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsQueryDeleteAll)
|
||||
t.Run("Scripts", testScriptsQueryDeleteAll)
|
||||
}
|
||||
|
||||
func TestSliceDeleteAll(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsSliceDeleteAll)
|
||||
t.Run("Scripts", testScriptsSliceDeleteAll)
|
||||
}
|
||||
|
||||
func TestExists(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsExists)
|
||||
t.Run("Scripts", testScriptsExists)
|
||||
}
|
||||
|
||||
func TestFind(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsFind)
|
||||
t.Run("Scripts", testScriptsFind)
|
||||
}
|
||||
|
||||
func TestBind(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsBind)
|
||||
t.Run("Scripts", testScriptsBind)
|
||||
}
|
||||
|
||||
func TestOne(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsOne)
|
||||
t.Run("Scripts", testScriptsOne)
|
||||
}
|
||||
|
||||
func TestAll(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsAll)
|
||||
t.Run("Scripts", testScriptsAll)
|
||||
}
|
||||
|
||||
func TestCount(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsCount)
|
||||
t.Run("Scripts", testScriptsCount)
|
||||
}
|
||||
|
||||
func TestHooks(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsHooks)
|
||||
t.Run("Scripts", testScriptsHooks)
|
||||
}
|
||||
|
||||
func TestInsert(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsInsert)
|
||||
t.Run("AuditEvents", testAuditEventsInsertWhitelist)
|
||||
t.Run("Scripts", testScriptsInsert)
|
||||
t.Run("Scripts", testScriptsInsertWhitelist)
|
||||
}
|
||||
|
||||
// TestToOne tests cannot be run in parallel
|
||||
@@ -102,20 +115,25 @@ func TestToManyRemove(t *testing.T) {}
|
||||
|
||||
func TestReload(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsReload)
|
||||
t.Run("Scripts", testScriptsReload)
|
||||
}
|
||||
|
||||
func TestReloadAll(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsReloadAll)
|
||||
t.Run("Scripts", testScriptsReloadAll)
|
||||
}
|
||||
|
||||
func TestSelect(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsSelect)
|
||||
t.Run("Scripts", testScriptsSelect)
|
||||
}
|
||||
|
||||
func TestUpdate(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsUpdate)
|
||||
t.Run("Scripts", testScriptsUpdate)
|
||||
}
|
||||
|
||||
func TestSliceUpdateAll(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsSliceUpdateAll)
|
||||
t.Run("Scripts", testScriptsSliceUpdateAll)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,11 @@
|
||||
package postgres
|
||||
|
||||
var TableNames = struct {
|
||||
AuditEvent string
|
||||
AuditEvent string
|
||||
Script string
|
||||
ScriptExecution string
|
||||
}{
|
||||
AuditEvent: "audit_event",
|
||||
AuditEvent: "audit_event",
|
||||
Script: "script",
|
||||
ScriptExecution: "script_execution",
|
||||
}
|
||||
|
||||
@@ -7,4 +7,5 @@ import "testing"
|
||||
|
||||
func TestUpsert(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsUpsert)
|
||||
t.Run("Scripts", testScriptsUpsert)
|
||||
}
|
||||
|
||||
1179
database/models/postgres/script.go
Normal file
1179
database/models/postgres/script.go
Normal file
File diff suppressed because it is too large
Load Diff
1104
database/models/postgres/script_execution.go
Normal file
1104
database/models/postgres/script_execution.go
Normal file
File diff suppressed because it is too large
Load Diff
892
database/models/postgres/script_execution_test.go
Normal file
892
database/models/postgres/script_execution_test.go
Normal file
@@ -0,0 +1,892 @@
|
||||
// Code generated by SQLBoiler 3.5.0-gct (https://github.com/thrasher-corp/sqlboiler). DO NOT EDIT.
|
||||
// This file is meant to be re-generated in place and/or deleted at any time.
|
||||
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-corp/sqlboiler/boil"
|
||||
"github.com/thrasher-corp/sqlboiler/queries"
|
||||
"github.com/thrasher-corp/sqlboiler/randomize"
|
||||
"github.com/thrasher-corp/sqlboiler/strmangle"
|
||||
)
|
||||
|
||||
var (
|
||||
// Relationships sometimes use the reflection helper queries.Equal/queries.Assign
|
||||
// so force a package dependency in case they don't.
|
||||
_ = queries.Equal
|
||||
)
|
||||
|
||||
func testScriptExecutions(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
query := ScriptExecutions()
|
||||
|
||||
if query.Query == nil {
|
||||
t.Error("expected a query, got nothing")
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsDelete(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if rowsAff, err := o.Delete(ctx, tx); err != nil {
|
||||
t.Error(err)
|
||||
} else if rowsAff != 1 {
|
||||
t.Error("should only have deleted one row, but affected:", rowsAff)
|
||||
}
|
||||
|
||||
count, err := ScriptExecutions().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if count != 0 {
|
||||
t.Error("want zero records, got:", count)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsQueryDeleteAll(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if rowsAff, err := ScriptExecutions().DeleteAll(ctx, tx); err != nil {
|
||||
t.Error(err)
|
||||
} else if rowsAff != 1 {
|
||||
t.Error("should only have deleted one row, but affected:", rowsAff)
|
||||
}
|
||||
|
||||
count, err := ScriptExecutions().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if count != 0 {
|
||||
t.Error("want zero records, got:", count)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsSliceDeleteAll(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
slice := ScriptExecutionSlice{o}
|
||||
|
||||
if rowsAff, err := slice.DeleteAll(ctx, tx); err != nil {
|
||||
t.Error(err)
|
||||
} else if rowsAff != 1 {
|
||||
t.Error("should only have deleted one row, but affected:", rowsAff)
|
||||
}
|
||||
|
||||
count, err := ScriptExecutions().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if count != 0 {
|
||||
t.Error("want zero records, got:", count)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsExists(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
e, err := ScriptExecutionExists(ctx, tx, o.ID)
|
||||
if err != nil {
|
||||
t.Errorf("Unable to check if ScriptExecution exists: %s", err)
|
||||
}
|
||||
if !e {
|
||||
t.Errorf("Expected ScriptExecutionExists to return true, but got false.")
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsFind(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
scriptExecutionFound, err := FindScriptExecution(ctx, tx, o.ID)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if scriptExecutionFound == nil {
|
||||
t.Error("want a record, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsBind(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if err = ScriptExecutions().Bind(ctx, tx, o); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsOne(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if x, err := ScriptExecutions().One(ctx, tx); err != nil {
|
||||
t.Error(err)
|
||||
} else if x == nil {
|
||||
t.Error("expected to get a non nil record")
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsAll(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
scriptExecutionOne := &ScriptExecution{}
|
||||
scriptExecutionTwo := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, scriptExecutionOne, scriptExecutionDBTypes, false, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
if err = randomize.Struct(seed, scriptExecutionTwo, scriptExecutionDBTypes, false, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = scriptExecutionOne.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err = scriptExecutionTwo.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
slice, err := ScriptExecutions().All(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if len(slice) != 2 {
|
||||
t.Error("want 2 records, got:", len(slice))
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsCount(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var err error
|
||||
seed := randomize.NewSeed()
|
||||
scriptExecutionOne := &ScriptExecution{}
|
||||
scriptExecutionTwo := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, scriptExecutionOne, scriptExecutionDBTypes, false, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
if err = randomize.Struct(seed, scriptExecutionTwo, scriptExecutionDBTypes, false, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = scriptExecutionOne.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err = scriptExecutionTwo.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
count, err := ScriptExecutions().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if count != 2 {
|
||||
t.Error("want 2 records, got:", count)
|
||||
}
|
||||
}
|
||||
|
||||
func scriptExecutionBeforeInsertHook(ctx context.Context, e boil.ContextExecutor, o *ScriptExecution) error {
|
||||
*o = ScriptExecution{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scriptExecutionAfterInsertHook(ctx context.Context, e boil.ContextExecutor, o *ScriptExecution) error {
|
||||
*o = ScriptExecution{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scriptExecutionAfterSelectHook(ctx context.Context, e boil.ContextExecutor, o *ScriptExecution) error {
|
||||
*o = ScriptExecution{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scriptExecutionBeforeUpdateHook(ctx context.Context, e boil.ContextExecutor, o *ScriptExecution) error {
|
||||
*o = ScriptExecution{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scriptExecutionAfterUpdateHook(ctx context.Context, e boil.ContextExecutor, o *ScriptExecution) error {
|
||||
*o = ScriptExecution{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scriptExecutionBeforeDeleteHook(ctx context.Context, e boil.ContextExecutor, o *ScriptExecution) error {
|
||||
*o = ScriptExecution{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scriptExecutionAfterDeleteHook(ctx context.Context, e boil.ContextExecutor, o *ScriptExecution) error {
|
||||
*o = ScriptExecution{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scriptExecutionBeforeUpsertHook(ctx context.Context, e boil.ContextExecutor, o *ScriptExecution) error {
|
||||
*o = ScriptExecution{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scriptExecutionAfterUpsertHook(ctx context.Context, e boil.ContextExecutor, o *ScriptExecution) error {
|
||||
*o = ScriptExecution{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func testScriptExecutionsHooks(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var err error
|
||||
|
||||
ctx := context.Background()
|
||||
empty := &ScriptExecution{}
|
||||
o := &ScriptExecution{}
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, false); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution object: %s", err)
|
||||
}
|
||||
|
||||
AddScriptExecutionHook(boil.BeforeInsertHook, scriptExecutionBeforeInsertHook)
|
||||
if err = o.doBeforeInsertHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doBeforeInsertHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected BeforeInsertHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptExecutionBeforeInsertHooks = []ScriptExecutionHook{}
|
||||
|
||||
AddScriptExecutionHook(boil.AfterInsertHook, scriptExecutionAfterInsertHook)
|
||||
if err = o.doAfterInsertHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doAfterInsertHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected AfterInsertHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptExecutionAfterInsertHooks = []ScriptExecutionHook{}
|
||||
|
||||
AddScriptExecutionHook(boil.AfterSelectHook, scriptExecutionAfterSelectHook)
|
||||
if err = o.doAfterSelectHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doAfterSelectHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected AfterSelectHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptExecutionAfterSelectHooks = []ScriptExecutionHook{}
|
||||
|
||||
AddScriptExecutionHook(boil.BeforeUpdateHook, scriptExecutionBeforeUpdateHook)
|
||||
if err = o.doBeforeUpdateHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doBeforeUpdateHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected BeforeUpdateHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptExecutionBeforeUpdateHooks = []ScriptExecutionHook{}
|
||||
|
||||
AddScriptExecutionHook(boil.AfterUpdateHook, scriptExecutionAfterUpdateHook)
|
||||
if err = o.doAfterUpdateHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doAfterUpdateHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected AfterUpdateHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptExecutionAfterUpdateHooks = []ScriptExecutionHook{}
|
||||
|
||||
AddScriptExecutionHook(boil.BeforeDeleteHook, scriptExecutionBeforeDeleteHook)
|
||||
if err = o.doBeforeDeleteHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doBeforeDeleteHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected BeforeDeleteHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptExecutionBeforeDeleteHooks = []ScriptExecutionHook{}
|
||||
|
||||
AddScriptExecutionHook(boil.AfterDeleteHook, scriptExecutionAfterDeleteHook)
|
||||
if err = o.doAfterDeleteHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doAfterDeleteHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected AfterDeleteHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptExecutionAfterDeleteHooks = []ScriptExecutionHook{}
|
||||
|
||||
AddScriptExecutionHook(boil.BeforeUpsertHook, scriptExecutionBeforeUpsertHook)
|
||||
if err = o.doBeforeUpsertHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doBeforeUpsertHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected BeforeUpsertHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptExecutionBeforeUpsertHooks = []ScriptExecutionHook{}
|
||||
|
||||
AddScriptExecutionHook(boil.AfterUpsertHook, scriptExecutionAfterUpsertHook)
|
||||
if err = o.doAfterUpsertHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doAfterUpsertHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected AfterUpsertHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptExecutionAfterUpsertHooks = []ScriptExecutionHook{}
|
||||
}
|
||||
|
||||
func testScriptExecutionsInsert(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
count, err := ScriptExecutions().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if count != 1 {
|
||||
t.Error("want one record, got:", count)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsInsertWhitelist(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Whitelist(scriptExecutionColumnsWithoutDefault...)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
count, err := ScriptExecutions().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if count != 1 {
|
||||
t.Error("want one record, got:", count)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionToOneScriptUsingScript(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
|
||||
var local ScriptExecution
|
||||
var foreign Script
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
if err := randomize.Struct(seed, &local, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
if err := randomize.Struct(seed, &foreign, scriptDBTypes, false, scriptColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize Script struct: %s", err)
|
||||
}
|
||||
|
||||
if err := foreign.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
queries.Assign(&local.ScriptID, foreign.ID)
|
||||
if err := local.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
check, err := local.Script().One(ctx, tx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !queries.Equal(check.ID, foreign.ID) {
|
||||
t.Errorf("want: %v, got %v", foreign.ID, check.ID)
|
||||
}
|
||||
|
||||
slice := ScriptExecutionSlice{&local}
|
||||
if err = local.L.LoadScript(ctx, tx, false, (*[]*ScriptExecution)(&slice), nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if local.R.Script == nil {
|
||||
t.Error("struct should have been eager loaded")
|
||||
}
|
||||
|
||||
local.R.Script = nil
|
||||
if err = local.L.LoadScript(ctx, tx, true, &local, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if local.R.Script == nil {
|
||||
t.Error("struct should have been eager loaded")
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionToOneSetOpScriptUsingScript(t *testing.T) {
|
||||
var err error
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
|
||||
var a ScriptExecution
|
||||
var b, c Script
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
if err = randomize.Struct(seed, &a, scriptExecutionDBTypes, false, strmangle.SetComplement(scriptExecutionPrimaryKeyColumns, scriptExecutionColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = randomize.Struct(seed, &b, scriptDBTypes, false, strmangle.SetComplement(scriptPrimaryKeyColumns, scriptColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = randomize.Struct(seed, &c, scriptDBTypes, false, strmangle.SetComplement(scriptPrimaryKeyColumns, scriptColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := a.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = b.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for i, x := range []*Script{&b, &c} {
|
||||
err = a.SetScript(ctx, tx, i != 0, x)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if a.R.Script != x {
|
||||
t.Error("relationship struct not set to correct value")
|
||||
}
|
||||
|
||||
if x.R.ScriptExecutions[0] != &a {
|
||||
t.Error("failed to append to foreign relationship struct")
|
||||
}
|
||||
if !queries.Equal(a.ScriptID, x.ID) {
|
||||
t.Error("foreign key was wrong value", a.ScriptID)
|
||||
}
|
||||
|
||||
zero := reflect.Zero(reflect.TypeOf(a.ScriptID))
|
||||
reflect.Indirect(reflect.ValueOf(&a.ScriptID)).Set(zero)
|
||||
|
||||
if err = a.Reload(ctx, tx); err != nil {
|
||||
t.Fatal("failed to reload", err)
|
||||
}
|
||||
|
||||
if !queries.Equal(a.ScriptID, x.ID) {
|
||||
t.Error("foreign key was wrong value", a.ScriptID, x.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionToOneRemoveOpScriptUsingScript(t *testing.T) {
|
||||
var err error
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
|
||||
var a ScriptExecution
|
||||
var b Script
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
if err = randomize.Struct(seed, &a, scriptExecutionDBTypes, false, strmangle.SetComplement(scriptExecutionPrimaryKeyColumns, scriptExecutionColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = randomize.Struct(seed, &b, scriptDBTypes, false, strmangle.SetComplement(scriptPrimaryKeyColumns, scriptColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err = a.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err = a.SetScript(ctx, tx, true, &b); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err = a.RemoveScript(ctx, tx, &b); err != nil {
|
||||
t.Error("failed to remove relationship")
|
||||
}
|
||||
|
||||
count, err := a.Script().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if count != 0 {
|
||||
t.Error("want no relationships remaining")
|
||||
}
|
||||
|
||||
if a.R.Script != nil {
|
||||
t.Error("R struct entry should be nil")
|
||||
}
|
||||
|
||||
if !queries.IsValuerNil(a.ScriptID) {
|
||||
t.Error("foreign key value should be nil")
|
||||
}
|
||||
|
||||
if len(b.R.ScriptExecutions) != 0 {
|
||||
t.Error("failed to remove a from b's relationships")
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsReload(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if err = o.Reload(ctx, tx); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsReloadAll(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
slice := ScriptExecutionSlice{o}
|
||||
|
||||
if err = slice.ReloadAll(ctx, tx); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsSelect(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
slice, err := ScriptExecutions().All(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if len(slice) != 1 {
|
||||
t.Error("want one record, got:", len(slice))
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
scriptExecutionDBTypes = map[string]string{`ID`: `uuid`, `ScriptID`: `uuid`, `ExecutionType`: `character varying`, `ExecutionStatus`: `character varying`, `ExecutionTime`: `timestamp without time zone`}
|
||||
_ = bytes.MinRead
|
||||
)
|
||||
|
||||
func testScriptExecutionsUpdate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if 0 == len(scriptExecutionPrimaryKeyColumns) {
|
||||
t.Skip("Skipping table with no primary key columns")
|
||||
}
|
||||
if len(scriptExecutionAllColumns) == len(scriptExecutionPrimaryKeyColumns) {
|
||||
t.Skip("Skipping table with only primary key columns")
|
||||
}
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
count, err := ScriptExecutions().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if count != 1 {
|
||||
t.Error("want one record, got:", count)
|
||||
}
|
||||
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionPrimaryKeyColumns...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
if rowsAff, err := o.Update(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
} else if rowsAff != 1 {
|
||||
t.Error("should only affect one row but affected", rowsAff)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsSliceUpdateAll(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if len(scriptExecutionAllColumns) == len(scriptExecutionPrimaryKeyColumns) {
|
||||
t.Skip("Skipping table with only primary key columns")
|
||||
}
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
count, err := ScriptExecutions().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if count != 1 {
|
||||
t.Error("want one record, got:", count)
|
||||
}
|
||||
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionPrimaryKeyColumns...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
// Remove Primary keys and unique columns from what we plan to update
|
||||
var fields []string
|
||||
if strmangle.StringSliceMatch(scriptExecutionAllColumns, scriptExecutionPrimaryKeyColumns) {
|
||||
fields = scriptExecutionAllColumns
|
||||
} else {
|
||||
fields = strmangle.SetComplement(
|
||||
scriptExecutionAllColumns,
|
||||
scriptExecutionPrimaryKeyColumns,
|
||||
)
|
||||
}
|
||||
|
||||
value := reflect.Indirect(reflect.ValueOf(o))
|
||||
typ := reflect.TypeOf(o).Elem()
|
||||
n := typ.NumField()
|
||||
|
||||
updateMap := M{}
|
||||
for _, col := range fields {
|
||||
for i := 0; i < n; i++ {
|
||||
f := typ.Field(i)
|
||||
if f.Tag.Get("boil") == col {
|
||||
updateMap[col] = value.Field(i).Interface()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
slice := ScriptExecutionSlice{o}
|
||||
if rowsAff, err := slice.UpdateAll(ctx, tx, updateMap); err != nil {
|
||||
t.Error(err)
|
||||
} else if rowsAff != 1 {
|
||||
t.Error("wanted one record updated but got", rowsAff)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsUpsert(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if len(scriptExecutionAllColumns) == len(scriptExecutionPrimaryKeyColumns) {
|
||||
t.Skip("Skipping table with only primary key columns")
|
||||
}
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
// Attempt the INSERT side of an UPSERT
|
||||
o := ScriptExecution{}
|
||||
if err = randomize.Struct(seed, &o, scriptExecutionDBTypes, true); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Upsert(ctx, tx, false, nil, boil.Infer(), boil.Infer()); err != nil {
|
||||
t.Errorf("Unable to upsert ScriptExecution: %s", err)
|
||||
}
|
||||
|
||||
count, err := ScriptExecutions().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if count != 1 {
|
||||
t.Error("want one record, got:", count)
|
||||
}
|
||||
|
||||
// Attempt the UPDATE side of an UPSERT
|
||||
if err = randomize.Struct(seed, &o, scriptExecutionDBTypes, false, scriptExecutionPrimaryKeyColumns...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
if err = o.Upsert(ctx, tx, true, nil, boil.Infer(), boil.Infer()); err != nil {
|
||||
t.Errorf("Unable to upsert ScriptExecution: %s", err)
|
||||
}
|
||||
|
||||
count, err = ScriptExecutions().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if count != 1 {
|
||||
t.Error("want one record, got:", count)
|
||||
}
|
||||
}
|
||||
1060
database/models/postgres/script_test.go
Normal file
1060
database/models/postgres/script_test.go
Normal file
File diff suppressed because it is too large
Load Diff
@@ -13,56 +13,84 @@ import "testing"
|
||||
// Separating the tests thusly grants avoidance of Postgres deadlocks.
|
||||
func TestParent(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEvents)
|
||||
t.Run("Scripts", testScripts)
|
||||
t.Run("ScriptExecutions", testScriptExecutions)
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsDelete)
|
||||
t.Run("Scripts", testScriptsDelete)
|
||||
t.Run("ScriptExecutions", testScriptExecutionsDelete)
|
||||
}
|
||||
|
||||
func TestQueryDeleteAll(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsQueryDeleteAll)
|
||||
t.Run("Scripts", testScriptsQueryDeleteAll)
|
||||
t.Run("ScriptExecutions", testScriptExecutionsQueryDeleteAll)
|
||||
}
|
||||
|
||||
func TestSliceDeleteAll(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsSliceDeleteAll)
|
||||
t.Run("Scripts", testScriptsSliceDeleteAll)
|
||||
t.Run("ScriptExecutions", testScriptExecutionsSliceDeleteAll)
|
||||
}
|
||||
|
||||
func TestExists(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsExists)
|
||||
t.Run("Scripts", testScriptsExists)
|
||||
t.Run("ScriptExecutions", testScriptExecutionsExists)
|
||||
}
|
||||
|
||||
func TestFind(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsFind)
|
||||
t.Run("Scripts", testScriptsFind)
|
||||
t.Run("ScriptExecutions", testScriptExecutionsFind)
|
||||
}
|
||||
|
||||
func TestBind(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsBind)
|
||||
t.Run("Scripts", testScriptsBind)
|
||||
t.Run("ScriptExecutions", testScriptExecutionsBind)
|
||||
}
|
||||
|
||||
func TestOne(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsOne)
|
||||
t.Run("Scripts", testScriptsOne)
|
||||
t.Run("ScriptExecutions", testScriptExecutionsOne)
|
||||
}
|
||||
|
||||
func TestAll(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsAll)
|
||||
t.Run("Scripts", testScriptsAll)
|
||||
t.Run("ScriptExecutions", testScriptExecutionsAll)
|
||||
}
|
||||
|
||||
func TestCount(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsCount)
|
||||
t.Run("Scripts", testScriptsCount)
|
||||
t.Run("ScriptExecutions", testScriptExecutionsCount)
|
||||
}
|
||||
|
||||
func TestHooks(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsHooks)
|
||||
t.Run("Scripts", testScriptsHooks)
|
||||
t.Run("ScriptExecutions", testScriptExecutionsHooks)
|
||||
}
|
||||
|
||||
func TestInsert(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsInsert)
|
||||
t.Run("AuditEvents", testAuditEventsInsertWhitelist)
|
||||
t.Run("Scripts", testScriptsInsert)
|
||||
t.Run("Scripts", testScriptsInsertWhitelist)
|
||||
t.Run("ScriptExecutions", testScriptExecutionsInsert)
|
||||
t.Run("ScriptExecutions", testScriptExecutionsInsertWhitelist)
|
||||
}
|
||||
|
||||
// TestToOne tests cannot be run in parallel
|
||||
// or deadlocks can occur.
|
||||
func TestToOne(t *testing.T) {}
|
||||
func TestToOne(t *testing.T) {
|
||||
t.Run("ScriptExecutionToScriptUsingScript", testScriptExecutionToOneScriptUsingScript)
|
||||
}
|
||||
|
||||
// TestOneToOne tests cannot be run in parallel
|
||||
// or deadlocks can occur.
|
||||
@@ -70,11 +98,15 @@ func TestOneToOne(t *testing.T) {}
|
||||
|
||||
// TestToMany tests cannot be run in parallel
|
||||
// or deadlocks can occur.
|
||||
func TestToMany(t *testing.T) {}
|
||||
func TestToMany(t *testing.T) {
|
||||
t.Run("ScriptToScriptExecutions", testScriptToManyScriptExecutions)
|
||||
}
|
||||
|
||||
// TestToOneSet tests cannot be run in parallel
|
||||
// or deadlocks can occur.
|
||||
func TestToOneSet(t *testing.T) {}
|
||||
func TestToOneSet(t *testing.T) {
|
||||
t.Run("ScriptExecutionToScriptUsingScriptExecutions", testScriptExecutionToOneSetOpScriptUsingScript)
|
||||
}
|
||||
|
||||
// TestToOneRemove tests cannot be run in parallel
|
||||
// or deadlocks can occur.
|
||||
@@ -90,7 +122,9 @@ func TestOneToOneRemove(t *testing.T) {}
|
||||
|
||||
// TestToManyAdd tests cannot be run in parallel
|
||||
// or deadlocks can occur.
|
||||
func TestToManyAdd(t *testing.T) {}
|
||||
func TestToManyAdd(t *testing.T) {
|
||||
t.Run("ScriptToScriptExecutions", testScriptToManyAddOpScriptExecutions)
|
||||
}
|
||||
|
||||
// TestToManySet tests cannot be run in parallel
|
||||
// or deadlocks can occur.
|
||||
@@ -102,20 +136,30 @@ func TestToManyRemove(t *testing.T) {}
|
||||
|
||||
func TestReload(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsReload)
|
||||
t.Run("Scripts", testScriptsReload)
|
||||
t.Run("ScriptExecutions", testScriptExecutionsReload)
|
||||
}
|
||||
|
||||
func TestReloadAll(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsReloadAll)
|
||||
t.Run("Scripts", testScriptsReloadAll)
|
||||
t.Run("ScriptExecutions", testScriptExecutionsReloadAll)
|
||||
}
|
||||
|
||||
func TestSelect(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsSelect)
|
||||
t.Run("Scripts", testScriptsSelect)
|
||||
t.Run("ScriptExecutions", testScriptExecutionsSelect)
|
||||
}
|
||||
|
||||
func TestUpdate(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsUpdate)
|
||||
t.Run("Scripts", testScriptsUpdate)
|
||||
t.Run("ScriptExecutions", testScriptExecutionsUpdate)
|
||||
}
|
||||
|
||||
func TestSliceUpdateAll(t *testing.T) {
|
||||
t.Run("AuditEvents", testAuditEventsSliceUpdateAll)
|
||||
t.Run("Scripts", testScriptsSliceUpdateAll)
|
||||
t.Run("ScriptExecutions", testScriptExecutionsSliceUpdateAll)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,11 @@
|
||||
package sqlite3
|
||||
|
||||
var TableNames = struct {
|
||||
AuditEvent string
|
||||
AuditEvent string
|
||||
Script string
|
||||
ScriptExecution string
|
||||
}{
|
||||
AuditEvent: "audit_event",
|
||||
AuditEvent: "audit_event",
|
||||
Script: "script",
|
||||
ScriptExecution: "script_execution",
|
||||
}
|
||||
|
||||
987
database/models/sqlite3/script.go
Normal file
987
database/models/sqlite3/script.go
Normal file
@@ -0,0 +1,987 @@
|
||||
// Code generated by SQLBoiler 3.5.0-gct (https://github.com/thrasher-corp/sqlboiler). DO NOT EDIT.
|
||||
// This file is meant to be re-generated in place and/or deleted at any time.
|
||||
|
||||
package sqlite3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/thrasher-corp/sqlboiler/boil"
|
||||
"github.com/thrasher-corp/sqlboiler/queries"
|
||||
"github.com/thrasher-corp/sqlboiler/queries/qm"
|
||||
"github.com/thrasher-corp/sqlboiler/queries/qmhelper"
|
||||
"github.com/thrasher-corp/sqlboiler/strmangle"
|
||||
"github.com/volatiletech/null"
|
||||
)
|
||||
|
||||
// Script is an object representing the database table.
|
||||
type Script struct {
|
||||
ID string `boil:"id" json:"id" toml:"id" yaml:"id"`
|
||||
ScriptID string `boil:"script_id" json:"script_id" toml:"script_id" yaml:"script_id"`
|
||||
ScriptName string `boil:"script_name" json:"script_name" toml:"script_name" yaml:"script_name"`
|
||||
ScriptPath string `boil:"script_path" json:"script_path" toml:"script_path" yaml:"script_path"`
|
||||
ScriptData null.Bytes `boil:"script_data" json:"script_data,omitempty" toml:"script_data" yaml:"script_data,omitempty"`
|
||||
LastExecutedAt string `boil:"last_executed_at" json:"last_executed_at" toml:"last_executed_at" yaml:"last_executed_at"`
|
||||
CreatedAt string `boil:"created_at" json:"created_at" toml:"created_at" yaml:"created_at"`
|
||||
|
||||
R *scriptR `boil:"-" json:"-" toml:"-" yaml:"-"`
|
||||
L scriptL `boil:"-" json:"-" toml:"-" yaml:"-"`
|
||||
}
|
||||
|
||||
var ScriptColumns = struct {
|
||||
ID string
|
||||
ScriptID string
|
||||
ScriptName string
|
||||
ScriptPath string
|
||||
ScriptData string
|
||||
LastExecutedAt string
|
||||
CreatedAt string
|
||||
}{
|
||||
ID: "id",
|
||||
ScriptID: "script_id",
|
||||
ScriptName: "script_name",
|
||||
ScriptPath: "script_path",
|
||||
ScriptData: "script_data",
|
||||
LastExecutedAt: "last_executed_at",
|
||||
CreatedAt: "created_at",
|
||||
}
|
||||
|
||||
// Generated where
|
||||
|
||||
type whereHelpernull_Bytes struct{ field string }
|
||||
|
||||
func (w whereHelpernull_Bytes) EQ(x null.Bytes) qm.QueryMod {
|
||||
return qmhelper.WhereNullEQ(w.field, false, x)
|
||||
}
|
||||
func (w whereHelpernull_Bytes) NEQ(x null.Bytes) qm.QueryMod {
|
||||
return qmhelper.WhereNullEQ(w.field, true, x)
|
||||
}
|
||||
func (w whereHelpernull_Bytes) IsNull() qm.QueryMod { return qmhelper.WhereIsNull(w.field) }
|
||||
func (w whereHelpernull_Bytes) IsNotNull() qm.QueryMod { return qmhelper.WhereIsNotNull(w.field) }
|
||||
func (w whereHelpernull_Bytes) LT(x null.Bytes) qm.QueryMod {
|
||||
return qmhelper.Where(w.field, qmhelper.LT, x)
|
||||
}
|
||||
func (w whereHelpernull_Bytes) LTE(x null.Bytes) qm.QueryMod {
|
||||
return qmhelper.Where(w.field, qmhelper.LTE, x)
|
||||
}
|
||||
func (w whereHelpernull_Bytes) GT(x null.Bytes) qm.QueryMod {
|
||||
return qmhelper.Where(w.field, qmhelper.GT, x)
|
||||
}
|
||||
func (w whereHelpernull_Bytes) GTE(x null.Bytes) qm.QueryMod {
|
||||
return qmhelper.Where(w.field, qmhelper.GTE, x)
|
||||
}
|
||||
|
||||
var ScriptWhere = struct {
|
||||
ID whereHelperstring
|
||||
ScriptID whereHelperstring
|
||||
ScriptName whereHelperstring
|
||||
ScriptPath whereHelperstring
|
||||
ScriptData whereHelpernull_Bytes
|
||||
LastExecutedAt whereHelperstring
|
||||
CreatedAt whereHelperstring
|
||||
}{
|
||||
ID: whereHelperstring{field: "\"script\".\"id\""},
|
||||
ScriptID: whereHelperstring{field: "\"script\".\"script_id\""},
|
||||
ScriptName: whereHelperstring{field: "\"script\".\"script_name\""},
|
||||
ScriptPath: whereHelperstring{field: "\"script\".\"script_path\""},
|
||||
ScriptData: whereHelpernull_Bytes{field: "\"script\".\"script_data\""},
|
||||
LastExecutedAt: whereHelperstring{field: "\"script\".\"last_executed_at\""},
|
||||
CreatedAt: whereHelperstring{field: "\"script\".\"created_at\""},
|
||||
}
|
||||
|
||||
// ScriptRels is where relationship names are stored.
|
||||
var ScriptRels = struct {
|
||||
ScriptExecutions string
|
||||
}{
|
||||
ScriptExecutions: "ScriptExecutions",
|
||||
}
|
||||
|
||||
// scriptR is where relationships are stored.
|
||||
type scriptR struct {
|
||||
ScriptExecutions ScriptExecutionSlice
|
||||
}
|
||||
|
||||
// NewStruct creates a new relationship struct
|
||||
func (*scriptR) NewStruct() *scriptR {
|
||||
return &scriptR{}
|
||||
}
|
||||
|
||||
// scriptL is where Load methods for each relationship are stored.
|
||||
type scriptL struct{}
|
||||
|
||||
var (
|
||||
scriptAllColumns = []string{"id", "script_id", "script_name", "script_path", "script_data", "last_executed_at", "created_at"}
|
||||
scriptColumnsWithoutDefault = []string{"id", "script_id", "script_name", "script_path", "script_data"}
|
||||
scriptColumnsWithDefault = []string{"last_executed_at", "created_at"}
|
||||
scriptPrimaryKeyColumns = []string{"id"}
|
||||
)
|
||||
|
||||
type (
|
||||
// ScriptSlice is an alias for a slice of pointers to Script.
|
||||
// This should generally be used opposed to []Script.
|
||||
ScriptSlice []*Script
|
||||
// ScriptHook is the signature for custom Script hook methods
|
||||
ScriptHook func(context.Context, boil.ContextExecutor, *Script) error
|
||||
|
||||
scriptQuery struct {
|
||||
*queries.Query
|
||||
}
|
||||
)
|
||||
|
||||
// Cache for insert, update and upsert
|
||||
var (
|
||||
scriptType = reflect.TypeOf(&Script{})
|
||||
scriptMapping = queries.MakeStructMapping(scriptType)
|
||||
scriptPrimaryKeyMapping, _ = queries.BindMapping(scriptType, scriptMapping, scriptPrimaryKeyColumns)
|
||||
scriptInsertCacheMut sync.RWMutex
|
||||
scriptInsertCache = make(map[string]insertCache)
|
||||
scriptUpdateCacheMut sync.RWMutex
|
||||
scriptUpdateCache = make(map[string]updateCache)
|
||||
scriptUpsertCacheMut sync.RWMutex
|
||||
scriptUpsertCache = make(map[string]insertCache)
|
||||
)
|
||||
|
||||
var (
|
||||
// Force time package dependency for automated UpdatedAt/CreatedAt.
|
||||
_ = time.Second
|
||||
// Force qmhelper dependency for where clause generation (which doesn't
|
||||
// always happen)
|
||||
_ = qmhelper.Where
|
||||
)
|
||||
|
||||
var scriptBeforeInsertHooks []ScriptHook
|
||||
var scriptBeforeUpdateHooks []ScriptHook
|
||||
var scriptBeforeDeleteHooks []ScriptHook
|
||||
var scriptBeforeUpsertHooks []ScriptHook
|
||||
|
||||
var scriptAfterInsertHooks []ScriptHook
|
||||
var scriptAfterSelectHooks []ScriptHook
|
||||
var scriptAfterUpdateHooks []ScriptHook
|
||||
var scriptAfterDeleteHooks []ScriptHook
|
||||
var scriptAfterUpsertHooks []ScriptHook
|
||||
|
||||
// doBeforeInsertHooks executes all "before insert" hooks.
|
||||
func (o *Script) doBeforeInsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) {
|
||||
if boil.HooksAreSkipped(ctx) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, hook := range scriptBeforeInsertHooks {
|
||||
if err := hook(ctx, exec, o); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// doBeforeUpdateHooks executes all "before Update" hooks.
|
||||
func (o *Script) doBeforeUpdateHooks(ctx context.Context, exec boil.ContextExecutor) (err error) {
|
||||
if boil.HooksAreSkipped(ctx) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, hook := range scriptBeforeUpdateHooks {
|
||||
if err := hook(ctx, exec, o); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// doBeforeDeleteHooks executes all "before Delete" hooks.
|
||||
func (o *Script) doBeforeDeleteHooks(ctx context.Context, exec boil.ContextExecutor) (err error) {
|
||||
if boil.HooksAreSkipped(ctx) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, hook := range scriptBeforeDeleteHooks {
|
||||
if err := hook(ctx, exec, o); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// doBeforeUpsertHooks executes all "before Upsert" hooks.
|
||||
func (o *Script) doBeforeUpsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) {
|
||||
if boil.HooksAreSkipped(ctx) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, hook := range scriptBeforeUpsertHooks {
|
||||
if err := hook(ctx, exec, o); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// doAfterInsertHooks executes all "after Insert" hooks.
|
||||
func (o *Script) doAfterInsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) {
|
||||
if boil.HooksAreSkipped(ctx) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, hook := range scriptAfterInsertHooks {
|
||||
if err := hook(ctx, exec, o); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// doAfterSelectHooks executes all "after Select" hooks.
|
||||
func (o *Script) doAfterSelectHooks(ctx context.Context, exec boil.ContextExecutor) (err error) {
|
||||
if boil.HooksAreSkipped(ctx) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, hook := range scriptAfterSelectHooks {
|
||||
if err := hook(ctx, exec, o); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// doAfterUpdateHooks executes all "after Update" hooks.
|
||||
func (o *Script) doAfterUpdateHooks(ctx context.Context, exec boil.ContextExecutor) (err error) {
|
||||
if boil.HooksAreSkipped(ctx) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, hook := range scriptAfterUpdateHooks {
|
||||
if err := hook(ctx, exec, o); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// doAfterDeleteHooks executes all "after Delete" hooks.
|
||||
func (o *Script) doAfterDeleteHooks(ctx context.Context, exec boil.ContextExecutor) (err error) {
|
||||
if boil.HooksAreSkipped(ctx) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, hook := range scriptAfterDeleteHooks {
|
||||
if err := hook(ctx, exec, o); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// doAfterUpsertHooks executes all "after Upsert" hooks.
|
||||
func (o *Script) doAfterUpsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) {
|
||||
if boil.HooksAreSkipped(ctx) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, hook := range scriptAfterUpsertHooks {
|
||||
if err := hook(ctx, exec, o); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddScriptHook registers your hook function for all future operations.
|
||||
func AddScriptHook(hookPoint boil.HookPoint, scriptHook ScriptHook) {
|
||||
switch hookPoint {
|
||||
case boil.BeforeInsertHook:
|
||||
scriptBeforeInsertHooks = append(scriptBeforeInsertHooks, scriptHook)
|
||||
case boil.BeforeUpdateHook:
|
||||
scriptBeforeUpdateHooks = append(scriptBeforeUpdateHooks, scriptHook)
|
||||
case boil.BeforeDeleteHook:
|
||||
scriptBeforeDeleteHooks = append(scriptBeforeDeleteHooks, scriptHook)
|
||||
case boil.BeforeUpsertHook:
|
||||
scriptBeforeUpsertHooks = append(scriptBeforeUpsertHooks, scriptHook)
|
||||
case boil.AfterInsertHook:
|
||||
scriptAfterInsertHooks = append(scriptAfterInsertHooks, scriptHook)
|
||||
case boil.AfterSelectHook:
|
||||
scriptAfterSelectHooks = append(scriptAfterSelectHooks, scriptHook)
|
||||
case boil.AfterUpdateHook:
|
||||
scriptAfterUpdateHooks = append(scriptAfterUpdateHooks, scriptHook)
|
||||
case boil.AfterDeleteHook:
|
||||
scriptAfterDeleteHooks = append(scriptAfterDeleteHooks, scriptHook)
|
||||
case boil.AfterUpsertHook:
|
||||
scriptAfterUpsertHooks = append(scriptAfterUpsertHooks, scriptHook)
|
||||
}
|
||||
}
|
||||
|
||||
// One returns a single script record from the query.
|
||||
func (q scriptQuery) One(ctx context.Context, exec boil.ContextExecutor) (*Script, error) {
|
||||
o := &Script{}
|
||||
|
||||
queries.SetLimit(q.Query, 1)
|
||||
|
||||
err := q.Bind(ctx, exec, o)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return nil, sql.ErrNoRows
|
||||
}
|
||||
return nil, errors.Wrap(err, "sqlite3: failed to execute a one query for script")
|
||||
}
|
||||
|
||||
if err := o.doAfterSelectHooks(ctx, exec); err != nil {
|
||||
return o, err
|
||||
}
|
||||
|
||||
return o, nil
|
||||
}
|
||||
|
||||
// All returns all Script records from the query.
|
||||
func (q scriptQuery) All(ctx context.Context, exec boil.ContextExecutor) (ScriptSlice, error) {
|
||||
var o []*Script
|
||||
|
||||
err := q.Bind(ctx, exec, &o)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "sqlite3: failed to assign all query results to Script slice")
|
||||
}
|
||||
|
||||
if len(scriptAfterSelectHooks) != 0 {
|
||||
for _, obj := range o {
|
||||
if err := obj.doAfterSelectHooks(ctx, exec); err != nil {
|
||||
return o, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return o, nil
|
||||
}
|
||||
|
||||
// Count returns the count of all Script records in the query.
|
||||
func (q scriptQuery) Count(ctx context.Context, exec boil.ContextExecutor) (int64, error) {
|
||||
var count int64
|
||||
|
||||
queries.SetSelect(q.Query, nil)
|
||||
queries.SetCount(q.Query)
|
||||
|
||||
err := q.Query.QueryRowContext(ctx, exec).Scan(&count)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: failed to count script rows")
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// Exists checks if the row exists in the table.
|
||||
func (q scriptQuery) Exists(ctx context.Context, exec boil.ContextExecutor) (bool, error) {
|
||||
var count int64
|
||||
|
||||
queries.SetSelect(q.Query, nil)
|
||||
queries.SetCount(q.Query)
|
||||
queries.SetLimit(q.Query, 1)
|
||||
|
||||
err := q.Query.QueryRowContext(ctx, exec).Scan(&count)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "sqlite3: failed to check if script exists")
|
||||
}
|
||||
|
||||
return count > 0, nil
|
||||
}
|
||||
|
||||
// ScriptExecutions retrieves all the script_execution's ScriptExecutions with an executor.
|
||||
func (o *Script) ScriptExecutions(mods ...qm.QueryMod) scriptExecutionQuery {
|
||||
var queryMods []qm.QueryMod
|
||||
if len(mods) != 0 {
|
||||
queryMods = append(queryMods, mods...)
|
||||
}
|
||||
|
||||
queryMods = append(queryMods,
|
||||
qm.Where("\"script_execution\".\"script_id\"=?", o.ID),
|
||||
)
|
||||
|
||||
query := ScriptExecutions(queryMods...)
|
||||
queries.SetFrom(query.Query, "\"script_execution\"")
|
||||
|
||||
if len(queries.GetSelect(query.Query)) == 0 {
|
||||
queries.SetSelect(query.Query, []string{"\"script_execution\".*"})
|
||||
}
|
||||
|
||||
return query
|
||||
}
|
||||
|
||||
// LoadScriptExecutions allows an eager lookup of values, cached into the
|
||||
// loaded structs of the objects. This is for a 1-M or N-M relationship.
|
||||
func (scriptL) LoadScriptExecutions(ctx context.Context, e boil.ContextExecutor, singular bool, maybeScript interface{}, mods queries.Applicator) error {
|
||||
var slice []*Script
|
||||
var object *Script
|
||||
|
||||
if singular {
|
||||
object = maybeScript.(*Script)
|
||||
} else {
|
||||
slice = *maybeScript.(*[]*Script)
|
||||
}
|
||||
|
||||
args := make([]interface{}, 0, 1)
|
||||
if singular {
|
||||
if object.R == nil {
|
||||
object.R = &scriptR{}
|
||||
}
|
||||
args = append(args, object.ID)
|
||||
} else {
|
||||
Outer:
|
||||
for _, obj := range slice {
|
||||
if obj.R == nil {
|
||||
obj.R = &scriptR{}
|
||||
}
|
||||
|
||||
for _, a := range args {
|
||||
if a == obj.ID {
|
||||
continue Outer
|
||||
}
|
||||
}
|
||||
|
||||
args = append(args, obj.ID)
|
||||
}
|
||||
}
|
||||
|
||||
if len(args) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
query := NewQuery(qm.From(`script_execution`), qm.WhereIn(`script_execution.script_id in ?`, args...))
|
||||
if mods != nil {
|
||||
mods.Apply(query)
|
||||
}
|
||||
|
||||
results, err := query.QueryContext(ctx, e)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to eager load script_execution")
|
||||
}
|
||||
|
||||
var resultSlice []*ScriptExecution
|
||||
if err = queries.Bind(results, &resultSlice); err != nil {
|
||||
return errors.Wrap(err, "failed to bind eager loaded slice script_execution")
|
||||
}
|
||||
|
||||
if err = results.Close(); err != nil {
|
||||
return errors.Wrap(err, "failed to close results in eager load on script_execution")
|
||||
}
|
||||
if err = results.Err(); err != nil {
|
||||
return errors.Wrap(err, "error occurred during iteration of eager loaded relations for script_execution")
|
||||
}
|
||||
|
||||
if len(scriptExecutionAfterSelectHooks) != 0 {
|
||||
for _, obj := range resultSlice {
|
||||
if err := obj.doAfterSelectHooks(ctx, e); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if singular {
|
||||
object.R.ScriptExecutions = resultSlice
|
||||
for _, foreign := range resultSlice {
|
||||
if foreign.R == nil {
|
||||
foreign.R = &scriptExecutionR{}
|
||||
}
|
||||
foreign.R.Script = object
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, foreign := range resultSlice {
|
||||
for _, local := range slice {
|
||||
if local.ID == foreign.ScriptID {
|
||||
local.R.ScriptExecutions = append(local.R.ScriptExecutions, foreign)
|
||||
if foreign.R == nil {
|
||||
foreign.R = &scriptExecutionR{}
|
||||
}
|
||||
foreign.R.Script = local
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddScriptExecutions adds the given related objects to the existing relationships
|
||||
// of the script, optionally inserting them as new records.
|
||||
// Appends related to o.R.ScriptExecutions.
|
||||
// Sets related.R.Script appropriately.
|
||||
func (o *Script) AddScriptExecutions(ctx context.Context, exec boil.ContextExecutor, insert bool, related ...*ScriptExecution) error {
|
||||
var err error
|
||||
for _, rel := range related {
|
||||
if insert {
|
||||
rel.ScriptID = o.ID
|
||||
if err = rel.Insert(ctx, exec, boil.Infer()); err != nil {
|
||||
return errors.Wrap(err, "failed to insert into foreign table")
|
||||
}
|
||||
} else {
|
||||
updateQuery := fmt.Sprintf(
|
||||
"UPDATE \"script_execution\" SET %s WHERE %s",
|
||||
strmangle.SetParamNames("\"", "\"", 0, []string{"script_id"}),
|
||||
strmangle.WhereClause("\"", "\"", 0, scriptExecutionPrimaryKeyColumns),
|
||||
)
|
||||
values := []interface{}{o.ID, rel.ID}
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, updateQuery)
|
||||
fmt.Fprintln(boil.DebugWriter, values)
|
||||
}
|
||||
|
||||
if _, err = exec.ExecContext(ctx, updateQuery, values...); err != nil {
|
||||
return errors.Wrap(err, "failed to update foreign table")
|
||||
}
|
||||
|
||||
rel.ScriptID = o.ID
|
||||
}
|
||||
}
|
||||
|
||||
if o.R == nil {
|
||||
o.R = &scriptR{
|
||||
ScriptExecutions: related,
|
||||
}
|
||||
} else {
|
||||
o.R.ScriptExecutions = append(o.R.ScriptExecutions, related...)
|
||||
}
|
||||
|
||||
for _, rel := range related {
|
||||
if rel.R == nil {
|
||||
rel.R = &scriptExecutionR{
|
||||
Script: o,
|
||||
}
|
||||
} else {
|
||||
rel.R.Script = o
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Scripts retrieves all the records using an executor.
|
||||
func Scripts(mods ...qm.QueryMod) scriptQuery {
|
||||
mods = append(mods, qm.From("\"script\""))
|
||||
return scriptQuery{NewQuery(mods...)}
|
||||
}
|
||||
|
||||
// FindScript retrieves a single record by ID with an executor.
|
||||
// If selectCols is empty Find will return all columns.
|
||||
func FindScript(ctx context.Context, exec boil.ContextExecutor, iD string, selectCols ...string) (*Script, error) {
|
||||
scriptObj := &Script{}
|
||||
|
||||
sel := "*"
|
||||
if len(selectCols) > 0 {
|
||||
sel = strings.Join(strmangle.IdentQuoteSlice(dialect.LQ, dialect.RQ, selectCols), ",")
|
||||
}
|
||||
query := fmt.Sprintf(
|
||||
"select %s from \"script\" where \"id\"=?", sel,
|
||||
)
|
||||
|
||||
q := queries.Raw(query, iD)
|
||||
|
||||
err := q.Bind(ctx, exec, scriptObj)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return nil, sql.ErrNoRows
|
||||
}
|
||||
return nil, errors.Wrap(err, "sqlite3: unable to select from script")
|
||||
}
|
||||
|
||||
return scriptObj, nil
|
||||
}
|
||||
|
||||
// Insert a single record using an executor.
|
||||
// See boil.Columns.InsertColumnSet documentation to understand column list inference for inserts.
|
||||
func (o *Script) Insert(ctx context.Context, exec boil.ContextExecutor, columns boil.Columns) error {
|
||||
if o == nil {
|
||||
return errors.New("sqlite3: no script provided for insertion")
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
if err := o.doBeforeInsertHooks(ctx, exec); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nzDefaults := queries.NonZeroDefaultSet(scriptColumnsWithDefault, o)
|
||||
|
||||
key := makeCacheKey(columns, nzDefaults)
|
||||
scriptInsertCacheMut.RLock()
|
||||
cache, cached := scriptInsertCache[key]
|
||||
scriptInsertCacheMut.RUnlock()
|
||||
|
||||
if !cached {
|
||||
wl, returnColumns := columns.InsertColumnSet(
|
||||
scriptAllColumns,
|
||||
scriptColumnsWithDefault,
|
||||
scriptColumnsWithoutDefault,
|
||||
nzDefaults,
|
||||
)
|
||||
|
||||
cache.valueMapping, err = queries.BindMapping(scriptType, scriptMapping, wl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cache.retMapping, err = queries.BindMapping(scriptType, scriptMapping, returnColumns)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(wl) != 0 {
|
||||
cache.query = fmt.Sprintf("INSERT INTO \"script\" (\"%s\") %%sVALUES (%s)%%s", strings.Join(wl, "\",\""), strmangle.Placeholders(dialect.UseIndexPlaceholders, len(wl), 1, 1))
|
||||
} else {
|
||||
cache.query = "INSERT INTO \"script\" () VALUES ()%s%s"
|
||||
}
|
||||
|
||||
var queryOutput, queryReturning string
|
||||
|
||||
if len(cache.retMapping) != 0 {
|
||||
cache.retQuery = fmt.Sprintf("SELECT \"%s\" FROM \"script\" WHERE %s", strings.Join(returnColumns, "\",\""), strmangle.WhereClause("\"", "\"", 0, scriptPrimaryKeyColumns))
|
||||
}
|
||||
|
||||
cache.query = fmt.Sprintf(cache.query, queryOutput, queryReturning)
|
||||
}
|
||||
|
||||
value := reflect.Indirect(reflect.ValueOf(o))
|
||||
vals := queries.ValuesFromMapping(value, cache.valueMapping)
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, cache.query)
|
||||
fmt.Fprintln(boil.DebugWriter, vals)
|
||||
}
|
||||
|
||||
_, err = exec.ExecContext(ctx, cache.query, vals...)
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "sqlite3: unable to insert into script")
|
||||
}
|
||||
|
||||
var identifierCols []interface{}
|
||||
|
||||
if len(cache.retMapping) == 0 {
|
||||
goto CacheNoHooks
|
||||
}
|
||||
|
||||
identifierCols = []interface{}{
|
||||
o.ID,
|
||||
}
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, cache.retQuery)
|
||||
fmt.Fprintln(boil.DebugWriter, identifierCols...)
|
||||
}
|
||||
|
||||
err = exec.QueryRowContext(ctx, cache.retQuery, identifierCols...).Scan(queries.PtrsFromMapping(value, cache.retMapping)...)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "sqlite3: unable to populate default values for script")
|
||||
}
|
||||
|
||||
CacheNoHooks:
|
||||
if !cached {
|
||||
scriptInsertCacheMut.Lock()
|
||||
scriptInsertCache[key] = cache
|
||||
scriptInsertCacheMut.Unlock()
|
||||
}
|
||||
|
||||
return o.doAfterInsertHooks(ctx, exec)
|
||||
}
|
||||
|
||||
// Update uses an executor to update the Script.
|
||||
// See boil.Columns.UpdateColumnSet documentation to understand column list inference for updates.
|
||||
// Update does not automatically update the record in case of default values. Use .Reload() to refresh the records.
|
||||
func (o *Script) Update(ctx context.Context, exec boil.ContextExecutor, columns boil.Columns) (int64, error) {
|
||||
var err error
|
||||
if err = o.doBeforeUpdateHooks(ctx, exec); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
key := makeCacheKey(columns, nil)
|
||||
scriptUpdateCacheMut.RLock()
|
||||
cache, cached := scriptUpdateCache[key]
|
||||
scriptUpdateCacheMut.RUnlock()
|
||||
|
||||
if !cached {
|
||||
wl := columns.UpdateColumnSet(
|
||||
scriptAllColumns,
|
||||
scriptPrimaryKeyColumns,
|
||||
)
|
||||
|
||||
if len(wl) == 0 {
|
||||
return 0, errors.New("sqlite3: unable to update script, could not build whitelist")
|
||||
}
|
||||
|
||||
cache.query = fmt.Sprintf("UPDATE \"script\" SET %s WHERE %s",
|
||||
strmangle.SetParamNames("\"", "\"", 0, wl),
|
||||
strmangle.WhereClause("\"", "\"", 0, scriptPrimaryKeyColumns),
|
||||
)
|
||||
cache.valueMapping, err = queries.BindMapping(scriptType, scriptMapping, append(wl, scriptPrimaryKeyColumns...))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
values := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(o)), cache.valueMapping)
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, cache.query)
|
||||
fmt.Fprintln(boil.DebugWriter, values)
|
||||
}
|
||||
|
||||
var result sql.Result
|
||||
result, err = exec.ExecContext(ctx, cache.query, values...)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: unable to update script row")
|
||||
}
|
||||
|
||||
rowsAff, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: failed to get rows affected by update for script")
|
||||
}
|
||||
|
||||
if !cached {
|
||||
scriptUpdateCacheMut.Lock()
|
||||
scriptUpdateCache[key] = cache
|
||||
scriptUpdateCacheMut.Unlock()
|
||||
}
|
||||
|
||||
return rowsAff, o.doAfterUpdateHooks(ctx, exec)
|
||||
}
|
||||
|
||||
// UpdateAll updates all rows with the specified column values.
|
||||
func (q scriptQuery) UpdateAll(ctx context.Context, exec boil.ContextExecutor, cols M) (int64, error) {
|
||||
queries.SetUpdate(q.Query, cols)
|
||||
|
||||
result, err := q.Query.ExecContext(ctx, exec)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: unable to update all for script")
|
||||
}
|
||||
|
||||
rowsAff, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: unable to retrieve rows affected for script")
|
||||
}
|
||||
|
||||
return rowsAff, nil
|
||||
}
|
||||
|
||||
// UpdateAll updates all rows with the specified column values, using an executor.
|
||||
func (o ScriptSlice) UpdateAll(ctx context.Context, exec boil.ContextExecutor, cols M) (int64, error) {
|
||||
ln := int64(len(o))
|
||||
if ln == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
if len(cols) == 0 {
|
||||
return 0, errors.New("sqlite3: update all requires at least one column argument")
|
||||
}
|
||||
|
||||
colNames := make([]string, len(cols))
|
||||
args := make([]interface{}, len(cols))
|
||||
|
||||
i := 0
|
||||
for name, value := range cols {
|
||||
colNames[i] = name
|
||||
args[i] = value
|
||||
i++
|
||||
}
|
||||
|
||||
// Append all of the primary key values for each column
|
||||
for _, obj := range o {
|
||||
pkeyArgs := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(obj)), scriptPrimaryKeyMapping)
|
||||
args = append(args, pkeyArgs...)
|
||||
}
|
||||
|
||||
sql := fmt.Sprintf("UPDATE \"script\" SET %s WHERE %s",
|
||||
strmangle.SetParamNames("\"", "\"", 0, colNames),
|
||||
strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), 0, scriptPrimaryKeyColumns, len(o)))
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, sql)
|
||||
fmt.Fprintln(boil.DebugWriter, args...)
|
||||
}
|
||||
|
||||
result, err := exec.ExecContext(ctx, sql, args...)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: unable to update all in script slice")
|
||||
}
|
||||
|
||||
rowsAff, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: unable to retrieve rows affected all in update all script")
|
||||
}
|
||||
return rowsAff, nil
|
||||
}
|
||||
|
||||
// Delete deletes a single Script record with an executor.
|
||||
// Delete will match against the primary key column to find the record to delete.
|
||||
func (o *Script) Delete(ctx context.Context, exec boil.ContextExecutor) (int64, error) {
|
||||
if o == nil {
|
||||
return 0, errors.New("sqlite3: no Script provided for delete")
|
||||
}
|
||||
|
||||
if err := o.doBeforeDeleteHooks(ctx, exec); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
args := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(o)), scriptPrimaryKeyMapping)
|
||||
sql := "DELETE FROM \"script\" WHERE \"id\"=?"
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, sql)
|
||||
fmt.Fprintln(boil.DebugWriter, args...)
|
||||
}
|
||||
|
||||
result, err := exec.ExecContext(ctx, sql, args...)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: unable to delete from script")
|
||||
}
|
||||
|
||||
rowsAff, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: failed to get rows affected by delete for script")
|
||||
}
|
||||
|
||||
if err := o.doAfterDeleteHooks(ctx, exec); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return rowsAff, nil
|
||||
}
|
||||
|
||||
// DeleteAll deletes all matching rows.
|
||||
func (q scriptQuery) DeleteAll(ctx context.Context, exec boil.ContextExecutor) (int64, error) {
|
||||
if q.Query == nil {
|
||||
return 0, errors.New("sqlite3: no scriptQuery provided for delete all")
|
||||
}
|
||||
|
||||
queries.SetDelete(q.Query)
|
||||
|
||||
result, err := q.Query.ExecContext(ctx, exec)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: unable to delete all from script")
|
||||
}
|
||||
|
||||
rowsAff, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: failed to get rows affected by deleteall for script")
|
||||
}
|
||||
|
||||
return rowsAff, nil
|
||||
}
|
||||
|
||||
// DeleteAll deletes all rows in the slice, using an executor.
|
||||
func (o ScriptSlice) DeleteAll(ctx context.Context, exec boil.ContextExecutor) (int64, error) {
|
||||
if len(o) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
if len(scriptBeforeDeleteHooks) != 0 {
|
||||
for _, obj := range o {
|
||||
if err := obj.doBeforeDeleteHooks(ctx, exec); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var args []interface{}
|
||||
for _, obj := range o {
|
||||
pkeyArgs := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(obj)), scriptPrimaryKeyMapping)
|
||||
args = append(args, pkeyArgs...)
|
||||
}
|
||||
|
||||
sql := "DELETE FROM \"script\" WHERE " +
|
||||
strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), 0, scriptPrimaryKeyColumns, len(o))
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, sql)
|
||||
fmt.Fprintln(boil.DebugWriter, args)
|
||||
}
|
||||
|
||||
result, err := exec.ExecContext(ctx, sql, args...)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: unable to delete all from script slice")
|
||||
}
|
||||
|
||||
rowsAff, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: failed to get rows affected by deleteall for script")
|
||||
}
|
||||
|
||||
if len(scriptAfterDeleteHooks) != 0 {
|
||||
for _, obj := range o {
|
||||
if err := obj.doAfterDeleteHooks(ctx, exec); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rowsAff, nil
|
||||
}
|
||||
|
||||
// Reload refetches the object from the database
|
||||
// using the primary keys with an executor.
|
||||
func (o *Script) Reload(ctx context.Context, exec boil.ContextExecutor) error {
|
||||
ret, err := FindScript(ctx, exec, o.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*o = *ret
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReloadAll refetches every row with matching primary key column values
|
||||
// and overwrites the original object slice with the newly updated slice.
|
||||
func (o *ScriptSlice) ReloadAll(ctx context.Context, exec boil.ContextExecutor) error {
|
||||
if o == nil || len(*o) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
slice := ScriptSlice{}
|
||||
var args []interface{}
|
||||
for _, obj := range *o {
|
||||
pkeyArgs := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(obj)), scriptPrimaryKeyMapping)
|
||||
args = append(args, pkeyArgs...)
|
||||
}
|
||||
|
||||
sql := "SELECT \"script\".* FROM \"script\" WHERE " +
|
||||
strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), 0, scriptPrimaryKeyColumns, len(*o))
|
||||
|
||||
q := queries.Raw(sql, args...)
|
||||
|
||||
err := q.Bind(ctx, exec, &slice)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "sqlite3: unable to reload all in ScriptSlice")
|
||||
}
|
||||
|
||||
*o = slice
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ScriptExists checks if the Script row exists.
|
||||
func ScriptExists(ctx context.Context, exec boil.ContextExecutor, iD string) (bool, error) {
|
||||
var exists bool
|
||||
sql := "select exists(select 1 from \"script\" where \"id\"=? limit 1)"
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, sql)
|
||||
fmt.Fprintln(boil.DebugWriter, iD)
|
||||
}
|
||||
|
||||
row := exec.QueryRowContext(ctx, sql, iD)
|
||||
|
||||
err := row.Scan(&exists)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "sqlite3: unable to check if script exists")
|
||||
}
|
||||
|
||||
return exists, nil
|
||||
}
|
||||
957
database/models/sqlite3/script_execution.go
Normal file
957
database/models/sqlite3/script_execution.go
Normal file
@@ -0,0 +1,957 @@
|
||||
// Code generated by SQLBoiler 3.5.0-gct (https://github.com/thrasher-corp/sqlboiler). DO NOT EDIT.
|
||||
// This file is meant to be re-generated in place and/or deleted at any time.
|
||||
|
||||
package sqlite3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/thrasher-corp/sqlboiler/boil"
|
||||
"github.com/thrasher-corp/sqlboiler/queries"
|
||||
"github.com/thrasher-corp/sqlboiler/queries/qm"
|
||||
"github.com/thrasher-corp/sqlboiler/queries/qmhelper"
|
||||
"github.com/thrasher-corp/sqlboiler/strmangle"
|
||||
)
|
||||
|
||||
// ScriptExecution is an object representing the database table.
|
||||
type ScriptExecution struct {
|
||||
ID int64 `boil:"id" json:"id" toml:"id" yaml:"id"`
|
||||
ScriptID string `boil:"script_id" json:"script_id" toml:"script_id" yaml:"script_id"`
|
||||
ExecutionType string `boil:"execution_type" json:"execution_type" toml:"execution_type" yaml:"execution_type"`
|
||||
ExecutionStatus string `boil:"execution_status" json:"execution_status" toml:"execution_status" yaml:"execution_status"`
|
||||
ExecutionTime string `boil:"execution_time" json:"execution_time" toml:"execution_time" yaml:"execution_time"`
|
||||
|
||||
R *scriptExecutionR `boil:"-" json:"-" toml:"-" yaml:"-"`
|
||||
L scriptExecutionL `boil:"-" json:"-" toml:"-" yaml:"-"`
|
||||
}
|
||||
|
||||
var ScriptExecutionColumns = struct {
|
||||
ID string
|
||||
ScriptID string
|
||||
ExecutionType string
|
||||
ExecutionStatus string
|
||||
ExecutionTime string
|
||||
}{
|
||||
ID: "id",
|
||||
ScriptID: "script_id",
|
||||
ExecutionType: "execution_type",
|
||||
ExecutionStatus: "execution_status",
|
||||
ExecutionTime: "execution_time",
|
||||
}
|
||||
|
||||
// Generated where
|
||||
|
||||
var ScriptExecutionWhere = struct {
|
||||
ID whereHelperint64
|
||||
ScriptID whereHelperstring
|
||||
ExecutionType whereHelperstring
|
||||
ExecutionStatus whereHelperstring
|
||||
ExecutionTime whereHelperstring
|
||||
}{
|
||||
ID: whereHelperint64{field: "\"script_execution\".\"id\""},
|
||||
ScriptID: whereHelperstring{field: "\"script_execution\".\"script_id\""},
|
||||
ExecutionType: whereHelperstring{field: "\"script_execution\".\"execution_type\""},
|
||||
ExecutionStatus: whereHelperstring{field: "\"script_execution\".\"execution_status\""},
|
||||
ExecutionTime: whereHelperstring{field: "\"script_execution\".\"execution_time\""},
|
||||
}
|
||||
|
||||
// ScriptExecutionRels is where relationship names are stored.
|
||||
var ScriptExecutionRels = struct {
|
||||
Script string
|
||||
}{
|
||||
Script: "Script",
|
||||
}
|
||||
|
||||
// scriptExecutionR is where relationships are stored.
|
||||
type scriptExecutionR struct {
|
||||
Script *Script
|
||||
}
|
||||
|
||||
// NewStruct creates a new relationship struct
|
||||
func (*scriptExecutionR) NewStruct() *scriptExecutionR {
|
||||
return &scriptExecutionR{}
|
||||
}
|
||||
|
||||
// scriptExecutionL is where Load methods for each relationship are stored.
|
||||
type scriptExecutionL struct{}
|
||||
|
||||
var (
|
||||
scriptExecutionAllColumns = []string{"id", "script_id", "execution_type", "execution_status", "execution_time"}
|
||||
scriptExecutionColumnsWithoutDefault = []string{"script_id", "execution_type", "execution_status"}
|
||||
scriptExecutionColumnsWithDefault = []string{"id", "execution_time"}
|
||||
scriptExecutionPrimaryKeyColumns = []string{"id"}
|
||||
)
|
||||
|
||||
type (
|
||||
// ScriptExecutionSlice is an alias for a slice of pointers to ScriptExecution.
|
||||
// This should generally be used opposed to []ScriptExecution.
|
||||
ScriptExecutionSlice []*ScriptExecution
|
||||
// ScriptExecutionHook is the signature for custom ScriptExecution hook methods
|
||||
ScriptExecutionHook func(context.Context, boil.ContextExecutor, *ScriptExecution) error
|
||||
|
||||
scriptExecutionQuery struct {
|
||||
*queries.Query
|
||||
}
|
||||
)
|
||||
|
||||
// Cache for insert, update and upsert
|
||||
var (
|
||||
scriptExecutionType = reflect.TypeOf(&ScriptExecution{})
|
||||
scriptExecutionMapping = queries.MakeStructMapping(scriptExecutionType)
|
||||
scriptExecutionPrimaryKeyMapping, _ = queries.BindMapping(scriptExecutionType, scriptExecutionMapping, scriptExecutionPrimaryKeyColumns)
|
||||
scriptExecutionInsertCacheMut sync.RWMutex
|
||||
scriptExecutionInsertCache = make(map[string]insertCache)
|
||||
scriptExecutionUpdateCacheMut sync.RWMutex
|
||||
scriptExecutionUpdateCache = make(map[string]updateCache)
|
||||
scriptExecutionUpsertCacheMut sync.RWMutex
|
||||
scriptExecutionUpsertCache = make(map[string]insertCache)
|
||||
)
|
||||
|
||||
var (
|
||||
// Force time package dependency for automated UpdatedAt/CreatedAt.
|
||||
_ = time.Second
|
||||
// Force qmhelper dependency for where clause generation (which doesn't
|
||||
// always happen)
|
||||
_ = qmhelper.Where
|
||||
)
|
||||
|
||||
var scriptExecutionBeforeInsertHooks []ScriptExecutionHook
|
||||
var scriptExecutionBeforeUpdateHooks []ScriptExecutionHook
|
||||
var scriptExecutionBeforeDeleteHooks []ScriptExecutionHook
|
||||
var scriptExecutionBeforeUpsertHooks []ScriptExecutionHook
|
||||
|
||||
var scriptExecutionAfterInsertHooks []ScriptExecutionHook
|
||||
var scriptExecutionAfterSelectHooks []ScriptExecutionHook
|
||||
var scriptExecutionAfterUpdateHooks []ScriptExecutionHook
|
||||
var scriptExecutionAfterDeleteHooks []ScriptExecutionHook
|
||||
var scriptExecutionAfterUpsertHooks []ScriptExecutionHook
|
||||
|
||||
// doBeforeInsertHooks executes all "before insert" hooks.
|
||||
func (o *ScriptExecution) doBeforeInsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) {
|
||||
if boil.HooksAreSkipped(ctx) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, hook := range scriptExecutionBeforeInsertHooks {
|
||||
if err := hook(ctx, exec, o); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// doBeforeUpdateHooks executes all "before Update" hooks.
|
||||
func (o *ScriptExecution) doBeforeUpdateHooks(ctx context.Context, exec boil.ContextExecutor) (err error) {
|
||||
if boil.HooksAreSkipped(ctx) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, hook := range scriptExecutionBeforeUpdateHooks {
|
||||
if err := hook(ctx, exec, o); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// doBeforeDeleteHooks executes all "before Delete" hooks.
|
||||
func (o *ScriptExecution) doBeforeDeleteHooks(ctx context.Context, exec boil.ContextExecutor) (err error) {
|
||||
if boil.HooksAreSkipped(ctx) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, hook := range scriptExecutionBeforeDeleteHooks {
|
||||
if err := hook(ctx, exec, o); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// doBeforeUpsertHooks executes all "before Upsert" hooks.
|
||||
func (o *ScriptExecution) doBeforeUpsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) {
|
||||
if boil.HooksAreSkipped(ctx) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, hook := range scriptExecutionBeforeUpsertHooks {
|
||||
if err := hook(ctx, exec, o); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// doAfterInsertHooks executes all "after Insert" hooks.
|
||||
func (o *ScriptExecution) doAfterInsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) {
|
||||
if boil.HooksAreSkipped(ctx) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, hook := range scriptExecutionAfterInsertHooks {
|
||||
if err := hook(ctx, exec, o); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// doAfterSelectHooks executes all "after Select" hooks.
|
||||
func (o *ScriptExecution) doAfterSelectHooks(ctx context.Context, exec boil.ContextExecutor) (err error) {
|
||||
if boil.HooksAreSkipped(ctx) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, hook := range scriptExecutionAfterSelectHooks {
|
||||
if err := hook(ctx, exec, o); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// doAfterUpdateHooks executes all "after Update" hooks.
|
||||
func (o *ScriptExecution) doAfterUpdateHooks(ctx context.Context, exec boil.ContextExecutor) (err error) {
|
||||
if boil.HooksAreSkipped(ctx) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, hook := range scriptExecutionAfterUpdateHooks {
|
||||
if err := hook(ctx, exec, o); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// doAfterDeleteHooks executes all "after Delete" hooks.
|
||||
func (o *ScriptExecution) doAfterDeleteHooks(ctx context.Context, exec boil.ContextExecutor) (err error) {
|
||||
if boil.HooksAreSkipped(ctx) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, hook := range scriptExecutionAfterDeleteHooks {
|
||||
if err := hook(ctx, exec, o); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// doAfterUpsertHooks executes all "after Upsert" hooks.
|
||||
func (o *ScriptExecution) doAfterUpsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) {
|
||||
if boil.HooksAreSkipped(ctx) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, hook := range scriptExecutionAfterUpsertHooks {
|
||||
if err := hook(ctx, exec, o); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddScriptExecutionHook registers your hook function for all future operations.
|
||||
func AddScriptExecutionHook(hookPoint boil.HookPoint, scriptExecutionHook ScriptExecutionHook) {
|
||||
switch hookPoint {
|
||||
case boil.BeforeInsertHook:
|
||||
scriptExecutionBeforeInsertHooks = append(scriptExecutionBeforeInsertHooks, scriptExecutionHook)
|
||||
case boil.BeforeUpdateHook:
|
||||
scriptExecutionBeforeUpdateHooks = append(scriptExecutionBeforeUpdateHooks, scriptExecutionHook)
|
||||
case boil.BeforeDeleteHook:
|
||||
scriptExecutionBeforeDeleteHooks = append(scriptExecutionBeforeDeleteHooks, scriptExecutionHook)
|
||||
case boil.BeforeUpsertHook:
|
||||
scriptExecutionBeforeUpsertHooks = append(scriptExecutionBeforeUpsertHooks, scriptExecutionHook)
|
||||
case boil.AfterInsertHook:
|
||||
scriptExecutionAfterInsertHooks = append(scriptExecutionAfterInsertHooks, scriptExecutionHook)
|
||||
case boil.AfterSelectHook:
|
||||
scriptExecutionAfterSelectHooks = append(scriptExecutionAfterSelectHooks, scriptExecutionHook)
|
||||
case boil.AfterUpdateHook:
|
||||
scriptExecutionAfterUpdateHooks = append(scriptExecutionAfterUpdateHooks, scriptExecutionHook)
|
||||
case boil.AfterDeleteHook:
|
||||
scriptExecutionAfterDeleteHooks = append(scriptExecutionAfterDeleteHooks, scriptExecutionHook)
|
||||
case boil.AfterUpsertHook:
|
||||
scriptExecutionAfterUpsertHooks = append(scriptExecutionAfterUpsertHooks, scriptExecutionHook)
|
||||
}
|
||||
}
|
||||
|
||||
// One returns a single scriptExecution record from the query.
|
||||
func (q scriptExecutionQuery) One(ctx context.Context, exec boil.ContextExecutor) (*ScriptExecution, error) {
|
||||
o := &ScriptExecution{}
|
||||
|
||||
queries.SetLimit(q.Query, 1)
|
||||
|
||||
err := q.Bind(ctx, exec, o)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return nil, sql.ErrNoRows
|
||||
}
|
||||
return nil, errors.Wrap(err, "sqlite3: failed to execute a one query for script_execution")
|
||||
}
|
||||
|
||||
if err := o.doAfterSelectHooks(ctx, exec); err != nil {
|
||||
return o, err
|
||||
}
|
||||
|
||||
return o, nil
|
||||
}
|
||||
|
||||
// All returns all ScriptExecution records from the query.
|
||||
func (q scriptExecutionQuery) All(ctx context.Context, exec boil.ContextExecutor) (ScriptExecutionSlice, error) {
|
||||
var o []*ScriptExecution
|
||||
|
||||
err := q.Bind(ctx, exec, &o)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "sqlite3: failed to assign all query results to ScriptExecution slice")
|
||||
}
|
||||
|
||||
if len(scriptExecutionAfterSelectHooks) != 0 {
|
||||
for _, obj := range o {
|
||||
if err := obj.doAfterSelectHooks(ctx, exec); err != nil {
|
||||
return o, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return o, nil
|
||||
}
|
||||
|
||||
// Count returns the count of all ScriptExecution records in the query.
|
||||
func (q scriptExecutionQuery) Count(ctx context.Context, exec boil.ContextExecutor) (int64, error) {
|
||||
var count int64
|
||||
|
||||
queries.SetSelect(q.Query, nil)
|
||||
queries.SetCount(q.Query)
|
||||
|
||||
err := q.Query.QueryRowContext(ctx, exec).Scan(&count)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: failed to count script_execution rows")
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// Exists checks if the row exists in the table.
|
||||
func (q scriptExecutionQuery) Exists(ctx context.Context, exec boil.ContextExecutor) (bool, error) {
|
||||
var count int64
|
||||
|
||||
queries.SetSelect(q.Query, nil)
|
||||
queries.SetCount(q.Query)
|
||||
queries.SetLimit(q.Query, 1)
|
||||
|
||||
err := q.Query.QueryRowContext(ctx, exec).Scan(&count)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "sqlite3: failed to check if script_execution exists")
|
||||
}
|
||||
|
||||
return count > 0, nil
|
||||
}
|
||||
|
||||
// Script pointed to by the foreign key.
|
||||
func (o *ScriptExecution) Script(mods ...qm.QueryMod) scriptQuery {
|
||||
queryMods := []qm.QueryMod{
|
||||
qm.Where("\"id\" = ?", o.ScriptID),
|
||||
}
|
||||
|
||||
queryMods = append(queryMods, mods...)
|
||||
|
||||
query := Scripts(queryMods...)
|
||||
queries.SetFrom(query.Query, "\"script\"")
|
||||
|
||||
return query
|
||||
}
|
||||
|
||||
// LoadScript allows an eager lookup of values, cached into the
|
||||
// loaded structs of the objects. This is for an N-1 relationship.
|
||||
func (scriptExecutionL) LoadScript(ctx context.Context, e boil.ContextExecutor, singular bool, maybeScriptExecution interface{}, mods queries.Applicator) error {
|
||||
var slice []*ScriptExecution
|
||||
var object *ScriptExecution
|
||||
|
||||
if singular {
|
||||
object = maybeScriptExecution.(*ScriptExecution)
|
||||
} else {
|
||||
slice = *maybeScriptExecution.(*[]*ScriptExecution)
|
||||
}
|
||||
|
||||
args := make([]interface{}, 0, 1)
|
||||
if singular {
|
||||
if object.R == nil {
|
||||
object.R = &scriptExecutionR{}
|
||||
}
|
||||
args = append(args, object.ScriptID)
|
||||
|
||||
} else {
|
||||
Outer:
|
||||
for _, obj := range slice {
|
||||
if obj.R == nil {
|
||||
obj.R = &scriptExecutionR{}
|
||||
}
|
||||
|
||||
for _, a := range args {
|
||||
if a == obj.ScriptID {
|
||||
continue Outer
|
||||
}
|
||||
}
|
||||
|
||||
args = append(args, obj.ScriptID)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if len(args) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
query := NewQuery(qm.From(`script`), qm.WhereIn(`script.id in ?`, args...))
|
||||
if mods != nil {
|
||||
mods.Apply(query)
|
||||
}
|
||||
|
||||
results, err := query.QueryContext(ctx, e)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to eager load Script")
|
||||
}
|
||||
|
||||
var resultSlice []*Script
|
||||
if err = queries.Bind(results, &resultSlice); err != nil {
|
||||
return errors.Wrap(err, "failed to bind eager loaded slice Script")
|
||||
}
|
||||
|
||||
if err = results.Close(); err != nil {
|
||||
return errors.Wrap(err, "failed to close results of eager load for script")
|
||||
}
|
||||
if err = results.Err(); err != nil {
|
||||
return errors.Wrap(err, "error occurred during iteration of eager loaded relations for script")
|
||||
}
|
||||
|
||||
if len(scriptExecutionAfterSelectHooks) != 0 {
|
||||
for _, obj := range resultSlice {
|
||||
if err := obj.doAfterSelectHooks(ctx, e); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(resultSlice) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if singular {
|
||||
foreign := resultSlice[0]
|
||||
object.R.Script = foreign
|
||||
if foreign.R == nil {
|
||||
foreign.R = &scriptR{}
|
||||
}
|
||||
foreign.R.ScriptExecutions = append(foreign.R.ScriptExecutions, object)
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, local := range slice {
|
||||
for _, foreign := range resultSlice {
|
||||
if local.ScriptID == foreign.ID {
|
||||
local.R.Script = foreign
|
||||
if foreign.R == nil {
|
||||
foreign.R = &scriptR{}
|
||||
}
|
||||
foreign.R.ScriptExecutions = append(foreign.R.ScriptExecutions, local)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetScript of the scriptExecution to the related item.
|
||||
// Sets o.R.Script to related.
|
||||
// Adds o to related.R.ScriptExecutions.
|
||||
func (o *ScriptExecution) SetScript(ctx context.Context, exec boil.ContextExecutor, insert bool, related *Script) error {
|
||||
var err error
|
||||
if insert {
|
||||
if err = related.Insert(ctx, exec, boil.Infer()); err != nil {
|
||||
return errors.Wrap(err, "failed to insert into foreign table")
|
||||
}
|
||||
}
|
||||
|
||||
updateQuery := fmt.Sprintf(
|
||||
"UPDATE \"script_execution\" SET %s WHERE %s",
|
||||
strmangle.SetParamNames("\"", "\"", 0, []string{"script_id"}),
|
||||
strmangle.WhereClause("\"", "\"", 0, scriptExecutionPrimaryKeyColumns),
|
||||
)
|
||||
values := []interface{}{related.ID, o.ID}
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, updateQuery)
|
||||
fmt.Fprintln(boil.DebugWriter, values)
|
||||
}
|
||||
|
||||
if _, err = exec.ExecContext(ctx, updateQuery, values...); err != nil {
|
||||
return errors.Wrap(err, "failed to update local table")
|
||||
}
|
||||
|
||||
o.ScriptID = related.ID
|
||||
if o.R == nil {
|
||||
o.R = &scriptExecutionR{
|
||||
Script: related,
|
||||
}
|
||||
} else {
|
||||
o.R.Script = related
|
||||
}
|
||||
|
||||
if related.R == nil {
|
||||
related.R = &scriptR{
|
||||
ScriptExecutions: ScriptExecutionSlice{o},
|
||||
}
|
||||
} else {
|
||||
related.R.ScriptExecutions = append(related.R.ScriptExecutions, o)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ScriptExecutions retrieves all the records using an executor.
|
||||
func ScriptExecutions(mods ...qm.QueryMod) scriptExecutionQuery {
|
||||
mods = append(mods, qm.From("\"script_execution\""))
|
||||
return scriptExecutionQuery{NewQuery(mods...)}
|
||||
}
|
||||
|
||||
// FindScriptExecution retrieves a single record by ID with an executor.
|
||||
// If selectCols is empty Find will return all columns.
|
||||
func FindScriptExecution(ctx context.Context, exec boil.ContextExecutor, iD int64, selectCols ...string) (*ScriptExecution, error) {
|
||||
scriptExecutionObj := &ScriptExecution{}
|
||||
|
||||
sel := "*"
|
||||
if len(selectCols) > 0 {
|
||||
sel = strings.Join(strmangle.IdentQuoteSlice(dialect.LQ, dialect.RQ, selectCols), ",")
|
||||
}
|
||||
query := fmt.Sprintf(
|
||||
"select %s from \"script_execution\" where \"id\"=?", sel,
|
||||
)
|
||||
|
||||
q := queries.Raw(query, iD)
|
||||
|
||||
err := q.Bind(ctx, exec, scriptExecutionObj)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return nil, sql.ErrNoRows
|
||||
}
|
||||
return nil, errors.Wrap(err, "sqlite3: unable to select from script_execution")
|
||||
}
|
||||
|
||||
return scriptExecutionObj, nil
|
||||
}
|
||||
|
||||
// Insert a single record using an executor.
|
||||
// See boil.Columns.InsertColumnSet documentation to understand column list inference for inserts.
|
||||
func (o *ScriptExecution) Insert(ctx context.Context, exec boil.ContextExecutor, columns boil.Columns) error {
|
||||
if o == nil {
|
||||
return errors.New("sqlite3: no script_execution provided for insertion")
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
if err := o.doBeforeInsertHooks(ctx, exec); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nzDefaults := queries.NonZeroDefaultSet(scriptExecutionColumnsWithDefault, o)
|
||||
|
||||
key := makeCacheKey(columns, nzDefaults)
|
||||
scriptExecutionInsertCacheMut.RLock()
|
||||
cache, cached := scriptExecutionInsertCache[key]
|
||||
scriptExecutionInsertCacheMut.RUnlock()
|
||||
|
||||
if !cached {
|
||||
wl, returnColumns := columns.InsertColumnSet(
|
||||
scriptExecutionAllColumns,
|
||||
scriptExecutionColumnsWithDefault,
|
||||
scriptExecutionColumnsWithoutDefault,
|
||||
nzDefaults,
|
||||
)
|
||||
|
||||
cache.valueMapping, err = queries.BindMapping(scriptExecutionType, scriptExecutionMapping, wl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cache.retMapping, err = queries.BindMapping(scriptExecutionType, scriptExecutionMapping, returnColumns)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(wl) != 0 {
|
||||
cache.query = fmt.Sprintf("INSERT INTO \"script_execution\" (\"%s\") %%sVALUES (%s)%%s", strings.Join(wl, "\",\""), strmangle.Placeholders(dialect.UseIndexPlaceholders, len(wl), 1, 1))
|
||||
} else {
|
||||
cache.query = "INSERT INTO \"script_execution\" () VALUES ()%s%s"
|
||||
}
|
||||
|
||||
var queryOutput, queryReturning string
|
||||
|
||||
if len(cache.retMapping) != 0 {
|
||||
cache.retQuery = fmt.Sprintf("SELECT \"%s\" FROM \"script_execution\" WHERE %s", strings.Join(returnColumns, "\",\""), strmangle.WhereClause("\"", "\"", 0, scriptExecutionPrimaryKeyColumns))
|
||||
}
|
||||
|
||||
cache.query = fmt.Sprintf(cache.query, queryOutput, queryReturning)
|
||||
}
|
||||
|
||||
value := reflect.Indirect(reflect.ValueOf(o))
|
||||
vals := queries.ValuesFromMapping(value, cache.valueMapping)
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, cache.query)
|
||||
fmt.Fprintln(boil.DebugWriter, vals)
|
||||
}
|
||||
|
||||
result, err := exec.ExecContext(ctx, cache.query, vals...)
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "sqlite3: unable to insert into script_execution")
|
||||
}
|
||||
|
||||
var lastID int64
|
||||
var identifierCols []interface{}
|
||||
|
||||
if len(cache.retMapping) == 0 {
|
||||
goto CacheNoHooks
|
||||
}
|
||||
|
||||
lastID, err = result.LastInsertId()
|
||||
if err != nil {
|
||||
return ErrSyncFail
|
||||
}
|
||||
|
||||
o.ID = int64(lastID)
|
||||
if lastID != 0 && len(cache.retMapping) == 1 && cache.retMapping[0] == scriptExecutionMapping["ID"] {
|
||||
goto CacheNoHooks
|
||||
}
|
||||
|
||||
identifierCols = []interface{}{
|
||||
o.ID,
|
||||
}
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, cache.retQuery)
|
||||
fmt.Fprintln(boil.DebugWriter, identifierCols...)
|
||||
}
|
||||
|
||||
err = exec.QueryRowContext(ctx, cache.retQuery, identifierCols...).Scan(queries.PtrsFromMapping(value, cache.retMapping)...)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "sqlite3: unable to populate default values for script_execution")
|
||||
}
|
||||
|
||||
CacheNoHooks:
|
||||
if !cached {
|
||||
scriptExecutionInsertCacheMut.Lock()
|
||||
scriptExecutionInsertCache[key] = cache
|
||||
scriptExecutionInsertCacheMut.Unlock()
|
||||
}
|
||||
|
||||
return o.doAfterInsertHooks(ctx, exec)
|
||||
}
|
||||
|
||||
// Update uses an executor to update the ScriptExecution.
|
||||
// See boil.Columns.UpdateColumnSet documentation to understand column list inference for updates.
|
||||
// Update does not automatically update the record in case of default values. Use .Reload() to refresh the records.
|
||||
func (o *ScriptExecution) Update(ctx context.Context, exec boil.ContextExecutor, columns boil.Columns) (int64, error) {
|
||||
var err error
|
||||
if err = o.doBeforeUpdateHooks(ctx, exec); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
key := makeCacheKey(columns, nil)
|
||||
scriptExecutionUpdateCacheMut.RLock()
|
||||
cache, cached := scriptExecutionUpdateCache[key]
|
||||
scriptExecutionUpdateCacheMut.RUnlock()
|
||||
|
||||
if !cached {
|
||||
wl := columns.UpdateColumnSet(
|
||||
scriptExecutionAllColumns,
|
||||
scriptExecutionPrimaryKeyColumns,
|
||||
)
|
||||
|
||||
if len(wl) == 0 {
|
||||
return 0, errors.New("sqlite3: unable to update script_execution, could not build whitelist")
|
||||
}
|
||||
|
||||
cache.query = fmt.Sprintf("UPDATE \"script_execution\" SET %s WHERE %s",
|
||||
strmangle.SetParamNames("\"", "\"", 0, wl),
|
||||
strmangle.WhereClause("\"", "\"", 0, scriptExecutionPrimaryKeyColumns),
|
||||
)
|
||||
cache.valueMapping, err = queries.BindMapping(scriptExecutionType, scriptExecutionMapping, append(wl, scriptExecutionPrimaryKeyColumns...))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
values := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(o)), cache.valueMapping)
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, cache.query)
|
||||
fmt.Fprintln(boil.DebugWriter, values)
|
||||
}
|
||||
|
||||
var result sql.Result
|
||||
result, err = exec.ExecContext(ctx, cache.query, values...)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: unable to update script_execution row")
|
||||
}
|
||||
|
||||
rowsAff, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: failed to get rows affected by update for script_execution")
|
||||
}
|
||||
|
||||
if !cached {
|
||||
scriptExecutionUpdateCacheMut.Lock()
|
||||
scriptExecutionUpdateCache[key] = cache
|
||||
scriptExecutionUpdateCacheMut.Unlock()
|
||||
}
|
||||
|
||||
return rowsAff, o.doAfterUpdateHooks(ctx, exec)
|
||||
}
|
||||
|
||||
// UpdateAll updates all rows with the specified column values.
|
||||
func (q scriptExecutionQuery) UpdateAll(ctx context.Context, exec boil.ContextExecutor, cols M) (int64, error) {
|
||||
queries.SetUpdate(q.Query, cols)
|
||||
|
||||
result, err := q.Query.ExecContext(ctx, exec)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: unable to update all for script_execution")
|
||||
}
|
||||
|
||||
rowsAff, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: unable to retrieve rows affected for script_execution")
|
||||
}
|
||||
|
||||
return rowsAff, nil
|
||||
}
|
||||
|
||||
// UpdateAll updates all rows with the specified column values, using an executor.
|
||||
func (o ScriptExecutionSlice) UpdateAll(ctx context.Context, exec boil.ContextExecutor, cols M) (int64, error) {
|
||||
ln := int64(len(o))
|
||||
if ln == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
if len(cols) == 0 {
|
||||
return 0, errors.New("sqlite3: update all requires at least one column argument")
|
||||
}
|
||||
|
||||
colNames := make([]string, len(cols))
|
||||
args := make([]interface{}, len(cols))
|
||||
|
||||
i := 0
|
||||
for name, value := range cols {
|
||||
colNames[i] = name
|
||||
args[i] = value
|
||||
i++
|
||||
}
|
||||
|
||||
// Append all of the primary key values for each column
|
||||
for _, obj := range o {
|
||||
pkeyArgs := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(obj)), scriptExecutionPrimaryKeyMapping)
|
||||
args = append(args, pkeyArgs...)
|
||||
}
|
||||
|
||||
sql := fmt.Sprintf("UPDATE \"script_execution\" SET %s WHERE %s",
|
||||
strmangle.SetParamNames("\"", "\"", 0, colNames),
|
||||
strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), 0, scriptExecutionPrimaryKeyColumns, len(o)))
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, sql)
|
||||
fmt.Fprintln(boil.DebugWriter, args...)
|
||||
}
|
||||
|
||||
result, err := exec.ExecContext(ctx, sql, args...)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: unable to update all in scriptExecution slice")
|
||||
}
|
||||
|
||||
rowsAff, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: unable to retrieve rows affected all in update all scriptExecution")
|
||||
}
|
||||
return rowsAff, nil
|
||||
}
|
||||
|
||||
// Delete deletes a single ScriptExecution record with an executor.
|
||||
// Delete will match against the primary key column to find the record to delete.
|
||||
func (o *ScriptExecution) Delete(ctx context.Context, exec boil.ContextExecutor) (int64, error) {
|
||||
if o == nil {
|
||||
return 0, errors.New("sqlite3: no ScriptExecution provided for delete")
|
||||
}
|
||||
|
||||
if err := o.doBeforeDeleteHooks(ctx, exec); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
args := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(o)), scriptExecutionPrimaryKeyMapping)
|
||||
sql := "DELETE FROM \"script_execution\" WHERE \"id\"=?"
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, sql)
|
||||
fmt.Fprintln(boil.DebugWriter, args...)
|
||||
}
|
||||
|
||||
result, err := exec.ExecContext(ctx, sql, args...)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: unable to delete from script_execution")
|
||||
}
|
||||
|
||||
rowsAff, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: failed to get rows affected by delete for script_execution")
|
||||
}
|
||||
|
||||
if err := o.doAfterDeleteHooks(ctx, exec); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return rowsAff, nil
|
||||
}
|
||||
|
||||
// DeleteAll deletes all matching rows.
|
||||
func (q scriptExecutionQuery) DeleteAll(ctx context.Context, exec boil.ContextExecutor) (int64, error) {
|
||||
if q.Query == nil {
|
||||
return 0, errors.New("sqlite3: no scriptExecutionQuery provided for delete all")
|
||||
}
|
||||
|
||||
queries.SetDelete(q.Query)
|
||||
|
||||
result, err := q.Query.ExecContext(ctx, exec)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: unable to delete all from script_execution")
|
||||
}
|
||||
|
||||
rowsAff, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: failed to get rows affected by deleteall for script_execution")
|
||||
}
|
||||
|
||||
return rowsAff, nil
|
||||
}
|
||||
|
||||
// DeleteAll deletes all rows in the slice, using an executor.
|
||||
func (o ScriptExecutionSlice) DeleteAll(ctx context.Context, exec boil.ContextExecutor) (int64, error) {
|
||||
if len(o) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
if len(scriptExecutionBeforeDeleteHooks) != 0 {
|
||||
for _, obj := range o {
|
||||
if err := obj.doBeforeDeleteHooks(ctx, exec); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var args []interface{}
|
||||
for _, obj := range o {
|
||||
pkeyArgs := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(obj)), scriptExecutionPrimaryKeyMapping)
|
||||
args = append(args, pkeyArgs...)
|
||||
}
|
||||
|
||||
sql := "DELETE FROM \"script_execution\" WHERE " +
|
||||
strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), 0, scriptExecutionPrimaryKeyColumns, len(o))
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, sql)
|
||||
fmt.Fprintln(boil.DebugWriter, args)
|
||||
}
|
||||
|
||||
result, err := exec.ExecContext(ctx, sql, args...)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: unable to delete all from scriptExecution slice")
|
||||
}
|
||||
|
||||
rowsAff, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "sqlite3: failed to get rows affected by deleteall for script_execution")
|
||||
}
|
||||
|
||||
if len(scriptExecutionAfterDeleteHooks) != 0 {
|
||||
for _, obj := range o {
|
||||
if err := obj.doAfterDeleteHooks(ctx, exec); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rowsAff, nil
|
||||
}
|
||||
|
||||
// Reload refetches the object from the database
|
||||
// using the primary keys with an executor.
|
||||
func (o *ScriptExecution) Reload(ctx context.Context, exec boil.ContextExecutor) error {
|
||||
ret, err := FindScriptExecution(ctx, exec, o.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*o = *ret
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReloadAll refetches every row with matching primary key column values
|
||||
// and overwrites the original object slice with the newly updated slice.
|
||||
func (o *ScriptExecutionSlice) ReloadAll(ctx context.Context, exec boil.ContextExecutor) error {
|
||||
if o == nil || len(*o) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
slice := ScriptExecutionSlice{}
|
||||
var args []interface{}
|
||||
for _, obj := range *o {
|
||||
pkeyArgs := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(obj)), scriptExecutionPrimaryKeyMapping)
|
||||
args = append(args, pkeyArgs...)
|
||||
}
|
||||
|
||||
sql := "SELECT \"script_execution\".* FROM \"script_execution\" WHERE " +
|
||||
strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), 0, scriptExecutionPrimaryKeyColumns, len(*o))
|
||||
|
||||
q := queries.Raw(sql, args...)
|
||||
|
||||
err := q.Bind(ctx, exec, &slice)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "sqlite3: unable to reload all in ScriptExecutionSlice")
|
||||
}
|
||||
|
||||
*o = slice
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ScriptExecutionExists checks if the ScriptExecution row exists.
|
||||
func ScriptExecutionExists(ctx context.Context, exec boil.ContextExecutor, iD int64) (bool, error) {
|
||||
var exists bool
|
||||
sql := "select exists(select 1 from \"script_execution\" where \"id\"=? limit 1)"
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, sql)
|
||||
fmt.Fprintln(boil.DebugWriter, iD)
|
||||
}
|
||||
|
||||
row := exec.QueryRowContext(ctx, sql, iD)
|
||||
|
||||
err := row.Scan(&exists)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "sqlite3: unable to check if script_execution exists")
|
||||
}
|
||||
|
||||
return exists, nil
|
||||
}
|
||||
793
database/models/sqlite3/script_execution_test.go
Normal file
793
database/models/sqlite3/script_execution_test.go
Normal file
@@ -0,0 +1,793 @@
|
||||
// Code generated by SQLBoiler 3.5.0-gct (https://github.com/thrasher-corp/sqlboiler). DO NOT EDIT.
|
||||
// This file is meant to be re-generated in place and/or deleted at any time.
|
||||
|
||||
package sqlite3
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-corp/sqlboiler/boil"
|
||||
"github.com/thrasher-corp/sqlboiler/queries"
|
||||
"github.com/thrasher-corp/sqlboiler/randomize"
|
||||
"github.com/thrasher-corp/sqlboiler/strmangle"
|
||||
)
|
||||
|
||||
var (
|
||||
// Relationships sometimes use the reflection helper queries.Equal/queries.Assign
|
||||
// so force a package dependency in case they don't.
|
||||
_ = queries.Equal
|
||||
)
|
||||
|
||||
func testScriptExecutions(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
query := ScriptExecutions()
|
||||
|
||||
if query.Query == nil {
|
||||
t.Error("expected a query, got nothing")
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsDelete(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if rowsAff, err := o.Delete(ctx, tx); err != nil {
|
||||
t.Error(err)
|
||||
} else if rowsAff != 1 {
|
||||
t.Error("should only have deleted one row, but affected:", rowsAff)
|
||||
}
|
||||
|
||||
count, err := ScriptExecutions().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if count != 0 {
|
||||
t.Error("want zero records, got:", count)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsQueryDeleteAll(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if rowsAff, err := ScriptExecutions().DeleteAll(ctx, tx); err != nil {
|
||||
t.Error(err)
|
||||
} else if rowsAff != 1 {
|
||||
t.Error("should only have deleted one row, but affected:", rowsAff)
|
||||
}
|
||||
|
||||
count, err := ScriptExecutions().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if count != 0 {
|
||||
t.Error("want zero records, got:", count)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsSliceDeleteAll(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
slice := ScriptExecutionSlice{o}
|
||||
|
||||
if rowsAff, err := slice.DeleteAll(ctx, tx); err != nil {
|
||||
t.Error(err)
|
||||
} else if rowsAff != 1 {
|
||||
t.Error("should only have deleted one row, but affected:", rowsAff)
|
||||
}
|
||||
|
||||
count, err := ScriptExecutions().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if count != 0 {
|
||||
t.Error("want zero records, got:", count)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsExists(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
e, err := ScriptExecutionExists(ctx, tx, o.ID)
|
||||
if err != nil {
|
||||
t.Errorf("Unable to check if ScriptExecution exists: %s", err)
|
||||
}
|
||||
if !e {
|
||||
t.Errorf("Expected ScriptExecutionExists to return true, but got false.")
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsFind(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
scriptExecutionFound, err := FindScriptExecution(ctx, tx, o.ID)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if scriptExecutionFound == nil {
|
||||
t.Error("want a record, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsBind(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if err = ScriptExecutions().Bind(ctx, tx, o); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsOne(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if x, err := ScriptExecutions().One(ctx, tx); err != nil {
|
||||
t.Error(err)
|
||||
} else if x == nil {
|
||||
t.Error("expected to get a non nil record")
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsAll(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
scriptExecutionOne := &ScriptExecution{}
|
||||
scriptExecutionTwo := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, scriptExecutionOne, scriptExecutionDBTypes, false, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
if err = randomize.Struct(seed, scriptExecutionTwo, scriptExecutionDBTypes, false, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = scriptExecutionOne.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err = scriptExecutionTwo.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
slice, err := ScriptExecutions().All(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if len(slice) != 2 {
|
||||
t.Error("want 2 records, got:", len(slice))
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsCount(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var err error
|
||||
seed := randomize.NewSeed()
|
||||
scriptExecutionOne := &ScriptExecution{}
|
||||
scriptExecutionTwo := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, scriptExecutionOne, scriptExecutionDBTypes, false, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
if err = randomize.Struct(seed, scriptExecutionTwo, scriptExecutionDBTypes, false, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = scriptExecutionOne.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err = scriptExecutionTwo.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
count, err := ScriptExecutions().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if count != 2 {
|
||||
t.Error("want 2 records, got:", count)
|
||||
}
|
||||
}
|
||||
|
||||
func scriptExecutionBeforeInsertHook(ctx context.Context, e boil.ContextExecutor, o *ScriptExecution) error {
|
||||
*o = ScriptExecution{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scriptExecutionAfterInsertHook(ctx context.Context, e boil.ContextExecutor, o *ScriptExecution) error {
|
||||
*o = ScriptExecution{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scriptExecutionAfterSelectHook(ctx context.Context, e boil.ContextExecutor, o *ScriptExecution) error {
|
||||
*o = ScriptExecution{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scriptExecutionBeforeUpdateHook(ctx context.Context, e boil.ContextExecutor, o *ScriptExecution) error {
|
||||
*o = ScriptExecution{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scriptExecutionAfterUpdateHook(ctx context.Context, e boil.ContextExecutor, o *ScriptExecution) error {
|
||||
*o = ScriptExecution{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scriptExecutionBeforeDeleteHook(ctx context.Context, e boil.ContextExecutor, o *ScriptExecution) error {
|
||||
*o = ScriptExecution{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scriptExecutionAfterDeleteHook(ctx context.Context, e boil.ContextExecutor, o *ScriptExecution) error {
|
||||
*o = ScriptExecution{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scriptExecutionBeforeUpsertHook(ctx context.Context, e boil.ContextExecutor, o *ScriptExecution) error {
|
||||
*o = ScriptExecution{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scriptExecutionAfterUpsertHook(ctx context.Context, e boil.ContextExecutor, o *ScriptExecution) error {
|
||||
*o = ScriptExecution{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func testScriptExecutionsHooks(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var err error
|
||||
|
||||
ctx := context.Background()
|
||||
empty := &ScriptExecution{}
|
||||
o := &ScriptExecution{}
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, false); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution object: %s", err)
|
||||
}
|
||||
|
||||
AddScriptExecutionHook(boil.BeforeInsertHook, scriptExecutionBeforeInsertHook)
|
||||
if err = o.doBeforeInsertHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doBeforeInsertHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected BeforeInsertHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptExecutionBeforeInsertHooks = []ScriptExecutionHook{}
|
||||
|
||||
AddScriptExecutionHook(boil.AfterInsertHook, scriptExecutionAfterInsertHook)
|
||||
if err = o.doAfterInsertHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doAfterInsertHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected AfterInsertHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptExecutionAfterInsertHooks = []ScriptExecutionHook{}
|
||||
|
||||
AddScriptExecutionHook(boil.AfterSelectHook, scriptExecutionAfterSelectHook)
|
||||
if err = o.doAfterSelectHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doAfterSelectHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected AfterSelectHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptExecutionAfterSelectHooks = []ScriptExecutionHook{}
|
||||
|
||||
AddScriptExecutionHook(boil.BeforeUpdateHook, scriptExecutionBeforeUpdateHook)
|
||||
if err = o.doBeforeUpdateHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doBeforeUpdateHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected BeforeUpdateHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptExecutionBeforeUpdateHooks = []ScriptExecutionHook{}
|
||||
|
||||
AddScriptExecutionHook(boil.AfterUpdateHook, scriptExecutionAfterUpdateHook)
|
||||
if err = o.doAfterUpdateHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doAfterUpdateHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected AfterUpdateHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptExecutionAfterUpdateHooks = []ScriptExecutionHook{}
|
||||
|
||||
AddScriptExecutionHook(boil.BeforeDeleteHook, scriptExecutionBeforeDeleteHook)
|
||||
if err = o.doBeforeDeleteHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doBeforeDeleteHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected BeforeDeleteHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptExecutionBeforeDeleteHooks = []ScriptExecutionHook{}
|
||||
|
||||
AddScriptExecutionHook(boil.AfterDeleteHook, scriptExecutionAfterDeleteHook)
|
||||
if err = o.doAfterDeleteHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doAfterDeleteHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected AfterDeleteHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptExecutionAfterDeleteHooks = []ScriptExecutionHook{}
|
||||
|
||||
AddScriptExecutionHook(boil.BeforeUpsertHook, scriptExecutionBeforeUpsertHook)
|
||||
if err = o.doBeforeUpsertHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doBeforeUpsertHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected BeforeUpsertHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptExecutionBeforeUpsertHooks = []ScriptExecutionHook{}
|
||||
|
||||
AddScriptExecutionHook(boil.AfterUpsertHook, scriptExecutionAfterUpsertHook)
|
||||
if err = o.doAfterUpsertHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doAfterUpsertHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected AfterUpsertHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptExecutionAfterUpsertHooks = []ScriptExecutionHook{}
|
||||
}
|
||||
|
||||
func testScriptExecutionsInsert(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
count, err := ScriptExecutions().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if count != 1 {
|
||||
t.Error("want one record, got:", count)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsInsertWhitelist(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Whitelist(scriptExecutionColumnsWithoutDefault...)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
count, err := ScriptExecutions().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if count != 1 {
|
||||
t.Error("want one record, got:", count)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionToOneScriptUsingScript(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
|
||||
var local ScriptExecution
|
||||
var foreign Script
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
if err := randomize.Struct(seed, &local, scriptExecutionDBTypes, false, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
if err := randomize.Struct(seed, &foreign, scriptDBTypes, false, scriptColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize Script struct: %s", err)
|
||||
}
|
||||
|
||||
if err := foreign.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
local.ScriptID = foreign.ID
|
||||
if err := local.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
check, err := local.Script().One(ctx, tx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if check.ID != foreign.ID {
|
||||
t.Errorf("want: %v, got %v", foreign.ID, check.ID)
|
||||
}
|
||||
|
||||
slice := ScriptExecutionSlice{&local}
|
||||
if err = local.L.LoadScript(ctx, tx, false, (*[]*ScriptExecution)(&slice), nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if local.R.Script == nil {
|
||||
t.Error("struct should have been eager loaded")
|
||||
}
|
||||
|
||||
local.R.Script = nil
|
||||
if err = local.L.LoadScript(ctx, tx, true, &local, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if local.R.Script == nil {
|
||||
t.Error("struct should have been eager loaded")
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionToOneSetOpScriptUsingScript(t *testing.T) {
|
||||
var err error
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
|
||||
var a ScriptExecution
|
||||
var b, c Script
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
if err = randomize.Struct(seed, &a, scriptExecutionDBTypes, false, strmangle.SetComplement(scriptExecutionPrimaryKeyColumns, scriptExecutionColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = randomize.Struct(seed, &b, scriptDBTypes, false, strmangle.SetComplement(scriptPrimaryKeyColumns, scriptColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = randomize.Struct(seed, &c, scriptDBTypes, false, strmangle.SetComplement(scriptPrimaryKeyColumns, scriptColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := a.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = b.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for i, x := range []*Script{&b, &c} {
|
||||
err = a.SetScript(ctx, tx, i != 0, x)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if a.R.Script != x {
|
||||
t.Error("relationship struct not set to correct value")
|
||||
}
|
||||
|
||||
if x.R.ScriptExecutions[0] != &a {
|
||||
t.Error("failed to append to foreign relationship struct")
|
||||
}
|
||||
if a.ScriptID != x.ID {
|
||||
t.Error("foreign key was wrong value", a.ScriptID)
|
||||
}
|
||||
|
||||
zero := reflect.Zero(reflect.TypeOf(a.ScriptID))
|
||||
reflect.Indirect(reflect.ValueOf(&a.ScriptID)).Set(zero)
|
||||
|
||||
if err = a.Reload(ctx, tx); err != nil {
|
||||
t.Fatal("failed to reload", err)
|
||||
}
|
||||
|
||||
if a.ScriptID != x.ID {
|
||||
t.Error("foreign key was wrong value", a.ScriptID, x.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsReload(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if err = o.Reload(ctx, tx); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsReloadAll(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
slice := ScriptExecutionSlice{o}
|
||||
|
||||
if err = slice.ReloadAll(ctx, tx); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsSelect(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
slice, err := ScriptExecutions().All(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if len(slice) != 1 {
|
||||
t.Error("want one record, got:", len(slice))
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
scriptExecutionDBTypes = map[string]string{`ID`: `INTEGER`, `ScriptID`: `TEXT`, `ExecutionType`: `TEXT`, `ExecutionStatus`: `TEXT`, `ExecutionTime`: `TIMESTAMP`}
|
||||
_ = bytes.MinRead
|
||||
)
|
||||
|
||||
func testScriptExecutionsUpdate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if 0 == len(scriptExecutionPrimaryKeyColumns) {
|
||||
t.Skip("Skipping table with no primary key columns")
|
||||
}
|
||||
if len(scriptExecutionAllColumns) == len(scriptExecutionPrimaryKeyColumns) {
|
||||
t.Skip("Skipping table with only primary key columns")
|
||||
}
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
count, err := ScriptExecutions().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if count != 1 {
|
||||
t.Error("want one record, got:", count)
|
||||
}
|
||||
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionPrimaryKeyColumns...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
if rowsAff, err := o.Update(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
} else if rowsAff != 1 {
|
||||
t.Error("should only affect one row but affected", rowsAff)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptExecutionsSliceUpdateAll(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if len(scriptExecutionAllColumns) == len(scriptExecutionPrimaryKeyColumns) {
|
||||
t.Skip("Skipping table with only primary key columns")
|
||||
}
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &ScriptExecution{}
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
count, err := ScriptExecutions().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if count != 1 {
|
||||
t.Error("want one record, got:", count)
|
||||
}
|
||||
|
||||
if err = randomize.Struct(seed, o, scriptExecutionDBTypes, true, scriptExecutionPrimaryKeyColumns...); err != nil {
|
||||
t.Errorf("Unable to randomize ScriptExecution struct: %s", err)
|
||||
}
|
||||
|
||||
// Remove Primary keys and unique columns from what we plan to update
|
||||
var fields []string
|
||||
if strmangle.StringSliceMatch(scriptExecutionAllColumns, scriptExecutionPrimaryKeyColumns) {
|
||||
fields = scriptExecutionAllColumns
|
||||
} else {
|
||||
fields = strmangle.SetComplement(
|
||||
scriptExecutionAllColumns,
|
||||
scriptExecutionPrimaryKeyColumns,
|
||||
)
|
||||
}
|
||||
|
||||
value := reflect.Indirect(reflect.ValueOf(o))
|
||||
typ := reflect.TypeOf(o).Elem()
|
||||
n := typ.NumField()
|
||||
|
||||
updateMap := M{}
|
||||
for _, col := range fields {
|
||||
for i := 0; i < n; i++ {
|
||||
f := typ.Field(i)
|
||||
if f.Tag.Get("boil") == col {
|
||||
updateMap[col] = value.Field(i).Interface()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
slice := ScriptExecutionSlice{o}
|
||||
if rowsAff, err := slice.UpdateAll(ctx, tx, updateMap); err != nil {
|
||||
t.Error(err)
|
||||
} else if rowsAff != 1 {
|
||||
t.Error("wanted one record updated but got", rowsAff)
|
||||
}
|
||||
}
|
||||
838
database/models/sqlite3/script_test.go
Normal file
838
database/models/sqlite3/script_test.go
Normal file
@@ -0,0 +1,838 @@
|
||||
// Code generated by SQLBoiler 3.5.0-gct (https://github.com/thrasher-corp/sqlboiler). DO NOT EDIT.
|
||||
// This file is meant to be re-generated in place and/or deleted at any time.
|
||||
|
||||
package sqlite3
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-corp/sqlboiler/boil"
|
||||
"github.com/thrasher-corp/sqlboiler/queries"
|
||||
"github.com/thrasher-corp/sqlboiler/randomize"
|
||||
"github.com/thrasher-corp/sqlboiler/strmangle"
|
||||
)
|
||||
|
||||
var (
|
||||
// Relationships sometimes use the reflection helper queries.Equal/queries.Assign
|
||||
// so force a package dependency in case they don't.
|
||||
_ = queries.Equal
|
||||
)
|
||||
|
||||
func testScripts(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
query := Scripts()
|
||||
|
||||
if query.Query == nil {
|
||||
t.Error("expected a query, got nothing")
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptsDelete(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &Script{}
|
||||
if err = randomize.Struct(seed, o, scriptDBTypes, true, scriptColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize Script struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if rowsAff, err := o.Delete(ctx, tx); err != nil {
|
||||
t.Error(err)
|
||||
} else if rowsAff != 1 {
|
||||
t.Error("should only have deleted one row, but affected:", rowsAff)
|
||||
}
|
||||
|
||||
count, err := Scripts().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if count != 0 {
|
||||
t.Error("want zero records, got:", count)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptsQueryDeleteAll(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &Script{}
|
||||
if err = randomize.Struct(seed, o, scriptDBTypes, true, scriptColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize Script struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if rowsAff, err := Scripts().DeleteAll(ctx, tx); err != nil {
|
||||
t.Error(err)
|
||||
} else if rowsAff != 1 {
|
||||
t.Error("should only have deleted one row, but affected:", rowsAff)
|
||||
}
|
||||
|
||||
count, err := Scripts().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if count != 0 {
|
||||
t.Error("want zero records, got:", count)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptsSliceDeleteAll(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &Script{}
|
||||
if err = randomize.Struct(seed, o, scriptDBTypes, true, scriptColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize Script struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
slice := ScriptSlice{o}
|
||||
|
||||
if rowsAff, err := slice.DeleteAll(ctx, tx); err != nil {
|
||||
t.Error(err)
|
||||
} else if rowsAff != 1 {
|
||||
t.Error("should only have deleted one row, but affected:", rowsAff)
|
||||
}
|
||||
|
||||
count, err := Scripts().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if count != 0 {
|
||||
t.Error("want zero records, got:", count)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptsExists(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &Script{}
|
||||
if err = randomize.Struct(seed, o, scriptDBTypes, true, scriptColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize Script struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
e, err := ScriptExists(ctx, tx, o.ID)
|
||||
if err != nil {
|
||||
t.Errorf("Unable to check if Script exists: %s", err)
|
||||
}
|
||||
if !e {
|
||||
t.Errorf("Expected ScriptExists to return true, but got false.")
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptsFind(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &Script{}
|
||||
if err = randomize.Struct(seed, o, scriptDBTypes, true, scriptColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize Script struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
scriptFound, err := FindScript(ctx, tx, o.ID)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if scriptFound == nil {
|
||||
t.Error("want a record, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptsBind(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &Script{}
|
||||
if err = randomize.Struct(seed, o, scriptDBTypes, true, scriptColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize Script struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if err = Scripts().Bind(ctx, tx, o); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptsOne(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &Script{}
|
||||
if err = randomize.Struct(seed, o, scriptDBTypes, true, scriptColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize Script struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if x, err := Scripts().One(ctx, tx); err != nil {
|
||||
t.Error(err)
|
||||
} else if x == nil {
|
||||
t.Error("expected to get a non nil record")
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptsAll(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
scriptOne := &Script{}
|
||||
scriptTwo := &Script{}
|
||||
if err = randomize.Struct(seed, scriptOne, scriptDBTypes, false, scriptColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize Script struct: %s", err)
|
||||
}
|
||||
if err = randomize.Struct(seed, scriptTwo, scriptDBTypes, false, scriptColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize Script struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = scriptOne.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err = scriptTwo.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
slice, err := Scripts().All(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if len(slice) != 2 {
|
||||
t.Error("want 2 records, got:", len(slice))
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptsCount(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var err error
|
||||
seed := randomize.NewSeed()
|
||||
scriptOne := &Script{}
|
||||
scriptTwo := &Script{}
|
||||
if err = randomize.Struct(seed, scriptOne, scriptDBTypes, false, scriptColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize Script struct: %s", err)
|
||||
}
|
||||
if err = randomize.Struct(seed, scriptTwo, scriptDBTypes, false, scriptColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize Script struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = scriptOne.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err = scriptTwo.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
count, err := Scripts().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if count != 2 {
|
||||
t.Error("want 2 records, got:", count)
|
||||
}
|
||||
}
|
||||
|
||||
func scriptBeforeInsertHook(ctx context.Context, e boil.ContextExecutor, o *Script) error {
|
||||
*o = Script{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scriptAfterInsertHook(ctx context.Context, e boil.ContextExecutor, o *Script) error {
|
||||
*o = Script{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scriptAfterSelectHook(ctx context.Context, e boil.ContextExecutor, o *Script) error {
|
||||
*o = Script{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scriptBeforeUpdateHook(ctx context.Context, e boil.ContextExecutor, o *Script) error {
|
||||
*o = Script{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scriptAfterUpdateHook(ctx context.Context, e boil.ContextExecutor, o *Script) error {
|
||||
*o = Script{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scriptBeforeDeleteHook(ctx context.Context, e boil.ContextExecutor, o *Script) error {
|
||||
*o = Script{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scriptAfterDeleteHook(ctx context.Context, e boil.ContextExecutor, o *Script) error {
|
||||
*o = Script{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scriptBeforeUpsertHook(ctx context.Context, e boil.ContextExecutor, o *Script) error {
|
||||
*o = Script{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scriptAfterUpsertHook(ctx context.Context, e boil.ContextExecutor, o *Script) error {
|
||||
*o = Script{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func testScriptsHooks(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var err error
|
||||
|
||||
ctx := context.Background()
|
||||
empty := &Script{}
|
||||
o := &Script{}
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
if err = randomize.Struct(seed, o, scriptDBTypes, false); err != nil {
|
||||
t.Errorf("Unable to randomize Script object: %s", err)
|
||||
}
|
||||
|
||||
AddScriptHook(boil.BeforeInsertHook, scriptBeforeInsertHook)
|
||||
if err = o.doBeforeInsertHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doBeforeInsertHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected BeforeInsertHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptBeforeInsertHooks = []ScriptHook{}
|
||||
|
||||
AddScriptHook(boil.AfterInsertHook, scriptAfterInsertHook)
|
||||
if err = o.doAfterInsertHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doAfterInsertHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected AfterInsertHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptAfterInsertHooks = []ScriptHook{}
|
||||
|
||||
AddScriptHook(boil.AfterSelectHook, scriptAfterSelectHook)
|
||||
if err = o.doAfterSelectHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doAfterSelectHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected AfterSelectHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptAfterSelectHooks = []ScriptHook{}
|
||||
|
||||
AddScriptHook(boil.BeforeUpdateHook, scriptBeforeUpdateHook)
|
||||
if err = o.doBeforeUpdateHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doBeforeUpdateHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected BeforeUpdateHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptBeforeUpdateHooks = []ScriptHook{}
|
||||
|
||||
AddScriptHook(boil.AfterUpdateHook, scriptAfterUpdateHook)
|
||||
if err = o.doAfterUpdateHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doAfterUpdateHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected AfterUpdateHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptAfterUpdateHooks = []ScriptHook{}
|
||||
|
||||
AddScriptHook(boil.BeforeDeleteHook, scriptBeforeDeleteHook)
|
||||
if err = o.doBeforeDeleteHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doBeforeDeleteHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected BeforeDeleteHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptBeforeDeleteHooks = []ScriptHook{}
|
||||
|
||||
AddScriptHook(boil.AfterDeleteHook, scriptAfterDeleteHook)
|
||||
if err = o.doAfterDeleteHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doAfterDeleteHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected AfterDeleteHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptAfterDeleteHooks = []ScriptHook{}
|
||||
|
||||
AddScriptHook(boil.BeforeUpsertHook, scriptBeforeUpsertHook)
|
||||
if err = o.doBeforeUpsertHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doBeforeUpsertHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected BeforeUpsertHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptBeforeUpsertHooks = []ScriptHook{}
|
||||
|
||||
AddScriptHook(boil.AfterUpsertHook, scriptAfterUpsertHook)
|
||||
if err = o.doAfterUpsertHooks(ctx, nil); err != nil {
|
||||
t.Errorf("Unable to execute doAfterUpsertHooks: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(o, empty) {
|
||||
t.Errorf("Expected AfterUpsertHook function to empty object, but got: %#v", o)
|
||||
}
|
||||
scriptAfterUpsertHooks = []ScriptHook{}
|
||||
}
|
||||
|
||||
func testScriptsInsert(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &Script{}
|
||||
if err = randomize.Struct(seed, o, scriptDBTypes, true, scriptColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize Script struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
count, err := Scripts().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if count != 1 {
|
||||
t.Error("want one record, got:", count)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptsInsertWhitelist(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &Script{}
|
||||
if err = randomize.Struct(seed, o, scriptDBTypes, true); err != nil {
|
||||
t.Errorf("Unable to randomize Script struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Whitelist(scriptColumnsWithoutDefault...)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
count, err := Scripts().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if count != 1 {
|
||||
t.Error("want one record, got:", count)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptToManyScriptExecutions(t *testing.T) {
|
||||
var err error
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
|
||||
var a Script
|
||||
var b, c ScriptExecution
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
if err = randomize.Struct(seed, &a, scriptDBTypes, true, scriptColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize Script struct: %s", err)
|
||||
}
|
||||
|
||||
if err := a.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err = randomize.Struct(seed, &b, scriptExecutionDBTypes, false, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = randomize.Struct(seed, &c, scriptExecutionDBTypes, false, scriptExecutionColumnsWithDefault...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
b.ScriptID = a.ID
|
||||
c.ScriptID = a.ID
|
||||
|
||||
if err = b.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = c.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
check, err := a.ScriptExecutions().All(ctx, tx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
bFound, cFound := false, false
|
||||
for _, v := range check {
|
||||
if v.ScriptID == b.ScriptID {
|
||||
bFound = true
|
||||
}
|
||||
if v.ScriptID == c.ScriptID {
|
||||
cFound = true
|
||||
}
|
||||
}
|
||||
|
||||
if !bFound {
|
||||
t.Error("expected to find b")
|
||||
}
|
||||
if !cFound {
|
||||
t.Error("expected to find c")
|
||||
}
|
||||
|
||||
slice := ScriptSlice{&a}
|
||||
if err = a.L.LoadScriptExecutions(ctx, tx, false, (*[]*Script)(&slice), nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := len(a.R.ScriptExecutions); got != 2 {
|
||||
t.Error("number of eager loaded records wrong, got:", got)
|
||||
}
|
||||
|
||||
a.R.ScriptExecutions = nil
|
||||
if err = a.L.LoadScriptExecutions(ctx, tx, true, &a, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := len(a.R.ScriptExecutions); got != 2 {
|
||||
t.Error("number of eager loaded records wrong, got:", got)
|
||||
}
|
||||
|
||||
if t.Failed() {
|
||||
t.Logf("%#v", check)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptToManyAddOpScriptExecutions(t *testing.T) {
|
||||
var err error
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
|
||||
var a Script
|
||||
var b, c, d, e ScriptExecution
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
if err = randomize.Struct(seed, &a, scriptDBTypes, false, strmangle.SetComplement(scriptPrimaryKeyColumns, scriptColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
foreigners := []*ScriptExecution{&b, &c, &d, &e}
|
||||
for _, x := range foreigners {
|
||||
if err = randomize.Struct(seed, x, scriptExecutionDBTypes, false, strmangle.SetComplement(scriptExecutionPrimaryKeyColumns, scriptExecutionColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := a.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = b.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = c.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
foreignersSplitByInsertion := [][]*ScriptExecution{
|
||||
{&b, &c},
|
||||
{&d, &e},
|
||||
}
|
||||
|
||||
for i, x := range foreignersSplitByInsertion {
|
||||
err = a.AddScriptExecutions(ctx, tx, i != 0, x...)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
first := x[0]
|
||||
second := x[1]
|
||||
|
||||
if a.ID != first.ScriptID {
|
||||
t.Error("foreign key was wrong value", a.ID, first.ScriptID)
|
||||
}
|
||||
if a.ID != second.ScriptID {
|
||||
t.Error("foreign key was wrong value", a.ID, second.ScriptID)
|
||||
}
|
||||
|
||||
if first.R.Script != &a {
|
||||
t.Error("relationship was not added properly to the foreign slice")
|
||||
}
|
||||
if second.R.Script != &a {
|
||||
t.Error("relationship was not added properly to the foreign slice")
|
||||
}
|
||||
|
||||
if a.R.ScriptExecutions[i*2] != first {
|
||||
t.Error("relationship struct slice not set to correct value")
|
||||
}
|
||||
if a.R.ScriptExecutions[i*2+1] != second {
|
||||
t.Error("relationship struct slice not set to correct value")
|
||||
}
|
||||
|
||||
count, err := a.ScriptExecutions().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if want := int64((i + 1) * 2); count != want {
|
||||
t.Error("want", want, "got", count)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptsReload(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &Script{}
|
||||
if err = randomize.Struct(seed, o, scriptDBTypes, true, scriptColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize Script struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if err = o.Reload(ctx, tx); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptsReloadAll(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &Script{}
|
||||
if err = randomize.Struct(seed, o, scriptDBTypes, true, scriptColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize Script struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
slice := ScriptSlice{o}
|
||||
|
||||
if err = slice.ReloadAll(ctx, tx); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptsSelect(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &Script{}
|
||||
if err = randomize.Struct(seed, o, scriptDBTypes, true, scriptColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize Script struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
slice, err := Scripts().All(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if len(slice) != 1 {
|
||||
t.Error("want one record, got:", len(slice))
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
scriptDBTypes = map[string]string{`ID`: `TEXT`, `ScriptID`: `TEXT`, `ScriptName`: `TEXT`, `ScriptPath`: `TEXT`, `ScriptData`: `BLOB`, `LastExecutedAt`: `TIMESTAMP`, `CreatedAt`: `TIMESTAMP`}
|
||||
_ = bytes.MinRead
|
||||
)
|
||||
|
||||
func testScriptsUpdate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if 0 == len(scriptPrimaryKeyColumns) {
|
||||
t.Skip("Skipping table with no primary key columns")
|
||||
}
|
||||
if len(scriptAllColumns) == len(scriptPrimaryKeyColumns) {
|
||||
t.Skip("Skipping table with only primary key columns")
|
||||
}
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &Script{}
|
||||
if err = randomize.Struct(seed, o, scriptDBTypes, true, scriptColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize Script struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
count, err := Scripts().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if count != 1 {
|
||||
t.Error("want one record, got:", count)
|
||||
}
|
||||
|
||||
if err = randomize.Struct(seed, o, scriptDBTypes, true, scriptPrimaryKeyColumns...); err != nil {
|
||||
t.Errorf("Unable to randomize Script struct: %s", err)
|
||||
}
|
||||
|
||||
if rowsAff, err := o.Update(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
} else if rowsAff != 1 {
|
||||
t.Error("should only affect one row but affected", rowsAff)
|
||||
}
|
||||
}
|
||||
|
||||
func testScriptsSliceUpdateAll(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if len(scriptAllColumns) == len(scriptPrimaryKeyColumns) {
|
||||
t.Skip("Skipping table with only primary key columns")
|
||||
}
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
var err error
|
||||
o := &Script{}
|
||||
if err = randomize.Struct(seed, o, scriptDBTypes, true, scriptColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize Script struct: %s", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tx := MustTx(boil.BeginTx(ctx, nil))
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
if err = o.Insert(ctx, tx, boil.Infer()); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
count, err := Scripts().Count(ctx, tx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if count != 1 {
|
||||
t.Error("want one record, got:", count)
|
||||
}
|
||||
|
||||
if err = randomize.Struct(seed, o, scriptDBTypes, true, scriptPrimaryKeyColumns...); err != nil {
|
||||
t.Errorf("Unable to randomize Script struct: %s", err)
|
||||
}
|
||||
|
||||
// Remove Primary keys and unique columns from what we plan to update
|
||||
var fields []string
|
||||
if strmangle.StringSliceMatch(scriptAllColumns, scriptPrimaryKeyColumns) {
|
||||
fields = scriptAllColumns
|
||||
} else {
|
||||
fields = strmangle.SetComplement(
|
||||
scriptAllColumns,
|
||||
scriptPrimaryKeyColumns,
|
||||
)
|
||||
}
|
||||
|
||||
value := reflect.Indirect(reflect.ValueOf(o))
|
||||
typ := reflect.TypeOf(o).Elem()
|
||||
n := typ.NumField()
|
||||
|
||||
updateMap := M{}
|
||||
for _, col := range fields {
|
||||
for i := 0; i < n; i++ {
|
||||
f := typ.Field(i)
|
||||
if f.Tag.Get("boil") == col {
|
||||
updateMap[col] = value.Field(i).Interface()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
slice := ScriptSlice{o}
|
||||
if rowsAff, err := slice.UpdateAll(ctx, tx, updateMap); err != nil {
|
||||
t.Error(err)
|
||||
} else if rowsAff != 1 {
|
||||
t.Error("wanted one record updated but got", rowsAff)
|
||||
}
|
||||
}
|
||||
126
database/repository/script/script.go
Normal file
126
database/repository/script/script.go
Normal file
@@ -0,0 +1,126 @@
|
||||
package script
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/thrasher-corp/gocryptotrader/database"
|
||||
modelPSQL "github.com/thrasher-corp/gocryptotrader/database/models/postgres"
|
||||
modelSQLite "github.com/thrasher-corp/gocryptotrader/database/models/sqlite3"
|
||||
"github.com/thrasher-corp/gocryptotrader/database/repository"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/sqlboiler/boil"
|
||||
"github.com/volatiletech/null"
|
||||
)
|
||||
|
||||
// Event inserts a new script event into database with execution details (script name time status hash of script)
|
||||
func Event(id, name, path string, data null.Bytes, executionType, status string, time time.Time) {
|
||||
if database.DB.SQL == nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
ctx = boil.SkipTimestamps(ctx)
|
||||
tx, err := database.DB.SQL.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
log.Errorf(log.DatabaseMgr, "Event transaction begin failed: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if repository.GetSQLDialect() == database.DBSQLite3 {
|
||||
query := modelSQLite.ScriptWhere.ScriptID.EQ(id)
|
||||
f, errQry := modelSQLite.Scripts(query).Exists(ctx, tx)
|
||||
if errQry != nil {
|
||||
log.Errorf(log.DatabaseMgr, "Query failed: %v", errQry)
|
||||
err = tx.Rollback()
|
||||
if err != nil {
|
||||
log.Errorf(log.DatabaseMgr, "Event Transaction rollback failed: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
var tempEvent = modelSQLite.Script{}
|
||||
if !f {
|
||||
newUUID, errUUID := uuid.NewV4()
|
||||
if errUUID != nil {
|
||||
log.Errorf(log.DatabaseMgr, "Failed to generate UUID: %v", errUUID)
|
||||
_ = tx.Rollback()
|
||||
return
|
||||
}
|
||||
|
||||
tempEvent.ID = newUUID.String()
|
||||
tempEvent.ScriptID = id
|
||||
tempEvent.ScriptName = name
|
||||
tempEvent.ScriptPath = path
|
||||
tempEvent.ScriptData = data
|
||||
err = tempEvent.Insert(ctx, tx, boil.Infer())
|
||||
if err != nil {
|
||||
log.Errorf(log.DatabaseMgr, "Event insert failed: %v", err)
|
||||
err = tx.Rollback()
|
||||
if err != nil {
|
||||
log.Errorf(log.DatabaseMgr, "Event Transaction rollback failed: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
} else {
|
||||
tempEvent.ID = id
|
||||
}
|
||||
|
||||
tempScriptExecution := &modelSQLite.ScriptExecution{
|
||||
ScriptID: id,
|
||||
ExecutionTime: time.UTC().String(),
|
||||
ExecutionStatus: status,
|
||||
ExecutionType: executionType,
|
||||
}
|
||||
err = tempEvent.AddScriptExecutions(ctx, tx, true, tempScriptExecution)
|
||||
if err != nil {
|
||||
log.Errorf(log.DatabaseMgr, "Event insert failed: %v", err)
|
||||
err = tx.Rollback()
|
||||
if err != nil {
|
||||
log.Errorf(log.DatabaseMgr, "Event Transaction rollback failed: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
} else {
|
||||
var tempEvent = modelPSQL.Script{
|
||||
ScriptID: id,
|
||||
ScriptName: name,
|
||||
ScriptPath: path,
|
||||
ScriptData: data,
|
||||
}
|
||||
err = tempEvent.Upsert(ctx, tx, true, []string{"script_id"}, boil.Whitelist("last_executed_at"), boil.Infer())
|
||||
if err != nil {
|
||||
log.Errorf(log.DatabaseMgr, "Event insert failed: %v", err)
|
||||
err = tx.Rollback()
|
||||
if err != nil {
|
||||
log.Errorf(log.DatabaseMgr, "Event Transaction rollback failed: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
tempScriptExecution := &modelPSQL.ScriptExecution{
|
||||
ExecutionTime: time.UTC(),
|
||||
ExecutionStatus: status,
|
||||
ExecutionType: executionType,
|
||||
}
|
||||
|
||||
err = tempEvent.AddScriptExecutions(ctx, tx, true, tempScriptExecution)
|
||||
if err != nil {
|
||||
log.Errorf(log.DatabaseMgr, "Event insert failed: %v", err)
|
||||
err = tx.Rollback()
|
||||
if err != nil {
|
||||
log.Errorf(log.DatabaseMgr, "Event Transaction rollback failed: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
log.Errorf(log.DatabaseMgr, "Event Transaction commit failed: %v", err)
|
||||
err = tx.Rollback()
|
||||
if err != nil {
|
||||
log.Errorf(log.DatabaseMgr, "Event Transaction rollback failed: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
92
database/tests/script_test.go
Normal file
92
database/tests/script_test.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/database"
|
||||
"github.com/thrasher-corp/gocryptotrader/database/drivers"
|
||||
"github.com/thrasher-corp/gocryptotrader/database/repository"
|
||||
"github.com/thrasher-corp/gocryptotrader/database/repository/script"
|
||||
"github.com/thrasher-corp/goose"
|
||||
"github.com/volatiletech/null"
|
||||
)
|
||||
|
||||
func TestScript(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
config *database.Config
|
||||
runner func()
|
||||
closer func(t *testing.T, dbConn *database.Db) error
|
||||
output interface{}
|
||||
}{
|
||||
{
|
||||
"SQLite-Write",
|
||||
&database.Config{
|
||||
Driver: database.DBSQLite3,
|
||||
ConnectionDetails: drivers.ConnectionDetails{Database: "./testdb"},
|
||||
},
|
||||
|
||||
writeScript,
|
||||
closeDatabase,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"Postgres-Write",
|
||||
postgresTestDatabase,
|
||||
writeScript,
|
||||
nil,
|
||||
nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tests := range testCases {
|
||||
test := tests
|
||||
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
if !checkValidConfig(t, &test.config.ConnectionDetails) {
|
||||
t.Skip("database not configured skipping test")
|
||||
}
|
||||
|
||||
dbConn, err := connectToDatabase(t, test.config)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
path := filepath.Join("..", "migrations")
|
||||
err = goose.Run("up", dbConn.SQL, repository.GetSQLDialect(), path, "")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to run migrations %v", err)
|
||||
}
|
||||
|
||||
if test.runner != nil {
|
||||
test.runner()
|
||||
}
|
||||
|
||||
if test.closer != nil {
|
||||
err = test.closer(t, dbConn)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func writeScript() {
|
||||
var wg sync.WaitGroup
|
||||
for x := 0; x < 20; x++ {
|
||||
wg.Add(1)
|
||||
|
||||
go func(x int) {
|
||||
defer wg.Done()
|
||||
test := fmt.Sprintf("test-%v", x)
|
||||
var data null.Bytes
|
||||
script.Event(test, test, test, data, test, test, time.Now())
|
||||
}(x)
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/dispatch"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
gctscript "github.com/thrasher-corp/gocryptotrader/gctscript/vm"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/portfolio"
|
||||
"github.com/thrasher-corp/gocryptotrader/utils"
|
||||
@@ -32,6 +33,7 @@ type Engine struct {
|
||||
NTPManager ntpManager
|
||||
ConnectionManager connectionManager
|
||||
DatabaseManager databaseManager
|
||||
GctScriptManager gctScriptManager
|
||||
OrderManager orderManager
|
||||
PortfolioManager portfolioManager
|
||||
CommsManager commsManager
|
||||
@@ -115,6 +117,8 @@ func ValidateSettings(b *Engine, s *Settings) {
|
||||
b.Settings.EnablePortfolioManager = s.EnablePortfolioManager
|
||||
b.Settings.EnableCoinmarketcapAnalysis = s.EnableCoinmarketcapAnalysis
|
||||
b.Settings.EnableDatabaseManager = s.EnableDatabaseManager
|
||||
b.Settings.EnableGCTScriptManager = s.EnableGCTScriptManager
|
||||
b.Settings.MaxVirtualMachines = s.MaxVirtualMachines
|
||||
b.Settings.EnableDispatcher = s.EnableDispatcher
|
||||
|
||||
if flagSet["grpc"] {
|
||||
@@ -141,6 +145,14 @@ func ValidateSettings(b *Engine, s *Settings) {
|
||||
b.Settings.EnableDeprecatedRPC = b.Config.RemoteControl.DeprecatedRPC.Enabled
|
||||
}
|
||||
|
||||
if flagSet["gctscriptmanager"] {
|
||||
gctscript.GCTScriptConfig.Enabled = s.EnableGCTScriptManager
|
||||
}
|
||||
|
||||
if flagSet["maxvirtualmachines"] {
|
||||
gctscript.GCTScriptConfig.MaxVirtualMachines = uint8(s.MaxVirtualMachines)
|
||||
}
|
||||
|
||||
b.Settings.EnableCommsRelayer = s.EnableCommsRelayer
|
||||
b.Settings.EnableEventManager = s.EnableEventManager
|
||||
|
||||
@@ -266,10 +278,14 @@ func PrintSettings(s *Settings) {
|
||||
log.Debugf(log.Global, "\t Exchange HTTP timeout: %v", s.ExchangeHTTPTimeout)
|
||||
log.Debugf(log.Global, "\t Exchange HTTP user agent: %v", s.ExchangeHTTPUserAgent)
|
||||
log.Debugf(log.Global, "\t Exchange HTTP proxy: %v\n", s.ExchangeHTTPProxy)
|
||||
log.Debugf(log.Global, "- GCTSCRIPT SETTINGS: ")
|
||||
log.Debugf(log.Global, "\t Enable GCTScript manager: %v", s.EnableGCTScriptManager)
|
||||
log.Debugf(log.Global, "\t GCTScript max virtual machines: %v", s.MaxVirtualMachines)
|
||||
log.Debugf(log.Global, "- COMMON SETTINGS:")
|
||||
log.Debugf(log.Global, "\t Global HTTP timeout: %v", s.GlobalHTTPTimeout)
|
||||
log.Debugf(log.Global, "\t Global HTTP user agent: %v", s.GlobalHTTPUserAgent)
|
||||
log.Debugf(log.Global, "\t Global HTTP proxy: %v", s.ExchangeHTTPProxy)
|
||||
|
||||
log.Debugln(log.Global)
|
||||
}
|
||||
|
||||
@@ -423,6 +439,14 @@ func (e *Engine) Start() error {
|
||||
go WebsocketRoutine()
|
||||
}
|
||||
|
||||
if e.Settings.EnableGCTScriptManager {
|
||||
if e.Config.GCTScript.Enabled {
|
||||
if err := e.GctScriptManager.Start(); err != nil {
|
||||
log.Errorf(log.Global, "GCTScript manager unable to start: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -434,6 +458,11 @@ func (e *Engine) Stop() {
|
||||
e.Config.Portfolio = portfolio.Portfolio
|
||||
}
|
||||
|
||||
if e.GctScriptManager.Started() {
|
||||
if err := e.GctScriptManager.Stop(); err != nil {
|
||||
log.Errorf(log.Global, "GCTScript manager unable to stop. Error: %v", err)
|
||||
}
|
||||
}
|
||||
if e.OrderManager.Started() {
|
||||
if err := e.OrderManager.Stop(); err != nil {
|
||||
log.Errorf(log.Global, "Order manager unable to stop. Error: %v", err)
|
||||
|
||||
@@ -28,6 +28,7 @@ type Settings struct {
|
||||
EnableOrderManager bool
|
||||
EnableConnectivityMonitor bool
|
||||
EnableDatabaseManager bool
|
||||
EnableGCTScriptManager bool
|
||||
EnableNTPClient bool
|
||||
EnableWebsocketRoutine bool
|
||||
EventManagerDelay time.Duration
|
||||
@@ -73,4 +74,35 @@ type Settings struct {
|
||||
EnableDispatcher bool
|
||||
DispatchMaxWorkerAmount int
|
||||
DispatchJobsLimit int
|
||||
|
||||
// GCTscript settings
|
||||
MaxVirtualMachines uint
|
||||
}
|
||||
|
||||
const (
|
||||
// ErrSubSystemAlreadyStarted message to return when a subsystem is already started
|
||||
ErrSubSystemAlreadyStarted = "manager already started"
|
||||
// ErrSubSystemAlreadyStopped message to return when a subsystem is already stopped
|
||||
ErrSubSystemAlreadyStopped = "already stopped"
|
||||
// ErrSubSystemNotStarted message to return when subsystem not started
|
||||
ErrSubSystemNotStarted = "not started"
|
||||
|
||||
// ErrScriptFailedValidation message to display when a script fails its validation
|
||||
ErrScriptFailedValidation string = "validation failed"
|
||||
// MsgSubSystemStarting message to return when subsystem is starting up
|
||||
MsgSubSystemStarting = "manager starting..."
|
||||
// MsgSubSystemStarted message to return when subsystem has started
|
||||
MsgSubSystemStarted = "started."
|
||||
|
||||
// MsgSubSystemShuttingDown message to return when a subsystem is shutting down
|
||||
MsgSubSystemShuttingDown = "shutting down..."
|
||||
// MsgSubSystemShutdown message to return when a subsystem has shutdown
|
||||
MsgSubSystemShutdown = "manager shutdown."
|
||||
|
||||
// MsgStatusOK message to display when status is "OK"
|
||||
MsgStatusOK string = "ok"
|
||||
// MsgStatusSuccess message to display when status is successful
|
||||
MsgStatusSuccess string = "success"
|
||||
// MsgStatusError message to display when failure occurs
|
||||
MsgStatusError string = "error"
|
||||
)
|
||||
|
||||
@@ -308,8 +308,9 @@ func TestIsValidExchange(t *testing.T) {
|
||||
if s := IsValidExchange("invalidexchangerino"); s {
|
||||
t.Error("unexpected result")
|
||||
}
|
||||
|
||||
loadConfig(t)
|
||||
if !configLoaded {
|
||||
loadConfig(t)
|
||||
}
|
||||
if s := IsValidExchange(testExchange); !s {
|
||||
t.Error("unexpected result")
|
||||
}
|
||||
|
||||
98
engine/gctscript.go
Normal file
98
engine/gctscript.go
Normal file
@@ -0,0 +1,98 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/gctscript/vm"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const gctscriptManagerName = "GCTScript"
|
||||
|
||||
type gctScriptManager struct {
|
||||
started int32
|
||||
stopped int32
|
||||
shutdown chan struct{}
|
||||
}
|
||||
|
||||
// Started returns if gctscript manager subsystem is started
|
||||
func (g *gctScriptManager) Started() bool {
|
||||
return atomic.LoadInt32(&g.started) == 1
|
||||
}
|
||||
|
||||
// Start starts gctscript subsystem and creates shutdown channel
|
||||
func (g *gctScriptManager) Start() (err error) {
|
||||
if atomic.AddInt32(&g.started, 1) != 1 {
|
||||
return fmt.Errorf("%s %s", gctscriptManagerName, ErrSubSystemAlreadyStarted)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
atomic.CompareAndSwapInt32(&g.started, 1, 0)
|
||||
}
|
||||
}()
|
||||
|
||||
log.Debugln(log.Global, gctscriptManagerName, MsgSubSystemStarting)
|
||||
|
||||
g.shutdown = make(chan struct{})
|
||||
go g.run()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop stops gctscript subsystem along with all running Virtual Machines
|
||||
func (g *gctScriptManager) Stop() error {
|
||||
if atomic.LoadInt32(&g.started) == 0 {
|
||||
return fmt.Errorf("%s %s", gctscriptManagerName, ErrSubSystemNotStarted)
|
||||
}
|
||||
|
||||
if atomic.AddInt32(&g.stopped, 1) != 1 {
|
||||
return fmt.Errorf("%s %s", gctscriptManagerName, ErrSubSystemAlreadyStopped)
|
||||
}
|
||||
|
||||
log.Debugln(log.GCTScriptMgr, gctscriptManagerName, MsgSubSystemShuttingDown)
|
||||
close(g.shutdown)
|
||||
err := vm.ShutdownAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *gctScriptManager) run() {
|
||||
log.Debugln(log.Global, gctscriptManagerName, MsgSubSystemStarted)
|
||||
|
||||
Bot.ServicesWG.Add(1)
|
||||
g.autoLoad()
|
||||
defer func() {
|
||||
atomic.CompareAndSwapInt32(&g.stopped, 1, 0)
|
||||
atomic.CompareAndSwapInt32(&g.started, 1, 0)
|
||||
Bot.ServicesWG.Done()
|
||||
log.Debugln(log.GCTScriptMgr, gctscriptManagerName, MsgSubSystemShutdown)
|
||||
}()
|
||||
|
||||
<-g.shutdown
|
||||
}
|
||||
|
||||
func (g *gctScriptManager) autoLoad() {
|
||||
for x := range Bot.Config.GCTScript.AutoLoad {
|
||||
temp := vm.New()
|
||||
if temp == nil {
|
||||
log.Errorf(log.GCTScriptMgr, "Unable to create Virtual Machine, autoload failed for: %v",
|
||||
Bot.Config.GCTScript.AutoLoad[x])
|
||||
continue
|
||||
}
|
||||
var name = Bot.Config.GCTScript.AutoLoad[x]
|
||||
if filepath.Ext(name) != ".gct" {
|
||||
name += ".gct"
|
||||
}
|
||||
scriptPath := filepath.Join(vm.ScriptPath, name)
|
||||
err := temp.Load(scriptPath)
|
||||
if err != nil {
|
||||
log.Errorf(log.GCTScriptMgr, "%v failed to load: %v", filepath.Base(scriptPath), err)
|
||||
continue
|
||||
}
|
||||
go temp.CompileAndRun()
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/stats"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/withdraw"
|
||||
"github.com/thrasher-corp/gocryptotrader/gctscript/vm"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/portfolio"
|
||||
"github.com/thrasher-corp/gocryptotrader/utils"
|
||||
@@ -44,6 +45,7 @@ func GetSubsystemsStatus() map[string]bool {
|
||||
systems["exchange_syncer"] = Bot.Settings.EnableExchangeSyncManager
|
||||
systems["grpc"] = Bot.Settings.EnableGRPC
|
||||
systems["grpc_proxy"] = Bot.Settings.EnableGRPCProxy
|
||||
systems["gctscript"] = Bot.GctScriptManager.Started()
|
||||
systems["deprecated_rpc"] = Bot.Settings.EnableDeprecatedRPC
|
||||
systems["websocket_rpc"] = Bot.Settings.EnableWebsocketRPC
|
||||
systems["dispatch"] = dispatch.IsRunning()
|
||||
@@ -121,7 +123,15 @@ func SetSubsystem(subsys string, enable bool) error {
|
||||
return dispatch.Start(Bot.Settings.DispatchMaxWorkerAmount, Bot.Settings.DispatchJobsLimit)
|
||||
}
|
||||
return dispatch.Stop()
|
||||
case "gctscript":
|
||||
if enable {
|
||||
vm.GCTScriptConfig.Enabled = true
|
||||
return Bot.GctScriptManager.Start()
|
||||
}
|
||||
vm.GCTScriptConfig.Enabled = false
|
||||
return Bot.GctScriptManager.Stop()
|
||||
}
|
||||
|
||||
return errors.New("subsystem not found")
|
||||
}
|
||||
|
||||
@@ -417,19 +427,21 @@ func GetRelatableCurrencies(p currency.Pair, incOrig, incUSDT bool) currency.Pai
|
||||
// GetSpecificOrderbook returns a specific orderbook given the currency,
|
||||
// exchangeName and assetType
|
||||
func GetSpecificOrderbook(p currency.Pair, exchangeName string, assetType asset.Item) (*orderbook.Base, error) {
|
||||
if CheckExchangeExists(exchangeName) {
|
||||
return GetExchangeByName(exchangeName).FetchOrderbook(p, assetType)
|
||||
exch := GetExchangeByName(exchangeName)
|
||||
if exch == nil {
|
||||
return nil, ErrExchangeNotFound
|
||||
}
|
||||
return &orderbook.Base{}, errors.New("exchange is not loaded/doesn't exist")
|
||||
return exch.FetchOrderbook(p, assetType)
|
||||
}
|
||||
|
||||
// GetSpecificTicker returns a specific ticker given the currency,
|
||||
// exchangeName and assetType
|
||||
func GetSpecificTicker(p currency.Pair, exchangeName string, assetType asset.Item) (*ticker.Price, error) {
|
||||
if CheckExchangeExists(exchangeName) {
|
||||
return GetExchangeByName(exchangeName).FetchTicker(p, assetType)
|
||||
exch := GetExchangeByName(exchangeName)
|
||||
if exch == nil {
|
||||
return nil, ErrExchangeNotFound
|
||||
}
|
||||
return &ticker.Price{}, errors.New("exchange is not loaded/doesn't exist")
|
||||
return exch.FetchTicker(p, assetType)
|
||||
}
|
||||
|
||||
// GetCollatedExchangeAccountInfoByCoin collates individual exchange account
|
||||
|
||||
@@ -70,6 +70,7 @@ func (o *orderManager) Start() error {
|
||||
go o.run()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *orderManager) Stop() error {
|
||||
if atomic.LoadInt32(&o.started) == 0 {
|
||||
return errors.New("order manager not started")
|
||||
|
||||
@@ -17,6 +17,7 @@ func loadConfig(t *testing.T) *config.Config {
|
||||
if err != nil {
|
||||
t.Error("GetCurrencyConfig LoadConfig error", err)
|
||||
}
|
||||
configLoaded = true
|
||||
return cfg
|
||||
}
|
||||
|
||||
|
||||
@@ -4,16 +4,22 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
grpcauth "github.com/grpc-ecosystem/go-grpc-middleware/auth"
|
||||
grpcruntime "github.com/grpc-ecosystem/grpc-gateway/runtime"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/file"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/file/archive"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/database/models/postgres"
|
||||
"github.com/thrasher-corp/gocryptotrader/database/models/sqlite3"
|
||||
@@ -24,6 +30,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/gctrpc"
|
||||
"github.com/thrasher-corp/gocryptotrader/gctrpc/auth"
|
||||
gctscript "github.com/thrasher-corp/gocryptotrader/gctscript/vm"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/portfolio"
|
||||
"github.com/thrasher-corp/gocryptotrader/utils"
|
||||
@@ -1213,3 +1220,296 @@ func (s *RPCServer) GetAuditEvent(ctx context.Context, r *gctrpc.GetAuditEventRe
|
||||
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
// GCTScriptStatus returns a slice of current running scripts that includes next run time and uuid
|
||||
func (s *RPCServer) GCTScriptStatus(ctx context.Context, r *gctrpc.GCTScriptStatusRequest) (*gctrpc.GCTScriptStatusResponse, error) {
|
||||
if !gctscript.GCTScriptConfig.Enabled {
|
||||
return &gctrpc.GCTScriptStatusResponse{Status: gctscript.ErrScriptingDisabled.Error()}, nil
|
||||
}
|
||||
|
||||
if gctscript.VMSCount.Len() < 1 {
|
||||
return &gctrpc.GCTScriptStatusResponse{Status: "no scripts running"}, nil
|
||||
}
|
||||
|
||||
resp := &gctrpc.GCTScriptStatusResponse{
|
||||
Status: fmt.Sprintf("%v of %v virtual machines running", gctscript.VMSCount.Len(), gctscript.GCTScriptConfig.MaxVirtualMachines),
|
||||
}
|
||||
|
||||
gctscript.AllVMSync.Range(func(k, v interface{}) bool {
|
||||
vm := v.(*gctscript.VM)
|
||||
resp.Scripts = append(resp.Scripts, &gctrpc.GCTScript{
|
||||
UUID: vm.ID.String(),
|
||||
Name: vm.ShortName(),
|
||||
NextRun: vm.NextRun.String(),
|
||||
})
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GCTScriptQuery queries a running script and returns script running information
|
||||
func (s *RPCServer) GCTScriptQuery(ctx context.Context, r *gctrpc.GCTScriptQueryRequest) (*gctrpc.GCTScriptQueryResponse, error) {
|
||||
if !gctscript.GCTScriptConfig.Enabled {
|
||||
return &gctrpc.GCTScriptQueryResponse{Status: gctscript.ErrScriptingDisabled.Error()}, nil
|
||||
}
|
||||
|
||||
UUID, err := uuid.FromString(r.Script.UUID)
|
||||
if err != nil {
|
||||
return &gctrpc.GCTScriptQueryResponse{Status: MsgStatusError, Data: err.Error()}, nil
|
||||
}
|
||||
|
||||
if v, f := gctscript.AllVMSync.Load(UUID); f {
|
||||
resp := &gctrpc.GCTScriptQueryResponse{
|
||||
Status: MsgStatusOK,
|
||||
Script: &gctrpc.GCTScript{
|
||||
Name: v.(*gctscript.VM).ShortName(),
|
||||
UUID: v.(*gctscript.VM).ID.String(),
|
||||
Path: v.(*gctscript.VM).Path,
|
||||
NextRun: v.(*gctscript.VM).NextRun.String(),
|
||||
},
|
||||
}
|
||||
data, err := v.(*gctscript.VM).Read()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp.Data = string(data)
|
||||
return resp, nil
|
||||
}
|
||||
return &gctrpc.GCTScriptQueryResponse{Status: MsgStatusError, Data: "UUID not found"}, nil
|
||||
}
|
||||
|
||||
// GCTScriptExecute execute a script
|
||||
func (s *RPCServer) GCTScriptExecute(ctx context.Context, r *gctrpc.GCTScriptExecuteRequest) (*gctrpc.GCTScriptGenericResponse, error) {
|
||||
if !gctscript.GCTScriptConfig.Enabled {
|
||||
return &gctrpc.GCTScriptGenericResponse{Status: gctscript.ErrScriptingDisabled.Error()}, nil
|
||||
}
|
||||
|
||||
if r.Script.Path == "" {
|
||||
r.Script.Path = gctscript.ScriptPath
|
||||
}
|
||||
|
||||
gctVM := gctscript.New()
|
||||
if gctVM == nil {
|
||||
return &gctrpc.GCTScriptGenericResponse{Status: MsgStatusError, Data: "unable to create VM instance"}, nil
|
||||
}
|
||||
|
||||
script := filepath.Join(r.Script.Path, r.Script.Name)
|
||||
err := gctVM.Load(script)
|
||||
if err != nil {
|
||||
return &gctrpc.GCTScriptGenericResponse{
|
||||
Status: MsgStatusError,
|
||||
Data: err.Error(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
go gctVM.CompileAndRun()
|
||||
|
||||
return &gctrpc.GCTScriptGenericResponse{
|
||||
Status: MsgStatusOK,
|
||||
Data: gctVM.ShortName() + " (" + gctVM.ID.String() + ") executed",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GCTScriptStop terminate a running script
|
||||
func (s *RPCServer) GCTScriptStop(ctx context.Context, r *gctrpc.GCTScriptStopRequest) (*gctrpc.GCTScriptGenericResponse, error) {
|
||||
if !gctscript.GCTScriptConfig.Enabled {
|
||||
return &gctrpc.GCTScriptGenericResponse{Status: gctscript.ErrScriptingDisabled.Error()}, nil
|
||||
}
|
||||
|
||||
UUID, err := uuid.FromString(r.Script.UUID)
|
||||
if err != nil {
|
||||
return &gctrpc.GCTScriptGenericResponse{Status: MsgStatusError, Data: err.Error()}, nil
|
||||
}
|
||||
|
||||
if v, f := gctscript.AllVMSync.Load(UUID); f {
|
||||
err = v.(*gctscript.VM).Shutdown()
|
||||
status := " terminated"
|
||||
if err != nil {
|
||||
status = " " + err.Error()
|
||||
}
|
||||
return &gctrpc.GCTScriptGenericResponse{Status: MsgStatusOK, Data: v.(*gctscript.VM).ID.String() + status}, nil
|
||||
}
|
||||
return &gctrpc.GCTScriptGenericResponse{Status: MsgStatusError, Data: "no running script found"}, nil
|
||||
}
|
||||
|
||||
// GCTScriptUpload upload a new script to ScriptPath
|
||||
func (s *RPCServer) GCTScriptUpload(ctx context.Context, r *gctrpc.GCTScriptUploadRequest) (*gctrpc.GCTScriptGenericResponse, error) {
|
||||
if !gctscript.GCTScriptConfig.Enabled {
|
||||
return &gctrpc.GCTScriptGenericResponse{Status: gctscript.ErrScriptingDisabled.Error()}, nil
|
||||
}
|
||||
|
||||
fPath := filepath.Join(gctscript.ScriptPath, r.ScriptName)
|
||||
var fPathExits = fPath
|
||||
if filepath.Ext(fPath) == ".zip" {
|
||||
fPathExits = fPathExits[0 : len(fPathExits)-4]
|
||||
}
|
||||
|
||||
if s, err := os.Stat(fPathExits); !os.IsNotExist(err) {
|
||||
if !r.Overwrite {
|
||||
return nil, fmt.Errorf("%s script found and overwrite set to false", r.ScriptName)
|
||||
}
|
||||
f := filepath.Join(gctscript.ScriptPath, "version_history")
|
||||
err = os.MkdirAll(f, 0770)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
timeString := strconv.FormatInt(time.Now().UnixNano(), 10)
|
||||
renamedFile := filepath.Join(f, timeString+"-"+filepath.Base(fPathExits))
|
||||
if s.IsDir() {
|
||||
err = archive.Zip(fPathExits, renamedFile+".zip")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
err = file.Move(fPathExits, renamedFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newFile, err := os.Create(fPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = newFile.Write(r.Data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = newFile.Close()
|
||||
if err != nil {
|
||||
log.Errorln(log.Global, "Failed to close file handle, archive removal may fail")
|
||||
}
|
||||
|
||||
if r.Archived {
|
||||
files, errExtract := archive.UnZip(fPath, filepath.Join(gctscript.ScriptPath, r.ScriptName[:len(r.ScriptName)-4]))
|
||||
if errExtract != nil {
|
||||
log.Errorf(log.Global, "Failed to archive zip file %v", errExtract)
|
||||
return &gctrpc.GCTScriptGenericResponse{Status: MsgStatusError, Data: errExtract.Error()}, nil
|
||||
}
|
||||
var failedFiles []string
|
||||
for x := range files {
|
||||
err = gctscript.Validate(files[x])
|
||||
if err != nil {
|
||||
failedFiles = append(failedFiles, files[x])
|
||||
}
|
||||
}
|
||||
err = os.Remove(fPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(failedFiles) > 0 {
|
||||
err = os.RemoveAll(filepath.Join(gctscript.ScriptPath, r.ScriptName[:len(r.ScriptName)-4]))
|
||||
if err != nil {
|
||||
log.Errorf(log.GCTScriptMgr, "Failed to remove file %v (%v), manual deletion required", filepath.Base(fPath), err)
|
||||
}
|
||||
return &gctrpc.GCTScriptGenericResponse{Status: ErrScriptFailedValidation, Data: strings.Join(failedFiles, ", ")}, nil
|
||||
}
|
||||
} else {
|
||||
err = gctscript.Validate(fPath)
|
||||
if err != nil {
|
||||
errRemove := os.Remove(fPath)
|
||||
if errRemove != nil {
|
||||
log.Errorf(log.GCTScriptMgr, "Failed to remove file %v, manual deletion required: %v", filepath.Base(fPath), errRemove)
|
||||
}
|
||||
return &gctrpc.GCTScriptGenericResponse{Status: ErrScriptFailedValidation, Data: err.Error()}, nil
|
||||
}
|
||||
}
|
||||
|
||||
return &gctrpc.GCTScriptGenericResponse{
|
||||
Status: MsgStatusOK,
|
||||
Data: fmt.Sprintf("script %s written", newFile.Name()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GCTScriptReadScript read a script and return contents
|
||||
func (s *RPCServer) GCTScriptReadScript(ctx context.Context, r *gctrpc.GCTScriptReadScriptRequest) (*gctrpc.GCTScriptQueryResponse, error) {
|
||||
if !gctscript.GCTScriptConfig.Enabled {
|
||||
return &gctrpc.GCTScriptQueryResponse{Status: gctscript.ErrScriptingDisabled.Error()}, nil
|
||||
}
|
||||
|
||||
filename := filepath.Join(gctscript.ScriptPath, r.Script.Name)
|
||||
if !strings.HasPrefix(filename, filepath.Clean(gctscript.ScriptPath)+string(os.PathSeparator)) {
|
||||
return nil, fmt.Errorf("%s: invalid file path", filename)
|
||||
}
|
||||
data, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &gctrpc.GCTScriptQueryResponse{
|
||||
Status: MsgStatusOK,
|
||||
Script: &gctrpc.GCTScript{
|
||||
Name: filepath.Base(filename),
|
||||
Path: filepath.Dir(filename),
|
||||
},
|
||||
Data: string(data),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GCTScriptListAll lists all scripts inside the default script path
|
||||
func (s *RPCServer) GCTScriptListAll(context.Context, *gctrpc.GCTScriptListAllRequest) (*gctrpc.GCTScriptStatusResponse, error) {
|
||||
if !gctscript.GCTScriptConfig.Enabled {
|
||||
return &gctrpc.GCTScriptStatusResponse{Status: gctscript.ErrScriptingDisabled.Error()}, nil
|
||||
}
|
||||
|
||||
resp := &gctrpc.GCTScriptStatusResponse{}
|
||||
err := filepath.Walk(gctscript.ScriptPath,
|
||||
func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if filepath.Ext(path) == ".gct" {
|
||||
resp.Scripts = append(resp.Scripts, &gctrpc.GCTScript{
|
||||
Name: path,
|
||||
})
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GCTScriptStopAll stops all running scripts
|
||||
func (s *RPCServer) GCTScriptStopAll(context.Context, *gctrpc.GCTScriptStopAllRequest) (*gctrpc.GCTScriptGenericResponse, error) {
|
||||
if !gctscript.GCTScriptConfig.Enabled {
|
||||
return &gctrpc.GCTScriptGenericResponse{Status: gctscript.ErrScriptingDisabled.Error()}, nil
|
||||
}
|
||||
|
||||
err := gctscript.ShutdownAll()
|
||||
if err != nil {
|
||||
return &gctrpc.GCTScriptGenericResponse{Status: "error", Data: err.Error()}, nil
|
||||
}
|
||||
|
||||
return &gctrpc.GCTScriptGenericResponse{
|
||||
Status: MsgStatusOK,
|
||||
Data: "all running scripts have been stopped",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GCTScriptAutoLoadToggle adds or removes an entry to the autoload list
|
||||
func (s *RPCServer) GCTScriptAutoLoadToggle(ctx context.Context, r *gctrpc.GCTScriptAutoLoadRequest) (*gctrpc.GCTScriptGenericResponse, error) {
|
||||
if !gctscript.GCTScriptConfig.Enabled {
|
||||
return &gctrpc.GCTScriptGenericResponse{Status: gctscript.ErrScriptingDisabled.Error()}, nil
|
||||
}
|
||||
|
||||
if r.Status {
|
||||
err := gctscript.Autoload(r.Script, true)
|
||||
if err != nil {
|
||||
return &gctrpc.GCTScriptGenericResponse{Status: "error", Data: err.Error()}, nil
|
||||
}
|
||||
return &gctrpc.GCTScriptGenericResponse{Status: "success", Data: "script " + r.Script + " removed from autoload list"}, nil
|
||||
}
|
||||
|
||||
err := gctscript.Autoload(r.Script, false)
|
||||
if err != nil {
|
||||
return &gctrpc.GCTScriptGenericResponse{Status: "error", Data: err.Error()}, nil
|
||||
}
|
||||
return &gctrpc.GCTScriptGenericResponse{Status: "success", Data: "script " + r.Script + " added to autoload list"}, nil
|
||||
}
|
||||
|
||||
74
exchanges/withdraw/withdraw.go
Normal file
74
exchanges/withdraw/withdraw.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package withdraw
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
)
|
||||
|
||||
// Valid takes interface and passes to asset type to check the request meets requirements to submit
|
||||
func Valid(request interface{}) error {
|
||||
switch request := request.(type) {
|
||||
case *FiatRequest:
|
||||
return ValidateFiat(request)
|
||||
case *CryptoRequest:
|
||||
return ValidateCrypto(request)
|
||||
default:
|
||||
return ErrInvalidRequest
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateFiat checks if Fiat request is valid
|
||||
func ValidateFiat(request *FiatRequest) (err error) {
|
||||
if request == nil {
|
||||
return ErrRequestCannotBeNil
|
||||
}
|
||||
|
||||
var allErrors []string
|
||||
if (request.Currency != currency.Code{}) {
|
||||
if !request.Currency.IsFiatCurrency() {
|
||||
allErrors = append(allErrors, "currency is not a fiat currency")
|
||||
}
|
||||
} else {
|
||||
allErrors = append(allErrors, ErrStrNoCurrencySet)
|
||||
}
|
||||
|
||||
if request.Amount <= 0 {
|
||||
allErrors = append(allErrors, ErrStrAmountMustBeGreaterThanZero)
|
||||
}
|
||||
|
||||
if len(allErrors) > 0 {
|
||||
err = errors.New(strings.Join(allErrors, ", "))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// ValidateCrypto checks if Crypto request is valid
|
||||
func ValidateCrypto(request *CryptoRequest) (err error) {
|
||||
if request == nil {
|
||||
return ErrRequestCannotBeNil
|
||||
}
|
||||
|
||||
var allErrors []string
|
||||
if (request.Currency != currency.Code{}) {
|
||||
if !request.Currency.IsCryptocurrency() {
|
||||
allErrors = append(allErrors, "currency is not a crypto currency")
|
||||
}
|
||||
} else {
|
||||
allErrors = append(allErrors, ErrStrNoCurrencySet)
|
||||
}
|
||||
|
||||
if request.Amount <= 0 {
|
||||
allErrors = append(allErrors, ErrStrAmountMustBeGreaterThanZero)
|
||||
}
|
||||
|
||||
if request.Address == "" {
|
||||
allErrors = append(allErrors, ErrStrAddressNotSet)
|
||||
}
|
||||
|
||||
if len(allErrors) > 0 {
|
||||
err = errors.New(strings.Join(allErrors, ", "))
|
||||
}
|
||||
return err
|
||||
}
|
||||
178
exchanges/withdraw/withdraw_test.go
Normal file
178
exchanges/withdraw/withdraw_test.go
Normal file
@@ -0,0 +1,178 @@
|
||||
package withdraw
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
)
|
||||
|
||||
var (
|
||||
validFiatRequest = &FiatRequest{
|
||||
GenericInfo: GenericInfo{
|
||||
Currency: currency.AUD,
|
||||
Description: "Test Withdrawal",
|
||||
Amount: 0.1,
|
||||
},
|
||||
BankAccountName: "test-bank-account",
|
||||
BankAccountNumber: "test-bank-number",
|
||||
BankName: "test-bank-name",
|
||||
BSB: "",
|
||||
SwiftCode: "",
|
||||
IBAN: "",
|
||||
}
|
||||
|
||||
invalidFiatRequest = &FiatRequest{}
|
||||
invalidCurrencyFiatRequest = &FiatRequest{
|
||||
GenericInfo: GenericInfo{
|
||||
Currency: currency.BTC,
|
||||
Amount: 1,
|
||||
},
|
||||
}
|
||||
|
||||
validCryptoRequest = &CryptoRequest{
|
||||
GenericInfo: GenericInfo{
|
||||
Currency: currency.BTC,
|
||||
Description: "Test Withdrawal",
|
||||
Amount: 0.1,
|
||||
},
|
||||
Address: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
}
|
||||
invalidCryptoRequest = &CryptoRequest{}
|
||||
invalidCurrencyCryptoRequest = &CryptoRequest{
|
||||
GenericInfo: GenericInfo{
|
||||
Currency: currency.AUD,
|
||||
Amount: 0,
|
||||
},
|
||||
}
|
||||
invalidCryptoAddressRequest = &CryptoRequest{
|
||||
GenericInfo: GenericInfo{
|
||||
Currency: currency.BTC,
|
||||
Description: "Test Withdrawal",
|
||||
Amount: 0.1,
|
||||
},
|
||||
Address: "1D10TH0RS3",
|
||||
}
|
||||
)
|
||||
|
||||
func TestValid(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
request interface{}
|
||||
output interface{}
|
||||
}{
|
||||
{
|
||||
"Fiat",
|
||||
validFiatRequest,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"Crypto",
|
||||
validCryptoRequest,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"Invalid",
|
||||
nil,
|
||||
ErrInvalidRequest,
|
||||
},
|
||||
}
|
||||
for _, tests := range testCases {
|
||||
test := tests
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
err := Valid(test.request)
|
||||
if err != nil {
|
||||
if test.output.(error).Error() != err.Error() {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateFiat(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
request *FiatRequest
|
||||
output interface{}
|
||||
}{
|
||||
{
|
||||
"Valid",
|
||||
validFiatRequest,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"Invalid",
|
||||
invalidFiatRequest,
|
||||
errors.New("currency not set, amount must be greater than 0"),
|
||||
},
|
||||
{
|
||||
"NoRequest",
|
||||
nil,
|
||||
ErrRequestCannotBeNil,
|
||||
},
|
||||
{
|
||||
"CryptoCurrency",
|
||||
invalidCurrencyFiatRequest,
|
||||
errors.New("currency is not a fiat currency"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tests := range testCases {
|
||||
test := tests
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
err := ValidateFiat(test.request)
|
||||
if err != nil {
|
||||
if test.output.(error).Error() != err.Error() {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateCrypto(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
request *CryptoRequest
|
||||
output interface{}
|
||||
}{
|
||||
{
|
||||
"Valid",
|
||||
validCryptoRequest,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"Invalid",
|
||||
invalidCryptoRequest,
|
||||
errors.New("currency not set, amount must be greater than 0, address cannot be empty"),
|
||||
},
|
||||
{
|
||||
"NoRequest",
|
||||
nil,
|
||||
ErrRequestCannotBeNil,
|
||||
},
|
||||
{
|
||||
"FiatCurrency",
|
||||
invalidCurrencyCryptoRequest,
|
||||
errors.New("currency is not a crypto currency, amount must be greater than 0, address cannot be empty"),
|
||||
},
|
||||
{
|
||||
"InvalidAddress",
|
||||
invalidCryptoAddressRequest,
|
||||
errors.New(ErrStrAddressisInvalid),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tests := range testCases {
|
||||
test := tests
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
err := ValidateCrypto(test.request)
|
||||
if err != nil {
|
||||
if test.output.(error).Error() != err.Error() {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,26 @@
|
||||
package withdraw
|
||||
|
||||
import "github.com/thrasher-corp/gocryptotrader/currency"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
)
|
||||
|
||||
const (
|
||||
// ErrStrAmountMustBeGreaterThanZero message to return when withdraw amount is less than 0
|
||||
ErrStrAmountMustBeGreaterThanZero = "amount must be greater than 0"
|
||||
// ErrStrAddressisInvalid message to return when address is invalid for crypto request
|
||||
ErrStrAddressisInvalid = "address is not valid"
|
||||
// ErrStrAddressNotSet message to returh when address is empty
|
||||
ErrStrAddressNotSet = "address cannot be empty"
|
||||
// ErrStrNoCurrencySet message to return when no currency is set
|
||||
ErrStrNoCurrencySet = "currency not set"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrRequestCannotBeNil = errors.New("request cannot be nil")
|
||||
ErrInvalidRequest = errors.New("invalid request type")
|
||||
)
|
||||
|
||||
// GenericInfo stores genric withdraw request info
|
||||
type GenericInfo struct {
|
||||
|
||||
1554
gctrpc/rpc.pb.go
1554
gctrpc/rpc.pb.go
File diff suppressed because it is too large
Load Diff
@@ -1423,6 +1423,294 @@ func local_request_GoCryptoTrader_GetAuditEvent_0(ctx context.Context, marshaler
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
filter_GoCryptoTrader_GCTScriptExecute_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
|
||||
)
|
||||
|
||||
func request_GoCryptoTrader_GCTScriptExecute_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GCTScriptExecuteRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GCTScriptExecute_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.GCTScriptExecute(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_GoCryptoTrader_GCTScriptExecute_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GCTScriptExecuteRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GCTScriptExecute_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.GCTScriptExecute(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_GoCryptoTrader_GCTScriptUpload_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GCTScriptUploadRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.GCTScriptUpload(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_GoCryptoTrader_GCTScriptUpload_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GCTScriptUploadRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.GCTScriptUpload(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_GoCryptoTrader_GCTScriptReadScript_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GCTScriptReadScriptRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.GCTScriptReadScript(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_GoCryptoTrader_GCTScriptReadScript_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GCTScriptReadScriptRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.GCTScriptReadScript(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_GoCryptoTrader_GCTScriptStatus_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GCTScriptStatusRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := client.GCTScriptStatus(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_GoCryptoTrader_GCTScriptStatus_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GCTScriptStatusRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := server.GCTScriptStatus(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
filter_GoCryptoTrader_GCTScriptQuery_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
|
||||
)
|
||||
|
||||
func request_GoCryptoTrader_GCTScriptQuery_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GCTScriptQueryRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GCTScriptQuery_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.GCTScriptQuery(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_GoCryptoTrader_GCTScriptQuery_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GCTScriptQueryRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GCTScriptQuery_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.GCTScriptQuery(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_GoCryptoTrader_GCTScriptStop_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GCTScriptStopRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.GCTScriptStop(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_GoCryptoTrader_GCTScriptStop_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GCTScriptStopRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.GCTScriptStop(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_GoCryptoTrader_GCTScriptStopAll_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GCTScriptStopAllRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.GCTScriptStopAll(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_GoCryptoTrader_GCTScriptStopAll_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GCTScriptStopAllRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.GCTScriptStopAll(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_GoCryptoTrader_GCTScriptListAll_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GCTScriptListAllRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.GCTScriptListAll(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_GoCryptoTrader_GCTScriptListAll_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GCTScriptListAllRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.GCTScriptListAll(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_GoCryptoTrader_GCTScriptAutoLoadToggle_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GCTScriptAutoLoadRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.GCTScriptAutoLoadToggle(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_GoCryptoTrader_GCTScriptAutoLoadToggle_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GCTScriptAutoLoadRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.GCTScriptAutoLoadToggle(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
// RegisterGoCryptoTraderHandlerServer registers the http handlers for service GoCryptoTrader to "mux".
|
||||
// UnaryRPC :call GoCryptoTraderServer directly.
|
||||
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
|
||||
@@ -2336,6 +2624,186 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_GoCryptoTrader_GCTScriptExecute_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_GoCryptoTrader_GCTScriptExecute_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptExecute_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_GoCryptoTrader_GCTScriptUpload_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_GoCryptoTrader_GCTScriptUpload_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptUpload_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_GoCryptoTrader_GCTScriptReadScript_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_GoCryptoTrader_GCTScriptReadScript_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptReadScript_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_GoCryptoTrader_GCTScriptStatus_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_GoCryptoTrader_GCTScriptStatus_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptStatus_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_GoCryptoTrader_GCTScriptQuery_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_GoCryptoTrader_GCTScriptQuery_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptQuery_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_GoCryptoTrader_GCTScriptStop_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_GoCryptoTrader_GCTScriptStop_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptStop_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_GoCryptoTrader_GCTScriptStopAll_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_GoCryptoTrader_GCTScriptStopAll_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptStopAll_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_GoCryptoTrader_GCTScriptListAll_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_GoCryptoTrader_GCTScriptListAll_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptListAll_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_GoCryptoTrader_GCTScriptAutoLoadToggle_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_GoCryptoTrader_GCTScriptAutoLoadToggle_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptAutoLoadToggle_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3337,6 +3805,186 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_GoCryptoTrader_GCTScriptExecute_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_GoCryptoTrader_GCTScriptExecute_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptExecute_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_GoCryptoTrader_GCTScriptUpload_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_GoCryptoTrader_GCTScriptUpload_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptUpload_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_GoCryptoTrader_GCTScriptReadScript_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_GoCryptoTrader_GCTScriptReadScript_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptReadScript_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_GoCryptoTrader_GCTScriptStatus_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_GoCryptoTrader_GCTScriptStatus_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptStatus_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_GoCryptoTrader_GCTScriptQuery_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_GoCryptoTrader_GCTScriptQuery_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptQuery_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_GoCryptoTrader_GCTScriptStop_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_GoCryptoTrader_GCTScriptStop_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptStop_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_GoCryptoTrader_GCTScriptStopAll_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_GoCryptoTrader_GCTScriptStopAll_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptStopAll_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_GoCryptoTrader_GCTScriptListAll_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_GoCryptoTrader_GCTScriptListAll_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptListAll_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_GoCryptoTrader_GCTScriptAutoLoadToggle_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_GoCryptoTrader_GCTScriptAutoLoadToggle_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptAutoLoadToggle_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3436,6 +4084,24 @@ var (
|
||||
pattern_GoCryptoTrader_GetExchangeTickerStream_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "getexchangetickerstream"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_GoCryptoTrader_GetAuditEvent_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "getauditevent"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_GoCryptoTrader_GCTScriptExecute_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "gctscript", "execute"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_GoCryptoTrader_GCTScriptUpload_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "gctscript", "upload"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_GoCryptoTrader_GCTScriptReadScript_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "gctscript", "read"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_GoCryptoTrader_GCTScriptStatus_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "gctscript", "status"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_GoCryptoTrader_GCTScriptQuery_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "gctscript", "query"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_GoCryptoTrader_GCTScriptStop_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "gctscript", "stop"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_GoCryptoTrader_GCTScriptStopAll_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "gctscript", "stop"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_GoCryptoTrader_GCTScriptListAll_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "gctscript", "stop"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_GoCryptoTrader_GCTScriptAutoLoadToggle_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "gctscript", "autoload"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -3534,4 +4200,22 @@ var (
|
||||
forward_GoCryptoTrader_GetExchangeTickerStream_0 = runtime.ForwardResponseStream
|
||||
|
||||
forward_GoCryptoTrader_GetAuditEvent_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptExecute_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptUpload_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptReadScript_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptStatus_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptQuery_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptStop_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptStopAll_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptListAll_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_GoCryptoTrader_GCTScriptAutoLoadToggle_0 = runtime.ForwardResponseMessage
|
||||
)
|
||||
|
||||
121
gctrpc/rpc.proto
121
gctrpc/rpc.proto
@@ -528,6 +528,62 @@ message AuditEvent {
|
||||
string timestamp = 4;
|
||||
}
|
||||
|
||||
message GCTScript {
|
||||
string UUID = 1;
|
||||
string name = 2;
|
||||
string path = 3;
|
||||
string next_run = 4;
|
||||
}
|
||||
|
||||
message GCTScriptExecuteRequest {
|
||||
GCTScript script = 1;
|
||||
}
|
||||
|
||||
message GCTScriptStopRequest {
|
||||
GCTScript script = 1;
|
||||
}
|
||||
|
||||
message GCTScriptStopAllRequest{}
|
||||
message GCTScriptStatusRequest {}
|
||||
message GCTScriptListAllRequest{}
|
||||
|
||||
message GCTScriptUploadRequest {
|
||||
string script_name = 1;
|
||||
string script_data = 2;
|
||||
bytes data = 3;
|
||||
bool archived = 4;
|
||||
bool overwrite = 5;
|
||||
}
|
||||
|
||||
message GCTScriptReadScriptRequest{
|
||||
GCTScript script = 1;
|
||||
}
|
||||
|
||||
message GCTScriptQueryRequest{
|
||||
GCTScript script = 1;
|
||||
}
|
||||
|
||||
message GCTScriptAutoLoadRequest{
|
||||
string script = 1;
|
||||
bool status = 2;
|
||||
}
|
||||
|
||||
message GCTScriptStatusResponse{
|
||||
string status = 1;
|
||||
repeated GCTScript scripts = 2;
|
||||
}
|
||||
|
||||
message GCTScriptQueryResponse{
|
||||
string status = 1;
|
||||
GCTScript script = 2;
|
||||
string data = 3;
|
||||
}
|
||||
|
||||
message GCTScriptGenericResponse {
|
||||
string status = 1;
|
||||
string data = 2;
|
||||
}
|
||||
|
||||
service GoCryptoTrader {
|
||||
rpc GetInfo (GetInfoRequest) returns (GetInfoResponse) {
|
||||
option (google.api.http) = {
|
||||
@@ -831,13 +887,74 @@ service GoCryptoTrader {
|
||||
|
||||
rpc GetExchangeTickerStream(GetExchangeTickerStreamRequest) returns (stream TickerResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/v1/getexchangetickerstream"
|
||||
get: "/v1/getexchangetickerstream",
|
||||
};
|
||||
}
|
||||
|
||||
rpc GetAuditEvent(GetAuditEventRequest) returns (GetAuditEventResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/v1/getauditevent"
|
||||
get: "/v1/getauditevent",
|
||||
};
|
||||
}
|
||||
|
||||
rpc GCTScriptExecute(GCTScriptExecuteRequest) returns (GCTScriptGenericResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/v1/gctscript/execute",
|
||||
};
|
||||
}
|
||||
|
||||
rpc GCTScriptUpload(GCTScriptUploadRequest) returns (GCTScriptGenericResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/v1/gctscript/upload",
|
||||
body: "*"
|
||||
};
|
||||
}
|
||||
|
||||
rpc GCTScriptReadScript(GCTScriptReadScriptRequest) returns (GCTScriptQueryResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/v1/gctscript/read",
|
||||
body: "*"
|
||||
};
|
||||
}
|
||||
|
||||
rpc GCTScriptStatus(GCTScriptStatusRequest) returns (GCTScriptStatusResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/v1/gctscript/status",
|
||||
};
|
||||
}
|
||||
|
||||
rpc GCTScriptQuery(GCTScriptQueryRequest) returns (GCTScriptQueryResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/v1/gctscript/query",
|
||||
};
|
||||
}
|
||||
|
||||
rpc GCTScriptStop(GCTScriptStopRequest) returns (GCTScriptGenericResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/v1/gctscript/stop",
|
||||
body: "*"
|
||||
};
|
||||
}
|
||||
|
||||
rpc GCTScriptStopAll(GCTScriptStopAllRequest) returns (GCTScriptGenericResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/v1/gctscript/stop",
|
||||
body: "*"
|
||||
};
|
||||
}
|
||||
|
||||
rpc GCTScriptListAll(GCTScriptListAllRequest) returns (GCTScriptStatusResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/v1/gctscript/stop",
|
||||
body: "*"
|
||||
};
|
||||
}
|
||||
rpc GCTScriptAutoLoadToggle(GCTScriptAutoLoadRequest) returns (GCTScriptGenericResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/v1/gctscript/autoload",
|
||||
body: "*"
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -4,10 +4,6 @@
|
||||
"title": "rpc.proto",
|
||||
"version": "version not set"
|
||||
},
|
||||
"schemes": [
|
||||
"http",
|
||||
"https"
|
||||
],
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
@@ -271,6 +267,210 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/gctscript/autoload": {
|
||||
"post": {
|
||||
"operationId": "GCTScriptAutoLoadToggle",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/gctrpcGCTScriptGenericResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/gctrpcGCTScriptAutoLoadRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"GoCryptoTrader"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/gctscript/execute": {
|
||||
"get": {
|
||||
"operationId": "GCTScriptExecute",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/gctrpcGCTScriptGenericResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "script.UUID",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "script.name",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "script.path",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "script.next_run",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"GoCryptoTrader"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/gctscript/query": {
|
||||
"get": {
|
||||
"operationId": "GCTScriptQuery",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/gctrpcGCTScriptQueryResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "script.UUID",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "script.name",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "script.path",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "script.next_run",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"GoCryptoTrader"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/gctscript/read": {
|
||||
"post": {
|
||||
"operationId": "GCTScriptReadScript",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/gctrpcGCTScriptQueryResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/gctrpcGCTScriptReadScriptRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"GoCryptoTrader"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/gctscript/status": {
|
||||
"get": {
|
||||
"operationId": "GCTScriptStatus",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/gctrpcGCTScriptStatusResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"GoCryptoTrader"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/gctscript/stop": {
|
||||
"post": {
|
||||
"operationId": "GCTScriptListAll",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/gctrpcGCTScriptStatusResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/gctrpcGCTScriptListAllRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"GoCryptoTrader"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/gctscript/upload": {
|
||||
"post": {
|
||||
"operationId": "GCTScriptUpload",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/gctrpcGCTScriptGenericResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/gctrpcGCTScriptUploadRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"GoCryptoTrader"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/getaccountinfo": {
|
||||
"get": {
|
||||
"operationId": "GetAccountInfo",
|
||||
@@ -1481,6 +1681,119 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"gctrpcGCTScript": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"UUID": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"next_run": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"gctrpcGCTScriptAutoLoadRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"script": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "boolean",
|
||||
"format": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"gctrpcGCTScriptGenericResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"status": {
|
||||
"type": "string"
|
||||
},
|
||||
"data": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"gctrpcGCTScriptListAllRequest": {
|
||||
"type": "object"
|
||||
},
|
||||
"gctrpcGCTScriptQueryResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"status": {
|
||||
"type": "string"
|
||||
},
|
||||
"script": {
|
||||
"$ref": "#/definitions/gctrpcGCTScript"
|
||||
},
|
||||
"data": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"gctrpcGCTScriptReadScriptRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"script": {
|
||||
"$ref": "#/definitions/gctrpcGCTScript"
|
||||
}
|
||||
}
|
||||
},
|
||||
"gctrpcGCTScriptStatusResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"status": {
|
||||
"type": "string"
|
||||
},
|
||||
"scripts": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/gctrpcGCTScript"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"gctrpcGCTScriptStopAllRequest": {
|
||||
"type": "object"
|
||||
},
|
||||
"gctrpcGCTScriptStopRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"script": {
|
||||
"$ref": "#/definitions/gctrpcGCTScript"
|
||||
}
|
||||
}
|
||||
},
|
||||
"gctrpcGCTScriptUploadRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"script_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"script_data": {
|
||||
"type": "string"
|
||||
},
|
||||
"data": {
|
||||
"type": "string",
|
||||
"format": "byte"
|
||||
},
|
||||
"archived": {
|
||||
"type": "boolean",
|
||||
"format": "boolean"
|
||||
},
|
||||
"overwrite": {
|
||||
"type": "boolean",
|
||||
"format": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"gctrpcGenericExchangeNameRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
262
gctscript/README.md
Normal file
262
gctscript/README.md
Normal file
@@ -0,0 +1,262 @@
|
||||
# GoCryptoTrader package gctscript
|
||||
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-corp/gocryptotrader)
|
||||
[](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-corp/gocryptotrader/portfolio)
|
||||
[](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader)
|
||||
|
||||
|
||||
This gctscript package is part of the GoCryptoTrader codebase.
|
||||
|
||||
## This is still in active development
|
||||
|
||||
You can track ideas, planned features and what's in progress on this Trello board: [https://trello.com/b/ZAhMhpOy/gocryptotrader](https://trello.com/b/ZAhMhpOy/gocryptotrader).
|
||||
|
||||
Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader Slack](https://join.slack.com/t/gocryptotrader/shared_invite/enQtNTQ5NDAxMjA2Mjc5LTc5ZDE1ZTNiOGM3ZGMyMmY1NTAxYWZhODE0MWM5N2JlZDk1NDU0YTViYzk4NTk3OTRiMDQzNGQ1YTc4YmRlMTk)
|
||||
|
||||
## Current Features for gctscript package
|
||||
|
||||
+ Execute scripts
|
||||
+ Terminate scripts
|
||||
+ Autoload scripts on bot startup
|
||||
+ Current Exchange features supported:
|
||||
+ Enabled Exchanges
|
||||
+ Enabled currency pairs
|
||||
+ Account information
|
||||
+ Query Order
|
||||
+ Submit Order
|
||||
+ Cancel Order
|
||||
+ Ticker
|
||||
+ Orderbook
|
||||
|
||||
## How to use
|
||||
|
||||
##### Prerequisites
|
||||
|
||||
To Enable database logging support you must have an active migrated database by following the [database setup guide](../database/README.md)
|
||||
|
||||
##### Configuration
|
||||
|
||||
The gctscript configuration struct is currently:
|
||||
```shell script
|
||||
type Config struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
ScriptTimeout time.Duration `json:"timeout"`
|
||||
AllowImports bool `json:"allow_imports"`
|
||||
AutoLoad []string `json:"auto_load"`
|
||||
Verbose bool `json:"Verbose"`
|
||||
}
|
||||
```
|
||||
|
||||
With an example configuration being:
|
||||
|
||||
```sh
|
||||
"gctscript": {
|
||||
"enabled": true,
|
||||
"timeout": 600000000,
|
||||
"allow_imports": true,
|
||||
"auto_load": [],
|
||||
"debug": false
|
||||
},
|
||||
```
|
||||
##### Script Control
|
||||
+ You can autoload scripts on bot start up by placing their name in the "auto_load" config entry
|
||||
```shell script
|
||||
"auto_load": ["one","two"]
|
||||
```
|
||||
This will look in your GoCryptoTrader data directory in a folder called "scripts" for files one.gct and two.gct and autoload them
|
||||
+ Manual control of scripts can be done via the gctcli command with support for the following:
|
||||
|
||||
- Enable/Disable GCTScript:
|
||||
```shell script
|
||||
gctcli enablesubsystem "gctscript"
|
||||
gctcli disablesubsystem "gctscript"
|
||||
```
|
||||
- Start/Execute:
|
||||
```shell script
|
||||
gctcli gctscript execute <scriptname> <pathoverride>
|
||||
gctcli gctscript execute "timer.gct" "~/gctscript"
|
||||
|
||||
{
|
||||
"status": "ok",
|
||||
"data": "timer.gct executed"
|
||||
}
|
||||
```
|
||||
- Stop:
|
||||
```shell script
|
||||
gctcli gctscript stop <uuid>
|
||||
gctcli gctscript stop 821bd73e-02b1-4974-9463-874cb49f130d
|
||||
|
||||
{
|
||||
"status": "ok",
|
||||
"data": "821bd73e-02b1-4974-9463-874cb49f130d terminated"
|
||||
}
|
||||
```
|
||||
- Status:
|
||||
```shell script
|
||||
gctcli gctscript status
|
||||
|
||||
{
|
||||
"status": "ok",
|
||||
"scripts": [
|
||||
{
|
||||
"uuid": "821bd73e-02b1-4974-9463-874cb49f130d",
|
||||
"name": "timer.gct",
|
||||
"next_run": "2019-11-14 13:11:40.224919456 +1100 AEDT m=+91.062103259"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
- Read file:
|
||||
```shell script
|
||||
gctcli gctscript read <filename>
|
||||
gctcli gctscript read "timer.gct"
|
||||
|
||||
{
|
||||
"status": "ok",
|
||||
"script": {
|
||||
"name": "timer.gct",
|
||||
"path": "/home/x/.gocryptotrader/scripts"
|
||||
},
|
||||
"data": "fmt := import(\"fmt\")\nt := import(\"times\")\n\nname := \"run\"\ntimer := \"5s\"\n\nload := func() {\n\tfmt.printf(\"5s %s\\n\",t.now())\n}\n\nload()\n"
|
||||
}
|
||||
```
|
||||
- Query running script:
|
||||
```shell script
|
||||
gctcli gctscript query <uuid>
|
||||
gctcli gctscript query 821bd73e-02b1-4974-9463-874cb49f130d
|
||||
{
|
||||
"status": "ok",
|
||||
"script": {
|
||||
"UUID": "bf692e2d-fa1e-4d95-92fd-33d7634d3d77",
|
||||
"name": "timer.gct",
|
||||
"path": "/home/x/.gocryptotrader/scripts",
|
||||
"next_run": "2019-12-12 07:44:19.747572406 +1100 AEDT m=+16.782773385"
|
||||
},
|
||||
"data": "fmt := import(\"fmt\")\nt := import(\"times\")\n\nname := \"run\"\ntimer := \"5s\"\n\nload := func() {\n\tfmt.printf(\"5s %s\\n\",t.now())\n}\n\nload()\n"
|
||||
}
|
||||
load()
|
||||
```
|
||||
- Add script to autoload:
|
||||
```shell script
|
||||
gctcli gctscript autoload add timer
|
||||
{
|
||||
"status": "success",
|
||||
"data": "script timer added to autoload list"
|
||||
}
|
||||
```
|
||||
- Remove script from autoload:
|
||||
```shell script
|
||||
gctcli gctscript autoload remove timer
|
||||
{
|
||||
"status": "success",
|
||||
"data": "script timer removed from autoload list"
|
||||
}
|
||||
```
|
||||
##### Scripting & Extending modules
|
||||
|
||||
The scripting engine utilises [tengo](https://github.com/d5/tengo) an intro tutorial for it can be found [here](https://github.com/d5/tengo/blob/master/docs/tutorial.md)
|
||||
|
||||
Modules have been written so far linking up common exchange features including
|
||||
|
||||
- Orderbook
|
||||
- Ticker
|
||||
- Order Management
|
||||
- Account information
|
||||
- Withdraw funds
|
||||
- Get Deposit Addresses
|
||||
|
||||
Extending or creating new modules:
|
||||
|
||||
Extending an existing module the exchange module for example is simple
|
||||
- Open required [module](modules/gct/exchange.go)
|
||||
- Add to exchangeModule map
|
||||
- Define function with signature ```(args ...objects.Object) (ret objects.Object, err error)```
|
||||
|
||||
Similar steps can be taken to add a new module with a few adjustments
|
||||
- Open required [GCT](modules/gct/gct_types.go)
|
||||
- Add module name to GCTModules map
|
||||
|
||||
##### GCT module methods
|
||||
|
||||
Current supported methods added and exposed to scripts are as follows:
|
||||
|
||||
```
|
||||
accountinfo
|
||||
-> exchange:string
|
||||
|
||||
depositaddress
|
||||
-> exchange:string
|
||||
-> currency:string
|
||||
|
||||
orderbook
|
||||
-> exchange:string
|
||||
-> currency pair:string
|
||||
-> delimiter:string
|
||||
-> asset:string
|
||||
|
||||
ticker
|
||||
-> exchange:string
|
||||
-> currency pair:string
|
||||
-> delimiter:string
|
||||
-> asset:string
|
||||
|
||||
pairs
|
||||
-> exchange:string
|
||||
-> enabled only:bool
|
||||
-> asset:string
|
||||
|
||||
queryorder
|
||||
-> exchange:string
|
||||
-> order id:string
|
||||
|
||||
submitorder
|
||||
-> exchange:string
|
||||
-> currency pair:string
|
||||
-> delimiter:string
|
||||
-> order type:string
|
||||
-> order side:string
|
||||
-> price:float64
|
||||
-> amount:float64
|
||||
-> client_id:string
|
||||
|
||||
withdrawfiat
|
||||
-> exchange:string
|
||||
-> currency:string
|
||||
-> description:string
|
||||
-> amount:float64
|
||||
-> bank id:string
|
||||
|
||||
withdrawcrypto
|
||||
-> exchange:string
|
||||
-> currency:string
|
||||
-> address:string
|
||||
-> address tag:string
|
||||
-> amount:float64
|
||||
-> fee:float64
|
||||
-> description:string
|
||||
```
|
||||
|
||||
## Contribution
|
||||
|
||||
Please feel free to submit any pull requests or suggest any desired features to be added.
|
||||
|
||||
When submitting a PR, please abide by our coding guidelines:
|
||||
|
||||
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
|
||||
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Pull requests need to be based on and opened against the `master` branch.
|
||||
|
||||
## Donations
|
||||
|
||||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
***1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB***
|
||||
|
||||
13
gctscript/examples/exchange/account_info.gct
Normal file
13
gctscript/examples/exchange/account_info.gct
Normal file
@@ -0,0 +1,13 @@
|
||||
// import fmt package
|
||||
fmt := import("fmt")
|
||||
// import exchange package
|
||||
exch := import("exchange")
|
||||
|
||||
load := func() {
|
||||
// retrieve account information from exchange and store in info variable
|
||||
info := exch.accountinfo("BTC Markets")
|
||||
// print out info
|
||||
fmt.print(info)
|
||||
}
|
||||
|
||||
load()
|
||||
9
gctscript/examples/exchange/deposit_address.gct
Normal file
9
gctscript/examples/exchange/deposit_address.gct
Normal file
@@ -0,0 +1,9 @@
|
||||
fmt := import("fmt")
|
||||
exch := import("exchange")
|
||||
|
||||
load := func() {
|
||||
info := exch.depositaddress("BTC Markets", "BTC", "")
|
||||
fmt.println(info)
|
||||
}
|
||||
|
||||
load()
|
||||
12
gctscript/examples/exchange/orderbook.gct
Normal file
12
gctscript/examples/exchange/orderbook.gct
Normal file
@@ -0,0 +1,12 @@
|
||||
fmt := import("fmt")
|
||||
exch := import("exchange")
|
||||
|
||||
name := "run"
|
||||
timer := "5s"
|
||||
|
||||
load := func() {
|
||||
tx := exch.orderbook("btc markets", "btc-aud", "-", "spot")
|
||||
fmt.println(tx)
|
||||
}
|
||||
|
||||
load()
|
||||
9
gctscript/examples/exchange/pairs.gct
Normal file
9
gctscript/examples/exchange/pairs.gct
Normal file
@@ -0,0 +1,9 @@
|
||||
fmt := import("fmt")
|
||||
exch := import("exchange")
|
||||
|
||||
load := func() {
|
||||
info := exch.pairs("BTC Markets", false, "SPOT")
|
||||
fmt.print(info)
|
||||
}
|
||||
|
||||
load()
|
||||
9
gctscript/examples/exchange/query_order.gct
Normal file
9
gctscript/examples/exchange/query_order.gct
Normal file
@@ -0,0 +1,9 @@
|
||||
fmt := import("fmt")
|
||||
exch := import("exchange")
|
||||
|
||||
load := func() {
|
||||
info := exch.orderquery("BTC Markets", "4491600698")
|
||||
fmt.print(info)
|
||||
}
|
||||
|
||||
load()
|
||||
9
gctscript/examples/exchange/submit_order.gct
Normal file
9
gctscript/examples/exchange/submit_order.gct
Normal file
@@ -0,0 +1,9 @@
|
||||
fmt := import("fmt")
|
||||
exch := import("exchange")
|
||||
|
||||
load := func() {
|
||||
info := exch.ordersubmit("BTC Markets","BTC-AUD","-","LIMIT","SELL",1000000, 1,"")
|
||||
fmt.print(info)
|
||||
}
|
||||
|
||||
load()
|
||||
13
gctscript/examples/exchange/ticker.gct
Normal file
13
gctscript/examples/exchange/ticker.gct
Normal file
@@ -0,0 +1,13 @@
|
||||
fmt := import("fmt")
|
||||
exch := import("exchange")
|
||||
|
||||
name := "run"
|
||||
timer := "5s"
|
||||
|
||||
load := func() {
|
||||
tx := exch.ticker("btc markets", "btc-aud", "-", "spot")
|
||||
fmt.println(tx)
|
||||
}
|
||||
|
||||
load()
|
||||
|
||||
25
gctscript/examples/exchange/withdraw.gct
Normal file
25
gctscript/examples/exchange/withdraw.gct
Normal file
@@ -0,0 +1,25 @@
|
||||
// import fmt package
|
||||
fmt := import("fmt")
|
||||
// import exchange package
|
||||
exch := import("exchange")
|
||||
|
||||
|
||||
load := func() {
|
||||
// retrieve account information from exchange and store in info variable
|
||||
// withdrawcrypto
|
||||
// 1: Exchange name
|
||||
// 2: currency
|
||||
// 3: address
|
||||
// 4: address tag
|
||||
// 5: amount
|
||||
// 6: fee amount
|
||||
// 7: trade password
|
||||
// 8: OTP
|
||||
|
||||
// submit request to withdraw funds
|
||||
info := exch.withdrawfiat("BTC Markets", "AUD", "hello", 1, "-")
|
||||
// print out info
|
||||
fmt.print(info)
|
||||
}
|
||||
|
||||
load()
|
||||
24
gctscript/examples/exchange/withdraw_crypto.gct
Normal file
24
gctscript/examples/exchange/withdraw_crypto.gct
Normal file
@@ -0,0 +1,24 @@
|
||||
// import fmt package
|
||||
fmt := import("fmt")
|
||||
// import exchange package
|
||||
exch := import("exchange")
|
||||
|
||||
|
||||
load := func() {
|
||||
// retrieve account information from exchange and store in info variable
|
||||
// withdrawcrypto
|
||||
// 1: Exchange name
|
||||
// 2: currency
|
||||
// 3: address
|
||||
// 4: address tag
|
||||
// 5: amount
|
||||
// 6: fee amount
|
||||
// 7: trade password
|
||||
// 8: OTP
|
||||
|
||||
info := exch.withdrawcrypto("BTC Markets","BTC", "1234562362", "1231", 1.0, 0.0, "","" )
|
||||
// print out info
|
||||
fmt.print(info)
|
||||
}
|
||||
|
||||
load()
|
||||
16
gctscript/examples/exit.gct
Normal file
16
gctscript/examples/exit.gct
Normal file
@@ -0,0 +1,16 @@
|
||||
fmt := import("fmt")
|
||||
|
||||
timer := "5s"
|
||||
|
||||
exit := func() {
|
||||
timer = 0
|
||||
}
|
||||
|
||||
load := func() {
|
||||
for x := 0 ; x < 20; x++ {
|
||||
fmt.printf("Hello %v", x)
|
||||
}
|
||||
exit()
|
||||
}
|
||||
|
||||
load()
|
||||
11
gctscript/gctscript.go
Normal file
11
gctscript/gctscript.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package gctscript
|
||||
|
||||
import (
|
||||
"github.com/thrasher-corp/gocryptotrader/gctscript/modules"
|
||||
"github.com/thrasher-corp/gocryptotrader/gctscript/wrappers/gct"
|
||||
)
|
||||
|
||||
// Setup configures the wrapper interface to use
|
||||
func Setup() {
|
||||
modules.SetModuleWrapper(gct.Setup())
|
||||
}
|
||||
498
gctscript/modules/gct/exchange.go
Normal file
498
gctscript/modules/gct/exchange.go
Normal file
@@ -0,0 +1,498 @@
|
||||
package gct
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
objects "github.com/d5/tengo/v2"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/withdraw"
|
||||
"github.com/thrasher-corp/gocryptotrader/gctscript/wrappers"
|
||||
)
|
||||
|
||||
var exchangeModule = map[string]objects.Object{
|
||||
"orderbook": &objects.UserFunction{Name: "orderbook", Value: ExchangeOrderbook},
|
||||
"ticker": &objects.UserFunction{Name: "ticker", Value: ExchangeTicker},
|
||||
"exchanges": &objects.UserFunction{Name: "exchanges", Value: ExchangeExchanges},
|
||||
"pairs": &objects.UserFunction{Name: "pairs", Value: ExchangePairs},
|
||||
"accountinfo": &objects.UserFunction{Name: "accountinfo", Value: ExchangeAccountInfo},
|
||||
"depositaddress": &objects.UserFunction{Name: "depositaddress", Value: ExchangeDepositAddress},
|
||||
"orderquery": &objects.UserFunction{Name: "orderquery", Value: ExchangeOrderQuery},
|
||||
"ordercancel": &objects.UserFunction{Name: "ordercancel", Value: ExchangeOrderCancel},
|
||||
"ordersubmit": &objects.UserFunction{Name: "ordersubmit", Value: ExchangeOrderSubmit},
|
||||
"withdrawcrypto": &objects.UserFunction{Name: "withdrawcrypto", Value: ExchangeWithdrawCrypto},
|
||||
"withdrawfiat": &objects.UserFunction{Name: "withdrawfiat", Value: ExchangeWithdrawFiat},
|
||||
}
|
||||
|
||||
// ExchangeOrderbook returns orderbook for requested exchange & currencypair
|
||||
func ExchangeOrderbook(args ...objects.Object) (objects.Object, error) {
|
||||
if len(args) != 4 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
exchangeName, ok := objects.ToString(args[0])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, exchangeName)
|
||||
}
|
||||
currencyPair, ok := objects.ToString(args[1])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, currencyPair)
|
||||
}
|
||||
delimiter, ok := objects.ToString(args[2])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, delimiter)
|
||||
}
|
||||
assetTypeParam, ok := objects.ToString(args[3])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, assetTypeParam)
|
||||
}
|
||||
|
||||
pairs := currency.NewPairDelimiter(currencyPair, delimiter)
|
||||
assetType := asset.Item(assetTypeParam)
|
||||
|
||||
ob, err := wrappers.GetWrapper().Orderbook(exchangeName, pairs, assetType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var asks, bids objects.Array
|
||||
|
||||
for x := range ob.Asks {
|
||||
temp := make(map[string]objects.Object, 2)
|
||||
temp["amount"] = &objects.Float{Value: ob.Asks[x].Amount}
|
||||
temp["price"] = &objects.Float{Value: ob.Asks[x].Price}
|
||||
asks.Value = append(asks.Value, &objects.Map{Value: temp})
|
||||
}
|
||||
|
||||
for x := range ob.Bids {
|
||||
temp := make(map[string]objects.Object, 2)
|
||||
temp["amount"] = &objects.Float{Value: ob.Bids[x].Amount}
|
||||
temp["price"] = &objects.Float{Value: ob.Bids[x].Price}
|
||||
bids.Value = append(bids.Value, &objects.Map{Value: temp})
|
||||
}
|
||||
|
||||
data := make(map[string]objects.Object, 5)
|
||||
data["exchange"] = &objects.String{Value: ob.ExchangeName}
|
||||
data["pair"] = &objects.String{Value: ob.Pair.String()}
|
||||
data["asks"] = &asks
|
||||
data["bids"] = &bids
|
||||
data["asset"] = &objects.String{Value: ob.AssetType.String()}
|
||||
|
||||
return &objects.Map{
|
||||
Value: data,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ExchangeTicker returns ticker data for requested exchange and currency pair
|
||||
func ExchangeTicker(args ...objects.Object) (objects.Object, error) {
|
||||
if len(args) != 4 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
exchangeName, ok := objects.ToString(args[0])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, exchangeName)
|
||||
}
|
||||
currencyPair, ok := objects.ToString(args[1])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, currencyPair)
|
||||
}
|
||||
delimiter, ok := objects.ToString(args[2])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, delimiter)
|
||||
}
|
||||
assetTypeParam, ok := objects.ToString(args[3])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, assetTypeParam)
|
||||
}
|
||||
|
||||
pairs := currency.NewPairDelimiter(currencyPair, delimiter)
|
||||
assetType := asset.Item(assetTypeParam)
|
||||
|
||||
tx, err := wrappers.GetWrapper().Ticker(exchangeName, pairs, assetType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := make(map[string]objects.Object, 14)
|
||||
data["exchange"] = &objects.String{Value: tx.ExchangeName}
|
||||
data["last"] = &objects.Float{Value: tx.Last}
|
||||
data["High"] = &objects.Float{Value: tx.High}
|
||||
data["Low"] = &objects.Float{Value: tx.Low}
|
||||
data["bid"] = &objects.Float{Value: tx.Bid}
|
||||
data["ask"] = &objects.Float{Value: tx.Ask}
|
||||
data["volume"] = &objects.Float{Value: tx.Volume}
|
||||
data["quotevolume"] = &objects.Float{Value: tx.QuoteVolume}
|
||||
data["priceath"] = &objects.Float{Value: tx.PriceATH}
|
||||
data["open"] = &objects.Float{Value: tx.Open}
|
||||
data["close"] = &objects.Float{Value: tx.Close}
|
||||
data["pair"] = &objects.String{Value: tx.Pair.String()}
|
||||
data["asset"] = &objects.String{Value: tx.AssetType.String()}
|
||||
data["updated"] = &objects.Time{Value: tx.LastUpdated}
|
||||
|
||||
return &objects.Map{
|
||||
Value: data,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ExchangeExchanges returns list of exchanges either enabled or all
|
||||
func ExchangeExchanges(args ...objects.Object) (objects.Object, error) {
|
||||
if len(args) != 1 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
enabledOnly, ok := objects.ToBool(args[0])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, enabledOnly)
|
||||
}
|
||||
rtnValue := wrappers.GetWrapper().Exchanges(enabledOnly)
|
||||
|
||||
r := objects.Array{}
|
||||
for x := range rtnValue {
|
||||
r.Value = append(r.Value, &objects.String{Value: rtnValue[x]})
|
||||
}
|
||||
|
||||
return &r, nil
|
||||
}
|
||||
|
||||
// ExchangePairs returns currency pairs for requested exchange
|
||||
func ExchangePairs(args ...objects.Object) (objects.Object, error) {
|
||||
if len(args) != 3 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
exchangeName, ok := objects.ToString(args[0])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, exchangeName)
|
||||
}
|
||||
enabledOnly, ok := objects.ToBool(args[1])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, enabledOnly)
|
||||
}
|
||||
assetTypeParam, ok := objects.ToString(args[2])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, assetTypeParam)
|
||||
}
|
||||
assetType := asset.Item(strings.ToLower(assetTypeParam))
|
||||
|
||||
rtnValue, err := wrappers.GetWrapper().Pairs(exchangeName, enabledOnly, assetType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r := objects.Array{}
|
||||
for x := range rtnValue.Slice() {
|
||||
r.Value = append(r.Value, &objects.String{Value: rtnValue.Slice()[x].String()})
|
||||
}
|
||||
return &r, nil
|
||||
}
|
||||
|
||||
// ExchangeAccountInfo returns account information for requested exchange
|
||||
func ExchangeAccountInfo(args ...objects.Object) (objects.Object, error) {
|
||||
if len(args) != 1 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
exchangeName, ok := objects.ToString(args[0])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, exchangeName)
|
||||
}
|
||||
rtnValue, err := wrappers.GetWrapper().AccountInformation(exchangeName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var funds objects.Array
|
||||
for x := range rtnValue.Accounts {
|
||||
for y := range rtnValue.Accounts[x].Currencies {
|
||||
temp := make(map[string]objects.Object, 3)
|
||||
temp["name"] = &objects.String{Value: rtnValue.Accounts[x].Currencies[y].CurrencyName.String()}
|
||||
temp["total"] = &objects.Float{Value: rtnValue.Accounts[x].Currencies[y].TotalValue}
|
||||
temp["hold"] = &objects.Float{Value: rtnValue.Accounts[x].Currencies[y].Hold}
|
||||
funds.Value = append(funds.Value, &objects.Map{Value: temp})
|
||||
}
|
||||
}
|
||||
|
||||
data := make(map[string]objects.Object, 2)
|
||||
data["exchange"] = &objects.String{Value: rtnValue.Exchange}
|
||||
data["currencies"] = &funds
|
||||
|
||||
return &objects.Map{
|
||||
Value: data,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ExchangeOrderQuery query order on exchange
|
||||
func ExchangeOrderQuery(args ...objects.Object) (objects.Object, error) {
|
||||
if len(args) != 2 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
exchangeName, ok := objects.ToString(args[0])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, exchangeName)
|
||||
}
|
||||
orderID, ok := objects.ToString(args[1])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, orderID)
|
||||
}
|
||||
orderDetails, err := wrappers.GetWrapper().QueryOrder(exchangeName, orderID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tradeHistory objects.Array
|
||||
for x := range orderDetails.Trades {
|
||||
temp := make(map[string]objects.Object, 7)
|
||||
temp["timestamp"] = &objects.Time{Value: orderDetails.Trades[x].Timestamp}
|
||||
temp["price"] = &objects.Float{Value: orderDetails.Trades[x].Price}
|
||||
temp["fee"] = &objects.Float{Value: orderDetails.Trades[x].Fee}
|
||||
temp["amount"] = &objects.Float{Value: orderDetails.Trades[x].Amount}
|
||||
temp["type"] = &objects.String{Value: orderDetails.Trades[x].Type.String()}
|
||||
temp["side"] = &objects.String{Value: orderDetails.Trades[x].Side.String()}
|
||||
temp["description"] = &objects.String{Value: orderDetails.Trades[x].Description}
|
||||
tradeHistory.Value = append(tradeHistory.Value, &objects.Map{Value: temp})
|
||||
}
|
||||
|
||||
data := make(map[string]objects.Object, 14)
|
||||
data["exchange"] = &objects.String{Value: orderDetails.Exchange}
|
||||
data["id"] = &objects.String{Value: orderDetails.ID}
|
||||
data["accountid"] = &objects.String{Value: orderDetails.AccountID}
|
||||
data["currencypair"] = &objects.String{Value: orderDetails.CurrencyPair.String()}
|
||||
data["price"] = &objects.Float{Value: orderDetails.Price}
|
||||
data["amount"] = &objects.Float{Value: orderDetails.Amount}
|
||||
data["amountexecuted"] = &objects.Float{Value: orderDetails.ExecutedAmount}
|
||||
data["amountremaining"] = &objects.Float{Value: orderDetails.RemainingAmount}
|
||||
data["fee"] = &objects.Float{Value: orderDetails.Fee}
|
||||
data["side"] = &objects.String{Value: orderDetails.OrderSide.String()}
|
||||
data["type"] = &objects.String{Value: orderDetails.OrderType.String()}
|
||||
data["date"] = &objects.String{Value: orderDetails.OrderDate.String()}
|
||||
data["status"] = &objects.String{Value: orderDetails.Status.String()}
|
||||
data["trades"] = &tradeHistory
|
||||
|
||||
return &objects.Map{
|
||||
Value: data,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ExchangeOrderCancel cancels order on requested exchange
|
||||
func ExchangeOrderCancel(args ...objects.Object) (objects.Object, error) {
|
||||
if len(args) != 2 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
exchangeName, ok := objects.ToString(args[0])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, exchangeName)
|
||||
}
|
||||
orderID, ok := objects.ToString(args[1])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, orderID)
|
||||
}
|
||||
|
||||
rtn, err := wrappers.GetWrapper().CancelOrder(exchangeName, orderID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if rtn {
|
||||
return objects.TrueValue, nil
|
||||
}
|
||||
return objects.FalseValue, nil
|
||||
}
|
||||
|
||||
// ExchangeOrderSubmit submit order on exchange
|
||||
func ExchangeOrderSubmit(args ...objects.Object) (objects.Object, error) {
|
||||
if len(args) != 8 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
exchangeName, ok := objects.ToString(args[0])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, exchangeName)
|
||||
}
|
||||
currencyPair, ok := objects.ToString(args[1])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, currencyPair)
|
||||
}
|
||||
delimiter, ok := objects.ToString(args[2])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, delimiter)
|
||||
}
|
||||
orderType, ok := objects.ToString(args[3])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, orderType)
|
||||
}
|
||||
orderSide, ok := objects.ToString(args[4])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, orderSide)
|
||||
}
|
||||
orderPrice, ok := objects.ToFloat64(args[5])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, orderPrice)
|
||||
}
|
||||
orderAmount, ok := objects.ToFloat64(args[6])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, orderAmount)
|
||||
}
|
||||
orderClientID, ok := objects.ToString(args[7])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, orderClientID)
|
||||
}
|
||||
pair := currency.NewPairDelimiter(currencyPair, delimiter)
|
||||
|
||||
tempSubmit := &order.Submit{
|
||||
Pair: pair,
|
||||
OrderType: order.Type(orderType),
|
||||
OrderSide: order.Side(orderSide),
|
||||
Price: orderPrice,
|
||||
Amount: orderAmount,
|
||||
ClientID: orderClientID,
|
||||
}
|
||||
|
||||
err := tempSubmit.Validate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rtn, err := wrappers.GetWrapper().SubmitOrder(exchangeName, tempSubmit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := make(map[string]objects.Object, 2)
|
||||
data["orderid"] = &objects.String{Value: rtn.OrderID}
|
||||
if rtn.IsOrderPlaced {
|
||||
data["isorderplaced"] = objects.TrueValue
|
||||
} else {
|
||||
data["isorderplaced"] = objects.FalseValue
|
||||
}
|
||||
|
||||
return &objects.Map{
|
||||
Value: data,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ExchangeDepositAddress returns deposit address (if supported by exchange)
|
||||
func ExchangeDepositAddress(args ...objects.Object) (objects.Object, error) {
|
||||
if len(args) != 2 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
exchangeName, ok := objects.ToString(args[0])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, exchangeName)
|
||||
}
|
||||
currencyCode, ok := objects.ToString(args[1])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, currencyCode)
|
||||
}
|
||||
|
||||
currCode := currency.NewCode(currencyCode)
|
||||
|
||||
rtn, err := wrappers.GetWrapper().DepositAddress(exchangeName, currCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &objects.String{Value: rtn}, nil
|
||||
}
|
||||
|
||||
// ExchangeWithdrawCrypto submit request to withdraw crypto assets
|
||||
func ExchangeWithdrawCrypto(args ...objects.Object) (objects.Object, error) {
|
||||
if len(args) != 7 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
exchangeName, ok := objects.ToString(args[0])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, exchangeName)
|
||||
}
|
||||
cur, ok := objects.ToString(args[1])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, cur)
|
||||
}
|
||||
address, ok := objects.ToString(args[2])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, address)
|
||||
}
|
||||
addressTag, ok := objects.ToString(args[3])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, addressTag)
|
||||
}
|
||||
amount, ok := objects.ToFloat64(args[4])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, amount)
|
||||
}
|
||||
feeAmount, ok := objects.ToFloat64(args[5])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, feeAmount)
|
||||
}
|
||||
description, ok := objects.ToString(args[6])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, description)
|
||||
}
|
||||
|
||||
withdrawRequest := &withdraw.CryptoRequest{
|
||||
GenericInfo: withdraw.GenericInfo{
|
||||
Currency: currency.NewCode(cur),
|
||||
Description: description,
|
||||
Amount: amount,
|
||||
},
|
||||
Address: address,
|
||||
AddressTag: addressTag,
|
||||
FeeAmount: feeAmount,
|
||||
}
|
||||
|
||||
rtn, err := wrappers.GetWrapper().WithdrawalCryptoFunds(exchangeName, withdrawRequest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &objects.String{Value: rtn}, nil
|
||||
}
|
||||
|
||||
// ExchangeWithdrawFiat submit request to withdraw fiat assets
|
||||
func ExchangeWithdrawFiat(args ...objects.Object) (objects.Object, error) {
|
||||
if len(args) != 5 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
exchangeName, ok := objects.ToString(args[0])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, exchangeName)
|
||||
}
|
||||
cur, ok := objects.ToString(args[1])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, cur)
|
||||
}
|
||||
description, ok := objects.ToString(args[2])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, description)
|
||||
}
|
||||
amount, ok := objects.ToFloat64(args[3])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, amount)
|
||||
}
|
||||
bankAccountID, ok := objects.ToString(args[4])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, bankAccountID)
|
||||
}
|
||||
|
||||
withdrawRequest := &withdraw.FiatRequest{
|
||||
GenericInfo: withdraw.GenericInfo{
|
||||
Currency: currency.NewCode(cur),
|
||||
Description: description,
|
||||
Amount: amount,
|
||||
},
|
||||
}
|
||||
|
||||
rtn, err := wrappers.GetWrapper().WithdrawalFiatFunds(exchangeName, bankAccountID, withdrawRequest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &objects.String{Value: rtn}, nil
|
||||
}
|
||||
10
gctscript/modules/gct/gct.go
Normal file
10
gctscript/modules/gct/gct.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package gct
|
||||
|
||||
// AllModuleNames returns a list of all default module names.
|
||||
func AllModuleNames() []string {
|
||||
var names []string
|
||||
for name := range Modules {
|
||||
names = append(names, name)
|
||||
}
|
||||
return names
|
||||
}
|
||||
270
gctscript/modules/gct/gct_test.go
Normal file
270
gctscript/modules/gct/gct_test.go
Normal file
@@ -0,0 +1,270 @@
|
||||
package gct
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
objects "github.com/d5/tengo/v2"
|
||||
"github.com/thrasher-corp/gocryptotrader/gctscript/modules"
|
||||
"github.com/thrasher-corp/gocryptotrader/gctscript/wrappers/validator"
|
||||
)
|
||||
|
||||
var (
|
||||
exch = &objects.String{
|
||||
Value: "BTC Markets",
|
||||
}
|
||||
exchError = &objects.String{
|
||||
Value: "error",
|
||||
}
|
||||
currencyPair = &objects.String{
|
||||
Value: "BTC-AUD",
|
||||
}
|
||||
delimiter = &objects.String{
|
||||
Value: "-",
|
||||
}
|
||||
assetType = &objects.String{
|
||||
Value: "SPOT",
|
||||
}
|
||||
orderID = &objects.String{
|
||||
Value: "1235",
|
||||
}
|
||||
|
||||
tv = objects.TrueValue
|
||||
fv = objects.FalseValue
|
||||
errTestFailed = errors.New("test failed")
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
modules.SetModuleWrapper(validator.Wrapper{})
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestExchangeOrderbook(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := ExchangeOrderbook(exch, currencyPair, delimiter, assetType)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeOrderbook(exchError, currencyPair, delimiter, assetType)
|
||||
if err != nil && errors.Is(err, errTestFailed) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeOrderbook()
|
||||
if !errors.Is(err, objects.ErrWrongNumArguments) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExchangeTicker(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := ExchangeTicker(exch, currencyPair, delimiter, assetType)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeTicker(exchError, currencyPair, delimiter, assetType)
|
||||
if err != nil && errors.Is(err, errTestFailed) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeTicker()
|
||||
if !errors.Is(err, objects.ErrWrongNumArguments) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExchangeExchanges(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := ExchangeExchanges(tv)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeExchanges(exch)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeExchanges(fv)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeExchanges()
|
||||
if !errors.Is(err, objects.ErrWrongNumArguments) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExchangePairs(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := ExchangePairs(exch, tv, assetType)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = ExchangePairs(exchError, tv, assetType)
|
||||
if err != nil && errors.Is(err, errTestFailed) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = ExchangePairs()
|
||||
if !errors.Is(err, objects.ErrWrongNumArguments) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAccountInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := ExchangeAccountInfo()
|
||||
if !errors.Is(err, objects.ErrWrongNumArguments) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeAccountInfo(exch)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeAccountInfo(exchError)
|
||||
if err != nil && !errors.Is(err, errTestFailed) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExchangeOrderQuery(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := ExchangeOrderQuery()
|
||||
if !errors.Is(err, objects.ErrWrongNumArguments) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeOrderQuery(exch, orderID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeOrderQuery(exchError, orderID)
|
||||
if err != nil && !errors.Is(err, errTestFailed) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExchangeOrderCancel(t *testing.T) {
|
||||
_, err := ExchangeOrderCancel()
|
||||
if !errors.Is(err, objects.ErrWrongNumArguments) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeOrderCancel(exch, orderID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeOrderCancel(exch, objects.FalseValue)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeOrderCancel(exchError, orderID)
|
||||
if err != nil && !errors.Is(err, errTestFailed) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExchangeOrderSubmit(t *testing.T) {
|
||||
_, err := ExchangeOrderSubmit()
|
||||
if !errors.Is(err, objects.ErrWrongNumArguments) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
orderSide := &objects.String{Value: "ASK"}
|
||||
orderType := &objects.String{Value: "LIMIT"}
|
||||
orderPrice := &objects.Float{Value: 1}
|
||||
orderAmount := &objects.Float{Value: 1}
|
||||
|
||||
_, err = ExchangeOrderSubmit(exch, currencyPair, delimiter,
|
||||
orderType, orderSide, orderPrice, orderAmount, orderID)
|
||||
if err != nil && !errors.Is(err, errTestFailed) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeOrderSubmit(exch, currencyPair, delimiter,
|
||||
orderType, orderSide, orderPrice, orderAmount, orderID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeOrderSubmit(objects.TrueValue, currencyPair, delimiter,
|
||||
orderType, orderSide, orderPrice, orderAmount, orderID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllModuleNames(t *testing.T) {
|
||||
x := AllModuleNames()
|
||||
xType := reflect.TypeOf(x).Kind()
|
||||
if xType != reflect.Slice {
|
||||
t.Fatalf("AllModuleNames() should return slice instead received: %v", x)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExchangeDepositAddress(t *testing.T) {
|
||||
_, err := ExchangeDepositAddress()
|
||||
if !errors.Is(err, objects.ErrWrongNumArguments) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
currCode := &objects.String{Value: "BTC"}
|
||||
_, err = ExchangeDepositAddress(exch, currCode)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeDepositAddress(exchError, currCode)
|
||||
if err != nil && !errors.Is(err, errTestFailed) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExchangeWithdrawCrypto(t *testing.T) {
|
||||
_, err := ExchangeWithdrawCrypto()
|
||||
if !errors.Is(err, objects.ErrWrongNumArguments) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
currCode := &objects.String{Value: "BTC"}
|
||||
desc := &objects.String{Value: "HELLO"}
|
||||
address := &objects.String{Value: "0xTHISISALEGITBTCADDRESSS"}
|
||||
amount := &objects.Float{Value: 1.0}
|
||||
|
||||
_, err = ExchangeWithdrawCrypto(exch, currCode, address, address, amount, amount, desc)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExchangeWithdrawFiat(t *testing.T) {
|
||||
_, err := ExchangeWithdrawFiat()
|
||||
if !errors.Is(err, objects.ErrWrongNumArguments) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
currCode := &objects.String{Value: "AUD"}
|
||||
desc := &objects.String{Value: "Hello"}
|
||||
amount := &objects.Float{Value: 1.0}
|
||||
bankID := &objects.String{Value: "test-bank-01"}
|
||||
_, err = ExchangeWithdrawFiat(exch, currCode, desc, amount, bankID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
15
gctscript/modules/gct/gct_types.go
Normal file
15
gctscript/modules/gct/gct_types.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package gct
|
||||
|
||||
import (
|
||||
"github.com/d5/tengo/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
// ErrParameterConvertFailed error to return when type conversion fails
|
||||
ErrParameterConvertFailed = "%v failed conversion"
|
||||
)
|
||||
|
||||
// Modules map of all loadable modules
|
||||
var Modules = map[string]map[string]tengo.Object{
|
||||
"exchange": exchangeModule,
|
||||
}
|
||||
32
gctscript/modules/loader/loader.go
Normal file
32
gctscript/modules/loader/loader.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package loader
|
||||
|
||||
import (
|
||||
"github.com/d5/tengo/v2"
|
||||
"github.com/d5/tengo/v2/stdlib"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/gctscript/modules/gct"
|
||||
)
|
||||
|
||||
// GetModuleMap returns the module map that includes all modules
|
||||
// for the given module names.
|
||||
func GetModuleMap() *tengo.ModuleMap {
|
||||
modules := tengo.NewModuleMap()
|
||||
|
||||
gctModuleList := gct.AllModuleNames()
|
||||
for _, name := range gctModuleList {
|
||||
if mod := gct.Modules[name]; mod != nil {
|
||||
modules.AddBuiltinModule(name, mod)
|
||||
}
|
||||
}
|
||||
|
||||
stdLib := stdlib.AllModuleNames()
|
||||
for _, name := range stdLib {
|
||||
if mod := stdlib.BuiltinModules[name]; mod != nil {
|
||||
modules.AddBuiltinModule(name, mod)
|
||||
}
|
||||
if mod := stdlib.SourceModules[name]; mod != "" {
|
||||
modules.AddSourceModule(name, []byte(mod))
|
||||
}
|
||||
}
|
||||
return modules
|
||||
}
|
||||
18
gctscript/modules/loader/loader_test.go
Normal file
18
gctscript/modules/loader/loader_test.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package loader
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetModuleMap(t *testing.T) {
|
||||
x := GetModuleMap()
|
||||
xType := reflect.TypeOf(x).String()
|
||||
if xType != "*tengo.ModuleMap" {
|
||||
t.Fatalf("GetModuleMap() should return pointer to ModuleMap instead received: %v", x)
|
||||
}
|
||||
|
||||
if x.Len() == 0 {
|
||||
t.Fatal("expected GetModuleMap() to contain module results instead received 0 value")
|
||||
}
|
||||
}
|
||||
59
gctscript/modules/wrapper_types.go
Normal file
59
gctscript/modules/wrapper_types.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package modules
|
||||
|
||||
import (
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/withdraw"
|
||||
)
|
||||
|
||||
// Wrapper instance of GCT to use for modules
|
||||
var Wrapper GCT
|
||||
|
||||
// GCT interface requirements
|
||||
type GCT interface {
|
||||
Exchange
|
||||
}
|
||||
|
||||
// Exchange interface requirements
|
||||
type Exchange interface {
|
||||
Exchanges(enabledOnly bool) []string
|
||||
IsEnabled(exch string) bool
|
||||
Orderbook(exch string, pair currency.Pair, item asset.Item) (*orderbook.Base, error)
|
||||
Ticker(exch string, pair currency.Pair, item asset.Item) (*ticker.Price, error)
|
||||
Pairs(exch string, enabledOnly bool, item asset.Item) (*currency.Pairs, error)
|
||||
QueryOrder(exch, orderid string) (*order.Detail, error)
|
||||
SubmitOrder(exch string, submit *order.Submit) (*order.SubmitResponse, error)
|
||||
CancelOrder(exch, orderid string) (bool, error)
|
||||
AccountInformation(exch string) (*AccountInfo, error)
|
||||
DepositAddress(exch string, currencyCode currency.Code) (string, error)
|
||||
WithdrawalFiatFunds(exch, bankaccountid string, request *withdraw.FiatRequest) (out string, err error)
|
||||
WithdrawalCryptoFunds(exch string, request *withdraw.CryptoRequest) (out string, err error)
|
||||
}
|
||||
|
||||
// SetModuleWrapper link the wrapper and interface to use for modules
|
||||
func SetModuleWrapper(wrapper GCT) {
|
||||
Wrapper = wrapper
|
||||
}
|
||||
|
||||
// AccountInfo is a Generic type to hold each exchange's holdings in
|
||||
// all enabled currencies
|
||||
type AccountInfo struct {
|
||||
Exchange string
|
||||
Accounts []Account
|
||||
}
|
||||
|
||||
// Account defines a singular account type with associated currencies
|
||||
type Account struct {
|
||||
ID string
|
||||
Currencies []AccountCurrencyInfo
|
||||
}
|
||||
|
||||
// AccountCurrencyInfo is a sub type to store currency name and value
|
||||
type AccountCurrencyInfo struct {
|
||||
CurrencyName currency.Code
|
||||
TotalValue float64
|
||||
Hold float64
|
||||
}
|
||||
43
gctscript/vm/autoload.go
Normal file
43
gctscript/vm/autoload.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// Autoload remove entry from autoload slice
|
||||
func Autoload(name string, remove bool) error {
|
||||
if filepath.Ext(name) != ".gct" {
|
||||
name += ".gct"
|
||||
}
|
||||
if remove {
|
||||
for x := range GCTScriptConfig.AutoLoad {
|
||||
if GCTScriptConfig.AutoLoad[x] != name {
|
||||
continue
|
||||
}
|
||||
GCTScriptConfig.AutoLoad = append(GCTScriptConfig.AutoLoad[:x], GCTScriptConfig.AutoLoad[x+1:]...)
|
||||
if GCTScriptConfig.Verbose {
|
||||
log.Debugf(log.GCTScriptMgr, "Removing script: %s from autoload", name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("%v - not found", name)
|
||||
}
|
||||
|
||||
script := filepath.Join(ScriptPath, name)
|
||||
_, err := os.Stat(script)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return fmt.Errorf("%v - not found", script)
|
||||
}
|
||||
return err
|
||||
}
|
||||
GCTScriptConfig.AutoLoad = append(GCTScriptConfig.AutoLoad, name)
|
||||
if GCTScriptConfig.Verbose {
|
||||
log.Debugf(log.GCTScriptMgr, "Adding script: %s to autoload", name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
81
gctscript/vm/gctscript.go
Normal file
81
gctscript/vm/gctscript.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/thrasher-corp/gocryptotrader/gctscript/wrappers/validator"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// New returns a new instance of VM
|
||||
func New() *VM {
|
||||
if VMSCount.Len() >= int32(GCTScriptConfig.MaxVirtualMachines) {
|
||||
if GCTScriptConfig.Verbose {
|
||||
log.Warnf(log.GCTScriptMgr, "GCTScript MaxVirtualMachines (%v) hit, unable to start further instances",
|
||||
GCTScriptConfig.MaxVirtualMachines)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
VMSCount.add()
|
||||
vm := NewVM()
|
||||
if vm == nil {
|
||||
VMSCount.remove()
|
||||
} else {
|
||||
AllVMSync.Store(vm.ID, vm)
|
||||
}
|
||||
return vm
|
||||
}
|
||||
|
||||
// Validate will attempt to execute a script in a test/non-live environment
|
||||
// to confirm it passes requirements for execution
|
||||
func Validate(file string) (err error) {
|
||||
validator.IsTestExecution.Store(true)
|
||||
defer validator.IsTestExecution.Store(false)
|
||||
tempVM := NewVM()
|
||||
err = tempVM.Load(file)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = tempVM.Compile()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return tempVM.Run()
|
||||
}
|
||||
|
||||
// ShutdownAll shutdown all
|
||||
func ShutdownAll() (err error) {
|
||||
if GCTScriptConfig.Verbose {
|
||||
log.Debugln(log.GCTScriptMgr, "Shutting down all Virtual Machines")
|
||||
}
|
||||
|
||||
var errors []error
|
||||
AllVMSync.Range(func(k, v interface{}) bool {
|
||||
errShutdown := v.(*VM).Shutdown()
|
||||
if err != nil {
|
||||
errors = append(errors, errShutdown)
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
if len(errors) > 0 {
|
||||
err = fmt.Errorf("failed to shutdown the following Virtual Machines: %v", errors)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// RemoveVM remove VM from list
|
||||
func RemoveVM(id uuid.UUID) error {
|
||||
if _, f := AllVMSync.Load(id); !f {
|
||||
return fmt.Errorf(ErrNoVMFound, id.String())
|
||||
}
|
||||
|
||||
AllVMSync.Delete(id)
|
||||
VMSCount.remove()
|
||||
if GCTScriptConfig.Verbose {
|
||||
log.Debugf(log.GCTScriptMgr, "VM %v removed from AllVMs", id)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
39
gctscript/vm/gctscript_types.go
Normal file
39
gctscript/vm/gctscript_types.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
const gctScript = "GCT Script"
|
||||
|
||||
// Config user configurable options for gctscript
|
||||
type Config struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
ScriptTimeout time.Duration `json:"timeout"`
|
||||
MaxVirtualMachines uint8 `json:"max_virtual_machines"`
|
||||
AllowImports bool `json:"allow_imports"`
|
||||
AutoLoad []string `json:"auto_load"`
|
||||
Verbose bool `json:"verbose"`
|
||||
}
|
||||
|
||||
// Error interface to meet error requirements
|
||||
type Error struct {
|
||||
Script string
|
||||
Action string
|
||||
Cause error
|
||||
}
|
||||
|
||||
var (
|
||||
// GCTScriptConfig initialised global copy of Config{}
|
||||
GCTScriptConfig = &Config{}
|
||||
// ScriptPath path to load/save scripts
|
||||
ScriptPath string
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrScriptingDisabled error message displayed when gctscript is disabled
|
||||
ErrScriptingDisabled = errors.New("scripting is disabled")
|
||||
// ErrNoVMLoaded error message displayed if a virtual machine has not been initialised
|
||||
ErrNoVMLoaded = errors.New("no virtual machine loaded")
|
||||
)
|
||||
302
gctscript/vm/vm.go
Normal file
302
gctscript/vm/vm.go
Normal file
@@ -0,0 +1,302 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/d5/tengo/v2"
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
scriptevent "github.com/thrasher-corp/gocryptotrader/database/repository/script"
|
||||
"github.com/thrasher-corp/gocryptotrader/gctscript/modules/loader"
|
||||
"github.com/thrasher-corp/gocryptotrader/gctscript/wrappers/validator"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
"github.com/volatiletech/null"
|
||||
)
|
||||
|
||||
// NewVM attempts to create a new Virtual Machine firstly from pool
|
||||
func NewVM() (vm *VM) {
|
||||
newUUID, err := uuid.NewV4()
|
||||
if err != nil {
|
||||
log.Error(log.GCTScriptMgr, Error{
|
||||
Action: "New: UUID",
|
||||
Cause: err,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
if GCTScriptConfig.Verbose {
|
||||
log.Debugln(log.GCTScriptMgr, "New GCTScript VM created")
|
||||
}
|
||||
|
||||
vm = &VM{
|
||||
ID: newUUID,
|
||||
Script: pool.Get().(*tengo.Script),
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Load parses and creates a new instance of tengo script vm
|
||||
func (vm *VM) Load(file string) error {
|
||||
if vm == nil {
|
||||
return ErrNoVMLoaded
|
||||
}
|
||||
|
||||
if !GCTScriptConfig.Enabled {
|
||||
return &Error{
|
||||
Action: "Load",
|
||||
Cause: ErrScriptingDisabled,
|
||||
}
|
||||
}
|
||||
|
||||
if filepath.Ext(file) != ".gct" {
|
||||
file += ".gct"
|
||||
}
|
||||
|
||||
if GCTScriptConfig.Verbose {
|
||||
log.Debugf(log.GCTScriptMgr, "Loading script: %s ID: %v", vm.ShortName(), vm.ID)
|
||||
}
|
||||
|
||||
f, err := os.Open(file)
|
||||
if err != nil {
|
||||
return &Error{
|
||||
Action: "Load: Open",
|
||||
Script: file,
|
||||
Cause: err,
|
||||
}
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
code, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return &Error{
|
||||
Action: "Load: Read",
|
||||
Script: file,
|
||||
Cause: err,
|
||||
}
|
||||
}
|
||||
|
||||
vm.File = file
|
||||
vm.Path = filepath.Dir(file)
|
||||
vm.Script = tengo.NewScript(code)
|
||||
vm.Script.SetImports(loader.GetModuleMap())
|
||||
vm.Hash = vm.getHash()
|
||||
|
||||
if GCTScriptConfig.AllowImports {
|
||||
if GCTScriptConfig.Verbose {
|
||||
log.Debugf(log.GCTScriptMgr, "File imports enabled for vm: %v", vm.ID)
|
||||
}
|
||||
vm.Script.EnableFileImport(true)
|
||||
}
|
||||
vm.event(StatusSuccess, TypeLoad)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Compile compiles to byte code loaded copy of vm script
|
||||
func (vm *VM) Compile() (err error) {
|
||||
vm.Compiled = new(tengo.Compiled)
|
||||
vm.Compiled, err = vm.Script.Compile()
|
||||
return
|
||||
}
|
||||
|
||||
// Run runs byte code
|
||||
func (vm *VM) Run() (err error) {
|
||||
if GCTScriptConfig.Verbose {
|
||||
log.Debugf(log.GCTScriptMgr, "Running script: %s ID: %v", vm.ShortName(), vm.ID)
|
||||
}
|
||||
|
||||
err = vm.Compiled.Run()
|
||||
if err != nil {
|
||||
vm.event(StatusFailure, TypeExecute)
|
||||
return Error{
|
||||
Action: "Run",
|
||||
Cause: err,
|
||||
}
|
||||
}
|
||||
vm.event(StatusSuccess, TypeExecute)
|
||||
return
|
||||
}
|
||||
|
||||
// RunCtx runs compiled byte code with context.Context support.
|
||||
func (vm *VM) RunCtx() (err error) {
|
||||
if vm.ctx == nil {
|
||||
vm.ctx = context.Background()
|
||||
}
|
||||
|
||||
ct, cancel := context.WithTimeout(vm.ctx, GCTScriptConfig.ScriptTimeout)
|
||||
defer cancel()
|
||||
|
||||
if GCTScriptConfig.Verbose {
|
||||
log.Debugf(log.GCTScriptMgr, "Running script: %s ID: %v", vm.ShortName(), vm.ID)
|
||||
}
|
||||
|
||||
err = vm.Compiled.RunContext(ct)
|
||||
if err != nil {
|
||||
vm.event(StatusFailure, TypeExecute)
|
||||
return Error{
|
||||
Action: "RunCtx",
|
||||
Cause: err,
|
||||
}
|
||||
}
|
||||
vm.event(StatusSuccess, TypeExecute)
|
||||
return
|
||||
}
|
||||
|
||||
// CompileAndRun Compile and Run script with support for task running
|
||||
func (vm *VM) CompileAndRun() {
|
||||
if vm == nil {
|
||||
return
|
||||
}
|
||||
err := vm.Compile()
|
||||
if err != nil {
|
||||
log.Error(log.GCTScriptMgr, err)
|
||||
err = RemoveVM(vm.ID)
|
||||
if err != nil {
|
||||
log.Error(log.GCTScriptMgr, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
err = vm.RunCtx()
|
||||
if err != nil {
|
||||
log.Error(log.GCTScriptMgr, err)
|
||||
err = RemoveVM(vm.ID)
|
||||
if err != nil {
|
||||
log.Error(log.GCTScriptMgr, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if vm.Compiled.Get("timer").String() != "" {
|
||||
vm.T, err = time.ParseDuration(vm.Compiled.Get("timer").String())
|
||||
if err != nil {
|
||||
log.Error(log.GCTScriptMgr, err)
|
||||
err = vm.Shutdown()
|
||||
if err != nil {
|
||||
log.Error(log.GCTScriptMgr, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if vm.T < time.Nanosecond {
|
||||
log.Error(log.GCTScriptMgr, "Repeat timer cannot be under 1 nano second")
|
||||
err = vm.Shutdown()
|
||||
if err != nil {
|
||||
log.Errorln(log.GCTScriptMgr, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
vm.runner()
|
||||
} else {
|
||||
err = vm.Shutdown()
|
||||
if err != nil {
|
||||
log.Error(log.GCTScriptMgr, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Shutdown shuts down current VM
|
||||
func (vm *VM) Shutdown() error {
|
||||
if vm == nil {
|
||||
return ErrNoVMLoaded
|
||||
}
|
||||
if vm.S != nil {
|
||||
close(vm.S)
|
||||
}
|
||||
if GCTScriptConfig.Verbose {
|
||||
log.Debugf(log.GCTScriptMgr, "Shutting down script: %s ID: %v", vm.ShortName(), vm.ID)
|
||||
}
|
||||
vm.Script = nil
|
||||
pool.Put(vm.Script)
|
||||
vm.event(StatusSuccess, TypeStop)
|
||||
return RemoveVM(vm.ID)
|
||||
}
|
||||
|
||||
// Read contents of script back and create script event
|
||||
func (vm *VM) Read() ([]byte, error) {
|
||||
vm.event(StatusSuccess, TypeRead)
|
||||
return vm.read()
|
||||
}
|
||||
|
||||
// Read contents of script back
|
||||
func (vm *VM) read() ([]byte, error) {
|
||||
if GCTScriptConfig.Verbose {
|
||||
log.Debugf(log.GCTScriptMgr, "Read script: %s ID: %v", vm.ShortName(), vm.ID)
|
||||
}
|
||||
return ioutil.ReadFile(vm.File)
|
||||
}
|
||||
|
||||
// ShortName returns short (just filename.extension) of running script
|
||||
func (vm *VM) ShortName() string {
|
||||
return filepath.Base(vm.File)
|
||||
}
|
||||
|
||||
func (vm *VM) event(status, executionType string) {
|
||||
if validator.IsTestExecution.Load() == true {
|
||||
return
|
||||
}
|
||||
|
||||
var data null.Bytes
|
||||
if executionType == TypeLoad {
|
||||
scriptData, err := vm.scriptData()
|
||||
if err != nil {
|
||||
log.Errorf(log.GCTScriptMgr, "Failed to retrieve scriptData: %v", err)
|
||||
}
|
||||
data.SetValid(scriptData)
|
||||
}
|
||||
scriptevent.Event(vm.getHash(), vm.ShortName(), vm.Path, data, executionType, status, time.Now())
|
||||
}
|
||||
|
||||
func (vm *VM) scriptData() ([]byte, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
w := zip.NewWriter(buf)
|
||||
|
||||
f, err := w.Create(vm.ShortName())
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
contents, err := vm.read()
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
_, err = f.Write(contents)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
err = w.Close()
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func (vm *VM) getHash() string {
|
||||
if vm.Hash != "" {
|
||||
return vm.Hash
|
||||
}
|
||||
contents, err := vm.read()
|
||||
if err != nil {
|
||||
log.Errorln(log.GCTScriptMgr, err)
|
||||
}
|
||||
contents = append(contents, vm.ShortName()...)
|
||||
return hex.EncodeToString(crypto.GetSHA256(contents))
|
||||
}
|
||||
|
||||
func (vmc *vmscount) add() {
|
||||
atomic.AddInt32((*int32)(vmc), 1)
|
||||
}
|
||||
|
||||
func (vmc *vmscount) remove() {
|
||||
atomic.AddInt32((*int32)(vmc), -1)
|
||||
}
|
||||
|
||||
// Len() returns current length vmscount
|
||||
func (vmc *vmscount) Len() int32 {
|
||||
return atomic.LoadInt32((*int32)(vmc))
|
||||
}
|
||||
29
gctscript/vm/vm_error.go
Normal file
29
gctscript/vm/vm_error.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
const (
|
||||
// ErrNoVMFound error returned when no virtual machine is found
|
||||
ErrNoVMFound = "VM %v not found"
|
||||
)
|
||||
|
||||
func (e Error) Error() string {
|
||||
var scriptName, action string
|
||||
if e.Script != "" {
|
||||
scriptName = fmt.Sprintf("(SCRIPT) %s ", filepath.Base(e.Script))
|
||||
}
|
||||
|
||||
if e.Action != "" {
|
||||
action = fmt.Sprintf("(ACTION) %s ", e.Action)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s: %s%s%s", gctScript, action, scriptName, e.Cause)
|
||||
}
|
||||
|
||||
// Unwrap returns e.Cause meeting errors interface requirements.
|
||||
func (e Error) Unwrap() error {
|
||||
return e.Cause
|
||||
}
|
||||
30
gctscript/vm/vm_task.go
Normal file
30
gctscript/vm/vm_task.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
func (vm *VM) runner() {
|
||||
vm.S = make(chan struct{}, 1)
|
||||
waitTime := time.NewTicker(vm.T)
|
||||
vm.NextRun = time.Now().Add(vm.T)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-waitTime.C:
|
||||
vm.NextRun = time.Now().Add(vm.T)
|
||||
err := vm.RunCtx()
|
||||
if err != nil {
|
||||
log.Error(log.GCTScriptMgr, err)
|
||||
return
|
||||
}
|
||||
case <-vm.S:
|
||||
waitTime.Stop()
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
478
gctscript/vm/vm_test.go
Normal file
478
gctscript/vm/vm_test.go
Normal file
@@ -0,0 +1,478 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
"github.com/thrasher-corp/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
maxTestVirtualMachines uint8 = 30
|
||||
testVirtualMachineTimeout = time.Minute
|
||||
scriptName = "1D01TH0RS3.gct"
|
||||
)
|
||||
|
||||
var (
|
||||
testScript = filepath.Join("..", "..", "testdata", "gctscript", "once.gct")
|
||||
testInvalidScript = filepath.Join("..", "..", "testdata", "gctscript", "invalid.gct")
|
||||
testBrokenScript = filepath.Join("..", "..", "testdata", "gctscript", "broken.gct")
|
||||
testScriptRunner = filepath.Join("..", "..", "testdata", "gctscript", "timer.gct")
|
||||
testScriptRunner1s = filepath.Join("..", "..", "testdata", "gctscript", "1s_timer.gct")
|
||||
testScriptRunnerInvalid = filepath.Join("..", "..", "testdata", "gctscript", "invalid_timer.gct")
|
||||
testScriptRunnerNegative = filepath.Join("..", "..", "testdata", "gctscript", "negative_timer.gct")
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
c := logger.GenDefaultSettings()
|
||||
c.Enabled = convert.BoolPtr(false)
|
||||
logger.GlobalLogConfig = &c
|
||||
GCTScriptConfig = configHelper(true, true, maxTestVirtualMachines)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestNewVM(t *testing.T) {
|
||||
x := New()
|
||||
xType := reflect.TypeOf(x).String()
|
||||
if xType != "*vm.VM" {
|
||||
t.Fatalf("vm.New should return pointer to VM instead received: %v", x)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMLoad(t *testing.T) {
|
||||
GCTScriptConfig = configHelper(true, true, maxTestVirtualMachines)
|
||||
testVM := New()
|
||||
err := testVM.Load(testScript)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testScript = testScript[0 : len(testScript)-4]
|
||||
testVM = New()
|
||||
err = testVM.Load(testScript)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
GCTScriptConfig = configHelper(false, false, maxTestVirtualMachines)
|
||||
err = testVM.Load(testScript)
|
||||
if err != nil {
|
||||
if !errors.Is(err, ErrScriptingDisabled) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
GCTScriptConfig = configHelper(true, true, maxTestVirtualMachines)
|
||||
}
|
||||
|
||||
func TestVMLoad1s(t *testing.T) {
|
||||
testVM := New()
|
||||
err := testVM.Load(testScriptRunner1s)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testVM.CompileAndRun()
|
||||
time.Sleep(5000)
|
||||
err = testVM.Shutdown()
|
||||
if err != nil {
|
||||
if !errors.Is(err, ErrNoVMLoaded) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMLoadNegativeTimer(t *testing.T) {
|
||||
testVM := New()
|
||||
err := testVM.Load(testScriptRunnerNegative)
|
||||
if err != nil {
|
||||
if !errors.Is(err, ErrNoVMLoaded) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
testVM.CompileAndRun()
|
||||
err = testVM.Shutdown()
|
||||
if err == nil {
|
||||
t.Fatal("expect error on shutdown due to invalid VM")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMLoadNilVM(t *testing.T) {
|
||||
testVM := New()
|
||||
err := testVM.Load(testScript)
|
||||
if err != nil {
|
||||
if !errors.Is(err, ErrNoVMLoaded) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
testVM = nil
|
||||
err = testVM.Load(testScript)
|
||||
if err != nil {
|
||||
if !errors.Is(err, ErrNoVMLoaded) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompileAndRunNilVM(t *testing.T) {
|
||||
vmcount := VMSCount.Len()
|
||||
testVM := New()
|
||||
err := testVM.Load(testScript)
|
||||
if err != nil {
|
||||
if !errors.Is(err, ErrNoVMLoaded) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
err = testVM.Load(testScript)
|
||||
if err != nil {
|
||||
if !errors.Is(err, ErrNoVMLoaded) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
testVM = nil
|
||||
testVM.CompileAndRun()
|
||||
err = testVM.Shutdown()
|
||||
if err == nil {
|
||||
t.Fatal("VM should not be running with invalid timer")
|
||||
}
|
||||
if VMSCount.Len() == vmcount-1 {
|
||||
t.Fatal("expected VM count to decrease")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMLoadNoFile(t *testing.T) {
|
||||
testVM := New()
|
||||
err := testVM.Load("missing file")
|
||||
if err != nil {
|
||||
if !errors.Is(err, os.ErrNotExist) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMCompile(t *testing.T) {
|
||||
testVM := New()
|
||||
err := testVM.Load(testScript)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = testVM.Compile()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMRun(t *testing.T) {
|
||||
testVM := NewVM()
|
||||
err := testVM.Load(testScript)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = testVM.Compile()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = testVM.Run()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMRunTX(t *testing.T) {
|
||||
testVM := NewVM()
|
||||
err := testVM.Load(testScript)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = testVM.Compile()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = testVM.RunCtx()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMWithRunner(t *testing.T) {
|
||||
vmCount := VMSCount.Len()
|
||||
VM := New()
|
||||
if VM == nil {
|
||||
t.Fatal("Failed to allocate new VM exiting")
|
||||
}
|
||||
err := VM.Load(testScriptRunner)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if VMSCount.Len() == vmCount {
|
||||
t.Fatal("expected VM count to increase")
|
||||
}
|
||||
VM.CompileAndRun()
|
||||
err = VM.Shutdown()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if VMSCount.Len() == vmCount-1 {
|
||||
t.Fatal("expected VM count to decrease")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMWithRunnerOnce(t *testing.T) {
|
||||
vmCount := VMSCount.Len()
|
||||
VM := New()
|
||||
if VM == nil {
|
||||
t.Fatal("Failed to allocate new VM exiting")
|
||||
}
|
||||
err := VM.Load(testScript)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if VMSCount.Len() == vmCount {
|
||||
t.Fatal("expected VM count to increase")
|
||||
}
|
||||
VM.CompileAndRun()
|
||||
err = VM.Shutdown()
|
||||
if err == nil {
|
||||
t.Fatal("VM should not be running with invalid timer")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMWithRunnerNegativeTimer(t *testing.T) {
|
||||
vmCount := VMSCount.Len()
|
||||
VM := New()
|
||||
if VM == nil {
|
||||
t.Fatal("Failed to allocate new VM exiting")
|
||||
}
|
||||
err := VM.Load(testScriptRunnerNegative)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if VMSCount.Len() == vmCount {
|
||||
t.Fatal("expected VM count to increase")
|
||||
}
|
||||
VM.CompileAndRun()
|
||||
err = VM.Shutdown()
|
||||
if err == nil {
|
||||
t.Fatal("VM should not be running with invalid timer")
|
||||
}
|
||||
if VMSCount.Len() == vmCount-1 {
|
||||
t.Fatal("expected VM count to decrease")
|
||||
}
|
||||
}
|
||||
|
||||
func TestShutdownAll(t *testing.T) {
|
||||
vmCount := VMSCount.Len()
|
||||
VM := New()
|
||||
err := VM.Load(testScriptRunner)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
VM.CompileAndRun()
|
||||
|
||||
if VMSCount.Len() == vmCount {
|
||||
t.Fatal("expected VM count to increase")
|
||||
}
|
||||
err = ShutdownAll()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if VMSCount.Len() == vmCount-1 {
|
||||
t.Fatal("expected VM count to decrease")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRead(t *testing.T) {
|
||||
VM := NewVM()
|
||||
err := VM.Load(testScriptRunner)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ScriptPath = filepath.Join("..", "..", "testdata", "gctscript")
|
||||
data, err := VM.Read()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(data) < 1 {
|
||||
t.Fatal("expected data to be returned")
|
||||
}
|
||||
_ = VM.Shutdown()
|
||||
}
|
||||
|
||||
func TestRemoveVM(t *testing.T) {
|
||||
id, _ := uuid.FromString("6f20c907-64a0-48f2-848a-7837dee61672")
|
||||
err := RemoveVM(id)
|
||||
|
||||
if err != nil {
|
||||
if err.Error() != "VM 6f20c907-64a0-48f2-848a-7837dee61672 not found" {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestError_Error(t *testing.T) {
|
||||
x := Error{
|
||||
Script: "noscript.gct",
|
||||
Action: "test",
|
||||
Cause: errors.New("HELLO ERROR"),
|
||||
}
|
||||
|
||||
if x.Error() != "GCT Script: (ACTION) test (SCRIPT) noscript.gct HELLO ERROR" {
|
||||
t.Fatal(x.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestVM_CompileInvalid(t *testing.T) {
|
||||
testVM := New()
|
||||
err := testVM.Load(testInvalidScript)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = testVM.Compile()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = testVM.Run()
|
||||
if err == nil {
|
||||
t.Fatal("unexpected result broken script compiled successfully ")
|
||||
}
|
||||
|
||||
testVM = New()
|
||||
err = testVM.Load(testInvalidScript)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = testVM.Compile()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = testVM.RunCtx()
|
||||
if err == nil {
|
||||
t.Fatal("unexpected result broken script compiled successfully ")
|
||||
}
|
||||
|
||||
testVM = New()
|
||||
err = testVM.Load(testInvalidScript)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testVM.CompileAndRun()
|
||||
err = testVM.Shutdown()
|
||||
if err == nil {
|
||||
t.Fatal("Shutdown() passed successfully but expected to fail with invalid script")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVM_CompileBroken(t *testing.T) {
|
||||
testVM := New()
|
||||
err := testVM.Load(testBrokenScript)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = testVM.Compile()
|
||||
if err == nil {
|
||||
t.Fatal("unexpected result broken script compiled successfully ")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVM_CompileAndRunBroken(t *testing.T) {
|
||||
testVM := New()
|
||||
err := testVM.Load(testBrokenScript)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testVM.CompileAndRun()
|
||||
err = testVM.Shutdown()
|
||||
if err == nil {
|
||||
t.Fatal("expect error on shutdown due to invalid VM")
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidate(t *testing.T) {
|
||||
err := Validate(testBrokenScript)
|
||||
if err == nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = Validate(testScript)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMLimit(t *testing.T) {
|
||||
GCTScriptConfig = configHelper(true, false, 0)
|
||||
testVM := New()
|
||||
if testVM != nil {
|
||||
t.Fatal("expected nil but received pointer to VM")
|
||||
}
|
||||
GCTScriptConfig = configHelper(true, true, maxTestVirtualMachines)
|
||||
}
|
||||
|
||||
func TestAutoload(t *testing.T) {
|
||||
GCTScriptConfig = &Config{
|
||||
Enabled: true,
|
||||
AutoLoad: []string{
|
||||
scriptName,
|
||||
},
|
||||
Verbose: true,
|
||||
}
|
||||
|
||||
ScriptPath = filepath.Join("..", "..", "testdata", "gctscript")
|
||||
err := Autoload(scriptName, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = Autoload(scriptName, true)
|
||||
if err == nil {
|
||||
t.Fatal("expected err to be script not found received nil")
|
||||
}
|
||||
err = Autoload("once", false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = Autoload(scriptName, false)
|
||||
if err == nil {
|
||||
t.Fatal("expected err to be script not found received nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMCount(t *testing.T) {
|
||||
var c vmscount
|
||||
c.add()
|
||||
if c.Len() != 1 {
|
||||
t.Fatalf("expect c len to be 1 instead received %v", c.Len())
|
||||
}
|
||||
c.remove()
|
||||
if c.Len() != 0 {
|
||||
t.Fatalf("expect c len to be 0 instead received %v", c.Len())
|
||||
}
|
||||
}
|
||||
|
||||
func configHelper(enabled, imports bool, max uint8) *Config {
|
||||
return &Config{
|
||||
Enabled: enabled,
|
||||
AllowImports: imports,
|
||||
ScriptTimeout: testVirtualMachineTimeout,
|
||||
MaxVirtualMachines: max,
|
||||
Verbose: true,
|
||||
}
|
||||
}
|
||||
61
gctscript/vm/vm_types.go
Normal file
61
gctscript/vm/vm_types.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/d5/tengo/v2"
|
||||
"github.com/gofrs/uuid"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultTimeoutValue default timeout value for virtual machines
|
||||
DefaultTimeoutValue = 30 * time.Second
|
||||
// DefaultMaxVirtualMachines max number of virtual machines that can be loaded at one time
|
||||
DefaultMaxVirtualMachines uint8 = 10
|
||||
|
||||
// TypeLoad text to display in script_event table when a VM is loaded
|
||||
TypeLoad = "load"
|
||||
// TypeCreate text to display in script_event table when a VM is created
|
||||
TypeCreate = "create"
|
||||
// TypeExecute text to display in script_event table when a script is executed
|
||||
TypeExecute = "execute"
|
||||
// TypeStop text to display in script_event table when a running script is stopped
|
||||
TypeStop = "stop"
|
||||
// TypeRead text to display in script_event table when a script contents is read
|
||||
TypeRead = "read"
|
||||
|
||||
// StatusSuccess text to display in script_event table on successful execution
|
||||
StatusSuccess = "success"
|
||||
// StatusFailure text to display in script_event table when script execution fails
|
||||
StatusFailure = "failure"
|
||||
)
|
||||
|
||||
type vmscount int32
|
||||
|
||||
var (
|
||||
pool = &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new(tengo.Script)
|
||||
},
|
||||
}
|
||||
// AllVMSync stores all current Virtual Machine instances
|
||||
AllVMSync = &sync.Map{}
|
||||
// VMSCount running total count of Virtual Machines
|
||||
VMSCount vmscount
|
||||
)
|
||||
|
||||
// VM contains a pointer to "script" (precompiled source) and "compiled" (compiled byte code) instances
|
||||
type VM struct {
|
||||
ID uuid.UUID
|
||||
Hash string
|
||||
File string
|
||||
Path string
|
||||
Script *tengo.Script
|
||||
Compiled *tengo.Compiled
|
||||
ctx context.Context
|
||||
T time.Duration
|
||||
NextRun time.Time
|
||||
S chan struct{}
|
||||
}
|
||||
216
gctscript/wrappers/gct/exchange/exchange.go
Normal file
216
gctscript/wrappers/gct/exchange/exchange.go
Normal file
@@ -0,0 +1,216 @@
|
||||
package exchange
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/engine"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/withdraw"
|
||||
"github.com/thrasher-corp/gocryptotrader/gctscript/modules"
|
||||
)
|
||||
|
||||
// Exchange implements all required methods for Wrapper
|
||||
type Exchange struct{}
|
||||
|
||||
// Exchanges returns slice of all current exchanges
|
||||
func (e Exchange) Exchanges(enabledOnly bool) []string {
|
||||
return engine.GetExchanges(enabledOnly)
|
||||
}
|
||||
|
||||
// GetExchange returns IBotExchange for exchange or error if exchange is not found
|
||||
func (e Exchange) GetExchange(exch string) (exchange.IBotExchange, error) {
|
||||
ex := engine.GetExchangeByName(exch)
|
||||
if ex == nil {
|
||||
return nil, fmt.Errorf("%v exchange not found", exch)
|
||||
}
|
||||
|
||||
return ex, nil
|
||||
}
|
||||
|
||||
// IsEnabled returns if requested exchange is enabled or disabled
|
||||
func (e Exchange) IsEnabled(exch string) bool {
|
||||
ex, err := e.GetExchange(exch)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return ex.IsEnabled()
|
||||
}
|
||||
|
||||
// Orderbook returns current orderbook requested exchange, pair and asset
|
||||
func (e Exchange) Orderbook(exch string, pair currency.Pair, item asset.Item) (*orderbook.Base, error) {
|
||||
return engine.GetSpecificOrderbook(pair, exch, item)
|
||||
}
|
||||
|
||||
// Ticker returns ticker for provided currency pair & asset type
|
||||
func (e Exchange) Ticker(exch string, pair currency.Pair, item asset.Item) (*ticker.Price, error) {
|
||||
ex, err := e.GetExchange(exch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ex.FetchTicker(pair, item)
|
||||
}
|
||||
|
||||
// Pairs returns either all or enabled currency pairs
|
||||
func (e Exchange) Pairs(exch string, enabledOnly bool, item asset.Item) (*currency.Pairs, error) {
|
||||
x, err := engine.Bot.Config.GetExchangeConfig(exch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if enabledOnly {
|
||||
return &x.CurrencyPairs.Get(item).Enabled, nil
|
||||
}
|
||||
return &x.CurrencyPairs.Get(item).Available, nil
|
||||
}
|
||||
|
||||
// QueryOrder returns details of a valid exchange order
|
||||
func (e Exchange) QueryOrder(exch, orderID string) (*order.Detail, error) {
|
||||
ex, err := e.GetExchange(exch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r, err := ex.GetOrderInfo(orderID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &r, nil
|
||||
}
|
||||
|
||||
// SubmitOrder submit new order on exchange
|
||||
func (e Exchange) SubmitOrder(exch string, submit *order.Submit) (*order.SubmitResponse, error) {
|
||||
r, err := engine.Bot.OrderManager.Submit(exch, submit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &r.SubmitResponse, nil
|
||||
}
|
||||
|
||||
// CancelOrder wrapper to cancel order on exchange
|
||||
func (e Exchange) CancelOrder(exch, orderID string) (bool, error) {
|
||||
orderDetails, err := e.QueryOrder(exch, orderID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
cancel := &order.Cancel{
|
||||
AccountID: orderDetails.AccountID,
|
||||
OrderID: orderDetails.ID,
|
||||
CurrencyPair: orderDetails.CurrencyPair,
|
||||
Side: orderDetails.OrderSide,
|
||||
}
|
||||
|
||||
err = engine.Bot.OrderManager.Cancel(exch, cancel)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// AccountInformation returns account information (balance etc) for requested exchange
|
||||
func (e Exchange) AccountInformation(exch string) (*modules.AccountInfo, error) {
|
||||
ex, err := e.GetExchange(exch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r, err := ex.GetAccountInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
temp, err := json.Marshal(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
accountInfo := modules.AccountInfo{}
|
||||
err = json.Unmarshal(temp, &accountInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &accountInfo, nil
|
||||
}
|
||||
|
||||
// DepositAddress gets the address required to deposit funds for currency type
|
||||
func (e Exchange) DepositAddress(exch string, currencyCode currency.Code) (out string, err error) {
|
||||
if currencyCode.IsEmpty() {
|
||||
err = errors.New("currency code is empty")
|
||||
return
|
||||
}
|
||||
return engine.Bot.DepositAddressManager.GetDepositAddressByExchange(exch, currencyCode)
|
||||
}
|
||||
|
||||
// WithdrawalFiatFunds withdraw funds from exchange to requested fiat source
|
||||
func (e Exchange) WithdrawalFiatFunds(exch, bankaccountid string, request *withdraw.FiatRequest) (string, error) {
|
||||
ex, err := e.GetExchange(exch)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
v, err := engine.Bot.Config.GetBankAccountByID(bankaccountid)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
otp, err := engine.GetExchangeoOTPByName(exch)
|
||||
if err == nil {
|
||||
otpValue, errParse := strconv.ParseInt(otp, 10, 64)
|
||||
if errParse != nil {
|
||||
return "", errors.New("failed to generate OTP unable to continue")
|
||||
}
|
||||
request.GenericInfo.OneTimePassword = otpValue
|
||||
}
|
||||
request.BankAccountName = v.AccountName
|
||||
request.BankAccountNumber = v.AccountNumber
|
||||
request.BankName = v.BankName
|
||||
request.BankAddress = v.BankAddress
|
||||
request.BankCity = v.BankPostalCity
|
||||
request.BankCountry = v.BankCountry
|
||||
request.BankPostalCode = v.BankPostalCode
|
||||
request.BSB = v.BSBNumber
|
||||
request.SwiftCode = v.SWIFTCode
|
||||
request.IBAN = v.IBAN
|
||||
|
||||
err = withdraw.Valid(request)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return ex.WithdrawFiatFunds(request)
|
||||
}
|
||||
|
||||
// WithdrawalCryptoFunds withdraw funds from exchange to requested Crypto source
|
||||
func (e Exchange) WithdrawalCryptoFunds(exch string, request *withdraw.CryptoRequest) (out string, err error) {
|
||||
ex, err := e.GetExchange(exch)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
otp, err := engine.GetExchangeoOTPByName(exch)
|
||||
if err == nil {
|
||||
v, errParse := strconv.ParseInt(otp, 10, 64)
|
||||
if errParse != nil {
|
||||
return "", errors.New("failed to generate OTP unable to continue")
|
||||
}
|
||||
request.GenericInfo.OneTimePassword = v
|
||||
}
|
||||
|
||||
err = withdraw.Valid(request)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return ex.WithdrawCryptocurrencyFunds(request)
|
||||
}
|
||||
190
gctscript/wrappers/gct/exchange/exchange_test.go
Normal file
190
gctscript/wrappers/gct/exchange/exchange_test.go
Normal file
@@ -0,0 +1,190 @@
|
||||
package exchange
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/engine"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
)
|
||||
|
||||
// change these if you wish to test another exchange and/or currency pair
|
||||
const (
|
||||
exchName = "BTC Markets" // change to test on another exchange
|
||||
exchAPIKEY = ""
|
||||
exchAPISECRET = ""
|
||||
exchClientID = ""
|
||||
pairs = "BTC-AUD" // change to test another currency pair
|
||||
delimiter = "-"
|
||||
assetType = asset.Spot
|
||||
orderID = "1234"
|
||||
orderType = order.Limit
|
||||
orderSide = order.Buy
|
||||
orderClientID = ""
|
||||
orderPrice = 1
|
||||
orderAmount = 1
|
||||
)
|
||||
|
||||
var (
|
||||
settings = engine.Settings{
|
||||
ConfigFile: filepath.Join("..", "..", "..", "..", "testdata", "configtest.json"),
|
||||
EnableDryRun: true,
|
||||
DataDir: filepath.Join("..", "..", "..", "..", "testdata", "gocryptotrader"),
|
||||
Verbose: false,
|
||||
EnableGRPC: false,
|
||||
EnableDeprecatedRPC: false,
|
||||
EnableWebsocketRPC: false,
|
||||
}
|
||||
exchangeTest = Exchange{}
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var t int
|
||||
err := setupEngine()
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to configure exchange test cannot continue: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
t = m.Run()
|
||||
cleanup()
|
||||
os.Exit(t)
|
||||
}
|
||||
|
||||
func TestExchange_Exchanges(t *testing.T) {
|
||||
t.Parallel()
|
||||
x := exchangeTest.Exchanges(false)
|
||||
y := len(x)
|
||||
if y != 27 {
|
||||
t.Fatalf("expected 27 received %v", y)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExchange_GetExchange(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := exchangeTest.GetExchange(exchName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = exchangeTest.GetExchange("hello world")
|
||||
if err == nil {
|
||||
t.Fatal("unexpected error message received nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestExchange_IsEnabled(t *testing.T) {
|
||||
t.Parallel()
|
||||
x := exchangeTest.IsEnabled(exchName)
|
||||
if !x {
|
||||
t.Fatal("expected return to be true")
|
||||
}
|
||||
x = exchangeTest.IsEnabled("fake_exchange")
|
||||
if x {
|
||||
t.Fatal("expected return to be false")
|
||||
}
|
||||
}
|
||||
|
||||
func TestExchange_Ticker(t *testing.T) {
|
||||
t.Parallel()
|
||||
c := currency.NewPairDelimiter(pairs, delimiter)
|
||||
_, err := exchangeTest.Ticker(exchName, c, assetType)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExchange_Orderbook(t *testing.T) {
|
||||
t.Parallel()
|
||||
c := currency.NewPairDelimiter(pairs, delimiter)
|
||||
_, err := exchangeTest.Orderbook(exchName, c, assetType)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExchange_Pairs(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := exchangeTest.Pairs(exchName, false, assetType)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = exchangeTest.Pairs(exchName, true, assetType)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExchange_AccountInformation(t *testing.T) {
|
||||
if !configureExchangeKeys() {
|
||||
t.Skip("no exchange configured test skipped")
|
||||
}
|
||||
_, err := exchangeTest.AccountInformation(exchName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExchange_QueryOrder(t *testing.T) {
|
||||
if !configureExchangeKeys() {
|
||||
t.Skip("no exchange configured test skipped")
|
||||
}
|
||||
_, err := exchangeTest.QueryOrder(exchName, orderID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExchange_SubmitOrder(t *testing.T) {
|
||||
if !configureExchangeKeys() {
|
||||
t.Skip("no exchange configured test skipped")
|
||||
}
|
||||
tempOrder := &order.Submit{
|
||||
Pair: currency.NewPairDelimiter(pairs, delimiter),
|
||||
OrderType: orderType,
|
||||
OrderSide: orderSide,
|
||||
TriggerPrice: 0,
|
||||
TargetAmount: 0,
|
||||
Price: orderPrice,
|
||||
Amount: orderAmount,
|
||||
ClientID: orderClientID,
|
||||
}
|
||||
_, err := exchangeTest.SubmitOrder(exchName, tempOrder)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExchange_CancelOrder(t *testing.T) {
|
||||
if !configureExchangeKeys() {
|
||||
t.Skip("no exchange configured test skipped")
|
||||
}
|
||||
_, err := exchangeTest.CancelOrder(exchName, orderID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func setupEngine() (err error) {
|
||||
engine.Bot, err = engine.NewFromSettings(&settings)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return engine.Bot.Start()
|
||||
}
|
||||
|
||||
func cleanup() {
|
||||
err := os.RemoveAll(settings.DataDir)
|
||||
if err != nil {
|
||||
fmt.Printf("Clean up failed to remove file: %v manual removal may be required", err)
|
||||
}
|
||||
}
|
||||
|
||||
func configureExchangeKeys() bool {
|
||||
ex := engine.GetExchangeByName(exchName).GetBase()
|
||||
ex.SetAPIKeys(exchAPIKEY, exchAPISECRET, exchClientID)
|
||||
ex.SkipAuthCheck = true
|
||||
return ex.ValidateAPICredentials()
|
||||
}
|
||||
10
gctscript/wrappers/gct/gctwrapper.go
Normal file
10
gctscript/wrappers/gct/gctwrapper.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package gct
|
||||
|
||||
import "github.com/thrasher-corp/gocryptotrader/gctscript/wrappers/gct/exchange"
|
||||
|
||||
// Setup returns a Wrapper
|
||||
func Setup() *Wrapper {
|
||||
return &Wrapper{
|
||||
&exchange.Exchange{},
|
||||
}
|
||||
}
|
||||
14
gctscript/wrappers/gct/gctwrapper_test.go
Normal file
14
gctscript/wrappers/gct/gctwrapper_test.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package gct
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
x := Setup()
|
||||
xType := reflect.TypeOf(x).String()
|
||||
if xType != "*gct.Wrapper" {
|
||||
t.Fatalf("Setup() should return pointer to Wrapper instead received: %v", x)
|
||||
}
|
||||
}
|
||||
8
gctscript/wrappers/gct/gctwrapper_type.go
Normal file
8
gctscript/wrappers/gct/gctwrapper_type.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package gct
|
||||
|
||||
import "github.com/thrasher-corp/gocryptotrader/gctscript/wrappers/gct/exchange"
|
||||
|
||||
// Wrapper struct
|
||||
type Wrapper struct {
|
||||
*exchange.Exchange
|
||||
}
|
||||
211
gctscript/wrappers/validator/validator.go
Normal file
211
gctscript/wrappers/validator/validator.go
Normal file
@@ -0,0 +1,211 @@
|
||||
package validator
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/withdraw"
|
||||
"github.com/thrasher-corp/gocryptotrader/gctscript/modules"
|
||||
)
|
||||
|
||||
// Exchanges validator for test execution/scripts
|
||||
func (w Wrapper) Exchanges(enabledOnly bool) []string {
|
||||
if enabledOnly {
|
||||
return []string{
|
||||
"hello world",
|
||||
}
|
||||
}
|
||||
return []string{
|
||||
"nope",
|
||||
}
|
||||
}
|
||||
|
||||
// IsEnabled returns if requested exchange is enabled or disabled
|
||||
func (w Wrapper) IsEnabled(exch string) (v bool) {
|
||||
if exch == exchError.String() {
|
||||
return
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Orderbook validator for test execution/scripts
|
||||
func (w Wrapper) Orderbook(exch string, pair currency.Pair, item asset.Item) (*orderbook.Base, error) {
|
||||
if exch == exchError.String() {
|
||||
return nil, errTestFailed
|
||||
}
|
||||
|
||||
return &orderbook.Base{
|
||||
ExchangeName: exch,
|
||||
AssetType: item,
|
||||
Pair: pair,
|
||||
Bids: []orderbook.Item{
|
||||
{
|
||||
Amount: 1,
|
||||
Price: 1,
|
||||
},
|
||||
},
|
||||
Asks: []orderbook.Item{
|
||||
{
|
||||
Amount: 1,
|
||||
Price: 1,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Ticker validator for test execution/scripts
|
||||
func (w Wrapper) Ticker(exch string, pair currency.Pair, item asset.Item) (*ticker.Price, error) {
|
||||
if exch == exchError.String() {
|
||||
return nil, errTestFailed
|
||||
}
|
||||
return &ticker.Price{
|
||||
Last: 1,
|
||||
High: 2,
|
||||
Low: 3,
|
||||
Bid: 4,
|
||||
Ask: 5,
|
||||
Volume: 6,
|
||||
QuoteVolume: 7,
|
||||
PriceATH: 8,
|
||||
Open: 9,
|
||||
Close: 10,
|
||||
Pair: pair,
|
||||
ExchangeName: exch,
|
||||
AssetType: item,
|
||||
LastUpdated: time.Now(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Pairs validator for test execution/scripts
|
||||
func (w Wrapper) Pairs(exch string, _ bool, _ asset.Item) (*currency.Pairs, error) {
|
||||
if exch == exchError.String() {
|
||||
return nil, errTestFailed
|
||||
}
|
||||
|
||||
pairs := currency.NewPairsFromStrings([]string{"btc_usd", "btc_aud", "btc_ltc"})
|
||||
return &pairs, nil
|
||||
}
|
||||
|
||||
// QueryOrder validator for test execution/scripts
|
||||
func (w Wrapper) QueryOrder(exch, _ string) (*order.Detail, error) {
|
||||
if exch == exchError.String() {
|
||||
return nil, errTestFailed
|
||||
}
|
||||
return &order.Detail{
|
||||
Exchange: exch,
|
||||
AccountID: "hello",
|
||||
ID: "1",
|
||||
CurrencyPair: currency.NewPairFromString("BTCAUD"),
|
||||
OrderSide: "ask",
|
||||
OrderType: "limit",
|
||||
OrderDate: time.Now(),
|
||||
Status: "cancelled",
|
||||
Price: 1,
|
||||
Amount: 2,
|
||||
ExecutedAmount: 1,
|
||||
RemainingAmount: 0,
|
||||
Fee: 0,
|
||||
Trades: []order.TradeHistory{
|
||||
{
|
||||
Timestamp: time.Now(),
|
||||
TID: "",
|
||||
Price: 1,
|
||||
Amount: 2,
|
||||
Exchange: exch,
|
||||
Type: "limit",
|
||||
Side: "ask",
|
||||
Fee: 0,
|
||||
Description: "",
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SubmitOrder validator for test execution/scripts
|
||||
func (w Wrapper) SubmitOrder(exch string, _ *order.Submit) (*order.SubmitResponse, error) {
|
||||
if exch == exchError.String() {
|
||||
return nil, errTestFailed
|
||||
}
|
||||
|
||||
tempOrder := &order.SubmitResponse{
|
||||
IsOrderPlaced: false,
|
||||
OrderID: exch,
|
||||
}
|
||||
|
||||
if exch == "true" {
|
||||
tempOrder.IsOrderPlaced = true
|
||||
}
|
||||
|
||||
return tempOrder, nil
|
||||
}
|
||||
|
||||
// CancelOrder validator for test execution/scripts
|
||||
func (w Wrapper) CancelOrder(exch, orderid string) (bool, error) {
|
||||
if exch == exchError.String() {
|
||||
return false, errTestFailed
|
||||
}
|
||||
return orderid != "false", nil
|
||||
}
|
||||
|
||||
// AccountInformation validator for test execution/scripts
|
||||
func (w Wrapper) AccountInformation(exch string) (*modules.AccountInfo, error) {
|
||||
if exch == exchError.String() {
|
||||
return &modules.AccountInfo{}, errTestFailed
|
||||
}
|
||||
|
||||
return &modules.AccountInfo{
|
||||
Exchange: exch,
|
||||
Accounts: []modules.Account{
|
||||
{
|
||||
ID: exch,
|
||||
Currencies: []modules.AccountCurrencyInfo{
|
||||
{
|
||||
CurrencyName: currency.Code{
|
||||
Item: ¤cy.Item{
|
||||
ID: 0,
|
||||
FullName: "Bitcoin",
|
||||
Symbol: "BTC",
|
||||
Role: 1,
|
||||
AssocChain: "",
|
||||
AssocExchange: nil,
|
||||
},
|
||||
},
|
||||
TotalValue: 100,
|
||||
Hold: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DepositAddress validator for test execution/scripts
|
||||
func (w Wrapper) DepositAddress(exch string, _ currency.Code) (string, error) {
|
||||
if exch == exchError.String() {
|
||||
return exch, errTestFailed
|
||||
}
|
||||
|
||||
return exch, nil
|
||||
}
|
||||
|
||||
// WithdrawalCryptoFunds validator for test execution/scripts
|
||||
func (w Wrapper) WithdrawalCryptoFunds(exch string, _ *withdraw.CryptoRequest) (out string, err error) {
|
||||
if exch == exchError.String() {
|
||||
return exch, errTestFailed
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// WithdrawalFiatFunds validator for test execution/scripts
|
||||
func (w Wrapper) WithdrawalFiatFunds(exch, _ string, _ *withdraw.FiatRequest) (out string, err error) {
|
||||
if exch == exchError.String() {
|
||||
return exch, errTestFailed
|
||||
}
|
||||
|
||||
return "123", nil
|
||||
}
|
||||
205
gctscript/wrappers/validator/validator_test.go
Normal file
205
gctscript/wrappers/validator/validator_test.go
Normal file
@@ -0,0 +1,205 @@
|
||||
package validator
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
)
|
||||
|
||||
const (
|
||||
exchName = "BTC Markets" // change to test on another exchange
|
||||
exchAPIKEY = ""
|
||||
exchAPISECRET = ""
|
||||
exchClientID = ""
|
||||
pairs = "BTC-AUD" // change to test another currency pair
|
||||
delimiter = "-"
|
||||
assetType = asset.Spot
|
||||
orderID = "1234"
|
||||
orderType = order.Limit
|
||||
orderSide = order.Buy
|
||||
orderClientID = ""
|
||||
orderPrice = 1
|
||||
orderAmount = 1
|
||||
)
|
||||
|
||||
var (
|
||||
currencyPair = currency.NewPairFromString("BTCAUD")
|
||||
testWrapper = Wrapper{}
|
||||
)
|
||||
|
||||
func TestWrapper_Exchanges(t *testing.T) {
|
||||
t.Parallel()
|
||||
x := testWrapper.Exchanges(false)
|
||||
y := len(x)
|
||||
if y != 1 {
|
||||
t.Fatalf("expected 1 received %v", y)
|
||||
}
|
||||
|
||||
x = testWrapper.Exchanges(true)
|
||||
y = len(x)
|
||||
if y != 1 {
|
||||
t.Fatalf("expected 1 received %v", y)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrapper_IsEnabled(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := testWrapper.IsEnabled("hello")
|
||||
if !f {
|
||||
t.Fatal("expected IsEnabled to return true for enabled exchange")
|
||||
}
|
||||
|
||||
f = testWrapper.IsEnabled(exchError.String())
|
||||
if f {
|
||||
t.Fatal("expected IsEnabled to return false for disabled exchange")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrapper_AccountInformation(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := testWrapper.AccountInformation(exchName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = testWrapper.AccountInformation(exchError.String())
|
||||
if err == nil {
|
||||
t.Fatal("expected AccountInformation to return error on invalid name")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrapper_CancelOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := testWrapper.CancelOrder(exchName, orderID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = testWrapper.CancelOrder(exchError.String(), "")
|
||||
if err == nil {
|
||||
t.Fatal("expected CancelOrder to return error on invalid name")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrapper_DepositAddress(t *testing.T) {
|
||||
_, err := testWrapper.DepositAddress(exchError.String(), currency.NewCode("BTC"))
|
||||
if err == nil {
|
||||
t.Fatal("expected DepositAddress to return error on invalid name")
|
||||
}
|
||||
|
||||
_, err = testWrapper.DepositAddress(exchName, currency.NewCode("BTC"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrapper_Orderbook(t *testing.T) {
|
||||
t.Parallel()
|
||||
c := currency.NewPairDelimiter(pairs, delimiter)
|
||||
_, err := testWrapper.Orderbook(exchName, c, assetType)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = testWrapper.Orderbook(exchError.String(), currencyPair, asset.Spot)
|
||||
if err == nil {
|
||||
t.Fatal("expected Orderbook to return error with invalid name")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrapper_Pairs(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := testWrapper.Pairs(exchName, false, assetType)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = testWrapper.Pairs(exchName, true, assetType)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = testWrapper.Pairs(exchError.String(), false, asset.Spot)
|
||||
if err == nil {
|
||||
t.Fatal("expected Pairs to return error on invalid name")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrapper_QueryOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := testWrapper.QueryOrder(exchName, orderID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = testWrapper.QueryOrder(exchError.String(), "")
|
||||
if err == nil {
|
||||
t.Fatal("expected QueryOrder to return error on invalid name")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrapper_SubmitOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tempOrder := &order.Submit{
|
||||
Pair: currency.NewPairDelimiter(pairs, delimiter),
|
||||
OrderType: orderType,
|
||||
OrderSide: orderSide,
|
||||
TriggerPrice: 0,
|
||||
TargetAmount: 0,
|
||||
Price: orderPrice,
|
||||
Amount: orderAmount,
|
||||
ClientID: orderClientID,
|
||||
}
|
||||
_, err := testWrapper.SubmitOrder("true", tempOrder)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = testWrapper.SubmitOrder(exchError.String(), nil)
|
||||
if err == nil {
|
||||
t.Fatal("expected SubmitOrder to return error with invalid name")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrapper_Ticker(t *testing.T) {
|
||||
t.Parallel()
|
||||
c := currency.NewPairDelimiter(pairs, delimiter)
|
||||
_, err := testWrapper.Ticker(exchName, c, assetType)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = testWrapper.Ticker(exchError.String(), currencyPair, asset.Spot)
|
||||
if err == nil {
|
||||
t.Fatal("expected Ticker to return error with invalid name")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrapper_WithdrawalCryptoFunds(t *testing.T) {
|
||||
_, err := testWrapper.WithdrawalCryptoFunds(exchError.String(), nil)
|
||||
if err == nil {
|
||||
t.Fatal("expected WithdrawalCryptoFunds to return error with invalid name")
|
||||
}
|
||||
|
||||
_, err = testWrapper.WithdrawalCryptoFunds(exchName, nil)
|
||||
if err != nil {
|
||||
t.Fatal("expected WithdrawalCryptoFunds to return error with invalid name")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrapper_WithdrawalFiatFunds(t *testing.T) {
|
||||
_, err := testWrapper.WithdrawalFiatFunds(exchError.String(), "", nil)
|
||||
if err == nil {
|
||||
t.Fatal("expected WithdrawalFiatFunds to return error with invalid name")
|
||||
}
|
||||
|
||||
_, err = testWrapper.WithdrawalFiatFunds(exchName, "", nil)
|
||||
if err != nil {
|
||||
t.Fatal("expected WithdrawalCryptoFunds to return error with invalid name")
|
||||
}
|
||||
}
|
||||
21
gctscript/wrappers/validator/validator_types.go
Normal file
21
gctscript/wrappers/validator/validator_types.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package validator
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sync/atomic"
|
||||
|
||||
objects "github.com/d5/tengo/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
// IsTestExecution if test is executed under test conditions
|
||||
IsTestExecution atomic.Value
|
||||
|
||||
exchError = &objects.String{
|
||||
Value: "error",
|
||||
}
|
||||
errTestFailed = errors.New("test failed")
|
||||
)
|
||||
|
||||
// Wrapper for validator interface
|
||||
type Wrapper struct{}
|
||||
14
gctscript/wrappers/wrappers.go
Normal file
14
gctscript/wrappers/wrappers.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package wrappers
|
||||
|
||||
import (
|
||||
"github.com/thrasher-corp/gocryptotrader/gctscript/modules"
|
||||
"github.com/thrasher-corp/gocryptotrader/gctscript/wrappers/validator"
|
||||
)
|
||||
|
||||
// GetWrapper returns the instance of each wrapper to use
|
||||
func GetWrapper() modules.GCT {
|
||||
if validator.IsTestExecution.Load() == true {
|
||||
return validator.Wrapper{}
|
||||
}
|
||||
return modules.Wrapper
|
||||
}
|
||||
2
go.mod
2
go.mod
@@ -3,6 +3,7 @@ module github.com/thrasher-corp/gocryptotrader
|
||||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/d5/tengo/v2 v2.0.2
|
||||
github.com/gofrs/uuid v3.2.0+incompatible
|
||||
github.com/golang/protobuf v1.3.2
|
||||
github.com/google/go-querystring v1.0.0
|
||||
@@ -20,6 +21,7 @@ require (
|
||||
github.com/thrasher-corp/sqlboiler v1.0.1-0.20191001234224-71e17f37a85e
|
||||
github.com/toorop/go-pusher v0.0.0-20180521062818-4521e2eb39fb
|
||||
github.com/urfave/cli v1.20.0
|
||||
github.com/volatiletech/null v8.0.0+incompatible
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5
|
||||
golang.org/x/net v0.0.0-20190606173856-1492cefac77f // indirect
|
||||
golang.org/x/sys v0.0.0-20191003212358-c178f38b412c // indirect
|
||||
|
||||
2
go.sum
2
go.sum
@@ -25,6 +25,8 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/d5/tengo/v2 v2.0.2 h1:3APkPZPc1FExaJoWrN5YzvDqc6GNkQH6ehmCRDmN83I=
|
||||
github.com/d5/tengo/v2 v2.0.2/go.mod h1:XRGjEs5I9jYIKTxly6HCF8oiiilk5E/RYXOZ5b0DZC8=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
)
|
||||
|
||||
func getWriters(s *SubLoggerConfig) io.Writer {
|
||||
@@ -32,23 +34,20 @@ func getWriters(s *SubLoggerConfig) io.Writer {
|
||||
|
||||
// GenDefaultSettings return struct with known sane/working logger settings
|
||||
func GenDefaultSettings() (log Config) {
|
||||
t := func(t bool) *bool { return &t }(true)
|
||||
f := func(f bool) *bool { return &f }(false)
|
||||
|
||||
log = Config{
|
||||
Enabled: t,
|
||||
Enabled: convert.BoolPtr(true),
|
||||
SubLoggerConfig: SubLoggerConfig{
|
||||
Level: "INFO|DEBUG|WARN|ERROR",
|
||||
Output: "console",
|
||||
},
|
||||
LoggerFileConfig: &loggerFileConfig{
|
||||
FileName: "log.txt",
|
||||
Rotate: f,
|
||||
Rotate: convert.BoolPtr(false),
|
||||
MaxSize: 0,
|
||||
},
|
||||
AdvancedSettings: advancedSettings{
|
||||
ShowLogSystemName: f,
|
||||
Spacer: " | ",
|
||||
ShowLogSystemName: convert.BoolPtr(false),
|
||||
Spacer: spacer,
|
||||
TimeStampFormat: timestampFormat,
|
||||
Headers: headers{
|
||||
Info: "[INFO]",
|
||||
@@ -145,6 +144,7 @@ func init() {
|
||||
PortfolioMgr = registerNewSubLogger("PORTFOLIO")
|
||||
SyncMgr = registerNewSubLogger("SYNC")
|
||||
TimeMgr = registerNewSubLogger("TIMEKEEPER")
|
||||
GCTScriptMgr = registerNewSubLogger("GCTSCRIPT")
|
||||
WebsocketMgr = registerNewSubLogger("WEBSOCKET")
|
||||
EventMgr = registerNewSubLogger("EVENT")
|
||||
DispatchMgr = registerNewSubLogger("DISPATCH")
|
||||
|
||||
@@ -7,6 +7,9 @@ import (
|
||||
|
||||
const (
|
||||
timestampFormat = " 02/01/2006 15:04:05 "
|
||||
spacer = " | "
|
||||
// DefaultMaxFileSize for logger rotation file
|
||||
DefaultMaxFileSize int64 = 100
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
// Info takes a pointer subLogger struct and string sends to newLogEvent
|
||||
func Info(sl *subLogger, data string) {
|
||||
if sl == nil {
|
||||
if sl == nil || !enabled() {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ func Info(sl *subLogger, data string) {
|
||||
|
||||
// Infoln takes a pointer subLogger struct and interface sends to newLogEvent
|
||||
func Infoln(sl *subLogger, v ...interface{}) {
|
||||
if sl == nil {
|
||||
if sl == nil || !enabled() {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ func Infoln(sl *subLogger, v ...interface{}) {
|
||||
|
||||
// Infof takes a pointer subLogger struct, string & interface formats and sends to Info()
|
||||
func Infof(sl *subLogger, data string, v ...interface{}) {
|
||||
if sl == nil {
|
||||
if sl == nil || !enabled() {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ func Infof(sl *subLogger, data string, v ...interface{}) {
|
||||
|
||||
// Debug takes a pointer subLogger struct and string sends to multiwriter
|
||||
func Debug(sl *subLogger, data string) {
|
||||
if sl == nil {
|
||||
if sl == nil || !enabled() {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ func Debug(sl *subLogger, data string) {
|
||||
|
||||
// Debugln takes a pointer subLogger struct, string and interface sends to newLogEvent
|
||||
func Debugln(sl *subLogger, v ...interface{}) {
|
||||
if sl == nil {
|
||||
if sl == nil || !enabled() {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ func Debugln(sl *subLogger, v ...interface{}) {
|
||||
|
||||
// Debugf takes a pointer subLogger struct, string & interface formats and sends to Info()
|
||||
func Debugf(sl *subLogger, data string, v ...interface{}) {
|
||||
if sl == nil {
|
||||
if sl == nil || !enabled() {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ func Debugf(sl *subLogger, data string, v ...interface{}) {
|
||||
|
||||
// Warn takes a pointer subLogger struct & string and sends to newLogEvent()
|
||||
func Warn(sl *subLogger, data string) {
|
||||
if sl == nil {
|
||||
if sl == nil || !enabled() {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ func Warn(sl *subLogger, data string) {
|
||||
|
||||
// Warnln takes a pointer subLogger struct & interface formats and sends to newLogEvent()
|
||||
func Warnln(sl *subLogger, v ...interface{}) {
|
||||
if sl == nil {
|
||||
if sl == nil || !enabled() {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ func Warnln(sl *subLogger, v ...interface{}) {
|
||||
|
||||
// Warnf takes a pointer subLogger struct, string & interface formats and sends to Warn()
|
||||
func Warnf(sl *subLogger, data string, v ...interface{}) {
|
||||
if sl == nil {
|
||||
if sl == nil || !enabled() {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ func Warnf(sl *subLogger, data string, v ...interface{}) {
|
||||
|
||||
// Error takes a pointer subLogger struct & interface formats and sends to newLogEvent()
|
||||
func Error(sl *subLogger, data ...interface{}) {
|
||||
if sl == nil {
|
||||
if sl == nil || !enabled() {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ func Error(sl *subLogger, data ...interface{}) {
|
||||
|
||||
// Errorln takes a pointer subLogger struct, string & interface formats and sends to newLogEvent()
|
||||
func Errorln(sl *subLogger, v ...interface{}) {
|
||||
if sl == nil {
|
||||
if sl == nil || !enabled() {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ func Errorln(sl *subLogger, v ...interface{}) {
|
||||
|
||||
// Errorf takes a pointer subLogger struct, string & interface formats and sends to Debug()
|
||||
func Errorf(sl *subLogger, data string, v ...interface{}) {
|
||||
if sl == nil {
|
||||
if sl == nil || !enabled() {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -166,3 +166,10 @@ func displayError(err error) {
|
||||
log.Printf("Logger write error: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func enabled() bool {
|
||||
if GlobalLogConfig.Enabled == nil {
|
||||
return false
|
||||
}
|
||||
return *GlobalLogConfig.Enabled
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ var (
|
||||
CommunicationMgr *subLogger
|
||||
ConfigMgr *subLogger
|
||||
DatabaseMgr *subLogger
|
||||
GCTScriptMgr *subLogger
|
||||
OrderMgr *subLogger
|
||||
PortfolioMgr *subLogger
|
||||
SyncMgr *subLogger
|
||||
|
||||
8
main.go
8
main.go
@@ -13,6 +13,8 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/dispatch"
|
||||
"github.com/thrasher-corp/gocryptotrader/engine"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/gctscript"
|
||||
gctscriptVM "github.com/thrasher-corp/gocryptotrader/gctscript/vm"
|
||||
log "github.com/thrasher-corp/gocryptotrader/logger"
|
||||
"github.com/thrasher-corp/gocryptotrader/signaler"
|
||||
)
|
||||
@@ -44,6 +46,7 @@ func main() {
|
||||
flag.BoolVar(&settings.EnableDepositAddressManager, "depositaddressmanager", true, "enables the deposit address manager")
|
||||
flag.BoolVar(&settings.EnableConnectivityMonitor, "connectivitymonitor", true, "enables the connectivity monitor")
|
||||
flag.BoolVar(&settings.EnableDatabaseManager, "databasemanager", true, "enables database manager")
|
||||
flag.BoolVar(&settings.EnableGCTScriptManager, "gctscriptmanager", true, "enables gctscript manager")
|
||||
flag.DurationVar(&settings.EventManagerDelay, "eventmanagerdelay", time.Duration(0), "sets the event managers sleep delay between event checking")
|
||||
flag.BoolVar(&settings.EnableNTPClient, "ntpclient", true, "enables the NTP client to check system clock drift")
|
||||
flag.BoolVar(&settings.EnableDispatcher, "dispatch", true, "enables the dispatch system")
|
||||
@@ -85,6 +88,9 @@ func main() {
|
||||
flag.StringVar(&settings.GlobalHTTPUserAgent, "globalhttpuseragent", "", "sets the common HTTP client's user agent")
|
||||
flag.StringVar(&settings.GlobalHTTPProxy, "globalhttpproxy", "", "sets the common HTTP client's proxy server")
|
||||
|
||||
// GCTScript tuning settings
|
||||
flag.UintVar(&settings.MaxVirtualMachines, "maxvirtualmachines", uint(gctscriptVM.DefaultMaxVirtualMachines), "set max virtual machines that can load")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
if *versionFlag {
|
||||
@@ -103,6 +109,8 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
gctscript.Setup()
|
||||
|
||||
engine.PrintSettings(&engine.Bot.Settings)
|
||||
if err = engine.Bot.Start(); err != nil {
|
||||
log.Errorf(log.Global, "Unable to start bot engine. Error: %s\n", err)
|
||||
|
||||
@@ -18,7 +18,7 @@ func TestNTPClient(t *testing.T) {
|
||||
t.Error("NTPClient should return valid time received zero value")
|
||||
}
|
||||
|
||||
const timeFormat = "2006-01-02T15:04:05"
|
||||
const timeFormat = "2006-01-02T15:04"
|
||||
|
||||
if v.UTC().Format(timeFormat) != time.Now().UTC().Format(timeFormat) {
|
||||
t.Errorf("NTPClient returned incorrect time received: %v", v.UTC().Format(timeFormat))
|
||||
|
||||
11
testdata/gctscript/1s_timer.gct
vendored
Normal file
11
testdata/gctscript/1s_timer.gct
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
fmt := import("fmt")
|
||||
t := import("times")
|
||||
|
||||
name := "run"
|
||||
timer := "1ns"
|
||||
|
||||
load := func() {
|
||||
fmt.printf("1ns %s\n",t.now())
|
||||
}
|
||||
|
||||
load()
|
||||
BIN
testdata/gctscript/archived.zip
vendored
Normal file
BIN
testdata/gctscript/archived.zip
vendored
Normal file
Binary file not shown.
1
testdata/gctscript/broken.gct
vendored
Normal file
1
testdata/gctscript/broken.gct
vendored
Normal file
@@ -0,0 +1 @@
|
||||
hello
|
||||
BIN
testdata/gctscript/broken.zip
vendored
Normal file
BIN
testdata/gctscript/broken.zip
vendored
Normal file
Binary file not shown.
3
testdata/gctscript/invalid.gct
vendored
Normal file
3
testdata/gctscript/invalid.gct
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
fmt := import("fmt")
|
||||
|
||||
fmt.printnope("hello world")
|
||||
3
testdata/gctscript/invalid_timer.gct
vendored
Normal file
3
testdata/gctscript/invalid_timer.gct
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
fmt := import("fmt")
|
||||
timer := "abc1234"
|
||||
fmt.print("hello")
|
||||
11
testdata/gctscript/negative_timer.gct
vendored
Normal file
11
testdata/gctscript/negative_timer.gct
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
fmt := import("fmt")
|
||||
t := import("times")
|
||||
|
||||
name := "run"
|
||||
timer := "-5s"
|
||||
|
||||
load := func() {
|
||||
fmt.printf("5s %s\n",t.now())
|
||||
}
|
||||
|
||||
load()
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user