forked from misskey-dev/misskey
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bump aws-sdk to v3 for s3 (misskey-dev#10363)
* indent * aws-sdk v3移行
- Loading branch information
Showing
6 changed files
with
1,268 additions
and
165 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,55 +1,56 @@ | ||
process.env.NODE_ENV = 'test'; | ||
|
||
import { jest } from '@jest/globals'; | ||
import { Test } from '@nestjs/testing'; | ||
import { DeleteObjectCommandOutput, DeleteObjectCommand, NoSuchKey, InvalidObjectState, S3Client } from '@aws-sdk/client-s3'; | ||
import { mockClient } from 'aws-sdk-client-mock'; | ||
import { GlobalModule } from '@/GlobalModule.js'; | ||
import { DriveService } from '@/core/DriveService.js'; | ||
import { CoreModule } from '@/core/CoreModule.js'; | ||
import { S3Service } from '@/core/S3Service'; | ||
import type { Meta } from '@/models'; | ||
import type { DeleteObjectOutput } from 'aws-sdk/clients/s3'; | ||
import type { AWSError } from 'aws-sdk/lib/error'; | ||
import type { PromiseResult, Request } from 'aws-sdk/lib/request'; | ||
import type { TestingModule } from '@nestjs/testing'; | ||
|
||
describe('DriveService', () => { | ||
let app: TestingModule; | ||
let driveService: DriveService; | ||
const s3Mock = mockClient(S3Client); | ||
|
||
beforeEach(async () => { | ||
beforeAll(async () => { | ||
app = await Test.createTestingModule({ | ||
imports: [GlobalModule, CoreModule], | ||
providers: [DriveService, S3Service], | ||
providers: [DriveService], | ||
}).compile(); | ||
app.enableShutdownHooks(); | ||
driveService = app.get<DriveService>(DriveService); | ||
}); | ||
|
||
const s3Service = app.get<S3Service>(S3Service); | ||
const s3 = s3Service.getS3({} as Meta); | ||
|
||
// new S3() surprisingly does not return an instance of class S3. | ||
// Let's use getPrototypeOf here to get a real prototype, since spying on S3.prototype doesn't work. | ||
// TODO: Use `aws-sdk-client-mock` package when upgrading to AWS SDK v3. | ||
jest.spyOn(Object.getPrototypeOf(s3), 'deleteObject').mockImplementation(() => { | ||
// Roughly mock AWS request object | ||
return { | ||
async promise(): Promise<PromiseResult<DeleteObjectOutput, AWSError>> { | ||
const err = new Error('mock') as AWSError; | ||
err.code = 'NoSuchKey'; | ||
throw err; | ||
}, | ||
} as Request<DeleteObjectOutput, AWSError>; | ||
}); | ||
beforeEach(async () => { | ||
s3Mock.reset(); | ||
}); | ||
|
||
afterAll(async () => { | ||
await app.close(); | ||
}); | ||
|
||
describe('Object storage', () => { | ||
test('delete a file', async () => { | ||
s3Mock.on(DeleteObjectCommand) | ||
.resolves({} as DeleteObjectCommandOutput); | ||
|
||
await driveService.deleteObjectStorageFile('peace of the world'); | ||
}); | ||
|
||
test('delete a file then unexpected error', async () => { | ||
s3Mock.on(DeleteObjectCommand) | ||
.rejects(new InvalidObjectState({ $metadata: {}, message: '' })); | ||
|
||
await expect(driveService.deleteObjectStorageFile('unexpected')).rejects.toThrowError(Error); | ||
}); | ||
|
||
test('delete a file with no valid key', async () => { | ||
try { | ||
await driveService.deleteObjectStorageFile('lol no way'); | ||
} catch (err: any) { | ||
console.log(err.cause); | ||
throw err; | ||
} | ||
// Some S3 implementations returns 404 Not Found on deleting with a non-existent key | ||
s3Mock.on(DeleteObjectCommand) | ||
.rejects(new NoSuchKey({ $metadata: {}, message: 'allowed error.' })); | ||
|
||
await driveService.deleteObjectStorageFile('lol no way'); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
process.env.NODE_ENV = 'test'; | ||
|
||
import { Test } from '@nestjs/testing'; | ||
import { UploadPartCommand, CompleteMultipartUploadCommand, CreateMultipartUploadCommand, S3Client, PutObjectCommand } from '@aws-sdk/client-s3'; | ||
import { mockClient } from 'aws-sdk-client-mock'; | ||
import { GlobalModule } from '@/GlobalModule.js'; | ||
import { CoreModule } from '@/core/CoreModule.js'; | ||
import { S3Service } from '@/core/S3Service'; | ||
import { Meta } from '@/models'; | ||
import type { TestingModule } from '@nestjs/testing'; | ||
|
||
describe('S3Service', () => { | ||
let app: TestingModule; | ||
let s3Service: S3Service; | ||
const s3Mock = mockClient(S3Client); | ||
|
||
beforeAll(async () => { | ||
app = await Test.createTestingModule({ | ||
imports: [GlobalModule, CoreModule], | ||
providers: [S3Service], | ||
}).compile(); | ||
app.enableShutdownHooks(); | ||
s3Service = app.get<S3Service>(S3Service); | ||
}); | ||
|
||
beforeEach(async () => { | ||
s3Mock.reset(); | ||
}); | ||
|
||
afterAll(async () => { | ||
await app.close(); | ||
}); | ||
|
||
describe('upload', () => { | ||
test('upload a file', async () => { | ||
s3Mock.on(PutObjectCommand).resolves({}); | ||
|
||
await s3Service.upload({ objectStorageRegion: 'us-east-1' } as Meta, { | ||
Bucket: 'fake', | ||
Key: 'fake', | ||
Body: 'x', | ||
}); | ||
}); | ||
|
||
test('upload a large file', async () => { | ||
s3Mock.on(CreateMultipartUploadCommand).resolves({ UploadId: '1' }); | ||
s3Mock.on(UploadPartCommand).resolves({ ETag: '1' }); | ||
s3Mock.on(CompleteMultipartUploadCommand).resolves({ Bucket: 'fake', Key: 'fake' }); | ||
|
||
await s3Service.upload({} as Meta, { | ||
Bucket: 'fake', | ||
Key: 'fake', | ||
Body: 'x'.repeat(8 * 1024 * 1024 + 1), // デフォルトpartSizeにしている 8 * 1024 * 1024 を越えるサイズ | ||
}); | ||
}); | ||
|
||
test('upload a file error', async () => { | ||
s3Mock.on(PutObjectCommand).rejects({ name: 'Fake Error' }); | ||
|
||
await expect(s3Service.upload({ objectStorageRegion: 'us-east-1' } as Meta, { | ||
Bucket: 'fake', | ||
Key: 'fake', | ||
Body: 'x', | ||
})).rejects.toThrowError(Error); | ||
}); | ||
|
||
test('upload a large file error', async () => { | ||
s3Mock.on(UploadPartCommand).rejects(); | ||
|
||
await expect(s3Service.upload({} as Meta, { | ||
Bucket: 'fake', | ||
Key: 'fake', | ||
Body: 'x'.repeat(8 * 1024 * 1024 + 1), // デフォルトpartSizeにしている 8 * 1024 * 1024 を越えるサイズ | ||
})).rejects.toThrowError(Error); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.