//go:build !integration package utils import ( "math" "strconv" "testing" "time" "github.com/stretchr/testify/require" ) func TestPrepareExpirationHeader(t *testing.T) { tomorrow := time.Now().Add(24 * time.Hour) tomorrowUnix := tomorrow.Unix() tomorrowUnixNano := tomorrow.UnixNano() tomorrowUnixMilli := tomorrowUnixNano / 1e6 epoch := "100" duration := "24h" timestampSec := strconv.FormatInt(tomorrowUnix, 10) timestampMilli := strconv.FormatInt(tomorrowUnixMilli, 10) timestampNano := strconv.FormatInt(tomorrowUnixNano, 10) defaultDurations := &EpochDurations{ CurrentEpoch: 10, MsPerBlock: 1000, BlockPerEpoch: 101, } msPerBlock := defaultDurations.BlockPerEpoch * uint64(defaultDurations.MsPerBlock) epochPerDay := uint64((24 * time.Hour).Milliseconds()) / msPerBlock if uint64((24*time.Hour).Milliseconds())%msPerBlock != 0 { epochPerDay++ } defaultExpEpoch := strconv.FormatUint(defaultDurations.CurrentEpoch+epochPerDay, 10) for _, transformer := range transformers { for _, tc := range []struct { name string headers map[string]string durations *EpochDurations err bool expected map[string]string }{ { name: "valid epoch", headers: map[string]string{transformer.expirationEpochAttr(): epoch}, expected: map[string]string{transformer.expirationEpochAttr(): epoch}, durations: defaultDurations, }, { name: "valid epoch, valid duration", headers: map[string]string{ transformer.expirationEpochAttr(): epoch, transformer.expirationDurationAttr(): duration, }, durations: defaultDurations, expected: map[string]string{transformer.expirationEpochAttr(): epoch}, }, { name: "valid epoch, valid rfc3339", headers: map[string]string{ transformer.expirationEpochAttr(): epoch, transformer.expirationRFC3339Attr(): tomorrow.Format(time.RFC3339), }, durations: defaultDurations, expected: map[string]string{transformer.expirationEpochAttr(): epoch}, }, { name: "valid epoch, valid timestamp sec", headers: map[string]string{ transformer.expirationEpochAttr(): epoch, transformer.expirationTimestampAttr(): timestampSec, }, durations: defaultDurations, expected: map[string]string{transformer.expirationEpochAttr(): epoch}, }, { name: "valid epoch, valid timestamp milli", headers: map[string]string{ transformer.expirationEpochAttr(): epoch, transformer.expirationTimestampAttr(): timestampMilli, }, durations: defaultDurations, expected: map[string]string{transformer.expirationEpochAttr(): epoch}, }, { name: "valid epoch, valid timestamp nano", headers: map[string]string{ transformer.expirationEpochAttr(): epoch, transformer.expirationTimestampAttr(): timestampNano, }, durations: defaultDurations, expected: map[string]string{transformer.expirationEpochAttr(): epoch}, }, { name: "valid timestamp sec", headers: map[string]string{transformer.expirationTimestampAttr(): timestampSec}, durations: defaultDurations, expected: map[string]string{transformer.expirationEpochAttr(): defaultExpEpoch}, }, { name: "valid duration", headers: map[string]string{transformer.expirationDurationAttr(): duration}, durations: defaultDurations, expected: map[string]string{transformer.expirationEpochAttr(): defaultExpEpoch}, }, { name: "valid rfc3339", headers: map[string]string{transformer.expirationRFC3339Attr(): tomorrow.Format(time.RFC3339)}, durations: defaultDurations, expected: map[string]string{transformer.expirationEpochAttr(): defaultExpEpoch}, }, { name: "valid max uint 64", headers: map[string]string{transformer.expirationRFC3339Attr(): tomorrow.Format(time.RFC3339)}, durations: &EpochDurations{ CurrentEpoch: math.MaxUint64 - 1, MsPerBlock: defaultDurations.MsPerBlock, BlockPerEpoch: defaultDurations.BlockPerEpoch, }, expected: map[string]string{transformer.expirationEpochAttr(): strconv.FormatUint(uint64(math.MaxUint64), 10)}, }, { name: "invalid timestamp sec", headers: map[string]string{transformer.expirationTimestampAttr(): "abc"}, err: true, }, { name: "invalid timestamp sec zero", headers: map[string]string{transformer.expirationTimestampAttr(): "0"}, err: true, }, { name: "invalid duration", headers: map[string]string{transformer.expirationDurationAttr(): "1d"}, err: true, }, { name: "invalid duration negative", headers: map[string]string{transformer.expirationDurationAttr(): "-5h"}, err: true, }, { name: "invalid rfc3339", headers: map[string]string{transformer.expirationRFC3339Attr(): "abc"}, err: true, }, { name: "invalid rfc3339 zero", headers: map[string]string{transformer.expirationRFC3339Attr(): time.RFC3339}, err: true, }, } { t.Run(tc.name, func(t *testing.T) { err := transformer.prepareExpirationHeader(tc.headers, tc.durations, time.Now()) if tc.err { require.Error(t, err) } else { require.NoError(t, err) require.Equal(t, tc.expected, tc.headers) } }) } } } func TestSystemBackwardTranslator(t *testing.T) { input := []string{ "__SYSTEM__EXPIRATION_EPOCH", "__SYSTEM__RANDOM_ATTR", "__NEOFS__EXPIRATION_EPOCH", "__NEOFS__RANDOM_ATTR", } expected := []string{ "System-Expiration-Epoch", "System-Random-Attr", "Neofs-Expiration-Epoch", "Neofs-Random-Attr", } for i, str := range input { res := BackwardTransformIfSystem(str) require.Equal(t, expected[i], res) } }