mirror of
https://github.com/retailcrm/mg-transport-core.git
synced 2025-02-16 21:03:13 +03:00
All retailCRM currencies support (#16)
* all currencies supported in retailCRM" * function which allows to pick currency symbol without interacting with map * tweak for new function test * check for undefined currency code * increase timeout for failing test * refactored test to WaitGroup, which resulted in finding and fixing actual data race in the job object
This commit is contained in:
parent
1de2e5626f
commit
ac9e7e768e
@ -8,7 +8,7 @@ go:
|
|||||||
before_install:
|
before_install:
|
||||||
- go mod tidy
|
- go mod tidy
|
||||||
script:
|
script:
|
||||||
- go test ./... -v -cpu 2 -timeout 2m -race -cover -coverprofile=coverage.txt -covermode=atomic
|
- go test ./... -v -cpu 2 -timeout 10s -race -cover -coverprofile=coverage.txt -covermode=atomic
|
||||||
- go get -v -u github.com/axw/gocov/gocov
|
- go get -v -u github.com/axw/gocov/gocov
|
||||||
- gocov convert ./coverage.txt | gocov report
|
- gocov convert ./coverage.txt | gocov report
|
||||||
after_success:
|
after_success:
|
||||||
|
@ -27,6 +27,7 @@ type Job struct {
|
|||||||
ErrorHandler JobErrorHandler
|
ErrorHandler JobErrorHandler
|
||||||
PanicHandler JobPanicHandler
|
PanicHandler JobPanicHandler
|
||||||
Interval time.Duration
|
Interval time.Duration
|
||||||
|
writeLock sync.RWMutex
|
||||||
Regular bool
|
Regular bool
|
||||||
active bool
|
active bool
|
||||||
stopChannel chan bool
|
stopChannel chan bool
|
||||||
@ -86,10 +87,18 @@ func (j *Job) getWrappedTimerFunc(name string, log JobLogFunc) func(chan bool) {
|
|||||||
|
|
||||||
// run job
|
// run job
|
||||||
func (j *Job) run(name string, log JobLogFunc) *Job {
|
func (j *Job) run(name string, log JobLogFunc) *Job {
|
||||||
|
j.writeLock.RLock()
|
||||||
|
|
||||||
if j.Regular && j.Interval > 0 && !j.active {
|
if j.Regular && j.Interval > 0 && !j.active {
|
||||||
|
j.writeLock.RUnlock()
|
||||||
|
defer j.writeLock.Unlock()
|
||||||
|
j.writeLock.Lock()
|
||||||
|
|
||||||
j.stopChannel = make(chan bool)
|
j.stopChannel = make(chan bool)
|
||||||
go j.getWrappedTimerFunc(name, log)(j.stopChannel)
|
go j.getWrappedTimerFunc(name, log)(j.stopChannel)
|
||||||
j.active = true
|
j.active = true
|
||||||
|
} else {
|
||||||
|
j.writeLock.RUnlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
return j
|
return j
|
||||||
@ -97,11 +106,18 @@ func (j *Job) run(name string, log JobLogFunc) *Job {
|
|||||||
|
|
||||||
// stop running job
|
// stop running job
|
||||||
func (j *Job) stop() *Job {
|
func (j *Job) stop() *Job {
|
||||||
|
j.writeLock.RLock()
|
||||||
|
|
||||||
if j.active && j.stopChannel != nil {
|
if j.active && j.stopChannel != nil {
|
||||||
|
j.writeLock.RUnlock()
|
||||||
go func() {
|
go func() {
|
||||||
|
defer j.writeLock.Unlock()
|
||||||
|
j.writeLock.Lock()
|
||||||
j.stopChannel <- true
|
j.stopChannel <- true
|
||||||
j.active = false
|
j.active = false
|
||||||
}()
|
}()
|
||||||
|
} else {
|
||||||
|
j.writeLock.RUnlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
return j
|
return j
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -28,7 +29,7 @@ type JobTest struct {
|
|||||||
type JobManagerTest struct {
|
type JobManagerTest struct {
|
||||||
suite.Suite
|
suite.Suite
|
||||||
manager *JobManager
|
manager *JobManager
|
||||||
runnerFlag chan bool
|
runnerWG sync.WaitGroup
|
||||||
syncRunnerFlag bool
|
syncRunnerFlag bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,15 +309,17 @@ func (t *JobManagerTest) SetupSuite() {
|
|||||||
t.manager = NewJobManager()
|
t.manager = NewJobManager()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *JobManagerTest) ranFlag() bool {
|
func (t *JobManagerTest) WaitForJob() bool {
|
||||||
if t.runnerFlag == nil {
|
c := make(chan bool)
|
||||||
return false
|
go func() {
|
||||||
}
|
t.runnerWG.Wait()
|
||||||
|
c <- true
|
||||||
|
}()
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case c := <-t.runnerFlag:
|
case <-c:
|
||||||
return c
|
return true
|
||||||
case <-time.After(time.Millisecond):
|
case <-time.After(time.Second):
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -349,7 +352,7 @@ func (t *JobManagerTest) Test_RegisterJob() {
|
|||||||
require.NotNil(t.T(), t.manager.jobs)
|
require.NotNil(t.T(), t.manager.jobs)
|
||||||
err := t.manager.RegisterJob("job", &Job{
|
err := t.manager.RegisterJob("job", &Job{
|
||||||
Command: func(log JobLogFunc) error {
|
Command: func(log JobLogFunc) error {
|
||||||
t.runnerFlag <- true
|
t.runnerWG.Done()
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
ErrorHandler: DefaultJobErrorHandler(),
|
ErrorHandler: DefaultJobErrorHandler(),
|
||||||
@ -358,7 +361,7 @@ func (t *JobManagerTest) Test_RegisterJob() {
|
|||||||
assert.NoError(t.T(), err)
|
assert.NoError(t.T(), err)
|
||||||
err = t.manager.RegisterJob("job_regular", &Job{
|
err = t.manager.RegisterJob("job_regular", &Job{
|
||||||
Command: func(log JobLogFunc) error {
|
Command: func(log JobLogFunc) error {
|
||||||
t.runnerFlag <- true
|
t.runnerWG.Done()
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
ErrorHandler: DefaultJobErrorHandler(),
|
ErrorHandler: DefaultJobErrorHandler(),
|
||||||
@ -431,15 +434,17 @@ func (t *JobManagerTest) Test_RunJobDoesntExist() {
|
|||||||
assert.EqualError(t.T(), err, "cannot find job `doesn't exist`")
|
assert.EqualError(t.T(), err, "cannot find job `doesn't exist`")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *JobManagerTest) Test_RunJob() {
|
func (t *JobManagerTest) Test_RunJob_RunJobOnce() {
|
||||||
require.NotNil(t.T(), t.manager.jobs)
|
require.NotNil(t.T(), t.manager.jobs)
|
||||||
t.runnerFlag = make(chan bool)
|
err := t.manager.StopJob("job_regular")
|
||||||
err := t.manager.RunJob("job_regular")
|
|
||||||
require.NoError(t.T(), err)
|
require.NoError(t.T(), err)
|
||||||
time.Sleep(time.Millisecond * 5)
|
t.runnerWG.Add(1)
|
||||||
assert.True(t.T(), <-t.runnerFlag)
|
err = t.manager.RunJobOnce("job_regular")
|
||||||
|
require.NoError(t.T(), err)
|
||||||
|
time.Sleep(time.Millisecond)
|
||||||
err = t.manager.StopJob("job_regular")
|
err = t.manager.StopJob("job_regular")
|
||||||
require.NoError(t.T(), err)
|
require.NoError(t.T(), err)
|
||||||
|
assert.True(t.T(), t.WaitForJob(), "Job was not executed in time")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *JobManagerTest) Test_RunJobOnceDoesntExist() {
|
func (t *JobManagerTest) Test_RunJobOnceDoesntExist() {
|
||||||
@ -448,15 +453,6 @@ func (t *JobManagerTest) Test_RunJobOnceDoesntExist() {
|
|||||||
assert.EqualError(t.T(), err, "cannot find job `doesn't exist`")
|
assert.EqualError(t.T(), err, "cannot find job `doesn't exist`")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *JobManagerTest) Test_RunJobOnce() {
|
|
||||||
require.NotNil(t.T(), t.manager.jobs)
|
|
||||||
go func() { t.runnerFlag <- false }()
|
|
||||||
err := t.manager.RunJobOnce("job")
|
|
||||||
time.Sleep(300 * time.Millisecond)
|
|
||||||
require.NoError(t.T(), err)
|
|
||||||
assert.True(t.T(), t.ranFlag())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *JobManagerTest) Test_RunJobOnceSyncDoesntExist() {
|
func (t *JobManagerTest) Test_RunJobOnceSyncDoesntExist() {
|
||||||
require.NotNil(t.T(), t.manager.jobs)
|
require.NotNil(t.T(), t.manager.jobs)
|
||||||
err := t.manager.RunJobOnceSync("doesn't exist")
|
err := t.manager.RunJobOnceSync("doesn't exist")
|
||||||
|
@ -21,6 +21,58 @@ import (
|
|||||||
v1 "github.com/retailcrm/mg-transport-api-client-go/v1"
|
v1 "github.com/retailcrm/mg-transport-api-client-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var defaultCurrencies = map[string]string{
|
||||||
|
"rub": "₽",
|
||||||
|
"uah": "₴",
|
||||||
|
"byn": "Br",
|
||||||
|
"kzt": "₸",
|
||||||
|
"usd": "$",
|
||||||
|
"eur": "€",
|
||||||
|
"prb": "PRB",
|
||||||
|
"mdl": "L",
|
||||||
|
"kgs": "с",
|
||||||
|
"pln": "zł",
|
||||||
|
"azn": "₼",
|
||||||
|
"amd": "֏",
|
||||||
|
"thb": "฿",
|
||||||
|
"aed": "AED",
|
||||||
|
"nok": "kr",
|
||||||
|
"cad": "C$",
|
||||||
|
"czk": "Kč",
|
||||||
|
"sek": "kr",
|
||||||
|
"dkk": "kr",
|
||||||
|
"ron": "lei",
|
||||||
|
"uzs": "So'm",
|
||||||
|
"aud": "$",
|
||||||
|
"chf": "₣",
|
||||||
|
"inr": "₹",
|
||||||
|
"bgn": "лв",
|
||||||
|
"ngn": "₦",
|
||||||
|
"huf": "ƒ",
|
||||||
|
"ils": "₪",
|
||||||
|
"try": "₺",
|
||||||
|
"stn": "₡",
|
||||||
|
"ars": "$",
|
||||||
|
"bob": "Bs",
|
||||||
|
"ves": "Bs",
|
||||||
|
"gtq": "Q",
|
||||||
|
"hnl": "L",
|
||||||
|
"dop": "RD$",
|
||||||
|
"cop": "COL$",
|
||||||
|
"crc": "₡",
|
||||||
|
"cup": "$MN",
|
||||||
|
"mxn": "NP$",
|
||||||
|
"nio": "C$",
|
||||||
|
"pab": "B/",
|
||||||
|
"pyg": "₲",
|
||||||
|
"pen": "S/",
|
||||||
|
"svc": "₡",
|
||||||
|
"uyu": "$U",
|
||||||
|
"clp": "Ch$",
|
||||||
|
"gel": "₾",
|
||||||
|
"gbp": "£",
|
||||||
|
}
|
||||||
|
|
||||||
// Utils service object
|
// Utils service object
|
||||||
type Utils struct {
|
type Utils struct {
|
||||||
IsDebug bool
|
IsDebug bool
|
||||||
@ -201,12 +253,15 @@ func ReplaceMarkdownSymbols(s string) string {
|
|||||||
|
|
||||||
// DefaultCurrencies will return default currencies list for all bots
|
// DefaultCurrencies will return default currencies list for all bots
|
||||||
func DefaultCurrencies() map[string]string {
|
func DefaultCurrencies() map[string]string {
|
||||||
return map[string]string{
|
return defaultCurrencies
|
||||||
"rub": "₽",
|
}
|
||||||
"uah": "₴",
|
|
||||||
"byr": "Br",
|
// GetCurrencySymbol returns currency symbol by it's ISO 4127 code.
|
||||||
"kzt": "₸",
|
// It returns provided currency code in uppercase if currency symbol cannot be found
|
||||||
"usd": "$",
|
func GetCurrencySymbol(code string) string {
|
||||||
"eur": "€",
|
if i, ok := DefaultCurrencies()[strings.ToLower(code)]; ok {
|
||||||
}
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.ToUpper(code)
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package core
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -241,6 +242,18 @@ func TestUtils_GetEntitySHA1(t *testing.T) {
|
|||||||
assert.Equal(t, "751b56fb98c9fd803140e8287b4236675554a668", hash)
|
assert.Equal(t, "751b56fb98c9fd803140e8287b4236675554a668", hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUtils_GetCurrencySymbol(t *testing.T) {
|
||||||
|
for code, _ := range DefaultCurrencies() {
|
||||||
|
if strings.ToUpper(code) == defaultCurrencies[code] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.NotEqual(t, strings.ToUpper(code), GetCurrencySymbol(code))
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, "XAG", GetCurrencySymbol("xag"))
|
||||||
|
}
|
||||||
|
|
||||||
func TestUtils_ReplaceMarkdownSymbols(t *testing.T) {
|
func TestUtils_ReplaceMarkdownSymbols(t *testing.T) {
|
||||||
test := "this *is* _test_ `string` [markdown"
|
test := "this *is* _test_ `string` [markdown"
|
||||||
expected := "this \\*is\\* \\_test\\_ \\`string\\` \\[markdown"
|
expected := "this \\*is\\* \\_test\\_ \\`string\\` \\[markdown"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user