2022-09-21 04:25:07 -05:00
|
|
|
package image
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"testing"
|
2023-01-05 10:07:46 -06:00
|
|
|
"time"
|
2022-09-21 04:25:07 -05:00
|
|
|
|
|
|
|
"github.com/golang/mock/gomock"
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
|
|
|
"github.com/grafana/grafana/pkg/components/imguploader"
|
|
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
|
|
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
|
|
|
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
|
|
|
"github.com/grafana/grafana/pkg/services/screenshot"
|
2023-03-06 04:23:15 -06:00
|
|
|
"github.com/grafana/grafana/pkg/util"
|
2022-09-21 04:25:07 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestScreenshotImageService(t *testing.T) {
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
|
|
|
|
|
|
|
var (
|
2022-11-08 19:52:16 -06:00
|
|
|
cache = NewMockCacheService(ctrl)
|
2022-09-21 04:25:07 -05:00
|
|
|
images = store.NewFakeImageStore(t)
|
|
|
|
limiter = screenshot.NoOpRateLimiter{}
|
|
|
|
screenshots = screenshot.NewMockScreenshotService(ctrl)
|
|
|
|
uploads = imguploader.NewMockImageUploader(ctrl)
|
|
|
|
)
|
|
|
|
|
2023-01-05 10:07:46 -06:00
|
|
|
s := NewScreenshotImageService(cache, &limiter, log.NewNopLogger(), screenshots, 5*time.Second, images,
|
2022-09-21 04:25:07 -05:00
|
|
|
NewUploadingService(uploads, prometheus.NewRegistry()))
|
|
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
2023-01-05 10:07:46 -06:00
|
|
|
t.Run("image is taken, uploaded, saved to database and cached", func(t *testing.T) {
|
|
|
|
// assert that the cache is checked for an existing image
|
2023-02-09 14:23:01 -06:00
|
|
|
cache.EXPECT().Get(gomock.Any(), "oyh1kYgaJwM=").Return(models.Image{}, false)
|
2023-01-05 10:07:46 -06:00
|
|
|
|
|
|
|
// assert that a screenshot is taken
|
|
|
|
screenshots.EXPECT().Take(gomock.Any(), screenshot.ScreenshotOptions{
|
2023-02-09 14:23:01 -06:00
|
|
|
OrgID: 1,
|
2023-01-05 10:07:46 -06:00
|
|
|
DashboardUID: "foo",
|
|
|
|
PanelID: 1,
|
|
|
|
Timeout: 5 * time.Second,
|
|
|
|
}).Return(&screenshot.Screenshot{
|
|
|
|
Path: "foo.png",
|
|
|
|
}, nil)
|
|
|
|
|
|
|
|
// assert that the screenshot is made into an image and uploaded
|
|
|
|
uploads.EXPECT().Upload(gomock.Any(), "foo.png").
|
|
|
|
Return("https://example.com/foo.png", nil)
|
|
|
|
|
|
|
|
// assert that the image is saved into the database
|
|
|
|
expected := models.Image{
|
|
|
|
ID: 1,
|
|
|
|
Token: "foo",
|
|
|
|
Path: "foo.png",
|
|
|
|
URL: "https://example.com/foo.png",
|
|
|
|
}
|
|
|
|
|
|
|
|
// assert that the image is saved into the cache
|
2023-02-09 14:23:01 -06:00
|
|
|
cache.EXPECT().Set(gomock.Any(), "oyh1kYgaJwM=", expected).Return(nil)
|
2023-01-05 10:07:46 -06:00
|
|
|
|
|
|
|
image, err := s.NewImage(ctx, &models.AlertRule{
|
|
|
|
OrgID: 1,
|
|
|
|
UID: "foo",
|
2023-03-06 04:23:15 -06:00
|
|
|
DashboardUID: util.Pointer("foo"),
|
|
|
|
PanelID: util.Pointer(int64(1))})
|
2023-01-05 10:07:46 -06:00
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, expected, *image)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("image is taken, upload return error, saved to database without URL and cached", func(t *testing.T) {
|
|
|
|
// assert that the cache is checked for an existing image
|
2023-02-09 14:23:01 -06:00
|
|
|
cache.EXPECT().Get(gomock.Any(), "yszV9tgmKAo=").Return(models.Image{}, false)
|
2023-01-05 10:07:46 -06:00
|
|
|
|
|
|
|
// assert that a screenshot is taken
|
|
|
|
screenshots.EXPECT().Take(gomock.Any(), screenshot.ScreenshotOptions{
|
2023-02-09 14:23:01 -06:00
|
|
|
OrgID: 1,
|
2023-01-05 10:07:46 -06:00
|
|
|
DashboardUID: "bar",
|
|
|
|
PanelID: 1,
|
|
|
|
Timeout: 5 * time.Second,
|
|
|
|
}).Return(&screenshot.Screenshot{
|
|
|
|
Path: "bar.png",
|
|
|
|
}, nil)
|
|
|
|
|
|
|
|
// the screenshot is made into an image and uploaded, but the upload returns an error
|
|
|
|
uploads.EXPECT().Upload(gomock.Any(), "bar.png").
|
|
|
|
Return("", errors.New("failed to upload bar.png"))
|
|
|
|
|
|
|
|
// and then saved into the database, but without a URL
|
|
|
|
expected := models.Image{
|
|
|
|
ID: 2,
|
|
|
|
Token: "bar",
|
|
|
|
Path: "bar.png",
|
|
|
|
}
|
|
|
|
|
|
|
|
// assert that the image is saved into the cache, but without a URL
|
2023-02-09 14:23:01 -06:00
|
|
|
cache.EXPECT().Set(gomock.Any(), "yszV9tgmKAo=", expected).Return(nil)
|
2023-01-05 10:07:46 -06:00
|
|
|
|
|
|
|
image, err := s.NewImage(ctx, &models.AlertRule{
|
|
|
|
OrgID: 1,
|
|
|
|
UID: "bar",
|
2023-03-06 04:23:15 -06:00
|
|
|
DashboardUID: util.Pointer("bar"),
|
|
|
|
PanelID: util.Pointer(int64(1))})
|
2023-01-05 10:07:46 -06:00
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, expected, *image)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("image is returned from cache", func(t *testing.T) {
|
|
|
|
expected := models.Image{Path: "baz.png", URL: "https://example.com/baz.png"}
|
|
|
|
|
|
|
|
// assert that the cache is checked for an existing image and it is returned
|
2023-02-09 14:23:01 -06:00
|
|
|
cache.EXPECT().Get(gomock.Any(), "he399rFDBPI=").Return(expected, true)
|
2023-01-05 10:07:46 -06:00
|
|
|
|
|
|
|
image, err := s.NewImage(ctx, &models.AlertRule{
|
|
|
|
OrgID: 1,
|
|
|
|
UID: "baz",
|
2023-03-06 04:23:15 -06:00
|
|
|
DashboardUID: util.Pointer("baz"),
|
|
|
|
PanelID: util.Pointer(int64(1))})
|
2023-01-05 10:07:46 -06:00
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, expected, *image)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("error is returned when timeout is exceeded", func(t *testing.T) {
|
|
|
|
// assert that the cache is checked for an existing image
|
2023-02-09 14:23:01 -06:00
|
|
|
cache.EXPECT().Get(gomock.Any(), "TTHub8HUe2U=").Return(models.Image{}, false)
|
2023-01-05 10:07:46 -06:00
|
|
|
|
|
|
|
// assert that when the timeout is exceeded an error is returned
|
|
|
|
screenshots.EXPECT().Take(gomock.Any(), screenshot.ScreenshotOptions{
|
2023-02-09 14:23:01 -06:00
|
|
|
OrgID: 1,
|
2023-01-05 10:07:46 -06:00
|
|
|
DashboardUID: "qux",
|
|
|
|
PanelID: 1,
|
|
|
|
Timeout: 5 * time.Second,
|
|
|
|
}).Return(nil, context.DeadlineExceeded)
|
|
|
|
|
|
|
|
image, err := s.NewImage(ctx, &models.AlertRule{
|
|
|
|
OrgID: 1,
|
|
|
|
UID: "qux",
|
2023-03-06 04:23:15 -06:00
|
|
|
DashboardUID: util.Pointer("qux"),
|
|
|
|
PanelID: util.Pointer(int64(1))})
|
2023-01-05 10:07:46 -06:00
|
|
|
assert.EqualError(t, err, "context deadline exceeded")
|
|
|
|
assert.Nil(t, image)
|
|
|
|
})
|
2022-09-21 04:25:07 -05:00
|
|
|
}
|