2021-06-28 17:08:42 +05:30
|
|
|
/*
|
|
|
|
Copyright 2021 The Ceph-CSI Authors.
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package rbd
|
|
|
|
|
|
|
|
import (
|
2021-11-26 12:08:21 +05:30
|
|
|
"context"
|
2023-06-05 21:48:29 +05:30
|
|
|
"errors"
|
2021-06-28 17:08:42 +05:30
|
|
|
"reflect"
|
|
|
|
"testing"
|
2022-09-09 16:56:41 +05:30
|
|
|
"time"
|
2021-06-28 17:08:42 +05:30
|
|
|
|
2023-01-12 15:22:51 +05:30
|
|
|
corerbd "github.com/ceph/ceph-csi/internal/rbd"
|
2025-03-03 11:45:43 +05:30
|
|
|
rbderrors "github.com/ceph/ceph-csi/internal/rbd/errors"
|
2024-07-26 10:01:02 +02:00
|
|
|
"github.com/ceph/ceph-csi/internal/rbd/types"
|
2024-07-30 18:37:40 +02:00
|
|
|
"github.com/ceph/ceph-csi/internal/util"
|
2023-01-12 15:22:51 +05:30
|
|
|
|
2021-10-25 15:54:12 +05:30
|
|
|
librbd "github.com/ceph/go-ceph/rbd"
|
2021-06-28 17:08:42 +05:30
|
|
|
"github.com/ceph/go-ceph/rbd/admin"
|
2024-04-04 10:51:19 +02:00
|
|
|
"github.com/stretchr/testify/require"
|
2023-06-05 21:48:29 +05:30
|
|
|
"google.golang.org/grpc/codes"
|
|
|
|
"google.golang.org/grpc/status"
|
2021-06-28 17:08:42 +05:30
|
|
|
)
|
|
|
|
|
|
|
|
func TestValidateSchedulingInterval(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
interval string
|
|
|
|
wantErr bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"valid interval in minutes",
|
|
|
|
"3m",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"valid interval in hour",
|
|
|
|
"22h",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"valid interval in days",
|
|
|
|
"13d",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid interval without number",
|
|
|
|
"d",
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid interval without (m|h|d) suffix",
|
|
|
|
"12",
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
2021-07-11 12:57:41 +05:30
|
|
|
t.Parallel()
|
2021-11-15 11:30:13 +05:30
|
|
|
err := validateSchedulingInterval(tt.interval)
|
2021-07-11 12:57:41 +05:30
|
|
|
if (err != nil) != tt.wantErr {
|
|
|
|
t.Errorf("validateSchedulingInterval() error = %v, wantErr %v", err, tt.wantErr)
|
2021-07-22 11:15:17 +05:30
|
|
|
|
2021-06-28 17:08:42 +05:30
|
|
|
return
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-15 11:30:13 +05:30
|
|
|
func TestValidateSchedulingDetails(t *testing.T) {
|
2021-07-11 12:57:41 +05:30
|
|
|
t.Parallel()
|
2025-04-29 11:36:03 +02:00
|
|
|
ctx := t.Context()
|
2021-06-28 17:08:42 +05:30
|
|
|
tests := []struct {
|
2021-11-15 11:30:13 +05:30
|
|
|
name string
|
|
|
|
parameters map[string]string
|
|
|
|
wantErr bool
|
2021-06-28 17:08:42 +05:30
|
|
|
}{
|
|
|
|
{
|
|
|
|
"valid parameters",
|
|
|
|
map[string]string{
|
|
|
|
imageMirroringKey: string(imageMirrorModeSnapshot),
|
|
|
|
schedulingIntervalKey: "1h",
|
|
|
|
schedulingStartTimeKey: "14:00:00-05:00",
|
|
|
|
},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"valid parameters when optional startTime is missing",
|
|
|
|
map[string]string{
|
|
|
|
imageMirroringKey: string(imageMirrorModeSnapshot),
|
|
|
|
schedulingIntervalKey: "1h",
|
|
|
|
},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"when mirroring mode is journal",
|
|
|
|
map[string]string{
|
2021-11-26 12:08:21 +05:30
|
|
|
imageMirroringKey: string(imageMirrorModeJournal),
|
2021-06-28 17:08:42 +05:30
|
|
|
schedulingIntervalKey: "1h",
|
|
|
|
},
|
2021-11-26 12:08:21 +05:30
|
|
|
false,
|
2021-06-28 17:08:42 +05:30
|
|
|
},
|
|
|
|
{
|
|
|
|
"when startTime is specified without interval",
|
|
|
|
map[string]string{
|
|
|
|
imageMirroringKey: string(imageMirrorModeSnapshot),
|
|
|
|
schedulingStartTimeKey: "14:00:00-05:00",
|
|
|
|
},
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"when no scheduling is specified",
|
|
|
|
map[string]string{
|
|
|
|
imageMirroringKey: string(imageMirrorModeSnapshot),
|
|
|
|
},
|
|
|
|
false,
|
|
|
|
},
|
2021-08-09 10:18:32 +05:30
|
|
|
{
|
|
|
|
"when no parameters and scheduling details are specified",
|
|
|
|
map[string]string{},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"when no mirroring mode is specified",
|
|
|
|
map[string]string{
|
|
|
|
schedulingIntervalKey: "1h",
|
|
|
|
schedulingStartTimeKey: "14:00:00-05:00",
|
|
|
|
},
|
|
|
|
false,
|
|
|
|
},
|
2021-06-28 17:08:42 +05:30
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
2021-07-11 12:57:41 +05:30
|
|
|
t.Parallel()
|
2021-11-26 12:08:21 +05:30
|
|
|
err := validateSchedulingDetails(ctx, tt.parameters)
|
2021-07-11 12:57:41 +05:30
|
|
|
if (err != nil) != tt.wantErr {
|
|
|
|
t.Errorf("getSchedulingDetails() error = %v, wantErr %v", err, tt.wantErr)
|
2021-07-22 11:15:17 +05:30
|
|
|
|
2021-06-28 17:08:42 +05:30
|
|
|
return
|
|
|
|
}
|
2021-11-15 11:30:13 +05:30
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGetSchedulingDetails(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
parameters map[string]string
|
|
|
|
wantInterval admin.Interval
|
|
|
|
wantStartTime admin.StartTime
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"valid parameters",
|
|
|
|
map[string]string{
|
|
|
|
schedulingIntervalKey: "1h",
|
|
|
|
schedulingStartTimeKey: "14:00:00-05:00",
|
|
|
|
},
|
|
|
|
admin.Interval("1h"),
|
|
|
|
admin.StartTime("14:00:00-05:00"),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"valid parameters when optional startTime is missing",
|
|
|
|
map[string]string{
|
|
|
|
imageMirroringKey: string(imageMirrorModeSnapshot),
|
|
|
|
schedulingIntervalKey: "1h",
|
|
|
|
},
|
|
|
|
admin.Interval("1h"),
|
|
|
|
admin.NoStartTime,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"when startTime is specified without interval",
|
|
|
|
map[string]string{
|
|
|
|
imageMirroringKey: string(imageMirrorModeSnapshot),
|
|
|
|
schedulingStartTimeKey: "14:00:00-05:00",
|
|
|
|
},
|
|
|
|
admin.NoInterval,
|
|
|
|
admin.StartTime("14:00:00-05:00"),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"when no parameters and scheduling details are specified",
|
|
|
|
map[string]string{},
|
|
|
|
admin.NoInterval,
|
|
|
|
admin.NoStartTime,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
interval, startTime := getSchedulingDetails(tt.parameters)
|
2021-07-11 12:57:41 +05:30
|
|
|
if !reflect.DeepEqual(interval, tt.wantInterval) {
|
|
|
|
t.Errorf("getSchedulingDetails() interval = %v, want %v", interval, tt.wantInterval)
|
2021-06-28 17:08:42 +05:30
|
|
|
}
|
2021-07-11 12:57:41 +05:30
|
|
|
if !reflect.DeepEqual(startTime, tt.wantStartTime) {
|
|
|
|
t.Errorf("getSchedulingDetails() startTime = %v, want %v", startTime, tt.wantStartTime)
|
2021-06-28 17:08:42 +05:30
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2021-10-25 15:54:12 +05:30
|
|
|
|
|
|
|
func TestCheckVolumeResyncStatus(t *testing.T) {
|
2025-04-29 11:36:03 +02:00
|
|
|
ctx := t.Context()
|
2021-10-25 15:54:12 +05:30
|
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
2024-07-26 10:01:02 +02:00
|
|
|
args corerbd.SiteMirrorImageStatus
|
2021-10-25 15:54:12 +05:30
|
|
|
wantErr bool
|
|
|
|
}{
|
2022-08-08 17:23:35 +05:30
|
|
|
{
|
2023-08-22 18:52:49 +02:00
|
|
|
name: "test when local_snapshot_timestamp is non zero",
|
2024-07-26 10:01:02 +02:00
|
|
|
args: corerbd.SiteMirrorImageStatus{
|
|
|
|
SiteMirrorImageStatus: librbd.SiteMirrorImageStatus{
|
|
|
|
//nolint:lll // sample output cannot be split into multiple lines.
|
|
|
|
Description: `replaying, {"bytes_per_second":0.0,"bytes_per_snapshot":81920.0,"last_snapshot_bytes":81920,"last_snapshot_sync_seconds":56743,"local_snapshot_timestamp":1684675261,"remote_snapshot_timestamp":1684675261,"replay_state":"idle"}`,
|
|
|
|
},
|
2021-10-25 15:54:12 +05:30
|
|
|
},
|
|
|
|
wantErr: false,
|
|
|
|
},
|
|
|
|
{
|
2023-08-22 18:52:49 +02:00
|
|
|
name: "test when local_snapshot_timestamp is zero",
|
|
|
|
//nolint:lll // sample output cannot be split into multiple lines.
|
2024-07-26 10:01:02 +02:00
|
|
|
args: corerbd.SiteMirrorImageStatus{
|
|
|
|
SiteMirrorImageStatus: librbd.SiteMirrorImageStatus{
|
|
|
|
Description: `replaying, {"bytes_per_second":0.0,"bytes_per_snapshot":81920.0,"last_snapshot_bytes":81920,"last_snapshot_sync_seconds":56743,"local_snapshot_timestamp":0,"remote_snapshot_timestamp":1684675261,"replay_state":"idle"}`,
|
|
|
|
},
|
2021-10-25 15:54:12 +05:30
|
|
|
},
|
|
|
|
wantErr: true,
|
|
|
|
},
|
|
|
|
{
|
2023-08-22 18:52:49 +02:00
|
|
|
name: "test when local_snapshot_timestamp is not present",
|
|
|
|
//nolint:lll // sample output cannot be split into multiple lines.
|
2024-07-26 10:01:02 +02:00
|
|
|
args: corerbd.SiteMirrorImageStatus{
|
|
|
|
SiteMirrorImageStatus: librbd.SiteMirrorImageStatus{
|
|
|
|
Description: `replaying, {"bytes_per_second":0.0,"bytes_per_snapshot":81920.0,"last_snapshot_bytes":81920,"last_snapshot_sync_seconds":56743,"remote_snapshot_timestamp":1684675261,"replay_state":"idle"}`,
|
|
|
|
},
|
2021-10-25 15:54:12 +05:30
|
|
|
},
|
|
|
|
wantErr: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
2024-04-26 10:35:01 +02:00
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
2021-10-25 15:54:12 +05:30
|
|
|
t.Parallel()
|
2024-04-26 10:35:01 +02:00
|
|
|
if err := checkVolumeResyncStatus(ctx, tt.args); (err != nil) != tt.wantErr {
|
|
|
|
t.Errorf("checkVolumeResyncStatus() error = %v, expect error = %v", err, tt.wantErr)
|
2021-10-25 15:54:12 +05:30
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2022-08-08 12:53:41 -05:00
|
|
|
|
|
|
|
func TestCheckRemoteSiteStatus(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
2024-07-26 10:01:02 +02:00
|
|
|
args corerbd.GlobalMirrorStatus
|
2022-08-08 12:53:41 -05:00
|
|
|
wantReady bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "Test a single peer in sync",
|
2024-07-26 10:01:02 +02:00
|
|
|
args: corerbd.GlobalMirrorStatus{
|
|
|
|
GlobalMirrorImageStatus: librbd.GlobalMirrorImageStatus{
|
|
|
|
SiteStatuses: []librbd.SiteMirrorImageStatus{
|
|
|
|
{
|
|
|
|
MirrorUUID: "remote",
|
|
|
|
State: librbd.MirrorImageStatusStateUnknown,
|
|
|
|
Up: true,
|
|
|
|
},
|
2022-08-08 12:53:41 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
wantReady: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Test a single peer in sync, including a local instance",
|
2024-07-26 10:01:02 +02:00
|
|
|
args: corerbd.GlobalMirrorStatus{
|
|
|
|
GlobalMirrorImageStatus: librbd.GlobalMirrorImageStatus{
|
|
|
|
SiteStatuses: []librbd.SiteMirrorImageStatus{
|
|
|
|
{
|
|
|
|
MirrorUUID: "remote",
|
|
|
|
State: librbd.MirrorImageStatusStateUnknown,
|
|
|
|
Up: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
MirrorUUID: "",
|
|
|
|
State: librbd.MirrorImageStatusStateUnknown,
|
|
|
|
Up: true,
|
|
|
|
},
|
2022-08-08 12:53:41 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
wantReady: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Test a multiple peers in sync",
|
2024-07-26 10:01:02 +02:00
|
|
|
args: corerbd.GlobalMirrorStatus{
|
|
|
|
GlobalMirrorImageStatus: librbd.GlobalMirrorImageStatus{
|
|
|
|
SiteStatuses: []librbd.SiteMirrorImageStatus{
|
|
|
|
{
|
|
|
|
MirrorUUID: "remote1",
|
|
|
|
State: librbd.MirrorImageStatusStateUnknown,
|
|
|
|
Up: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
MirrorUUID: "remote2",
|
|
|
|
State: librbd.MirrorImageStatusStateUnknown,
|
|
|
|
Up: true,
|
|
|
|
},
|
2022-08-08 12:53:41 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
wantReady: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Test no remote peers",
|
2024-07-26 10:01:02 +02:00
|
|
|
args: corerbd.GlobalMirrorStatus{
|
|
|
|
GlobalMirrorImageStatus: librbd.GlobalMirrorImageStatus{
|
|
|
|
SiteStatuses: []librbd.SiteMirrorImageStatus{},
|
|
|
|
},
|
2022-08-08 12:53:41 -05:00
|
|
|
},
|
|
|
|
wantReady: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Test single peer not in sync",
|
2024-07-26 10:01:02 +02:00
|
|
|
args: corerbd.GlobalMirrorStatus{
|
|
|
|
GlobalMirrorImageStatus: librbd.GlobalMirrorImageStatus{
|
|
|
|
SiteStatuses: []librbd.SiteMirrorImageStatus{
|
|
|
|
{
|
|
|
|
MirrorUUID: "remote",
|
|
|
|
State: librbd.MirrorImageStatusStateReplaying,
|
|
|
|
Up: true,
|
|
|
|
},
|
2022-08-08 12:53:41 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
wantReady: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Test single peer not up",
|
2024-07-26 10:01:02 +02:00
|
|
|
args: corerbd.GlobalMirrorStatus{
|
|
|
|
GlobalMirrorImageStatus: librbd.GlobalMirrorImageStatus{
|
|
|
|
SiteStatuses: []librbd.SiteMirrorImageStatus{
|
|
|
|
{
|
|
|
|
MirrorUUID: "remote",
|
|
|
|
State: librbd.MirrorImageStatusStateUnknown,
|
|
|
|
Up: false,
|
|
|
|
},
|
2022-08-08 12:53:41 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
wantReady: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Test multiple peers, when first peer is not in sync",
|
2024-07-26 10:01:02 +02:00
|
|
|
args: corerbd.GlobalMirrorStatus{
|
|
|
|
GlobalMirrorImageStatus: librbd.GlobalMirrorImageStatus{
|
|
|
|
SiteStatuses: []librbd.SiteMirrorImageStatus{
|
|
|
|
{
|
|
|
|
MirrorUUID: "remote1",
|
|
|
|
State: librbd.MirrorImageStatusStateStoppingReplay,
|
|
|
|
Up: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
MirrorUUID: "remote2",
|
|
|
|
State: librbd.MirrorImageStatusStateUnknown,
|
|
|
|
Up: true,
|
|
|
|
},
|
2022-08-08 12:53:41 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
wantReady: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Test multiple peers, when second peer is not up",
|
2024-07-26 10:01:02 +02:00
|
|
|
args: corerbd.GlobalMirrorStatus{
|
|
|
|
GlobalMirrorImageStatus: librbd.GlobalMirrorImageStatus{
|
|
|
|
SiteStatuses: []librbd.SiteMirrorImageStatus{
|
|
|
|
{
|
|
|
|
MirrorUUID: "remote1",
|
|
|
|
State: librbd.MirrorImageStatusStateUnknown,
|
|
|
|
Up: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
MirrorUUID: "remote2",
|
|
|
|
State: librbd.MirrorImageStatusStateUnknown,
|
|
|
|
Up: false,
|
|
|
|
},
|
2022-08-08 12:53:41 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
wantReady: false,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
2024-04-26 10:35:01 +02:00
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
2022-08-08 12:53:41 -05:00
|
|
|
t.Parallel()
|
2025-04-29 11:36:03 +02:00
|
|
|
if ready := checkRemoteSiteStatus(t.Context(), tt.args.GetAllSitesStatus()); ready != tt.wantReady {
|
2024-04-26 10:35:01 +02:00
|
|
|
t.Errorf("checkRemoteSiteStatus() ready = %v, expect ready = %v", ready, tt.wantReady)
|
2022-08-08 12:53:41 -05:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2022-09-09 16:56:41 +05:30
|
|
|
|
2023-06-05 21:48:29 +05:30
|
|
|
func TestGetGRPCError(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
err error
|
|
|
|
expectedErr error
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "InvalidArgument",
|
2025-03-03 11:45:43 +05:30
|
|
|
err: rbderrors.ErrInvalidArgument,
|
|
|
|
expectedErr: status.Error(codes.InvalidArgument, rbderrors.ErrInvalidArgument.Error()),
|
2023-06-05 21:48:29 +05:30
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Aborted",
|
2025-03-03 11:45:43 +05:30
|
|
|
err: rbderrors.ErrAborted,
|
|
|
|
expectedErr: status.Error(codes.Aborted, rbderrors.ErrAborted.Error()),
|
2023-06-05 21:48:29 +05:30
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "FailedPrecondition",
|
2025-03-03 11:45:43 +05:30
|
|
|
err: rbderrors.ErrFailedPrecondition,
|
|
|
|
expectedErr: status.Error(codes.FailedPrecondition, rbderrors.ErrFailedPrecondition.Error()),
|
2023-06-05 21:48:29 +05:30
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Unavailable",
|
2025-03-03 11:45:43 +05:30
|
|
|
err: rbderrors.ErrUnavailable,
|
|
|
|
expectedErr: status.Error(codes.Unavailable, rbderrors.ErrUnavailable.Error()),
|
2023-06-05 21:48:29 +05:30
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "InvalidError",
|
|
|
|
err: errors.New("some error"),
|
2024-06-10 15:27:05 +05:30
|
|
|
expectedErr: status.Error(codes.Internal, "some error"),
|
2023-06-05 21:48:29 +05:30
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "NilError",
|
|
|
|
err: nil,
|
|
|
|
expectedErr: status.Error(codes.OK, "ok string"),
|
|
|
|
},
|
2024-07-30 18:37:40 +02:00
|
|
|
{
|
|
|
|
name: "ErrImageNotFound",
|
2025-03-03 11:45:43 +05:30
|
|
|
err: rbderrors.ErrImageNotFound,
|
|
|
|
expectedErr: status.Error(codes.NotFound, rbderrors.ErrImageNotFound.Error()),
|
2024-07-30 18:37:40 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ErrPoolNotFound",
|
|
|
|
err: util.ErrPoolNotFound,
|
|
|
|
expectedErr: status.Error(codes.NotFound, util.ErrPoolNotFound.Error()),
|
|
|
|
},
|
2023-06-05 21:48:29 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
result := getGRPCError(tt.err)
|
2024-04-04 10:51:19 +02:00
|
|
|
require.Equal(t, tt.expectedErr, result)
|
2023-06-05 21:48:29 +05:30
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2023-08-22 18:52:49 +02:00
|
|
|
|
|
|
|
func Test_timestampFromString(t *testing.T) {
|
2024-08-05 18:27:15 +02:00
|
|
|
tm := time.Now()
|
2023-08-22 18:52:49 +02:00
|
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
timestamp string
|
|
|
|
want time.Time
|
|
|
|
wantErr bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "valid timestamp",
|
2024-08-05 18:27:15 +02:00
|
|
|
timestamp: timestampToString(&tm),
|
|
|
|
want: tm,
|
2023-08-22 18:52:49 +02:00
|
|
|
wantErr: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "invalid timestamp",
|
|
|
|
timestamp: "invalid",
|
|
|
|
want: time.Time{},
|
|
|
|
wantErr: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "empty timestamp",
|
|
|
|
timestamp: "",
|
|
|
|
want: time.Time{},
|
|
|
|
wantErr: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "invalid format",
|
|
|
|
timestamp: "seconds:%d nanos:%d",
|
|
|
|
want: time.Time{},
|
|
|
|
wantErr: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "missing nanos",
|
|
|
|
timestamp: "seconds:10",
|
|
|
|
want: time.Time{},
|
|
|
|
wantErr: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "missing seconds",
|
|
|
|
timestamp: "nanos:0",
|
|
|
|
want: time.Time{},
|
|
|
|
wantErr: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
got, err := timestampFromString(tt.timestamp)
|
|
|
|
if (err != nil) != tt.wantErr {
|
|
|
|
t.Errorf("timestampFromString() error = %v, wantErr %v", err, tt.wantErr)
|
|
|
|
}
|
2024-08-05 18:27:15 +02:00
|
|
|
if !tt.want.Equal(got) {
|
|
|
|
t.Errorf("timestampFromString() = %q, want %q", got, tt.want)
|
2023-08-22 18:52:49 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2024-06-06 17:14:08 +05:30
|
|
|
|
|
|
|
func Test_getFlattenMode(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
parameters map[string]string
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
args args
|
2024-07-26 10:01:02 +02:00
|
|
|
want types.FlattenMode
|
2024-06-06 17:14:08 +05:30
|
|
|
wantErr bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "flattenMode option not set",
|
|
|
|
args: args{
|
2025-04-29 11:36:03 +02:00
|
|
|
ctx: t.Context(),
|
2024-06-06 17:14:08 +05:30
|
|
|
parameters: map[string]string{},
|
|
|
|
},
|
2024-07-26 10:01:02 +02:00
|
|
|
want: types.FlattenModeNever,
|
2024-06-06 17:14:08 +05:30
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "flattenMode option set to never",
|
|
|
|
args: args{
|
2025-04-29 11:36:03 +02:00
|
|
|
ctx: t.Context(),
|
2024-06-06 17:14:08 +05:30
|
|
|
parameters: map[string]string{
|
2024-07-26 10:01:02 +02:00
|
|
|
flattenModeKey: string(types.FlattenModeNever),
|
2024-06-06 17:14:08 +05:30
|
|
|
},
|
|
|
|
},
|
2024-07-26 10:01:02 +02:00
|
|
|
want: types.FlattenModeNever,
|
2024-06-06 17:14:08 +05:30
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "flattenMode option set to force",
|
|
|
|
args: args{
|
2025-04-29 11:36:03 +02:00
|
|
|
ctx: t.Context(),
|
2024-06-06 17:14:08 +05:30
|
|
|
parameters: map[string]string{
|
2024-07-26 10:01:02 +02:00
|
|
|
flattenModeKey: string(types.FlattenModeForce),
|
2024-06-06 17:14:08 +05:30
|
|
|
},
|
|
|
|
},
|
2024-07-26 10:01:02 +02:00
|
|
|
want: types.FlattenModeForce,
|
2024-06-06 17:14:08 +05:30
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
name: "flattenMode option set to invalid value",
|
|
|
|
args: args{
|
2025-04-29 11:36:03 +02:00
|
|
|
ctx: t.Context(),
|
2024-06-06 17:14:08 +05:30
|
|
|
parameters: map[string]string{
|
|
|
|
flattenModeKey: "invalid123",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
wantErr: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
got, err := getFlattenMode(tt.args.ctx, tt.args.parameters)
|
|
|
|
if (err != nil) != tt.wantErr {
|
|
|
|
t.Errorf("getFlattenMode() error = %v, wantErr %v", err, tt.wantErr)
|
|
|
|
}
|
|
|
|
if !tt.wantErr && !reflect.DeepEqual(got, tt.want) {
|
|
|
|
t.Errorf("getFlattenMode() = %v, want %v", got, tt.want)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|