@naanlang/naan 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/README.md +46 -0
- package/dist/env_web.js +431 -0
- package/dist/naan.min.js +73 -0
- package/frameworks/browser/browser.nlg +30 -0
- package/frameworks/browser/pouchdb/pouchdb.min.js +7 -0
- package/frameworks/browser/spark-md5/spark-md5.min.js +1 -0
- package/frameworks/browser/sworker.js +192 -0
- package/frameworks/browser/terminals.nlg +787 -0
- package/frameworks/browser/workers.nlg +386 -0
- package/frameworks/client/apiclient.nlg +183 -0
- package/frameworks/client/client.nlg +29 -0
- package/frameworks/client/psm_client.nlg +572 -0
- package/frameworks/common/common.nlg +464 -0
- package/frameworks/common/preferences.nlg +131 -0
- package/frameworks/common/repltools.nlg +100 -0
- package/frameworks/common/watching.nlg +97 -0
- package/frameworks/node/apiserver.nlg +399 -0
- package/frameworks/node/filesystem.nlg +1012 -0
- package/frameworks/node/gitter.nlg +234 -0
- package/frameworks/node/node.nlg +81 -0
- package/frameworks/node/psm_server.nlg +465 -0
- package/frameworks/node/worker.nlg +560 -0
- package/frameworks/project/build.nlg +1229 -0
- package/frameworks/project/jszip.js +30 -0
- package/frameworks/project/jszip.nlg +87 -0
- package/frameworks/project/proj_cliser.nlg +139 -0
- package/frameworks/project/proj_console.nlg +137 -0
- package/frameworks/project/proj_folder.nlg +143 -0
- package/frameworks/project/proj_lambda.nlg +137 -0
- package/frameworks/project/proj_static.nlg +138 -0
- package/frameworks/project/project.nlg +29 -0
- package/frameworks/project/projects.nlg +587 -0
- package/frameworks/project/uglifyjs.js +1 -0
- package/frameworks/project/uglifyjs.nlg +79 -0
- package/frameworks/running/debugcom.nlg +163 -0
- package/frameworks/running/debugnub.nlg +565 -0
- package/frameworks/running/debugutil.nlg +510 -0
- package/frameworks/running/executors.nlg +767 -0
- package/frameworks/running/running.nlg +151 -0
- package/frameworks/running/sourcecode.nlg +346 -0
- package/frameworks/running/taskexec.nlg +196 -0
- package/frameworks/storage/dbt_pouch.nlg +773 -0
- package/frameworks/storage/file_manager.nlg +772 -0
- package/frameworks/storage/psm.nlg +326 -0
- package/frameworks/storage/psm_dbtables.nlg +814 -0
- package/frameworks/storage/resources.nlg +445 -0
- package/frameworks/storage/storage.nlg +52 -0
- package/lib/browser/env_web.js +431 -0
- package/lib/browser/env_webworker.js +146 -0
- package/lib/browser/require.js +1653 -0
- package/lib/core/naanlib.js +73 -0
- package/lib/env_node.js +282 -0
- package/lib/env_nodeworker.js +165 -0
- package/lib/node_repl.js +25 -0
- package/lib/node_repl_init.nlg +52 -0
- package/package.json +13 -0
- package/plugins/gitClient/clientops.nlg +317 -0
- package/plugins/gitClient/gitClient.nlg +63 -0
- package/plugins/gitClient/gitutils.nlg +1331 -0
- package/plugins/gitClient/minimatch.js +945 -0
- package/plugins/gitClient/minimatch_license.txt +15 -0
- package/plugins/gitClient/minimatch_readme.md +208 -0
- package/plugins/nodeLib/nodeLib.nlg +26 -0
- package/plugins/nodeLib/node_cp.nlg +65 -0
- package/plugins/nodeLib/node_fs.nlg +137 -0
- package/plugins/nodeLib/node_https.nlg +172 -0
- package/plugins/nodeLib/node_util.nlg +180 -0
- package/plugins/serviceAws/aws/aws-sdk.min.js +88 -0
- package/plugins/serviceAws/aws/lambda_rest_index.js +122 -0
- package/plugins/serviceAws/aws/lambda_rest_init.nlg +58 -0
- package/plugins/serviceAws/aws/lambda_ws_index.js +498 -0
- package/plugins/serviceAws/aws/lambda_ws_init.nlg +49 -0
- package/plugins/serviceAws/aws_cloudwatchlogs.nlg +122 -0
- package/plugins/serviceAws/aws_cognito.nlg +76 -0
- package/plugins/serviceAws/aws_dynamo.nlg +509 -0
- package/plugins/serviceAws/aws_lambda.nlg +95 -0
- package/plugins/serviceAws/aws_s3.nlg +134 -0
- package/plugins/serviceAws/aws_utils.nlg +86 -0
- package/plugins/serviceAws/dbt_aws.nlg +769 -0
- package/plugins/serviceAws/lambda_naan_control.nlg +175 -0
- package/plugins/serviceAws/psm_aws.nlg +258 -0
- package/plugins/serviceAws/serviceAws.nlg +38 -0
- package/plugins/serviceGitHub/gitops.nlg +522 -0
- package/plugins/serviceGitHub/psm_github.nlg +205 -0
- package/plugins/serviceGitHub/serviceGitHub.nlg +65 -0
- package/plugins/serviceGitLab/gitops.nlg +528 -0
- package/plugins/serviceGitLab/psm_gitlab.nlg +205 -0
- package/plugins/serviceGitLab/serviceGitLab.nlg +65 -0
- package/test/harness.nlg +312 -0
- package/test/node_test.js +33 -0
- package/test/test_01_core.nlg +768 -0
- package/test/test_02_context.nlg +269 -0
- package/test/test_03_jsinterop.nlg +137 -0
- package/test/test_04_numerics.nlg +450 -0
- package/test/test_05_strings.nlg +63 -0
- package/test/test_06_lingoparse.nlg +500 -0
- package/test/test_07_lingo.nlg +623 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* psm_gitlab.nlg
|
|
3
|
+
* serviceGitLab
|
|
4
|
+
*
|
|
5
|
+
* PSM connector for GitLab for browser and NodeJS.
|
|
6
|
+
*
|
|
7
|
+
* column positioning: // // !
|
|
8
|
+
*
|
|
9
|
+
* Copyright (c) 2021 by Richard C. Zulch
|
|
10
|
+
*
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
/*
|
|
15
|
+
* plabConnector
|
|
16
|
+
*
|
|
17
|
+
* Make a PSM connector for GitLab access.
|
|
18
|
+
*
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
closure plabConnector(psm, local connClassID, connector, watch) {
|
|
22
|
+
connClassID = "GLAB"
|
|
23
|
+
require("plugins/serviceGitLab/gitops.nlg")
|
|
24
|
+
connector = new(object, this)
|
|
25
|
+
connector.psm = psm
|
|
26
|
+
connector.vault = psm.vault(connClassID)
|
|
27
|
+
connector.label = "GitLab"
|
|
28
|
+
watch = psm.watchable(connector)
|
|
29
|
+
|
|
30
|
+
// uifields
|
|
31
|
+
//
|
|
32
|
+
// Report the UI fields we need to add a resource
|
|
33
|
+
connector.uifields = function uifields() {
|
|
34
|
+
[{
|
|
35
|
+
label: "Username"
|
|
36
|
+
placeholder: "GitLab username or email"
|
|
37
|
+
key: "userName" },
|
|
38
|
+
{
|
|
39
|
+
label: "Password"
|
|
40
|
+
placeholder: "Personal Access Token"
|
|
41
|
+
key: "userPat"
|
|
42
|
+
type: "password" }
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// hashResourceID
|
|
47
|
+
//
|
|
48
|
+
// Make a stable hash based on the resource credentials that we can persist or share between
|
|
49
|
+
// different domains accessing the same resource.
|
|
50
|
+
connector.hashResourceID = function hashResourceID(resource, local ident) {
|
|
51
|
+
ident = resource.userName
|
|
52
|
+
if resource.label
|
|
53
|
+
ident = ident.concat(resource.label)
|
|
54
|
+
HashSHA256(ident)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// findResource
|
|
58
|
+
//
|
|
59
|
+
// Find a resource with the specified contents, returning the resID or false. The loose criteria
|
|
60
|
+
// is: if added, would the specified contents be redundant to an existing resource?
|
|
61
|
+
connector.findResource = function findResource(resource, local resID, creds) {
|
|
62
|
+
for resID in listResources().1 {
|
|
63
|
+
creds = access(resID).1
|
|
64
|
+
if resource.userName == creds.userName
|
|
65
|
+
return (resID)
|
|
66
|
+
}
|
|
67
|
+
false
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// addResource
|
|
71
|
+
//
|
|
72
|
+
// Add credentials for a named resource. The label is a string. The resource is a dictionary
|
|
73
|
+
// comprising these keys:
|
|
74
|
+
// label - [optional] label we use for this resource
|
|
75
|
+
// userName - GitLab user name
|
|
76
|
+
// userPat - GitLab Personal Access Token
|
|
77
|
+
// hidden - [optional] don't enumerate to user
|
|
78
|
+
// locked - [optional] don't allow user delete
|
|
79
|
+
// The return value is (error, result) tuple. Error, if non-false, is a dictionary of field
|
|
80
|
+
// keys and error diagnostic strings. The special key "label" refers to the label string.
|
|
81
|
+
connector.addResource = function addResource(resource, local label, errors, creds, error, resID, data) {
|
|
82
|
+
function badField(str) { !string(str) || str.trim().length == 0 }
|
|
83
|
+
creds = {
|
|
84
|
+
userName: resource.userName,
|
|
85
|
+
userPat: resource.userPat
|
|
86
|
+
}
|
|
87
|
+
errors = { }
|
|
88
|
+
if resource.label
|
|
89
|
+
creds.label = resource.label
|
|
90
|
+
else
|
|
91
|
+
creds.label = resource.region.concat("-", resource.bucketName)
|
|
92
|
+
if badField(creds.label)
|
|
93
|
+
errors.label = "invalid label"
|
|
94
|
+
if badField(resource.userName)
|
|
95
|
+
errors.userName = "required field"
|
|
96
|
+
if badField(resource.userPat)
|
|
97
|
+
errors.userPat = "required field"
|
|
98
|
+
if length(errors) > 0
|
|
99
|
+
error = errors
|
|
100
|
+
else {
|
|
101
|
+
if resource.hidden
|
|
102
|
+
creds.hidden = resource.hidden
|
|
103
|
+
if resource.locked
|
|
104
|
+
creds.locked = resource.locked
|
|
105
|
+
resID = hashResourceID(resource)
|
|
106
|
+
`(error, data) = connector.vault.addResource(resID, creds)
|
|
107
|
+
if data {
|
|
108
|
+
watch.notify(connClassID, { added: [resID] })
|
|
109
|
+
data = resID }
|
|
110
|
+
}
|
|
111
|
+
list(error, data)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// deleteResource
|
|
115
|
+
//
|
|
116
|
+
// Delete credentials for a resource
|
|
117
|
+
connector.deleteResource = function deleteResource(resID) {
|
|
118
|
+
connector.vault.deleteResource(resID)
|
|
119
|
+
watch.notify(connClassID, { deleted: [resID] })
|
|
120
|
+
list(false, { ok: true})
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// listResources
|
|
124
|
+
//
|
|
125
|
+
// List saved resources in our database
|
|
126
|
+
connector.listResources = function listResources() {
|
|
127
|
+
connector.vault.listResources()
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// info
|
|
131
|
+
//
|
|
132
|
+
// Return info for a resource.
|
|
133
|
+
connector.info = function info(resID, local error, creds, info) {
|
|
134
|
+
info = {
|
|
135
|
+
classID: "GitLab"
|
|
136
|
+
type: "GitLab"
|
|
137
|
+
services: ["GitAPI"]
|
|
138
|
+
}
|
|
139
|
+
`(error, creds) = connector.vault.accessResource(resID)
|
|
140
|
+
if creds {
|
|
141
|
+
if creds.label
|
|
142
|
+
info.name = creds.label
|
|
143
|
+
if creds.locked
|
|
144
|
+
info.locked = true
|
|
145
|
+
if creds.hidden
|
|
146
|
+
info.hidden = true
|
|
147
|
+
info.where = creds.userName
|
|
148
|
+
}
|
|
149
|
+
list(false, info)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// access
|
|
153
|
+
//
|
|
154
|
+
// Return an access object.
|
|
155
|
+
|
|
156
|
+
connector.access = function access(resID, local error, creds, glab) {
|
|
157
|
+
`(error, creds) = connector.vault.accessResource(resID)
|
|
158
|
+
if error
|
|
159
|
+
return (list(error)) // can't access that resource
|
|
160
|
+
glab = {
|
|
161
|
+
userName: creds.userName,
|
|
162
|
+
userPat: creds.userPat }
|
|
163
|
+
list(false, glab)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// connect
|
|
167
|
+
//
|
|
168
|
+
// Connect to an GitLab filesystem.
|
|
169
|
+
|
|
170
|
+
connector.connect = function connect(resID, service, args, local error, glab, gitremote, table) {
|
|
171
|
+
`(error, glab) = connector.access(resID)
|
|
172
|
+
if !error
|
|
173
|
+
`(error, gitremote) = GitLabOps(glab) // get GitLab as a git remote
|
|
174
|
+
if error
|
|
175
|
+
list(error)
|
|
176
|
+
else if service == "GitAPI"
|
|
177
|
+
list(false, gitremote)
|
|
178
|
+
else
|
|
179
|
+
list(Error("unsupported service", service))
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// finis
|
|
183
|
+
|
|
184
|
+
psm.register(connClassID, connector)
|
|
185
|
+
connector
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
/*
|
|
190
|
+
* plabInit
|
|
191
|
+
*
|
|
192
|
+
* Initialize the GitLab module.
|
|
193
|
+
*
|
|
194
|
+
*/
|
|
195
|
+
|
|
196
|
+
function plabInit(local manifest) {
|
|
197
|
+
|
|
198
|
+
manifest = `(plabConnector, plabInit)
|
|
199
|
+
|
|
200
|
+
Naan.module.build(module.id, "psm_gitlab", function(modobj, compobj) {
|
|
201
|
+
compobj.manifest = manifest
|
|
202
|
+
modobj.exports.GitLabConnector = plabConnector
|
|
203
|
+
require("./serviceGitLab.nlg")
|
|
204
|
+
})
|
|
205
|
+
} ();
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* serviceGitLab.nlg
|
|
3
|
+
* serviceGitLab
|
|
4
|
+
*
|
|
5
|
+
* GitLab access for browser and NodeJS.
|
|
6
|
+
*
|
|
7
|
+
* column positioning: // // !
|
|
8
|
+
*
|
|
9
|
+
* Copyright (c) 2021 by Richard C. Zulch
|
|
10
|
+
*
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
/*
|
|
15
|
+
* glabReload
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
function glabReload() {
|
|
20
|
+
jspath = js.r("path")
|
|
21
|
+
if js.w {
|
|
22
|
+
hashMD5 = function browserMD5(text) {
|
|
23
|
+
js.w.SparkMD5.hash(text) }
|
|
24
|
+
hashMD5_base64 = function browserMD5_base64(text) {
|
|
25
|
+
js.w.btoa(js.w.SparkMD5.hash(text, true)) }
|
|
26
|
+
textEncoder = js.w.TextEncoder
|
|
27
|
+
textDecoder = js.w.TextDecoder
|
|
28
|
+
atob = js.w.atob
|
|
29
|
+
btoa = js.w.btoa
|
|
30
|
+
encodeURIComponent = js.w.encodeURIComponent
|
|
31
|
+
JSON = js.w.JSON }
|
|
32
|
+
else if js.g {
|
|
33
|
+
if !crypto
|
|
34
|
+
crypto = js.r("crypto")
|
|
35
|
+
hashMD5 = function nodejsMD5(text) {
|
|
36
|
+
crypto.createHash("MD5").update(text).digest("hex") }
|
|
37
|
+
hashMD5_base64 = function nodejsMD5_base64(text) {
|
|
38
|
+
crypto.createHash("MD5").update(text).digest("base64") }
|
|
39
|
+
textEncoder = js.g.TextEncoder
|
|
40
|
+
textDecoder = js.g.TextDecoder
|
|
41
|
+
atob = js.g.atob
|
|
42
|
+
btoa = js.g.btoa
|
|
43
|
+
encodeURIComponent = js.g.encodeURIComponent
|
|
44
|
+
JSON = js.g.JSON }
|
|
45
|
+
LoadNotify(glabReload)
|
|
46
|
+
}();
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
/*
|
|
50
|
+
* glabInit
|
|
51
|
+
*
|
|
52
|
+
* Initialize the GitLab module.
|
|
53
|
+
*
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
function glabInit(local manifest) {
|
|
57
|
+
|
|
58
|
+
manifest = `(glabReload, glabInit)
|
|
59
|
+
|
|
60
|
+
Naan.module.build(module.id, "serviceGitLab", function(modobj, compobj) {
|
|
61
|
+
compobj.manifest = manifest
|
|
62
|
+
})
|
|
63
|
+
require("frameworks/common", { in: naanlib }).LiveImport()
|
|
64
|
+
require("./psm_gitlab.nlg").GitLabConnector(App.psm)
|
|
65
|
+
} ();
|
package/test/harness.nlg
ADDED
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* harness.nlg
|
|
3
|
+
* Test
|
|
4
|
+
*
|
|
5
|
+
* Perform basic unit tests for Naan.
|
|
6
|
+
*
|
|
7
|
+
* column positioning: // // !
|
|
8
|
+
*
|
|
9
|
+
* Copyright (c) 2020-2021 by Richard C. Zulch
|
|
10
|
+
*
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
/*
|
|
16
|
+
* initPreload
|
|
17
|
+
*
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
loglevel(2);;
|
|
21
|
+
Naan.module.chns("Play");;
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
/*
|
|
25
|
+
* Parsenv
|
|
26
|
+
*
|
|
27
|
+
* Create a parsing environment.
|
|
28
|
+
*
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
closure Parsenv(name, local penv, gohome, saveOperators, lingo, libns, naansym) {
|
|
32
|
+
penv = new(object, this)
|
|
33
|
+
gohome = makeActivator()
|
|
34
|
+
sleep(1)
|
|
35
|
+
lingo = Dialect
|
|
36
|
+
penv.lib = Naan.module.modlist().Lib.exports
|
|
37
|
+
penv.parser = lingo.parser
|
|
38
|
+
penv.unparser = lingo.unparser
|
|
39
|
+
lingo.defsym(`("#e", "#i", "#pi"))
|
|
40
|
+
penv.ns = new(namespace, name)
|
|
41
|
+
if !penv.ns {
|
|
42
|
+
debuglog("parnParsenv: can't create namespace")
|
|
43
|
+
return (false)
|
|
44
|
+
}
|
|
45
|
+
if penv.naansym {
|
|
46
|
+
naansym = letlocal(Naan).0
|
|
47
|
+
assign(naansym, car(penv.naansym))
|
|
48
|
+
}
|
|
49
|
+
nsactive(cons(penv.ns, lingo.info().namespace, nsactive().-2))
|
|
50
|
+
penv.gons = makeActivator()
|
|
51
|
+
gohome()
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
// parse
|
|
55
|
+
//
|
|
56
|
+
// Parse the specified text into our environment, returning the following dictionary:
|
|
57
|
+
// {
|
|
58
|
+
// errors: <array of errors, if any>
|
|
59
|
+
// text: <array of output text, if any>
|
|
60
|
+
// exprs: <array of expressions that we have parsed>
|
|
61
|
+
// results: <array of evaluation results for the expressions>
|
|
62
|
+
// pretty: <array of pretty-printed results>
|
|
63
|
+
// }
|
|
64
|
+
|
|
65
|
+
penv.parse = function parse(text, local output, curns, source, xchan, errors, error, expr, savex, outext) {
|
|
66
|
+
output = {
|
|
67
|
+
errors: []
|
|
68
|
+
text: []
|
|
69
|
+
exprs: []
|
|
70
|
+
results: []
|
|
71
|
+
pretty: []
|
|
72
|
+
}
|
|
73
|
+
curns = nsactive()
|
|
74
|
+
source = new(textstream, text, `string)
|
|
75
|
+
xchan = textstreams(list(source, source))
|
|
76
|
+
try {
|
|
77
|
+
penv.gons()
|
|
78
|
+
loop {
|
|
79
|
+
try {
|
|
80
|
+
savex = `exception.proc
|
|
81
|
+
sudo(putproc(`exception, false)) // don't enter debugger during test
|
|
82
|
+
`(errors, expr) = lingo.parse(source)
|
|
83
|
+
for error in errors
|
|
84
|
+
output.errors.push(penv.lib.ParseErrorString(error))
|
|
85
|
+
if expr {
|
|
86
|
+
output.exprs.push(expr)
|
|
87
|
+
expr = function() { evalactive(expr) }() // return here if return executed outside procedure
|
|
88
|
+
output.results.push(expr)
|
|
89
|
+
if source.tokenlast().atom == `;>
|
|
90
|
+
output.pretty.push(tostring(expr, { quote: true }))
|
|
91
|
+
else if source.tokenlast().atom != `;;
|
|
92
|
+
output.pretty.push(lingo.print(expr))
|
|
93
|
+
}
|
|
94
|
+
} finally {
|
|
95
|
+
sudo(putproc(`exception, savex)) }
|
|
96
|
+
}
|
|
97
|
+
} catch {
|
|
98
|
+
if true {
|
|
99
|
+
if tostring(car(exception)) == "internal" and tostring(second(exception)) == "end-of-file"
|
|
100
|
+
{ }
|
|
101
|
+
else if tostring(car(exception)) == "internal" and string(second(exception))
|
|
102
|
+
output.errors.push(second(exception))
|
|
103
|
+
else
|
|
104
|
+
output.errors.push("exception: ".concat(exception))
|
|
105
|
+
}
|
|
106
|
+
} finally {
|
|
107
|
+
gohome()
|
|
108
|
+
textstreams(xchan)
|
|
109
|
+
outext = source.taketext().trim()
|
|
110
|
+
if outext.length > 0
|
|
111
|
+
output.text = new(outext.split("\n"))
|
|
112
|
+
}
|
|
113
|
+
output
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// unparse
|
|
117
|
+
//
|
|
118
|
+
// Unparse our environment into text.
|
|
119
|
+
|
|
120
|
+
penv.unparse = function unparse(local options, text, sym, didprop, key) {
|
|
121
|
+
options = {
|
|
122
|
+
wrapMaxCol: 240
|
|
123
|
+
}
|
|
124
|
+
text = ""
|
|
125
|
+
for sym in symlist(penv.ns) {
|
|
126
|
+
if !(sym eq car(sym))
|
|
127
|
+
text = text.concat(sym, " = ", car(sym), ";;\n\n")
|
|
128
|
+
didprop = false
|
|
129
|
+
for key in sym@*
|
|
130
|
+
if key.charAt(0) != "." {
|
|
131
|
+
didprop = true
|
|
132
|
+
text = text.concat(sym, "@", key, " = ", sym@[key], ";;\n") }
|
|
133
|
+
if didprop
|
|
134
|
+
text = text.concat("\n")
|
|
135
|
+
if sym.proc.1.namespace eq penv.ns
|
|
136
|
+
text = text.concat(lingo.print(sym.proc, options), ";\n\n")
|
|
137
|
+
}
|
|
138
|
+
text
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// destroy
|
|
142
|
+
//
|
|
143
|
+
// Destroy our environment to reclaim the namespace.
|
|
144
|
+
|
|
145
|
+
penv.destroy = function destroy() {
|
|
146
|
+
penv.ns = delete(penv.ns)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// finis
|
|
150
|
+
|
|
151
|
+
penv
|
|
152
|
+
};;
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
/*
|
|
156
|
+
* RegisterTestCategory
|
|
157
|
+
*
|
|
158
|
+
* Register a test category to run later.
|
|
159
|
+
*
|
|
160
|
+
*/
|
|
161
|
+
|
|
162
|
+
testsToRun = [];;
|
|
163
|
+
|
|
164
|
+
function RegisterTestCategory(name, tests) {
|
|
165
|
+
testsToRun.push({
|
|
166
|
+
name: name
|
|
167
|
+
tests: tests
|
|
168
|
+
})
|
|
169
|
+
};;
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
/*
|
|
173
|
+
* Load tests
|
|
174
|
+
*
|
|
175
|
+
*/
|
|
176
|
+
|
|
177
|
+
nodeparse("test_01_core.nlg");;
|
|
178
|
+
nodeparse("test_02_context.nlg");;
|
|
179
|
+
nodeparse("test_03_jsinterop.nlg");;
|
|
180
|
+
nodeparse("test_04_numerics.nlg");;
|
|
181
|
+
nodeparse("test_05_strings.nlg");;
|
|
182
|
+
nodeparse("test_06_lingoparse.nlg");;
|
|
183
|
+
nodeparse("test_07_lingo.nlg");;
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
/*
|
|
187
|
+
* RunTests
|
|
188
|
+
*
|
|
189
|
+
* Run all our tests and produce a total summary at the end.
|
|
190
|
+
*
|
|
191
|
+
*/
|
|
192
|
+
|
|
193
|
+
function RunTests(local totalTestCount, totalPassCount, totalTimeMS) {
|
|
194
|
+
totalTestCount = 0
|
|
195
|
+
totalPassCount = 0
|
|
196
|
+
totalTimeMS = 0
|
|
197
|
+
printline("Running Naan unit test suite")
|
|
198
|
+
printline("============================")
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
//
|
|
202
|
+
// testOneLocation
|
|
203
|
+
//
|
|
204
|
+
//
|
|
205
|
+
function testOneLocation(name, tests, local testCounter, successCounter, bannered,
|
|
206
|
+
parsenv, test, textout, elapsedMS) {
|
|
207
|
+
testCounter = 0
|
|
208
|
+
successCounter = 0
|
|
209
|
+
bannered = false
|
|
210
|
+
parsenv = Parsenv("Test-".concat(name))
|
|
211
|
+
textout = ""
|
|
212
|
+
|
|
213
|
+
function banner()
|
|
214
|
+
{
|
|
215
|
+
if !bannered {
|
|
216
|
+
textout = textout.concat("While running ", name, "...\n")
|
|
217
|
+
textout = textout.concat("-----\n") }
|
|
218
|
+
bannered = true
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function testOne(cmd, expect, local result, response, type, break1, break2)
|
|
222
|
+
{
|
|
223
|
+
if string(cmd)
|
|
224
|
+
result = parsenv.parse(cmd.concat("\n"))
|
|
225
|
+
else
|
|
226
|
+
return ("invalid cmd at test ".concat(testCounter, ": ", typeof(cmd), "\n"))
|
|
227
|
+
if string(expect) {
|
|
228
|
+
if result.errors.length > 0
|
|
229
|
+
return (strcat("test(\"", cmd, "\") failed:\n ", result.errors.join("|"), "\n"))
|
|
230
|
+
else
|
|
231
|
+
response = result.text.concat(result.pretty).join("|")
|
|
232
|
+
} else if dictionary(expect) {
|
|
233
|
+
for type in expect {
|
|
234
|
+
response = result[type].map(function(item){
|
|
235
|
+
if string(item)
|
|
236
|
+
item
|
|
237
|
+
else
|
|
238
|
+
tostring(item, { quote: true, nonamespace: true })})
|
|
239
|
+
response = response.join("|")
|
|
240
|
+
if response != expect[type]
|
|
241
|
+
break
|
|
242
|
+
}
|
|
243
|
+
if !expect.errors && result.errors.length > 0
|
|
244
|
+
return (strcat("test(\"", cmd, "\") unexpected errors = \"", result.errors.join("|"), "\"\n"))
|
|
245
|
+
if !expect.text && result.text.length > 0
|
|
246
|
+
return (strcat("test(\"", cmd, "\") unexpected text = \"", result.text.join("|"), "\"\n"))
|
|
247
|
+
expect = expect[type]
|
|
248
|
+
} else
|
|
249
|
+
return (strcat("test(\"", cmd, "\"): invalid response type ", typeof(expect), "\n"))
|
|
250
|
+
if response != expect {
|
|
251
|
+
break1 = ""
|
|
252
|
+
break2 = ", "
|
|
253
|
+
if cmd.length > 10 || result.length > 20 {
|
|
254
|
+
break1 = "\n "
|
|
255
|
+
break2 = "\n " }
|
|
256
|
+
return (strcat("test(\"", cmd, "\") ", break1, "reported \"", response, "\"", break2, "expected \"", expect, "\"", "\n")) }
|
|
257
|
+
|
|
258
|
+
++totalAllSuccess
|
|
259
|
+
return ("")
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function rrTest(cmd, expect, local error)
|
|
263
|
+
{
|
|
264
|
+
++testCounter
|
|
265
|
+
if ((error = testOne(cmd, expect)) == "")
|
|
266
|
+
++successCounter
|
|
267
|
+
else
|
|
268
|
+
{
|
|
269
|
+
banner()
|
|
270
|
+
textout = textout.concat(error)
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
elapsedMS = Date.now()
|
|
275
|
+
for test in tests
|
|
276
|
+
rrTest(test.0, test.1)
|
|
277
|
+
elapsedMS = Date.now() - elapsedMS
|
|
278
|
+
parsenv.destroy()
|
|
279
|
+
|
|
280
|
+
if (bannered) {
|
|
281
|
+
print(textout)
|
|
282
|
+
printline("-----") }
|
|
283
|
+
printline(prepad(name, 18).concat(": ", prepad(successCounter, 3), " of ", prepad(testCounter, 3), " tests ran successfully in ", (elapsedMS/1000.0).toFixed(3), " seconds"))
|
|
284
|
+
totalTestCount += testCounter
|
|
285
|
+
totalPassCount += successCounter
|
|
286
|
+
totalTimeMS += elapsedMS
|
|
287
|
+
{ ok: true }
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
//
|
|
292
|
+
// run registered tests
|
|
293
|
+
//
|
|
294
|
+
|
|
295
|
+
let(local categ) {
|
|
296
|
+
for categ in testsToRun
|
|
297
|
+
testOneLocation(categ.name, categ.tests)
|
|
298
|
+
}()
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
//
|
|
302
|
+
// report results
|
|
303
|
+
//
|
|
304
|
+
|
|
305
|
+
let () {
|
|
306
|
+
printline("============================")
|
|
307
|
+
printline(prepad(totalTestCount, 5), " tests in ", (totalTimeMS/1000.0).toFixed(3), " seconds")
|
|
308
|
+
printline(prepad(totalPassCount, 5), " succeeded")
|
|
309
|
+
printline(prepad(totalTestCount-totalPassCount, 5), " failed")
|
|
310
|
+
printline()
|
|
311
|
+
}()
|
|
312
|
+
}();;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* node_test.js
|
|
3
|
+
* Naanlib
|
|
4
|
+
*
|
|
5
|
+
* Conduct unit tests using a Naan repl in Node.
|
|
6
|
+
*
|
|
7
|
+
* column positioning: // // !
|
|
8
|
+
*
|
|
9
|
+
* Copyright (c) 2021 by Richard C. Zulch
|
|
10
|
+
*
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
"use strict";
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
/*
|
|
17
|
+
* Begin
|
|
18
|
+
*
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
var NaanNodeREPL = require('../lib/env_node.js');
|
|
22
|
+
var jspath = require("path");
|
|
23
|
+
|
|
24
|
+
var naanrepl = new NaanNodeREPL({
|
|
25
|
+
replDisable: true
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
naanrepl.setDirectory(__dirname);
|
|
29
|
+
|
|
30
|
+
naanrepl.textCommand("body("
|
|
31
|
+
+ "nodeparse('harness.nlg'),"
|
|
32
|
+
+ "sleep(1),"
|
|
33
|
+
+ "exec(quote(js.g.process.exit(0))));;\n");
|