"use strict";
/**
 * Tests persistent token management
 *
 *  Copyright (C) 2010-2019 R-T Specialty, LLC.
 *
 *  This file is part of the Liza Data Collection Framework.
 *
 *  liza is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
Object.defineProperty(exports, "__esModule", { value: true });
var PersistentTokenStore_1 = require("../../../../src/server/token/store/PersistentTokenStore");
var Token_1 = require("../../../../src/server/token/Token");
var chai_1 = require("chai");
chai_1.use(require('chai-as-promised'));
describe('PersistentTokenStore', function () {
    // required via the ctor, but this name is just used to denote that it's
    // not used for a particular test
    var voidIdgen = function () { return '00'; };
    describe('#lookupToken', function () {
        var _a;
        var doc_id = 5;
        var ns = 'namespace';
        var token_id = 'token';
        var expected_ts = 12345;
        var expected_data = 'token data';
        [
            [
                'returns existing token with matching last',
                {
                    id: token_id,
                    status: {
                        type: Token_1.TokenState.ACTIVE,
                        timestamp: expected_ts,
                        data: expected_data,
                    },
                    prev_status: null,
                    prev_last: {
                        id: token_id,
                        status: {
                            type: Token_1.TokenState.ACTIVE,
                            timestamp: expected_ts,
                            data: expected_data,
                        },
                        prev_status: null,
                        prev_last: null,
                    },
                },
                {
                    id: token_id,
                    state: Token_1.TokenState.ACTIVE,
                    timestamp: expected_ts,
                    data: expected_data,
                    last_mismatch: false,
                    last_created: false,
                },
            ],
            [
                'returns existing token with mismatched last',
                {
                    id: token_id,
                    status: {
                        type: Token_1.TokenState.DEAD,
                        timestamp: expected_ts,
                        data: expected_data,
                    },
                    prev_status: null,
                    prev_last: {
                        id: 'something-else',
                        status: {
                            type: Token_1.TokenState.DEAD,
                            timestamp: expected_ts,
                            data: expected_data,
                        },
                        prev_status: null,
                        prev_last: null,
                    },
                },
                {
                    id: token_id,
                    state: Token_1.TokenState.DEAD,
                    timestamp: expected_ts,
                    data: expected_data,
                    last_mismatch: true,
                    last_created: false,
                },
            ],
            [
                'returns existing token with set last created',
                {
                    id: token_id,
                    status: {
                        type: Token_1.TokenState.DEAD,
                        timestamp: expected_ts,
                        data: expected_data,
                    },
                    prev_status: null,
                    prev_last: null,
                    prev_state: (_a = {},
                        _a[Token_1.TokenState.ACTIVE] = token_id,
                        _a),
                },
                {
                    id: token_id,
                    state: Token_1.TokenState.DEAD,
                    timestamp: expected_ts,
                    data: expected_data,
                    last_mismatch: true,
                    last_created: true,
                },
            ],
        ].forEach(function (_a) {
            var label = _a[0], dbdata = _a[1], expected = _a[2];
            return it(label, function () {
                var dao = new (/** @class */ (function () {
                    function class_1() {
                    }
                    class_1.prototype.getToken = function (given_doc_id, given_ns, given_token_id) {
                        chai_1.expect(given_doc_id).to.equal(doc_id);
                        chai_1.expect(given_ns).to.equal(ns);
                        chai_1.expect(given_token_id).to.equal(token_id);
                        return Promise.resolve(dbdata);
                    };
                    class_1.prototype.updateToken = function () {
                        return Promise.reject('unused method');
                    };
                    return class_1;
                }()))();
                return chai_1.expect(new PersistentTokenStore_1.PersistentTokenStore(dao, doc_id, ns, voidIdgen).lookupToken(token_id)).to.eventually.deep.equal(expected);
            });
        });
        it('propagates database errors', function () {
            var doc_id = 0;
            var ns = 'badns';
            var token_id = 'badtok';
            var expected_e = new Error('test error');
            var dao = new (/** @class */ (function () {
                function class_2() {
                }
                class_2.prototype.getToken = function () {
                    return Promise.reject(expected_e);
                };
                class_2.prototype.updateToken = function () {
                    return Promise.reject('unused method');
                };
                return class_2;
            }()))();
            return chai_1.expect(new PersistentTokenStore_1.PersistentTokenStore(dao, doc_id, ns, voidIdgen).lookupToken(token_id)).to.eventually.be.rejectedWith(expected_e);
        });
    });
    describe('#createToken', function () {
        var doc_id = 5;
        var ns = 'namespace';
        var token_id = 'token';
        var expected_ts = 12345;
        var expected_data = 'token data';
        [
            [
                'creates token with last_mismatch given last',
                {
                    id: token_id,
                    status: {
                        type: Token_1.TokenState.ACTIVE,
                        timestamp: expected_ts,
                        data: expected_data,
                    },
                    prev_status: null,
                    prev_last: {
                        id: 'something-else',
                        status: {
                            type: Token_1.TokenState.ACTIVE,
                            timestamp: expected_ts,
                            data: expected_data,
                        },
                        prev_status: null,
                        prev_last: null,
                    },
                    prev_state: {},
                },
                {
                    id: token_id,
                    state: Token_1.TokenState.ACTIVE,
                    timestamp: expected_ts,
                    data: expected_data,
                    last_mismatch: true,
                    last_created: true,
                },
            ],
            [
                'creates token with last_mismatch given null last',
                {
                    id: token_id,
                    status: {
                        type: Token_1.TokenState.ACTIVE,
                        timestamp: expected_ts,
                        data: expected_data,
                    },
                    prev_status: null,
                    prev_last: null,
                    prev_state: {},
                },
                {
                    id: token_id,
                    state: Token_1.TokenState.ACTIVE,
                    timestamp: expected_ts,
                    data: expected_data,
                    last_mismatch: true,
                    last_created: true,
                },
            ],
        ].forEach(function (_a) {
            var label = _a[0], dbdata = _a[1], expected = _a[2];
            return it(label, function () {
                var dao = new (/** @class */ (function () {
                    function class_3() {
                    }
                    class_3.prototype.getToken = function () {
                        return Promise.reject('unused method');
                    };
                    class_3.prototype.updateToken = function (given_doc_id, given_ns, given_token_id, given_type, given_data) {
                        chai_1.expect(given_doc_id).to.equal(doc_id);
                        chai_1.expect(given_ns).to.equal(ns);
                        chai_1.expect(given_token_id).to.equal(token_id);
                        chai_1.expect(given_type).to.equal(Token_1.TokenState.ACTIVE);
                        chai_1.expect(given_data).to.equal(null);
                        return Promise.resolve(dbdata);
                    };
                    return class_3;
                }()))();
                return chai_1.expect(new PersistentTokenStore_1.PersistentTokenStore(dao, doc_id, ns, function () { return token_id; }).createToken()).to.eventually.deep.equal(expected);
            });
        });
    });
    // each of the state changes do the same thing, just behind a
    // type-restrictive API
    var expected_ts = 123;
    [
        [
            'completeToken',
            {
                id: 'complete-test',
                state: Token_1.TokenState.ACTIVE,
                timestamp: 0,
                data: '',
                last_mismatch: true,
                last_created: true,
            },
            'complete-data',
            {
                id: 'complete-test',
                state: Token_1.TokenState.DONE,
                timestamp: expected_ts,
                data: 'complete-data',
                last_mismatch: true,
                last_created: true,
            },
        ],
        [
            'acceptToken',
            {
                id: 'accept-test',
                state: Token_1.TokenState.DONE,
                timestamp: 0,
                data: 'accept',
                last_mismatch: true,
                last_created: true,
            },
            'accept-data',
            {
                id: 'accept-test',
                state: Token_1.TokenState.ACCEPTED,
                timestamp: expected_ts,
                data: 'accept-data',
                last_mismatch: true,
                last_created: true,
            },
        ],
        [
            'killToken',
            {
                id: 'kill-test',
                state: Token_1.TokenState.ACTIVE,
                timestamp: 0,
                data: 'kill',
                last_mismatch: true,
                last_created: true,
            },
            'kill-data',
            {
                id: 'kill-test',
                state: Token_1.TokenState.DEAD,
                timestamp: expected_ts,
                data: 'kill-data',
                last_mismatch: true,
                last_created: true,
            },
        ],
    ].forEach(function (_a) {
        var method = _a[0], token = _a[1], data = _a[2], expected = _a[3];
        return describe("#" + method, function () {
            var doc_id = 1234;
            var ns = 'update-ns';
            it('changes token state', function () {
                var dao = new (/** @class */ (function () {
                    function class_4() {
                    }
                    class_4.prototype.getToken = function () {
                        return Promise.reject('unused method');
                    };
                    class_4.prototype.updateToken = function (given_doc_id, given_ns, given_token_id, given_type, given_data) {
                        var _a;
                        chai_1.expect(given_doc_id).to.equal(doc_id);
                        chai_1.expect(given_ns).to.equal(ns);
                        chai_1.expect(given_token_id).to.equal(token.id);
                        chai_1.expect(given_type).to.equal(expected.state);
                        chai_1.expect(given_data).to.equal(data);
                        return Promise.resolve({
                            id: token.id,
                            status: {
                                // purposefully hard-coded, since this is ignored
                                type: Token_1.TokenState.ACTIVE,
                                timestamp: expected_ts,
                                data: given_data,
                            },
                            prev_status: null,
                            prev_last: null,
                            prev_state: (_a = {},
                                _a[Token_1.TokenState.ACTIVE] = token.id,
                                _a),
                        });
                    };
                    return class_4;
                }()))();
                // this discards some type information for the sake of dynamic
                // dispatch, so it's not testing the state transition
                // restrictions that are enforced by the compiler
                return chai_1.expect(new PersistentTokenStore_1.PersistentTokenStore(dao, doc_id, ns, voidIdgen)[method](token, data)).to.eventually.deep.equal(expected);
            });
        });
    });
});
//# sourceMappingURL=data:application/json;base64, 