Skip to content

Commit

Permalink
corrected some asset data source behavior and added unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Emyrk committed Aug 8, 2019
1 parent 573c8cc commit a2e9a89
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 16 deletions.
4 changes: 2 additions & 2 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,10 +236,10 @@ var datasources = &cobra.Command{
} else if common.AssetListContainsCaseInsensitive(polling.AllDataSourcesList(), args[0]) {
// Specified an exchange
source := polling.CorrectCasing(args[0])
if source == "" {
s, ok := polling.AllDataSources[source]
if !ok {
CmdErrorf(cmd, "%s is not a supported datasource", args[0])
}
s := polling.AllDataSources[source]

fmt.Printf("Datasource : %s\n", s.Name())
fmt.Printf("Datasource URL : %s\n", s.Url())
Expand Down
6 changes: 3 additions & 3 deletions common/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ func NewUnitTestConfig() *config.Config {
// This way we don't have to deal with pathing to find the
// `defaultconfig.ini`.
type UnitTestConfigProvider struct {
data string
Data string
}

func NewUnitTestConfigProvider() *UnitTestConfigProvider {
d := new(UnitTestConfigProvider)
d.data = `
d.Data = `
[Debug]
# Randomize adds a random factor +/- the give percent. 3.1 for 3.1%
Randomize=0.1
Expand Down Expand Up @@ -88,7 +88,7 @@ func NewUnitTestConfigProvider() *UnitTestConfigProvider {
func (this *UnitTestConfigProvider) Load() (map[string]string, error) {
settings := map[string]string{}

file, err := ini.Load([]byte(this.data))
file, err := ini.Load([]byte(this.Data))
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion common/monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ type Monitor struct {
errors []chan error
}

// MonitorEvent is the data sent to all listeners when being notified
// MonitorEvent is the Data sent to all listeners when being notified
type MonitorEvent struct {
Minute int64 `json:"minute"`
Dbht int32 `json:"dbht"`
Expand Down
28 changes: 20 additions & 8 deletions polling/assets.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,27 +44,36 @@ func CorrectCasing(in string) string {
return v
}
}
return ""

// For unit testing support
r, _ := regexp.Compile("UnitTest[0-9]*")
if r.Match([]byte(in)) {
return "UnitTest"
}

return in
}

func NewDataSource(source string, config *config.Config) (IDataSource, error) {
var ds IDataSource
var err error

// Make it case insensitive.
switch strings.ToLower(source) {
case strings.ToLower("APILayer"):
switch CorrectCasing(source) {
case "APILayer":
ds, err = NewAPILayerDataSource(config)
case strings.ToLower("CoinCap"):
case "CoinCap":
ds, err = NewCoinCapDataSource(config)
case strings.ToLower("ExchangeRates"):
case "ExchangeRates":
ds, err = NewExchangeRatesDataSource(config)
case strings.ToLower("Kitco"):
case "Kitco":
ds, err = NewKitcoDataSource(config)
case strings.ToLower("OpenExchangeRates"):
case "OpenExchangeRates":
ds, err = NewOpenExchangeRatesDataSource(config)
case strings.ToLower("CoinMarketCap"):
case "CoinMarketCap":
ds, err = NewCoinMarketCapDataSource(config)
case "UnitTest":
ds, err = NewTestingDataSource(config, source)
default:
return nil, fmt.Errorf("%s is not a supported data source", source)
}
Expand Down Expand Up @@ -236,6 +245,9 @@ func (d *DataSources) PullAllPEGAssets() (pa PegAssets, err error) {
if err != nil {
continue // Try the next source
}
if price.Value != 0 {
break
}
}

if err != nil { // This will only be the last err in the data source list.
Expand Down
119 changes: 117 additions & 2 deletions polling/assets_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,124 @@
package polling_test

import (
"fmt"
"strconv"
"testing"
"time"

"github.com/pegnet/pegnet/common"
. "github.com/pegnet/pegnet/polling"
"github.com/zpatrick/go-config"
)

func TestPolling(t *testing.T) {
//polling.NewDataSources()
// TestBasicPollingSources creates 8 polling sources. 5 have 1 asset, 3 have all.
// We then check to make sure the 5 sources are higher priority then the second 3.
// The second two have a priority order as well, and will be listed in the prioriy list
// for every asset.
func TestBasicPollingSources(t *testing.T) {
end := 6
// Create the unit test creator
NewTestingDataSource = func(config *config.Config, source string) (IDataSource, error) {
s := new(UnitTestDataSource)
v, err := strconv.Atoi(string(source[8]))
if err != nil {
panic(err)
}
s.value = float64(v)
s.assets = []string{common.AllAssets[v]}
s.name = fmt.Sprintf("UnitTest%d", v)

// Catch all
if v >= end {
s.assets = common.AllAssets[1:]
}
return s, nil
}

p := common.NewUnitTestConfigProvider()
// The order of these retrieved is random since the settings are a map
p.Data = `
[OracleDataSources]
UnitTest1=1
UnitTest2=2
UnitTest3=3
UnitTest4=4
UnitTest5=5
UnitTest6=6
UnitTest7=7
UnitTest8=8
`

config := config.NewConfig([]config.Provider{p})

s := NewDataSources(config)

pa, err := s.PullAllPEGAssets()
if err != nil {
t.Error(err)
}
for i, asset := range common.AllAssets {
v, ok := pa[asset]
if !ok {
t.Errorf("%s is missing", asset)
continue
}
if i < end {
if int(v.Value) != i {
t.Errorf("Exp value %d, found %d for %s", i, int(v.Value), asset)
}

// Let's also check there is 4 sources
if len(s.AssetSources[asset]) != 4 && asset != "PNT" {
t.Errorf("exp %d sources for %s, found %d", 4, asset, len(s.AssetSources[asset]))
}
} else {
if int(v.Value) != end {
t.Errorf("Exp value %d, found %d for %s", end, int(v.Value), asset)
}
// Let's also check there is 3 sources
if len(s.AssetSources[asset]) != 3 {
t.Errorf("exp %d sources for %s, found %d", 3, asset, len(s.AssetSources[asset]))
}
}
}
}

// UnitTestDataSource just reports the value for the supported assets
type UnitTestDataSource struct {
value float64
assets []string
name string
}

func NewUnitTestDataSource(config *config.Config) (*UnitTestDataSource, error) {
s := new(UnitTestDataSource)
return s, nil
}

func (d *UnitTestDataSource) Name() string {
return d.name
}

func (d *UnitTestDataSource) Url() string {
return "https://unit.test/"
}

func (d *UnitTestDataSource) SupportedPegs() []string {
return d.assets
}

func (d *UnitTestDataSource) FetchPegPrices() (peg PegAssets, err error) {
peg = make(map[string]PegItem)

timestamp := time.Now()
for _, asset := range d.SupportedPegs() {
peg[asset] = PegItem{Value: d.value, When: timestamp, WhenUnix: timestamp.Unix()}
}

return peg, nil
}

func (d *UnitTestDataSource) FetchPegPrice(peg string) (i PegItem, err error) {
return FetchPegPrice(peg, d.FetchPegPrices)
}
13 changes: 13 additions & 0 deletions polling/testing.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package polling

import (
"fmt"

"github.com/zpatrick/go-config"
)

// NewTestingDataSource is for unit test.
// Having a testing data source is for unit test mocking
var NewTestingDataSource = func(config *config.Config, source string) (IDataSource, error) {
return nil, fmt.Errorf("this is a testing datasource for unit tests only")
}

0 comments on commit a2e9a89

Please sign in to comment.