test.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*
  2. * Copyright (C) 2024 Puter Technologies Inc.
  3. *
  4. * This file is part of Puter.
  5. *
  6. * Puter is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License as published
  8. * by the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Affero General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License
  17. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  18. */
  19. const { AdvancedBase } = require("@heyputer/putility");
  20. const useapi = require("useapi");
  21. const { BaseService } = require("../exports");
  22. const CoreModule = require("../src/CoreModule");
  23. const { Context } = require("../src/util/context");
  24. const { Kernel } = require("../src/Kernel");
  25. const { HTTPThumbnailService } = require("../src/services/thumbnails/HTTPThumbnailService");
  26. class TestLogger {
  27. constructor () {
  28. console.log(
  29. `\x1B[36;1mBoot logger started :)\x1B[0m`,
  30. );
  31. }
  32. info (...args) {
  33. console.log(
  34. '\x1B[36;1m[TESTKERNEL/INFO]\x1B[0m',
  35. ...args,
  36. );
  37. }
  38. error (...args) {
  39. console.log(
  40. '\x1B[31;1m[TESTKERNEL/ERROR]\x1B[0m',
  41. ...args,
  42. );
  43. }
  44. }
  45. class TestKernel extends AdvancedBase {
  46. constructor () {
  47. super();
  48. this.modules = [];
  49. this.useapi = useapi();
  50. this.useapi.withuse(() => {
  51. def('Module', AdvancedBase)
  52. def('Service', BaseService)
  53. });
  54. this.logfn_ = (...a) => a;
  55. }
  56. add_module (module) {
  57. this.modules.push(module);
  58. }
  59. boot () {
  60. const { consoleLogManager } = require('../src/util/consolelog');
  61. consoleLogManager.initialize_proxy_methods();
  62. consoleLogManager.decorate_all(({ manager, replace }, ...a) => {
  63. replace(...this.logfn_(...a));
  64. });
  65. const { Container } = require('../src/services/Container');
  66. this.testLogger = new TestLogger();
  67. const services = new Container({ logger: this.testLogger });
  68. this.services = services;
  69. // app.set('services', services);
  70. const root_context = Context.create({
  71. services,
  72. useapi: this.useapi,
  73. }, 'app');
  74. globalThis.root_context = root_context;
  75. root_context.arun(async () => {
  76. await this._install_modules();
  77. // await this._boot_services();
  78. });
  79. // Error.stackTraceLimit = Infinity;
  80. Error.stackTraceLimit = 200;
  81. }
  82. async _install_modules () {
  83. const { services } = this;
  84. const mod_install_root_context = Context.get();
  85. for ( const module of this.modules ) {
  86. console.log('module?"???', module)
  87. const mod_context = this._create_mod_context(
  88. mod_install_root_context,
  89. {
  90. name: module.constructor.name,
  91. ['module']: module,
  92. external: false,
  93. },
  94. );
  95. await module.install(mod_context);
  96. }
  97. // Real kernel initializes services here, but in this test kernel
  98. // we don't initialize any services.
  99. // Real kernel adds legacy services here but these will break
  100. // the test kernel.
  101. services.ready.resolve();
  102. // provide services to helpers
  103. // const { tmp_provide_services } = require('../src/helpers');
  104. // tmp_provide_services(services);
  105. }
  106. }
  107. TestKernel.prototype._create_mod_context =
  108. Kernel.prototype._create_mod_context;
  109. const k = new TestKernel();
  110. k.add_module(new CoreModule());
  111. k.add_module({
  112. install: async (context) => {
  113. const services = context.get('services');
  114. services.registerService('thumbs-http', HTTPThumbnailService);
  115. }
  116. });
  117. k.boot();
  118. const do_after_tests_ = [];
  119. // const do_after_tests = (fn) => {
  120. // do_after_tests_.push(fn);
  121. // };
  122. const repeat_after = (fn) => {
  123. fn();
  124. do_after_tests_.push(fn);
  125. };
  126. let total_passed = 0;
  127. let total_failed = 0;
  128. const main = async () => {
  129. console.log('awaiting services readty');
  130. await k.services.ready;
  131. console.log('services have become ready');
  132. const service_names = process.argv.length > 2
  133. ? process.argv.slice(2)
  134. : Object.keys(k.services.instances_);
  135. for ( const name of service_names) {
  136. if ( ! k.services.instances_[name] ) {
  137. console.log(`\x1B[31;1mService not found: ${name}\x1B[0m`);
  138. process.exit(1);
  139. }
  140. const ins = k.services.instances_[name];
  141. ins.construct();
  142. if ( ! ins._test || typeof ins._test !== 'function' ) {
  143. continue;
  144. }
  145. let passed = 0;
  146. let failed = 0;
  147. repeat_after(() => {
  148. console.log(`\x1B[33;1m=== [ Service :: ${name} ] ===\x1B[0m`);
  149. });
  150. const testapi = {
  151. assert: (condition, name) => {
  152. name = name || condition.toString();
  153. if ( condition() ) {
  154. passed++;
  155. repeat_after(() => console.log(`\x1B[32;1m ✔ ${name}\x1B[0m`));
  156. } else {
  157. failed++;
  158. repeat_after(() => console.log(`\x1B[31;1m ✘ ${name}\x1B[0m`));
  159. }
  160. }
  161. };
  162. testapi.assert.equal = (a, b, name) => {
  163. name = name || `${a} === ${b}`;
  164. if ( a === b ) {
  165. passed++;
  166. repeat_after(() => console.log(`\x1B[32;1m ✔ ${name}\x1B[0m`));
  167. } else {
  168. failed++;
  169. repeat_after(() => {
  170. console.log(`\x1B[31;1m ✘ ${name}\x1B[0m`);
  171. console.log(`\x1B[31;1m Expected: ${b}\x1B[0m`);
  172. console.log(`\x1B[31;1m Got: ${a}\x1B[0m`);
  173. });
  174. }
  175. };
  176. await ins._test(testapi);
  177. total_passed += passed;
  178. total_failed += failed;
  179. }
  180. console.log(`\x1B[36;1m<===\x1B[0m ` +
  181. 'ASSERTION OUTPUTS ARE REPEATED BELOW' +
  182. ` \x1B[36;1m===>\x1B[0m`);
  183. for ( const fn of do_after_tests_ ) {
  184. fn();
  185. }
  186. console.log(`\x1B[36;1m=== [ Summary ] ===\x1B[0m`);
  187. console.log(`Passed: ${total_passed}`);
  188. console.log(`Failed: ${total_failed}`);
  189. process.exit(total_failed ? 1 : 0);
  190. }
  191. main();