package oci import ( "context" "encoding/json" "strings" "testing" "time" ) // namespace 为租户常量:缓存命中时直接返回,不构造客户端、不发起远程调用 // (凭据为空也能取到,证明未走回源路径)。 func TestGetObjectStorageNamespaceCached(t *testing.T) { c := NewClient() tests := []struct { name string tenancy string seed string }{ {name: "缓存命中直接返回", tenancy: "ocid1.tenancy.oc1..aaaa", seed: "ns-a"}, {name: "不同租户各取各的", tenancy: "ocid1.tenancy.oc1..bbbb", seed: "ns-b"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { c.namespaces.Store(tt.tenancy, tt.seed) got, err := c.GetObjectStorageNamespace(context.Background(), Credentials{TenancyOCID: tt.tenancy}, "us-ashburn-1") if err != nil || got != tt.seed { t.Fatalf("GetObjectStorageNamespace = %q, %v; want %q", got, err, tt.seed) } }) } } func TestCreatePARDetailsBucketListingAction(t *testing.T) { cases := []struct { accessType string wantList bool }{ {"AnyObjectRead", true}, {"AnyObjectReadWrite", true}, {"AnyObjectWrite", false}, {"ObjectRead", false}, } for _, tc := range cases { details := createPARDetails(CreatePARInput{AccessType: tc.accessType, ExpiresHours: 1}, time.Unix(100, 0)) gotList := string(details.BucketListingAction) == "ListObjects" if gotList != tc.wantList { t.Errorf("%s listing = %q, wantList %v", tc.accessType, details.BucketListingAction, tc.wantList) } wire, err := json.Marshal(details) if err != nil { t.Fatalf("marshal %s details: %v", tc.accessType, err) } gotWireList := strings.Contains(string(wire), `"bucketListingAction":"ListObjects"`) if gotWireList != tc.wantList { t.Errorf("%s wire = %s, wantList %v", tc.accessType, wire, tc.wantList) } } } func TestCreatePARDetailsExpirationAndObject(t *testing.T) { now := time.Date(2026, 7, 22, 12, 0, 0, 0, time.UTC) details := createPARDetails(CreatePARInput{ Name: "share", ObjectName: "folder/a.txt", AccessType: "ObjectRead", ExpiresHours: 48, }, now) if got, want := details.TimeExpires.Time, now.Add(48*time.Hour); !got.Equal(want) { t.Errorf("TimeExpires = %v, want %v", got, want) } if details.ObjectName == nil || *details.ObjectName != "folder/a.txt" { t.Errorf("ObjectName = %v, want folder/a.txt", details.ObjectName) } defaults := createPARDetails(CreatePARInput{AccessType: "ObjectRead"}, now) if got, want := defaults.TimeExpires.Time, now.Add(24*time.Hour); !got.Equal(want) { t.Errorf("default TimeExpires = %v, want %v", got, want) } }