Path: blob/master/src/packages/database/postgres/site-license/hook.test.ts
1503 views
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45/**67pnpm test hook.test.ts89* This tests the core of ./hook.ts10* It's not using it directly, though, because of the complex dependency of the database.11* The main purpose of this test is to simulate what happens, if first a partial set of licenses,12* and then one more license is fed through the quota function.13* There was a bug, where licenses were modified in place, and the second call to the quota function14* used the modified license, which led to very subtle but severe problems.15*16* The quota function uses a deep copy operation on all its arguments to avoid this.17*/1819// see packages/database/pool/pool.ts for where this name is also hard coded:20process.env.PGDATABASE = "smc_ephemeral_testing_database";2122import { isEqual } from "lodash";2324import getPool, { initEphemeralDatabase } from "@cocalc/database/pool";25import { quota_with_reasons, SiteLicenses } from "@cocalc/util/upgrades/quota";2627beforeAll(async () => {28await initEphemeralDatabase({});29}, 15000);3031afterAll(async () => {32await getPool().end();33});3435test("allow for much larger max_upgrades", () => {36const site_settings = {37default_quotas: {38internet: true,39idle_timeout: 1800,40mem: 2000,41cpu: 1,42cpu_oc: 20,43mem_oc: 10,44},45max_upgrades: {46disk_quota: 20000,47memory: 50000,48memory_request: 1000,49cores: 16,50network: 1,51cpu_shares: 1024,52mintime: 7776000,53member_host: 1,54ephemeral_state: 1,55ephemeral_disk: 1,56always_running: 1,57},58kucalc: "onprem",59datastore: true,60};6162const site_licenses: SiteLicenses = {63a: {64quota: { cpu: 2, ram: 13 },65},66b: {67quota: { cpu: 3, ram: 32 },68},69};7071const q1 = quota_with_reasons(72{},73{ userX: {} },74{ a: site_licenses.a },75site_settings,76);77expect(q1).toEqual({78quota: {79network: true,80member_host: false,81privileged: false,82gpu: false,83memory_request: 1000,84cpu_request: 0.1,85disk_quota: 3000,86memory_limit: 13000,87cpu_limit: 2,88idle_timeout: 1800,89always_running: false,90dedicated_vm: false,91dedicated_disks: [],92},93reasons: {},94});9596const q2 = quota_with_reasons(97{},98{ userX: {} },99site_licenses,100site_settings,101);102expect(q2).toEqual({103quota: {104always_running: false,105cpu_limit: 5,106cpu_request: 0.25,107dedicated_disks: [],108dedicated_vm: false,109disk_quota: 3000,110idle_timeout: 1800,111member_host: false,112memory_limit: 45000,113memory_request: 1000,114network: true,115privileged: false,116gpu: false,117},118reasons: {},119});120});121122test("two licenses", () => {123const site_settings = {124default_quotas: {125internet: true,126idle_timeout: 1800,127mem: 2000,128cpu: 1,129cpu_oc: 20,130mem_oc: 10,131},132max_upgrades: {133disk_quota: 20000,134memory: 50000,135memory_request: 1000,136cores: 16,137network: 1,138cpu_shares: 1024,139mintime: 7776000,140member_host: 1,141ephemeral_state: 1,142ephemeral_disk: 1,143always_running: 1,144},145kucalc: "onprem",146datastore: true,147};148149const site_licenses = {150a: {151quota: { cpu: 1, ram: 13 },152},153b: {154quota: { cpu: 3, ram: 32 },155},156};157158const q1 = quota_with_reasons(159{},160{ userX: {} },161{ a: site_licenses.a },162site_settings,163);164expect(q1).toEqual({165quota: {166network: true,167member_host: false,168privileged: false,169gpu: false,170memory_request: 1000,171cpu_request: 0.05,172disk_quota: 3000,173memory_limit: 13000,174cpu_limit: 1,175idle_timeout: 1800,176always_running: false,177dedicated_vm: false,178dedicated_disks: [],179},180reasons: {},181});182183const q2 = quota_with_reasons(184{},185{ userX: {} },186site_licenses,187site_settings,188);189expect(q1).toEqual({190quota: {191network: true,192member_host: false,193privileged: false,194gpu: false,195memory_request: 1000,196cpu_request: 0.05,197disk_quota: 3000,198memory_limit: 13000,199cpu_limit: 1,200idle_timeout: 1800,201always_running: false,202dedicated_vm: false,203dedicated_disks: [],204},205reasons: {},206});207208expect(q2).toEqual({209quota: {210always_running: false,211cpu_limit: 4,212cpu_request: 0.2,213dedicated_disks: [],214dedicated_vm: false,215disk_quota: 3000,216idle_timeout: 1800,217member_host: false,218memory_limit: 45000,219memory_request: 1000,220network: true,221privileged: false,222gpu: false,223},224reasons: {},225});226227// in particular, this implies that the second license indeed HAS an effect and hence will be used.228expect(isEqual(q1, q2)).toBe(false);229});230231// TODO the test below would be very important to get to work, but the call to the site_license_hook has no effect at all232233// describe("site_license_hook", () => {234// const pool = getPool();235// const account_id = uuid();236// const license_id_1 = uuid();237// const license_id_2 = uuid();238239// let project_id;240// test("creates a project", async () => {241// project_id = await createProject({242// account_id,243// title: "Test Project",244// });245// });246247// test("setup project license", async () => {248// const site_licenses_data: SiteLicenses = {249// [license_id_1]: {250// quota: {251// dedicated_disk: { speed: "standard", size_gb: 128, name: "bar" },252// },253// },254// [license_id_2]: {255// quota: {256// ram: 2,257// cpu: 1,258// disk: 3,259// always_running: true,260// member: true,261// user: "academic",262// },263// },264// };265266// await pool.query(267// "UPDATE projects SET site_license=$1 WHERE project_id=$2",268// [site_licenses_data, project_id]269// );270// });271272// test("PAYGO mixes with dedicated disk", async () => {273// // run the hook -- "true" means there are PAYGO upgrades, different mode of how the license hook operates274// await site_license_hook(db(), project_id, true);275276// const { rows } = await pool.query(277// "SELECT * FROM projects WHERE project_id=$1",278// [project_id]279// );280// expect(rows.length).toBe(1);281// const site_licenses = rows[0].site_license;282// expect(rows[0].site_license).toEqual({283// [license_id_1]: {284// quota: {285// dedicated_disk: { name: "bar", size_gb: 128, speed: "standard" },286// },287// },288// [license_id_2]: {289// quota: {290// always_running: true,291// cpu: 1,292// disk: 3,293// member: true,294// ram: 2,295// user: "academic",296// },297// },298// });299300// const q = quota_with_reasons({}, { [account_id]: {} }, site_licenses);301// // projects on dedicated VMs get this quota302// expect(q).toEqual({303// quota: {304// always_running: false,305// cpu_limit: 1,306// cpu_request: 0.02,307// dedicated_disks: [308// {309// name: "bar",310// size_gb: 128,311// speed: "standard",312// },313// ],314// dedicated_vm: false,315// disk_quota: 3000,316// idle_timeout: 1800,317// member_host: false,318// memory_limit: 1000,319// memory_request: 200,320// network: false,321// privileged: false,gpu:false,322// },323// reasons: {},324// });325// });326// });327328329