init
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
//go:build docker
|
||||
// +build docker
|
||||
|
||||
package feature
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDBDrivers(t *testing.T) {
|
||||
connections := []string{"postgres", "mysql", "sqlserver"}
|
||||
|
||||
for _, connection := range connections {
|
||||
database, err := facades.Testing().Docker().Database(connection)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := database.Build(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := database.Ready(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
facades.Config().Add("database.default", connection)
|
||||
facades.Config().Add("database.connections."+connection+".port", database.Config().Port)
|
||||
|
||||
facades.App().Refresh()
|
||||
|
||||
facades.Config().Add("database.default", "sqlite")
|
||||
facades.App().Refresh()
|
||||
|
||||
assert.NoError(t, database.Shutdown())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package feature
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/goravel/framework/contracts/event"
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"goravel/app/events"
|
||||
)
|
||||
|
||||
func TestEvent(t *testing.T) {
|
||||
// 测试事件调度是否成功
|
||||
err1 := facades.Event().Job(&events.OrderShipped{}, []event.Arg{
|
||||
{Type: "string", Value: "I'm OrderShipped"},
|
||||
}).Dispatch()
|
||||
assert.NoError(t, err1)
|
||||
|
||||
err2 := facades.Event().Job(&events.OrderCanceled{}, []event.Arg{
|
||||
{Type: "string", Value: "I'm OrderCanceled"},
|
||||
}).Dispatch()
|
||||
assert.NoError(t, err2)
|
||||
|
||||
// 等待队列处理
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
// 注意:由于移除了全局测试变量,这里只验证事件调度是否成功
|
||||
// 如果需要验证监听器执行结果,可以通过日志或其他方式验证
|
||||
t.Log("Events dispatched successfully")
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package feature
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"goravel/tests"
|
||||
)
|
||||
|
||||
type ExampleTestSuite struct {
|
||||
suite.Suite
|
||||
tests.TestCase
|
||||
}
|
||||
|
||||
func TestExampleTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(ExampleTestSuite))
|
||||
}
|
||||
|
||||
// SetupTest will run before each test in the suite.
|
||||
func (s *ExampleTestSuite) SetupTest() {
|
||||
}
|
||||
|
||||
// TearDownTest will run after each test in the suite.
|
||||
func (s *ExampleTestSuite) TearDownTest() {
|
||||
}
|
||||
|
||||
func (s *ExampleTestSuite) TestIndex() {
|
||||
s.True(true)
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
package feature
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"goravel/tests"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/goravel/framework/contracts/filesystem"
|
||||
contractsdocker "github.com/goravel/framework/contracts/testing/docker"
|
||||
"github.com/goravel/framework/facades"
|
||||
supportdocker "github.com/goravel/framework/support/docker"
|
||||
testingdocker "github.com/goravel/framework/testing/docker"
|
||||
"github.com/minio/minio-go/v7"
|
||||
"github.com/minio/minio-go/v7/pkg/credentials"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type FilesystemTestSuite struct {
|
||||
suite.Suite
|
||||
tests.TestCase
|
||||
minioDocker contractsdocker.ImageDriver
|
||||
drivers []string
|
||||
}
|
||||
|
||||
func TestFilesystemTestSuite(t *testing.T) {
|
||||
suite.Run(t, &FilesystemTestSuite{})
|
||||
}
|
||||
|
||||
func (s *FilesystemTestSuite) SetupSuite() {
|
||||
s.drivers = []string{
|
||||
"",
|
||||
"local",
|
||||
"public",
|
||||
}
|
||||
|
||||
if os.Getenv("AWS_ACCESS_KEY_ID") != "" {
|
||||
s.drivers = append(s.drivers, "s3")
|
||||
}
|
||||
if os.Getenv("ALIYUN_ACCESS_KEY_ID") != "" {
|
||||
s.drivers = append(s.drivers, "oss")
|
||||
}
|
||||
if os.Getenv("TENCENT_ACCESS_KEY_ID") != "" {
|
||||
s.drivers = append(s.drivers, "cos")
|
||||
}
|
||||
if os.Getenv("MINIO_ACCESS_KEY_ID") != "" {
|
||||
s.drivers = append(s.drivers, "minio")
|
||||
s.minioDocker = initMinio()
|
||||
}
|
||||
|
||||
fmt.Printf("testing filesystem drivers: %v\n", s.drivers)
|
||||
}
|
||||
|
||||
func (s *FilesystemTestSuite) SetupTest() {
|
||||
}
|
||||
|
||||
func (s *FilesystemTestSuite) TearDownSuite() {
|
||||
if s.minioDocker != nil {
|
||||
s.NoError(s.minioDocker.Shutdown())
|
||||
}
|
||||
}
|
||||
|
||||
func (s *FilesystemTestSuite) TestPutAndGet() {
|
||||
for _, driver := range s.drivers {
|
||||
var storage filesystem.Driver
|
||||
if driver == "" {
|
||||
storage = facades.Storage()
|
||||
} else {
|
||||
storage = facades.Storage().Disk(driver)
|
||||
}
|
||||
|
||||
s.NoError(storage.Put("test.txt", "test"))
|
||||
content, err := storage.Get("test.txt")
|
||||
|
||||
s.NoError(err)
|
||||
s.Equal("test", content)
|
||||
|
||||
s.NoError(storage.Delete("test.txt"))
|
||||
}
|
||||
}
|
||||
|
||||
func initMinio() contractsdocker.ImageDriver {
|
||||
minioAccessKey := os.Getenv("MINIO_ACCESS_KEY_ID")
|
||||
minioSecretKey := os.Getenv("MINIO_ACCESS_KEY_SECRET")
|
||||
minioBucket := os.Getenv("MINIO_BUCKET")
|
||||
|
||||
docker := testingdocker.NewImageDriver(contractsdocker.Image{
|
||||
Repository: "minio/minio",
|
||||
Tag: "latest",
|
||||
Cmd: []string{"server", "/data"},
|
||||
Env: []string{
|
||||
"MINIO_ACCESS_KEY=" + minioAccessKey,
|
||||
"MINIO_SECRET_KEY=" + minioSecretKey,
|
||||
},
|
||||
ExposedPorts: []string{
|
||||
"9000",
|
||||
},
|
||||
})
|
||||
err := docker.Build()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
config := docker.Config()
|
||||
endpoint := fmt.Sprintf("127.0.0.1:%s", supportdocker.ExposedPort(config.ExposedPorts, "9000"))
|
||||
facades.Config().Add("filesystems.disks.minio.endpoint", endpoint)
|
||||
facades.Config().Add("filesystems.disks.minio.url", fmt.Sprintf("http://%s/%s", endpoint, minioBucket))
|
||||
|
||||
if err := docker.Ready(func() error {
|
||||
client, err := minio.New(endpoint, &minio.Options{
|
||||
Creds: credentials.NewStaticV4(minioAccessKey, minioSecretKey, ""),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := client.MakeBucket(context.Background(), minioBucket, minio.MakeBucketOptions{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
policy := `{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Action": [
|
||||
"s3:GetObject",
|
||||
"s3:PutObject"
|
||||
],
|
||||
"Effect": "Allow",
|
||||
"Principal": "*",
|
||||
"Resource": [
|
||||
"arn:aws:s3:::` + minioBucket + `/*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Action": [
|
||||
"s3:ListBucket"
|
||||
],
|
||||
"Effect": "Allow",
|
||||
"Principal": "*",
|
||||
"Resource": [
|
||||
"arn:aws:s3:::` + minioBucket + `"
|
||||
]
|
||||
}
|
||||
]
|
||||
}`
|
||||
|
||||
if err := client.SetBucketPolicy(context.Background(), minioBucket, policy); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return docker
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
package feature
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
contractshttp "github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/support/http"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"goravel/tests"
|
||||
)
|
||||
|
||||
type HttpTestSuite struct {
|
||||
suite.Suite
|
||||
tests.TestCase
|
||||
}
|
||||
|
||||
func TestHttpTestSuite(t *testing.T) {
|
||||
suite.Run(t, &HttpTestSuite{})
|
||||
}
|
||||
|
||||
func (s *HttpTestSuite) SetupSuite() {
|
||||
}
|
||||
|
||||
// SetupTest will run before each test in the suite.
|
||||
func (s *HttpTestSuite) SetupTest() {
|
||||
s.RefreshDatabase()
|
||||
}
|
||||
|
||||
// TearDownTest will run after each test in the suite.
|
||||
func (s *HttpTestSuite) TearDownTest() {
|
||||
}
|
||||
|
||||
func (s *HttpTestSuite) TestBindQuery() {
|
||||
resp, err := s.Http(s.T()).Get("/bind-query?name=Goravel")
|
||||
|
||||
s.Require().NoError(err)
|
||||
resp.AssertSuccessful()
|
||||
|
||||
content, err := resp.Content()
|
||||
s.Require().NoError(err)
|
||||
s.Equal("{\"name\":\"Goravel\"}", content)
|
||||
}
|
||||
|
||||
func (s *HttpTestSuite) TestFallback() {
|
||||
resp, err := s.Http(s.T()).Get("/lang")
|
||||
s.Require().NoError(err)
|
||||
resp.AssertSuccessful()
|
||||
|
||||
resp, err = s.Http(s.T()).Get("/not-found")
|
||||
s.Require().NoError(err)
|
||||
resp.AssertNotFound()
|
||||
|
||||
content, err := resp.Content()
|
||||
s.Require().NoError(err)
|
||||
s.Equal("fallback", content)
|
||||
}
|
||||
|
||||
func (s *HttpTestSuite) TestFiles() {
|
||||
body, err := http.NewBody().SetFiles(map[string][]string{
|
||||
"files": []string{"lang/cn.json", "lang/en.json"},
|
||||
}).Build()
|
||||
s.Require().NoError(err)
|
||||
|
||||
resp, err := s.Http(s.T()).WithHeader("Content-Type", body.ContentType()).Post("/files", body.Reader())
|
||||
s.Require().NoError(err)
|
||||
resp.AssertSuccessful()
|
||||
|
||||
content, err := resp.Content()
|
||||
s.Require().NoError(err)
|
||||
s.Equal("{\"files\":[\"cn.json\",\"en.json\"]}", content)
|
||||
}
|
||||
|
||||
func (s *HttpTestSuite) TestInputMap() {
|
||||
body, err := http.NewBody().SetField("test", map[string]any{"key1": "value1", "key2": "value2"}).Build()
|
||||
s.Require().NoError(err)
|
||||
|
||||
resp, err := s.Http(s.T()).Post("/input-map", body.Reader())
|
||||
s.Require().NoError(err)
|
||||
resp.AssertSuccessful()
|
||||
|
||||
content, err := resp.Content()
|
||||
s.Require().NoError(err)
|
||||
s.Equal("{\"test\":{\"key1\":\"value1\",\"key2\":\"value2\"}}", content)
|
||||
}
|
||||
|
||||
func (s *HttpTestSuite) TestInputMapArray() {
|
||||
body, err := http.NewBody().SetField("test", []map[string]any{{"key1": "value1", "key2": "value2"}, {"key3": "value3", "key4": "value4"}}).Build()
|
||||
s.Require().NoError(err)
|
||||
|
||||
resp, err := s.Http(s.T()).Post("/input-map-array", body.Reader())
|
||||
s.Require().NoError(err)
|
||||
resp.AssertSuccessful()
|
||||
|
||||
content, err := resp.Content()
|
||||
s.Require().NoError(err)
|
||||
s.Equal("{\"test\":[{\"key1\":\"value1\",\"key2\":\"value2\"},{\"key3\":\"value3\",\"key4\":\"value4\"}]}", content)
|
||||
}
|
||||
|
||||
func (s *HttpTestSuite) TestLang() {
|
||||
tests := []struct {
|
||||
name string
|
||||
lang string
|
||||
expectResponse map[string]any
|
||||
}{
|
||||
{
|
||||
name: "use default lang",
|
||||
expectResponse: map[string]any{"current_locale": "en", "fallback": "Goravel 是一个基于 Go 语言的 Web 开发框架", "name": "Goravel Framework"},
|
||||
},
|
||||
{
|
||||
name: "lang is cn",
|
||||
lang: "cn",
|
||||
expectResponse: map[string]any{"current_locale": "cn", "fallback": "Goravel 是一个基于 Go 语言的 Web 开发框架", "name": "Goravel 框架"},
|
||||
},
|
||||
{
|
||||
name: "lang is fs",
|
||||
lang: "fs",
|
||||
expectResponse: map[string]any{"current_locale": "fs", "fallback": "Goravel 是一个基于 Go 语言的 Web 开发框架", "name": "fs name"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
s.Run(test.name, func() {
|
||||
resp, err := s.Http(s.T()).Get(fmt.Sprintf("/lang?lang=%s", test.lang))
|
||||
|
||||
s.NoError(err)
|
||||
resp.AssertSuccessful()
|
||||
resp.AssertJson(test.expectResponse)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *HttpTestSuite) TestPanic() {
|
||||
resp, err := s.Http(s.T()).Get("/panic")
|
||||
|
||||
s.Require().NoError(err)
|
||||
resp.AssertInternalServerError()
|
||||
|
||||
content, err := resp.Content()
|
||||
s.Require().NoError(err)
|
||||
s.Equal("recover", content)
|
||||
}
|
||||
|
||||
func (s *HttpTestSuite) TestStream() {
|
||||
resp, err := s.Http(s.T()).Get("/stream")
|
||||
|
||||
s.Require().NoError(err)
|
||||
resp.AssertSuccessful()
|
||||
|
||||
content, err := resp.Content()
|
||||
s.Require().NoError(err)
|
||||
s.Equal("a\nb\nc\n", content)
|
||||
}
|
||||
|
||||
func (s *HttpTestSuite) TestThrottle() {
|
||||
resp, err := s.Http(s.T()).Get("/throttle")
|
||||
s.Require().NoError(err)
|
||||
resp.AssertSuccessful()
|
||||
|
||||
resp, err = s.Http(s.T()).Get("/throttle")
|
||||
s.Require().NoError(err)
|
||||
resp.AssertSuccessful()
|
||||
|
||||
resp, err = s.Http(s.T()).Get("/throttle")
|
||||
s.Require().NoError(err)
|
||||
resp.AssertTooManyRequests()
|
||||
}
|
||||
|
||||
func (s *HttpTestSuite) TestTimeout() {
|
||||
resp, err := s.Http(s.T()).Get("/timeout")
|
||||
|
||||
s.Require().NoError(err)
|
||||
resp.AssertStatus(contractshttp.StatusRequestTimeout)
|
||||
}
|
||||
|
||||
func (s *HttpTestSuite) TestUrl() {
|
||||
resp, err := s.Http(s.T()).Get("/url/get/1?a=1&b=2")
|
||||
s.Require().NoError(err)
|
||||
resp.AssertSuccessful()
|
||||
|
||||
content, err := resp.Content()
|
||||
s.Require().NoError(err)
|
||||
s.Equal(`{"full_url":"http://example.com/url/get/1?a=1\u0026b=2","info":{"handler":"goravel/routes.Api.func11.1","method":"GET","name":"url.get","path":"/url/get/{id}"},"info1":{"handler":"goravel/routes.Api.func11.1","method":"GET|HEAD","name":"url.get","path":"/url/get/{id}"},"method":"GET","name":"url.get","origin_path":"/url/get/{id}","path":"/url/get/1","url":"/url/get/1?a=1\u0026b=2"}`, content)
|
||||
|
||||
resp, err = s.Http(s.T()).Post("/url/post/1?a=1&b=2", strings.NewReader("{\"name\":\"Goravel\"}"))
|
||||
s.Require().NoError(err)
|
||||
resp.AssertSuccessful()
|
||||
|
||||
content, err = resp.Content()
|
||||
s.Require().NoError(err)
|
||||
s.Equal(`{"full_url":"http://example.com/url/post/1?a=1\u0026b=2","info":{"handler":"goravel/routes.Api.func11.2","method":"POST","name":"url.post","path":"/url/post/{id}"},"info1":{"handler":"goravel/routes.Api.func11.2","method":"POST","name":"url.post","path":"/url/post/{id}"},"method":"POST","name":"url.post","origin_path":"/url/post/{id}","path":"/url/post/1","url":"/url/post/1?a=1\u0026b=2"}`, content)
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "Goravel 框架",
|
||||
"description": "Goravel 是一个基于 Go 语言的 Web 开发框架"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"name": "Goravel Framework"
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
//go:build docker
|
||||
// +build docker
|
||||
|
||||
package feature
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/goravel/framework/support/file"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
database, err := facades.Testing().Docker().Database()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := database.Build(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := database.Migrate(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
cache, err := facades.Testing().Docker().Cache("redis")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := cache.Build(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := cache.Ready(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
facades.Config().Add("database.redis.default.port", cache.Config().Port)
|
||||
|
||||
go func() {
|
||||
if err := facades.Route().Run(); err != nil {
|
||||
facades.Log().Errorf("Route run error: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
exit := m.Run()
|
||||
|
||||
if err := file.Remove("storage"); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := database.Shutdown(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := cache.Shutdown(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
os.Exit(exit)
|
||||
}
|
||||
@@ -0,0 +1,258 @@
|
||||
package feature
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
contractsqueue "github.com/goravel/framework/contracts/queue"
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/goravel/framework/queue/utils"
|
||||
"github.com/goravel/framework/support/carbon"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"goravel/app/jobs"
|
||||
"goravel/tests"
|
||||
)
|
||||
|
||||
type QueueTestSuite struct {
|
||||
suite.Suite
|
||||
tests.TestCase
|
||||
}
|
||||
|
||||
func TestQueueTestSuite(t *testing.T) {
|
||||
suite.Run(t, &QueueTestSuite{})
|
||||
}
|
||||
|
||||
// SetupTest will run before each test in the suite.
|
||||
func (s *QueueTestSuite) SetupTest() {
|
||||
jobs.TestResult = nil
|
||||
jobs.TestErrResult = nil
|
||||
}
|
||||
|
||||
// TearDownTest will run after each test in the suite.
|
||||
func (s *QueueTestSuite) TearDownTest() {
|
||||
}
|
||||
|
||||
func (s *QueueTestSuite) TestDispatch() {
|
||||
s.NoError(facades.Queue().Job(&jobs.Test{}, testQueueArgs).Dispatch())
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
s.Equal(utils.ConvertArgs(testQueueArgs), jobs.TestResult)
|
||||
}
|
||||
|
||||
func (s *QueueTestSuite) TestDispatchWithDelay() {
|
||||
s.NoError(facades.Queue().Job(&jobs.Test{}, testQueueArgs).Delay(time.Now().Add(1 * time.Second)).Dispatch())
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
s.Equal(utils.ConvertArgs(testQueueArgs), jobs.TestResult)
|
||||
}
|
||||
|
||||
func (s *QueueTestSuite) TestDispatchChain() {
|
||||
s.NoError(facades.Queue().Chain([]contractsqueue.ChainJob{
|
||||
{
|
||||
Job: &jobs.Test{},
|
||||
Args: testQueueArgs,
|
||||
},
|
||||
{
|
||||
Job: &jobs.Test{},
|
||||
Args: testQueueArgs,
|
||||
},
|
||||
}).Dispatch())
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
var args []any
|
||||
for i := 0; i < 2; i++ {
|
||||
args = append(args, utils.ConvertArgs(testQueueArgs)...)
|
||||
}
|
||||
|
||||
s.Equal(args, jobs.TestResult)
|
||||
}
|
||||
|
||||
func (s *QueueTestSuite) TestDispatchWithQueue() {
|
||||
s.NoError(facades.Queue().Job(&jobs.Test{}, testQueueArgs).OnQueue("test").Dispatch())
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
s.Equal(utils.ConvertArgs(testQueueArgs), jobs.TestResult)
|
||||
}
|
||||
|
||||
func (s *QueueTestSuite) TestDispatchWithConnectionAndQueue() {
|
||||
if facades.Config().GetString("queue.default") == "sync" {
|
||||
s.T().Skip("skip test due to only for redis")
|
||||
}
|
||||
|
||||
s.NoError(facades.Queue().Job(&jobs.Test{}, testQueueArgs).OnConnection("redis1").OnQueue("test").Dispatch())
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
s.Equal(utils.ConvertArgs(testQueueArgs), jobs.TestResult)
|
||||
}
|
||||
|
||||
func (s *QueueTestSuite) TestSyncFailedJob() {
|
||||
if facades.Config().GetString("queue.default") != "sync" {
|
||||
s.T().Skip("skip test due to only for sync")
|
||||
}
|
||||
|
||||
s.Equal(errors.New("test error"), facades.Queue().Job(&jobs.TestErr{}).Dispatch())
|
||||
}
|
||||
|
||||
func (s *QueueTestSuite) TestFailedJobAndRetry() {
|
||||
if facades.Config().GetString("queue.default") == "sync" {
|
||||
s.T().Skip("skip test due to only for non-sync")
|
||||
}
|
||||
|
||||
carbon.SetTestNow(carbon.Now())
|
||||
defer carbon.ClearTestNow()
|
||||
|
||||
testErr := &jobs.TestErr{}
|
||||
s.NoError(facades.Queue().Job(testErr, []contractsqueue.Arg{
|
||||
{
|
||||
Type: "string",
|
||||
Value: "test",
|
||||
},
|
||||
}).Dispatch())
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
s.Equal([]any{"test"}, jobs.TestErrResult)
|
||||
|
||||
failedJobs, err := facades.Queue().Failer().All()
|
||||
|
||||
s.Require().NoError(err)
|
||||
|
||||
if facades.Config().GetString("queue.default") != "machinery" {
|
||||
s.Require().Equal(1, len(failedJobs))
|
||||
s.Equal("default", failedJobs[0].Queue())
|
||||
s.Equal(facades.Config().GetString("queue.default"), failedJobs[0].Connection())
|
||||
s.Equal(carbon.NewDateTime(carbon.Now()), failedJobs[0].FailedAt())
|
||||
s.Equal(testErr.Signature(), failedJobs[0].Signature())
|
||||
s.NotEmpty(failedJobs[0].UUID())
|
||||
|
||||
s.NoError(facades.Artisan().Call("queue:retry"))
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
s.Equal([]any{"test", "test"}, jobs.TestErrResult)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
testQueueArgs = []contractsqueue.Arg{
|
||||
{
|
||||
Type: "bool",
|
||||
Value: true,
|
||||
},
|
||||
{
|
||||
Type: "int",
|
||||
Value: 1,
|
||||
},
|
||||
{
|
||||
Type: "int8",
|
||||
Value: int8(1),
|
||||
},
|
||||
{
|
||||
Type: "int16",
|
||||
Value: int16(1),
|
||||
},
|
||||
{
|
||||
Type: "int32",
|
||||
Value: int32(1),
|
||||
},
|
||||
{
|
||||
Type: "int64",
|
||||
Value: int64(1),
|
||||
},
|
||||
{
|
||||
Type: "uint",
|
||||
Value: uint(1),
|
||||
},
|
||||
{
|
||||
Type: "uint8",
|
||||
Value: uint8(1),
|
||||
},
|
||||
{
|
||||
Type: "uint16",
|
||||
Value: uint16(1),
|
||||
},
|
||||
{
|
||||
Type: "uint32",
|
||||
Value: uint32(1),
|
||||
},
|
||||
{
|
||||
Type: "uint64",
|
||||
Value: uint64(1),
|
||||
},
|
||||
{
|
||||
Type: "float32",
|
||||
Value: float32(1.1),
|
||||
},
|
||||
{
|
||||
Type: "float64",
|
||||
Value: float64(1.2),
|
||||
},
|
||||
{
|
||||
Type: "string",
|
||||
Value: "test",
|
||||
},
|
||||
{
|
||||
Type: "[]bool",
|
||||
Value: []bool{true, false},
|
||||
},
|
||||
{
|
||||
Type: "[]int",
|
||||
Value: []int{1, 2, 3},
|
||||
},
|
||||
{
|
||||
Type: "[]int8",
|
||||
Value: []int8{1, 2, 3},
|
||||
},
|
||||
{
|
||||
Type: "[]int16",
|
||||
Value: []int16{1, 2, 3},
|
||||
},
|
||||
{
|
||||
Type: "[]int32",
|
||||
Value: []int32{1, 2, 3},
|
||||
},
|
||||
{
|
||||
Type: "[]int64",
|
||||
Value: []int64{1, 2, 3},
|
||||
},
|
||||
{
|
||||
Type: "[]uint",
|
||||
Value: []uint{1, 2, 3},
|
||||
},
|
||||
{
|
||||
Type: "[]uint8",
|
||||
Value: []uint8{1, 2, 3},
|
||||
},
|
||||
{
|
||||
Type: "[]uint16",
|
||||
Value: []uint16{1, 2, 3},
|
||||
},
|
||||
{
|
||||
Type: "[]uint32",
|
||||
Value: []uint32{1, 2, 3},
|
||||
},
|
||||
{
|
||||
Type: "[]uint64",
|
||||
Value: []uint64{1, 2, 3},
|
||||
},
|
||||
{
|
||||
Type: "[]float32",
|
||||
Value: []float32{1.1, 1.2, 1.3},
|
||||
},
|
||||
{
|
||||
Type: "[]float64",
|
||||
Value: []float64{1.1, 1.2, 1.3},
|
||||
},
|
||||
{
|
||||
Type: "[]string",
|
||||
Value: []string{"test", "test2", "test3"},
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,81 @@
|
||||
package feature
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/goravel/framework/contracts/queue"
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
func TestRedisDriver(t *testing.T) {
|
||||
facades.Config().Add("cache.default", "redis")
|
||||
facades.Config().Add("queue.default", "redis")
|
||||
facades.App().Refresh()
|
||||
|
||||
go func() {
|
||||
if err := facades.Queue().Worker().Run(); err != nil {
|
||||
facades.Log().Errorf("Queue run error: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
if err := facades.Queue().Worker(queue.Args{
|
||||
Queue: "test",
|
||||
}).Run(); err != nil {
|
||||
facades.Log().Errorf("Queue run error: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
if err := facades.Queue().Worker(queue.Args{
|
||||
Connection: "redis1",
|
||||
Queue: "test",
|
||||
}).Run(); err != nil {
|
||||
facades.Log().Errorf("Queue run error: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
suite.Run(t, &HttpTestSuite{})
|
||||
suite.Run(t, &QueueTestSuite{})
|
||||
|
||||
facades.Config().Add("cache.default", "memory")
|
||||
facades.Config().Add("queue.default", "sync")
|
||||
facades.App().Refresh()
|
||||
}
|
||||
|
||||
func TestMachineryDriver(t *testing.T) {
|
||||
facades.Config().Add("cache.default", "redis")
|
||||
facades.Config().Add("queue.default", "machinery")
|
||||
facades.App().Refresh()
|
||||
|
||||
go func() {
|
||||
if err := facades.Queue().Worker().Run(); err != nil {
|
||||
facades.Log().Errorf("Queue run error: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
if err := facades.Queue().Worker(queue.Args{
|
||||
Queue: "test",
|
||||
Concurrent: 2,
|
||||
}).Run(); err != nil {
|
||||
facades.Log().Errorf("Queue run error: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
if err := facades.Queue().Worker(queue.Args{
|
||||
Connection: "redis1",
|
||||
Queue: "test",
|
||||
}).Run(); err != nil {
|
||||
facades.Log().Errorf("Queue run error: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
suite.Run(t, &QueueTestSuite{})
|
||||
|
||||
facades.Config().Add("cache.default", "memory")
|
||||
facades.Config().Add("queue.default", "sync")
|
||||
facades.App().Refresh()
|
||||
}
|
||||
Reference in New Issue
Block a user