"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const bytes_1 = tslib_1.__importDefault(require("bytes"));
const chai_1 = require("chai");
const fs_extra_1 = require("fs-extra");
const lodash_1 = require("lodash");
const shared_1 = require("../../shared");
const core_utils_1 = require("../../../../shared/core-utils");
const server_commands_1 = require("../../../../shared/server-commands");
function checkFiles(options) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const { video, playlistBucket, webtorrentBucket, baseMockUrl, playlistPrefix, webtorrentPrefix } = options;
        let allFiles = video.files;
        for (const file of video.files) {
            const baseUrl = baseMockUrl
                ? `${baseMockUrl}/${webtorrentBucket}/`
                : `http://${webtorrentBucket}.${server_commands_1.ObjectStorageCommand.getMockEndpointHost()}/`;
            const prefix = webtorrentPrefix || '';
            const start = baseUrl + prefix;
            (0, shared_1.expectStartWith)(file.fileUrl, start);
            const res = yield (0, server_commands_1.makeRawRequest)({ url: file.fileDownloadUrl, expectedStatus: 302 });
            const location = res.headers['location'];
            (0, shared_1.expectStartWith)(location, start);
            yield (0, server_commands_1.makeRawRequest)({ url: location, expectedStatus: 200 });
        }
        const hls = video.streamingPlaylists[0];
        if (hls) {
            allFiles = allFiles.concat(hls.files);
            const baseUrl = baseMockUrl
                ? `${baseMockUrl}/${playlistBucket}/`
                : `http://${playlistBucket}.${server_commands_1.ObjectStorageCommand.getMockEndpointHost()}/`;
            const prefix = playlistPrefix || '';
            const start = baseUrl + prefix;
            (0, shared_1.expectStartWith)(hls.playlistUrl, start);
            (0, shared_1.expectStartWith)(hls.segmentsSha256Url, start);
            yield (0, server_commands_1.makeRawRequest)({ url: hls.playlistUrl, expectedStatus: 200 });
            const resSha = yield (0, server_commands_1.makeRawRequest)({ url: hls.segmentsSha256Url, expectedStatus: 200 });
            (0, chai_1.expect)(JSON.stringify(resSha.body)).to.not.throw;
            for (const file of hls.files) {
                (0, shared_1.expectStartWith)(file.fileUrl, start);
                const res = yield (0, server_commands_1.makeRawRequest)({ url: file.fileDownloadUrl, expectedStatus: 302 });
                const location = res.headers['location'];
                (0, shared_1.expectStartWith)(location, start);
                yield (0, server_commands_1.makeRawRequest)({ url: location, expectedStatus: 200 });
            }
        }
        for (const file of allFiles) {
            const torrent = yield (0, server_commands_1.webtorrentAdd)(file.magnetUri, true);
            (0, chai_1.expect)(torrent.files).to.be.an('array');
            (0, chai_1.expect)(torrent.files.length).to.equal(1);
            (0, chai_1.expect)(torrent.files[0].path).to.exist.and.to.not.equal('');
            const res = yield (0, server_commands_1.makeRawRequest)({ url: file.fileUrl, expectedStatus: 200 });
            (0, chai_1.expect)(res.body).to.have.length.above(100);
        }
        return allFiles.map(f => f.fileUrl);
    });
}
function runTestSuite(options) {
    const mockObjectStorage = new shared_1.MockObjectStorage();
    const { fixture } = options;
    let baseMockUrl;
    let servers;
    let keptUrls = [];
    const uuidsToDelete = [];
    let deletedUrls = [];
    before(function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            this.timeout(120000);
            const port = yield mockObjectStorage.initialize();
            baseMockUrl = options.useMockBaseUrl ? `http://127.0.0.1:${port}` : undefined;
            yield server_commands_1.ObjectStorageCommand.createMockBucket(options.playlistBucket);
            yield server_commands_1.ObjectStorageCommand.createMockBucket(options.webtorrentBucket);
            const config = {
                object_storage: {
                    enabled: true,
                    endpoint: 'http://' + server_commands_1.ObjectStorageCommand.getMockEndpointHost(),
                    region: server_commands_1.ObjectStorageCommand.getMockRegion(),
                    credentials: server_commands_1.ObjectStorageCommand.getMockCredentialsConfig(),
                    max_upload_part: options.maxUploadPart || '5MB',
                    streaming_playlists: {
                        bucket_name: options.playlistBucket,
                        prefix: options.playlistPrefix,
                        base_url: baseMockUrl
                            ? `${baseMockUrl}/${options.playlistBucket}`
                            : undefined
                    },
                    videos: {
                        bucket_name: options.webtorrentBucket,
                        prefix: options.webtorrentPrefix,
                        base_url: baseMockUrl
                            ? `${baseMockUrl}/${options.webtorrentBucket}`
                            : undefined
                    }
                }
            };
            servers = yield (0, server_commands_1.createMultipleServers)(2, config);
            yield (0, server_commands_1.setAccessTokensToServers)(servers);
            yield (0, server_commands_1.doubleFollow)(servers[0], servers[1]);
            for (const server of servers) {
                const { uuid } = yield server.videos.quickUpload({ name: 'video to keep' });
                yield (0, server_commands_1.waitJobs)(servers);
                const files = yield server.videos.listFiles({ id: uuid });
                keptUrls = keptUrls.concat(files.map(f => f.fileUrl));
            }
        });
    });
    it('Should upload a video and move it to the object storage without transcoding', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            this.timeout(40000);
            const { uuid } = yield servers[0].videos.quickUpload({ name: 'video 1', fixture });
            uuidsToDelete.push(uuid);
            yield (0, server_commands_1.waitJobs)(servers);
            for (const server of servers) {
                const video = yield server.videos.get({ id: uuid });
                const files = yield checkFiles(Object.assign(Object.assign({}, options), { video, baseMockUrl }));
                deletedUrls = deletedUrls.concat(files);
            }
        });
    });
    it('Should upload a video and move it to the object storage with transcoding', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            this.timeout(120000);
            const { uuid } = yield servers[1].videos.quickUpload({ name: 'video 2', fixture });
            uuidsToDelete.push(uuid);
            yield (0, server_commands_1.waitJobs)(servers);
            for (const server of servers) {
                const video = yield server.videos.get({ id: uuid });
                const files = yield checkFiles(Object.assign(Object.assign({}, options), { video, baseMockUrl }));
                deletedUrls = deletedUrls.concat(files);
            }
        });
    });
    it('Should fetch correctly all the files', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            for (const url of deletedUrls.concat(keptUrls)) {
                yield (0, server_commands_1.makeRawRequest)({ url, expectedStatus: 200 });
            }
        });
    });
    it('Should correctly delete the files', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            yield servers[0].videos.remove({ id: uuidsToDelete[0] });
            yield servers[1].videos.remove({ id: uuidsToDelete[1] });
            yield (0, server_commands_1.waitJobs)(servers);
            for (const url of deletedUrls) {
                yield (0, server_commands_1.makeRawRequest)({ url, expectedStatus: 404 });
            }
        });
    });
    it('Should have kept other files', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            for (const url of keptUrls) {
                yield (0, server_commands_1.makeRawRequest)({ url, expectedStatus: 200 });
            }
        });
    });
    it('Should have an empty tmp directory', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            for (const server of servers) {
                yield (0, shared_1.checkTmpIsEmpty)(server);
            }
        });
    });
    it('Should not have downloaded files from object storage', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            for (const server of servers) {
                yield (0, shared_1.expectLogDoesNotContain)(server, 'from object storage');
            }
        });
    });
    after(function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            yield mockObjectStorage.terminate();
            yield (0, server_commands_1.cleanupTests)(servers);
        });
    });
}
describe('Object storage for videos', function () {
    if ((0, core_utils_1.areMockObjectStorageTestsDisabled)())
        return;
    describe('Test config', function () {
        let server;
        const baseConfig = {
            object_storage: {
                enabled: true,
                endpoint: 'http://' + server_commands_1.ObjectStorageCommand.getMockEndpointHost(),
                region: server_commands_1.ObjectStorageCommand.getMockRegion(),
                credentials: server_commands_1.ObjectStorageCommand.getMockCredentialsConfig(),
                streaming_playlists: {
                    bucket_name: server_commands_1.ObjectStorageCommand.DEFAULT_PLAYLIST_MOCK_BUCKET
                },
                videos: {
                    bucket_name: server_commands_1.ObjectStorageCommand.DEFAULT_WEBTORRENT_MOCK_BUCKET
                }
            }
        };
        const badCredentials = {
            access_key_id: 'AKIAIOSFODNN7EXAMPLE',
            secret_access_key: 'aJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'
        };
        it('Should fail with same bucket names without prefix', function (done) {
            const config = (0, lodash_1.merge)({}, baseConfig, {
                object_storage: {
                    streaming_playlists: {
                        bucket_name: 'aaa'
                    },
                    videos: {
                        bucket_name: 'aaa'
                    }
                }
            });
            (0, server_commands_1.createSingleServer)(1, config)
                .then(() => done(new Error('Did not throw')))
                .catch(() => done());
        });
        it('Should fail with bad credentials', function () {
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                this.timeout(60000);
                yield server_commands_1.ObjectStorageCommand.prepareDefaultMockBuckets();
                const config = (0, lodash_1.merge)({}, baseConfig, {
                    object_storage: {
                        credentials: badCredentials
                    }
                });
                server = yield (0, server_commands_1.createSingleServer)(1, config);
                yield (0, server_commands_1.setAccessTokensToServers)([server]);
                const { uuid } = yield server.videos.quickUpload({ name: 'video' });
                yield (0, server_commands_1.waitJobs)([server], { skipDelayed: true });
                const video = yield server.videos.get({ id: uuid });
                (0, shared_1.expectStartWith)(video.files[0].fileUrl, server.url);
                yield (0, server_commands_1.killallServers)([server]);
            });
        });
        it('Should succeed with credentials from env', function () {
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                this.timeout(60000);
                yield server_commands_1.ObjectStorageCommand.prepareDefaultMockBuckets();
                const config = (0, lodash_1.merge)({}, baseConfig, {
                    object_storage: {
                        credentials: {
                            access_key_id: '',
                            secret_access_key: ''
                        }
                    }
                });
                const goodCredentials = server_commands_1.ObjectStorageCommand.getMockCredentialsConfig();
                server = yield (0, server_commands_1.createSingleServer)(1, config, {
                    env: {
                        AWS_ACCESS_KEY_ID: goodCredentials.access_key_id,
                        AWS_SECRET_ACCESS_KEY: goodCredentials.secret_access_key
                    }
                });
                yield (0, server_commands_1.setAccessTokensToServers)([server]);
                const { uuid } = yield server.videos.quickUpload({ name: 'video' });
                yield (0, server_commands_1.waitJobs)([server], { skipDelayed: true });
                const video = yield server.videos.get({ id: uuid });
                (0, shared_1.expectStartWith)(video.files[0].fileUrl, server_commands_1.ObjectStorageCommand.getMockWebTorrentBaseUrl());
            });
        });
        after(function () {
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                yield (0, server_commands_1.killallServers)([server]);
            });
        });
    });
    describe('Test simple object storage', function () {
        runTestSuite({
            playlistBucket: 'streaming-playlists',
            webtorrentBucket: 'videos'
        });
    });
    describe('Test object storage with prefix', function () {
        runTestSuite({
            playlistBucket: 'mybucket',
            webtorrentBucket: 'mybucket',
            playlistPrefix: 'streaming-playlists_',
            webtorrentPrefix: 'webtorrent_'
        });
    });
    describe('Test object storage with prefix and base URL', function () {
        runTestSuite({
            playlistBucket: 'mybucket',
            webtorrentBucket: 'mybucket',
            playlistPrefix: 'streaming-playlists/',
            webtorrentPrefix: 'webtorrent/',
            useMockBaseUrl: true
        });
    });
    describe('Test object storage with file bigger than upload part', function () {
        let fixture;
        const maxUploadPart = '5MB';
        before(function () {
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                this.timeout(120000);
                fixture = yield (0, shared_1.generateHighBitrateVideo)();
                const { size } = yield (0, fs_extra_1.stat)(fixture);
                if (bytes_1.default.parse(maxUploadPart) > size) {
                    throw Error(`Fixture file is too small (${size}) to make sense for this test.`);
                }
            });
        });
        runTestSuite({
            maxUploadPart,
            playlistBucket: 'streaming-playlists',
            webtorrentBucket: 'videos',
            fixture
        });
    });
});
//# sourceMappingURL=videos.js.map