1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
/*
This file is part of GNU Taler
(C) 2021 Taler Systems S.A.
GNU Taler is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
GNU Taler 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 General Public License along with
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
* Imports.
*/
import { URL } from "@gnu-taler/taler-util";
import * as fs from "fs";
import * as util from "util";
import {
GlobalTestState,
pingProc,
ProcessWrapper,
} from "../harness/harness.js";
import { Configuration } from "@gnu-taler/taler-util";
import * as child_process from "child_process";
const exec = util.promisify(child_process.exec);
export interface SyncConfig {
/**
* Human-readable name used in the test harness logs.
*/
name: string;
httpPort: number;
/**
* Database connection string (only postgres is supported).
*/
database: string;
annualFee: string;
currency: string;
uploadLimitMb: number;
/**
* Fulfillment URL used for contract terms related to
* sync.
*/
fulfillmentUrl: string;
paymentBackendUrl: string;
}
function setSyncPaths(config: Configuration, home: string) {
config.setString("paths", "sync_home", home);
// We need to make sure that the path of taler_runtime_dir isn't too long,
// as it contains unix domain sockets (108 character limit).
const runDir = fs.mkdtempSync("/tmp/taler-test-");
config.setString("paths", "sync_runtime_dir", runDir);
config.setString("paths", "sync_data_home", "$SYNC_HOME/.local/share/sync/");
config.setString("paths", "sync_config_home", "$SYNC_HOME/.config/sync/");
config.setString("paths", "sync_cache_home", "$SYNC_HOME/.config/sync/");
}
export class SyncService {
static async create(
gc: GlobalTestState,
sc: SyncConfig,
): Promise<SyncService> {
const config = new Configuration();
const cfgFilename = gc.testDir + `/sync-${sc.name}.conf`;
setSyncPaths(config, gc.testDir + "/synchome");
config.setString("taler", "currency", sc.currency);
config.setString("sync", "serve", "tcp");
config.setString("sync", "port", `${sc.httpPort}`);
config.setString("sync", "db", "postgres");
config.setString("syncdb-postgres", "config", sc.database);
config.setString("sync", "payment_backend_url", sc.paymentBackendUrl);
config.setString("sync", "upload_limit_mb", `${sc.uploadLimitMb}`);
config.write(cfgFilename);
return new SyncService(gc, sc, cfgFilename);
}
proc: ProcessWrapper | undefined;
get baseUrl(): string {
return `http://localhost:${this.syncConfig.httpPort}/`;
}
async start(): Promise<void> {
await exec(`sync-dbinit -c "${this.configFilename}"`);
this.proc = this.globalState.spawnService(
"sync-httpd",
["-LDEBUG", "-c", this.configFilename],
`sync-${this.syncConfig.name}`,
);
}
async pingUntilAvailable(): Promise<void> {
const url = new URL("config", this.baseUrl).href;
await pingProc(this.proc, url, "sync");
}
constructor(
private globalState: GlobalTestState,
private syncConfig: SyncConfig,
private configFilename: string,
) {}
}
|